diff src/video/directfb/SDL_DirectFB_yuv.c @ 478:f8482d7c9595

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.
author Sam Lantinga <slouken@libsdl.org>
date Sat, 31 Aug 2002 04:13:28 +0000
parents
children b8d311d90021
line wrap: on
line diff
--- /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);
+    }
+}
+