Mercurial > sdl-ios-xcode
view src/video/directfb/SDL_DirectFB_yuv.c @ 1934:70139af5ac27
Implemented Mac OS X video mode selection.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 24 Jul 2006 07:21:16 +0000 |
parents | c121d94672cb |
children | 7ba4a732e3d0 |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" /* This is the DirectFB implementation of YUV video overlays */ #include "SDL_video.h" #include "SDL_DirectFB_yuv.h" #include "../SDL_yuvfuncs.h" /* The functions used to manipulate software video overlays */ static struct private_yuvhwfuncs directfb_yuvfuncs = { DirectFB_LockYUVOverlay, DirectFB_UnlockYUVOverlay, DirectFB_DisplayYUVOverlay, DirectFB_FreeYUVOverlay }; struct private_yuvhwdata { DFBDisplayLayerID layer_id; IDirectFBDisplayLayer *layer; IDirectFBSurface *surface; /* These are just so we don't have to allocate them separately */ Uint16 pitches[3]; Uint8 *planes[3]; }; static DFBEnumerationResult enum_layers_callback(DFBDisplayLayerID id, DFBDisplayLayerDescription desc, void *data) { struct private_yuvhwdata *hwdata = (struct private_yuvhwdata *) data; /* we don't want the primary */ if (id == DLID_PRIMARY) return DFENUM_OK; /* take the one with a surface for video */ if ((desc.caps & DLCAPS_SURFACE) && (desc.type & DLTF_VIDEO)) { hwdata->layer_id = id; return DFENUM_CANCEL; } return DFENUM_OK; } static DFBResult CreateYUVSurface(_THIS, struct private_yuvhwdata *hwdata, int width, int height, Uint32 format) { DFBResult ret; IDirectFB *dfb = HIDDEN->dfb; IDirectFBDisplayLayer *layer; DFBDisplayLayerConfig conf; ret = dfb->EnumDisplayLayers(dfb, enum_layers_callback, hwdata); if (ret) { SetDirectFBerror("IDirectFB::EnumDisplayLayers", ret); return ret; } if (!hwdata->layer_id) return DFB_UNSUPPORTED; ret = dfb->GetDisplayLayer(dfb, hwdata->layer_id, &layer); if (ret) { SetDirectFBerror("IDirectFB::GetDisplayLayer", ret); return ret; } conf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT; conf.width = width; conf.height = height; switch (format) { case SDL_YV12_OVERLAY: conf.pixelformat = DSPF_YV12; break; case SDL_IYUV_OVERLAY: conf.pixelformat = DSPF_I420; break; case SDL_YUY2_OVERLAY: conf.pixelformat = DSPF_YUY2; break; case SDL_UYVY_OVERLAY: conf.pixelformat = DSPF_UYVY; break; default: fprintf(stderr, "SDL_DirectFB: Unsupported YUV format (0x%08x)!\n", format); break; } ret = layer->SetConfiguration(layer, &conf); if (ret) { SetDirectFBerror("IDirectFBDisplayLayer::SetConfiguration", ret); layer->Release(layer); return ret; } ret = layer->GetSurface(layer, &hwdata->surface); if (ret) { SetDirectFBerror("IDirectFBDisplayLayer::GetSurface", ret); layer->Release(layer); return ret; } hwdata->layer = layer; return DFB_OK; } SDL_Overlay * DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface * display) { SDL_Overlay *overlay; struct private_yuvhwdata *hwdata; /* Create the overlay structure */ overlay = SDL_calloc(1, sizeof(SDL_Overlay)); if (!overlay) { SDL_OutOfMemory(); return NULL; } /* Fill in the basic members */ overlay->format = format; overlay->w = width; overlay->h = height; /* Set up the YUV surface function structure */ overlay->hwfuncs = &directfb_yuvfuncs; /* Create the pixel data and lookup tables */ hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata)); overlay->hwdata = hwdata; if (!hwdata) { SDL_OutOfMemory(); SDL_FreeYUVOverlay(overlay); return NULL; } if (CreateYUVSurface(this, hwdata, width, height, format)) { SDL_FreeYUVOverlay(overlay); return NULL; } overlay->hw_overlay = 1; /* Set up the plane pointers */ overlay->pitches = hwdata->pitches; overlay->pixels = hwdata->planes; switch (format) { case SDL_YV12_OVERLAY: case SDL_IYUV_OVERLAY: overlay->planes = 3; break; default: overlay->planes = 1; break; } /* We're all done.. */ return overlay; } int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay * overlay) { DFBResult ret; void *data; int pitch; IDirectFBSurface *surface = overlay->hwdata->surface; ret = surface->Lock(surface, DSLF_READ | DSLF_WRITE, &data, &pitch); if (ret) { SetDirectFBerror("IDirectFBSurface::Lock", ret); return -1; } /* Find the pitch and offset values for the overlay */ overlay->pitches[0] = (Uint16) pitch; overlay->pixels[0] = (Uint8 *) data; switch (overlay->format) { case SDL_YV12_OVERLAY: case SDL_IYUV_OVERLAY: /* Add the two extra planes */ overlay->pitches[1] = overlay->pitches[0] / 2; overlay->pitches[2] = overlay->pitches[0] / 2; overlay->pixels[1] = overlay->pixels[0] + overlay->pitches[0] * overlay->h; overlay->pixels[2] = overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2; break; default: /* Only one plane, no worries */ break; } return 0; } void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay) { IDirectFBSurface *surface = overlay->hwdata->surface; overlay->pixels[0] = overlay->pixels[1] = overlay->pixels[2] = NULL; surface->Unlock(surface); } int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, SDL_Rect * src, SDL_Rect * dst) { DFBResult ret; DFBDisplayLayerConfig conf; IDirectFBDisplayLayer *primary = HIDDEN->layer; IDirectFBDisplayLayer *layer = overlay->hwdata->layer; primary->GetConfiguration(primary, &conf); ret = layer->SetScreenLocation(layer, dst->x / (float) conf.width, dst->y / (float) conf.height, dst->w / (float) conf.width, dst->h / (float) conf.height); if (ret) { SetDirectFBerror("IDirectFBDisplayLayer::SetScreenLocation", ret); return -1; } return 0; } void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay * overlay) { struct private_yuvhwdata *hwdata; hwdata = overlay->hwdata; if (hwdata) { if (hwdata->surface) hwdata->surface->Release(hwdata->surface); if (hwdata->layer) hwdata->layer->Release(hwdata->layer); free(hwdata); } } /* vi: set ts=4 sw=4 expandtab: */