2002-08-31 04:13:28 +00:00
|
|
|
/*
|
|
|
|
SDL - Simple DirectMedia Layer
|
2006-02-01 06:32:25 +00:00
|
|
|
Copyright (C) 1997-2006 Sam Lantinga
|
2002-08-31 04:13:28 +00:00
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2006-02-01 06:32:25 +00:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
2002-08-31 04:13:28 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2006-02-01 06:32:25 +00:00
|
|
|
version 2.1 of the License, or (at your option) any later version.
|
2002-08-31 04:13:28 +00:00
|
|
|
|
|
|
|
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
|
2006-02-01 06:32:25 +00:00
|
|
|
Lesser General Public License for more details.
|
2002-08-31 04:13:28 +00:00
|
|
|
|
2006-02-01 06:32:25 +00:00
|
|
|
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
|
2002-08-31 04:13:28 +00:00
|
|
|
|
|
|
|
Sam Lantinga
|
|
|
|
slouken@libsdl.org
|
|
|
|
*/
|
2006-02-21 08:46:50 +00:00
|
|
|
#include "SDL_config.h"
|
2002-08-31 04:13:28 +00:00
|
|
|
|
|
|
|
/* This is the DirectFB implementation of YUV video overlays */
|
|
|
|
|
|
|
|
#include "SDL_video.h"
|
|
|
|
#include "SDL_DirectFB_yuv.h"
|
2006-02-16 10:11:48 +00:00
|
|
|
#include "../SDL_yuvfuncs.h"
|
2002-08-31 04:13:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* 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 */
|
2006-02-07 09:29:18 +00:00
|
|
|
overlay = SDL_calloc (1, sizeof(SDL_Overlay));
|
2002-08-31 04:13:28 +00:00
|
|
|
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 */
|
2006-02-07 09:29:18 +00:00
|
|
|
hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata));
|
2002-08-31 04:13:28 +00:00
|
|
|
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;
|
|
|
|
unsigned 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 *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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|