Date: Tue, 27 Aug 2002 19:07:38 +0200
From: Denis Oliver Kropp
Subject: YUV support
I just added YUV overlay support to the DirectFB backend.
--- a/src/video/directfb/Makefile.am Sat Aug 31 04:06:37 2002 +0000
+++ b/src/video/directfb/Makefile.am Sat Aug 31 04:13:28 2002 +0000
@@ -12,4 +12,6 @@
SDL_DirectFB_events.c \
SDL_DirectFB_events.h \
SDL_DirectFB_video.c \
- SDL_DirectFB_video.h
+ SDL_DirectFB_video.h \
+ SDL_DirectFB_yuv.c \
+ SDL_DirectFB_yuv.h
--- a/src/video/directfb/SDL_DirectFB_video.c Sat Aug 31 04:06:37 2002 +0000
+++ b/src/video/directfb/SDL_DirectFB_video.c Sat Aug 31 04:13:28 2002 +0000
@@ -46,6 +46,7 @@
#include "SDL_events_c.h"
#include "SDL_DirectFB_video.h"
#include "SDL_DirectFB_events.h"
+#include "SDL_DirectFB_yuv.h"
/* Initialization/Query functions */
@@ -123,6 +124,7 @@
device->SetVideoMode = DirectFB_SetVideoMode;
device->SetColors = DirectFB_SetColors;
device->UpdateRects = NULL;
+ device->CreateYUVOverlay = DirectFB_CreateYUVOverlay;
device->VideoQuit = DirectFB_VideoQuit;
device->AllocHWSurface = DirectFB_AllocHWSurface;
device->CheckHWBlit = DirectFB_CheckHWBlit;
--- a/src/video/directfb/SDL_DirectFB_video.h Sat Aug 31 04:06:37 2002 +0000
+++ b/src/video/directfb/SDL_DirectFB_video.h Sat Aug 31 04:13:28 2002 +0000
@@ -51,4 +51,6 @@
#define HIDDEN (this->hidden)
+void SetDirectFBerror (const char *function, DFBResult code);
+
#endif /* _SDL_DirectFB_video_h */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/directfb/SDL_DirectFB_yuv.c Sat Aug 31 04:13:28 2002 +0000
@@ -0,0 +1,289 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* This is the DirectFB implementation of YUV video overlays */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "SDL_error.h"
+#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 = 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 = 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;
+ 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);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/directfb/SDL_DirectFB_yuv.h Sat Aug 31 04:13:28 2002 +0000
@@ -0,0 +1,42 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* This is the DirectFB implementation of YUV video overlays */
+
+#include "SDL_video.h"
+#include "SDL_DirectFB_video.h"
+
+extern SDL_Overlay *DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display);
+
+extern int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay *overlay);
+
+extern void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay);
+
+extern int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect);
+
+extern void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay *overlay);
+