Skip to content

Commit

Permalink
Date: Tue, 27 Aug 2002 19:07:38 +0200
Browse files Browse the repository at this point in the history
From: Denis Oliver Kropp
Subject: YUV support

I just added YUV overlay support to the DirectFB backend.
  • Loading branch information
slouken committed Aug 31, 2002
1 parent 6ffa9f5 commit 298de68
Show file tree
Hide file tree
Showing 5 changed files with 338 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/video/directfb/Makefile.am
Expand Up @@ -12,4 +12,6 @@ DIRECTFB_SRCS = \
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
2 changes: 2 additions & 0 deletions src/video/directfb/SDL_DirectFB_video.c
Expand Up @@ -46,6 +46,7 @@ static char rcsid =
#include "SDL_events_c.h"
#include "SDL_DirectFB_video.h"
#include "SDL_DirectFB_events.h"
#include "SDL_DirectFB_yuv.h"


/* Initialization/Query functions */
Expand Down Expand Up @@ -123,6 +124,7 @@ static SDL_VideoDevice *DirectFB_CreateDevice(int devindex)
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;
Expand Down
2 changes: 2 additions & 0 deletions src/video/directfb/SDL_DirectFB_video.h
Expand Up @@ -51,4 +51,6 @@ struct SDL_PrivateVideoData

#define HIDDEN (this->hidden)

void SetDirectFBerror (const char *function, DFBResult code);

#endif /* _SDL_DirectFB_video_h */
289 changes: 289 additions & 0 deletions src/video/directfb/SDL_DirectFB_yuv.c
@@ -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);
}
}

42 changes: 42 additions & 0 deletions src/video/directfb/SDL_DirectFB_yuv.h
@@ -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);

0 comments on commit 298de68

Please sign in to comment.