src/video/directfb/SDL_DirectFB_yuv.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 06 Jan 2006 13:20:10 +0000
changeset 1234 73676c1f56ee
parent 769 b8d311d90021
child 1312 c9b51268668f
permissions -rw-r--r--
For sanity's sake, removed the '&' when passing copy_row array to asm.
slouken@478
     1
/*
slouken@478
     2
    SDL - Simple DirectMedia Layer
slouken@769
     3
    Copyright (C) 1997-2004 Sam Lantinga
slouken@478
     4
slouken@478
     5
    This library is free software; you can redistribute it and/or
slouken@478
     6
    modify it under the terms of the GNU Library General Public
slouken@478
     7
    License as published by the Free Software Foundation; either
slouken@478
     8
    version 2 of the License, or (at your option) any later version.
slouken@478
     9
slouken@478
    10
    This library is distributed in the hope that it will be useful,
slouken@478
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@478
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@478
    13
    Library General Public License for more details.
slouken@478
    14
slouken@478
    15
    You should have received a copy of the GNU Library General Public
slouken@478
    16
    License along with this library; if not, write to the Free
slouken@478
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
slouken@478
    18
slouken@478
    19
    Sam Lantinga
slouken@478
    20
    slouken@libsdl.org
slouken@478
    21
*/
slouken@478
    22
slouken@478
    23
#ifdef SAVE_RCSID
slouken@478
    24
static char rcsid =
slouken@478
    25
 "@(#) $Id$";
slouken@478
    26
#endif
slouken@478
    27
slouken@478
    28
/* This is the DirectFB implementation of YUV video overlays */
slouken@478
    29
slouken@478
    30
#include <stdlib.h>
slouken@478
    31
#include <string.h>
slouken@478
    32
slouken@478
    33
#include "SDL_error.h"
slouken@478
    34
#include "SDL_video.h"
slouken@478
    35
#include "SDL_DirectFB_yuv.h"
slouken@478
    36
#include "SDL_yuvfuncs.h"
slouken@478
    37
slouken@478
    38
slouken@478
    39
/* The functions used to manipulate software video overlays */
slouken@478
    40
static struct private_yuvhwfuncs directfb_yuvfuncs = {
slouken@478
    41
  DirectFB_LockYUVOverlay,
slouken@478
    42
  DirectFB_UnlockYUVOverlay,
slouken@478
    43
  DirectFB_DisplayYUVOverlay,
slouken@478
    44
  DirectFB_FreeYUVOverlay
slouken@478
    45
};
slouken@478
    46
slouken@478
    47
struct private_yuvhwdata {
slouken@478
    48
  DFBDisplayLayerID      layer_id;
slouken@478
    49
slouken@478
    50
  IDirectFBDisplayLayer *layer;
slouken@478
    51
  IDirectFBSurface      *surface;
slouken@478
    52
slouken@478
    53
  /* These are just so we don't have to allocate them separately */
slouken@478
    54
  Uint16 pitches[3];
slouken@478
    55
  Uint8 *planes[3];
slouken@478
    56
};
slouken@478
    57
slouken@478
    58
static DFBEnumerationResult
slouken@478
    59
enum_layers_callback( DFBDisplayLayerID            id,
slouken@478
    60
                      DFBDisplayLayerDescription   desc,
slouken@478
    61
                      void                        *data )
slouken@478
    62
{
slouken@478
    63
  struct private_yuvhwdata *hwdata = (struct private_yuvhwdata *) data;
slouken@478
    64
slouken@478
    65
  /* we don't want the primary */
slouken@478
    66
  if (id == DLID_PRIMARY)
slouken@478
    67
    return DFENUM_OK;
slouken@478
    68
slouken@478
    69
  /* take the one with a surface for video */
slouken@478
    70
  if ((desc.caps & DLCAPS_SURFACE) && (desc.type & DLTF_VIDEO))
slouken@478
    71
    {
slouken@478
    72
      hwdata->layer_id = id;
slouken@478
    73
slouken@478
    74
      return DFENUM_CANCEL;
slouken@478
    75
    }
slouken@478
    76
slouken@478
    77
  return DFENUM_OK;
slouken@478
    78
}
slouken@478
    79
slouken@478
    80
slouken@478
    81
static DFBResult CreateYUVSurface(_THIS, struct private_yuvhwdata *hwdata,
slouken@478
    82
                                  int width, int height, Uint32 format)
slouken@478
    83
{
slouken@478
    84
  DFBResult              ret;
slouken@478
    85
  IDirectFB             *dfb = HIDDEN->dfb;
slouken@478
    86
  IDirectFBDisplayLayer *layer;
slouken@478
    87
  DFBDisplayLayerConfig  conf;
slouken@478
    88
slouken@478
    89
  ret = dfb->EnumDisplayLayers (dfb, enum_layers_callback, hwdata);
slouken@478
    90
  if (ret)
slouken@478
    91
    {
slouken@478
    92
      SetDirectFBerror("IDirectFB::EnumDisplayLayers", ret);
slouken@478
    93
      return ret;
slouken@478
    94
    }
slouken@478
    95
slouken@478
    96
  if (!hwdata->layer_id)
slouken@478
    97
    return DFB_UNSUPPORTED;
slouken@478
    98
slouken@478
    99
  ret = dfb->GetDisplayLayer (dfb, hwdata->layer_id, &layer);
slouken@478
   100
  if (ret)
slouken@478
   101
    {
slouken@478
   102
      SetDirectFBerror("IDirectFB::GetDisplayLayer", ret);
slouken@478
   103
      return ret;
slouken@478
   104
    }
slouken@478
   105
slouken@478
   106
  conf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;
slouken@478
   107
  conf.width = width;
slouken@478
   108
  conf.height = height;
slouken@478
   109
slouken@478
   110
  switch (format)
slouken@478
   111
    {
slouken@478
   112
    case SDL_YV12_OVERLAY:
slouken@478
   113
      conf.pixelformat = DSPF_YV12;
slouken@478
   114
      break;
slouken@478
   115
    case SDL_IYUV_OVERLAY:
slouken@478
   116
      conf.pixelformat = DSPF_I420;
slouken@478
   117
      break;
slouken@478
   118
    case SDL_YUY2_OVERLAY:
slouken@478
   119
      conf.pixelformat = DSPF_YUY2;
slouken@478
   120
      break;
slouken@478
   121
    case SDL_UYVY_OVERLAY:
slouken@478
   122
      conf.pixelformat = DSPF_UYVY;
slouken@478
   123
      break;
slouken@478
   124
    default:
slouken@478
   125
      fprintf (stderr, "SDL_DirectFB: Unsupported YUV format (0x%08x)!\n", format);
slouken@478
   126
      break;
slouken@478
   127
    }
slouken@478
   128
slouken@478
   129
  ret = layer->SetConfiguration (layer, &conf);
slouken@478
   130
  if (ret)
slouken@478
   131
    {
slouken@478
   132
      SetDirectFBerror("IDirectFBDisplayLayer::SetConfiguration", ret);
slouken@478
   133
      layer->Release (layer);
slouken@478
   134
      return ret;
slouken@478
   135
    }
slouken@478
   136
slouken@478
   137
  ret = layer->GetSurface (layer, &hwdata->surface);
slouken@478
   138
  if (ret)
slouken@478
   139
    {
slouken@478
   140
      SetDirectFBerror("IDirectFBDisplayLayer::GetSurface", ret);
slouken@478
   141
      layer->Release (layer);
slouken@478
   142
      return ret;
slouken@478
   143
    }
slouken@478
   144
slouken@478
   145
  hwdata->layer = layer;
slouken@478
   146
slouken@478
   147
  return DFB_OK;
slouken@478
   148
}
slouken@478
   149
slouken@478
   150
SDL_Overlay *DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display)
slouken@478
   151
{
slouken@478
   152
  SDL_Overlay *overlay;
slouken@478
   153
  struct private_yuvhwdata *hwdata;
slouken@478
   154
slouken@478
   155
  /* Create the overlay structure */
slouken@478
   156
  overlay = calloc (1, sizeof(SDL_Overlay));
slouken@478
   157
  if (!overlay)
slouken@478
   158
    {
slouken@478
   159
      SDL_OutOfMemory();
slouken@478
   160
      return NULL;
slouken@478
   161
    }
slouken@478
   162
	
slouken@478
   163
  /* Fill in the basic members */
slouken@478
   164
  overlay->format = format;
slouken@478
   165
  overlay->w = width;
slouken@478
   166
  overlay->h = height;
slouken@478
   167
slouken@478
   168
  /* Set up the YUV surface function structure */
slouken@478
   169
  overlay->hwfuncs = &directfb_yuvfuncs;
slouken@478
   170
slouken@478
   171
  /* Create the pixel data and lookup tables */
slouken@478
   172
  hwdata = calloc(1, sizeof(struct private_yuvhwdata));
slouken@478
   173
  overlay->hwdata = hwdata;
slouken@478
   174
  if (!hwdata)
slouken@478
   175
    {
slouken@478
   176
      SDL_OutOfMemory();
slouken@478
   177
      SDL_FreeYUVOverlay (overlay);
slouken@478
   178
      return NULL;
slouken@478
   179
    }
slouken@478
   180
slouken@478
   181
  if (CreateYUVSurface (this, hwdata, width, height, format))
slouken@478
   182
    {
slouken@478
   183
      SDL_FreeYUVOverlay (overlay);
slouken@478
   184
      return NULL;
slouken@478
   185
    }
slouken@478
   186
slouken@478
   187
  overlay->hw_overlay = 1;
slouken@478
   188
slouken@478
   189
  /* Set up the plane pointers */
slouken@478
   190
  overlay->pitches = hwdata->pitches;
slouken@478
   191
  overlay->pixels = hwdata->planes;
slouken@478
   192
  switch (format)
slouken@478
   193
    {
slouken@478
   194
    case SDL_YV12_OVERLAY:
slouken@478
   195
    case SDL_IYUV_OVERLAY:
slouken@478
   196
      overlay->planes = 3;
slouken@478
   197
      break;
slouken@478
   198
    default:
slouken@478
   199
      overlay->planes = 1;
slouken@478
   200
      break;
slouken@478
   201
    }
slouken@478
   202
slouken@478
   203
  /* We're all done.. */
slouken@478
   204
  return overlay;
slouken@478
   205
}
slouken@478
   206
slouken@478
   207
int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay *overlay)
slouken@478
   208
{
slouken@478
   209
  DFBResult         ret;
slouken@478
   210
  void             *data;
slouken@478
   211
  unsigned int      pitch;
slouken@478
   212
  IDirectFBSurface *surface = overlay->hwdata->surface;
slouken@478
   213
slouken@478
   214
  ret = surface->Lock (surface, DSLF_READ | DSLF_WRITE, &data, &pitch);
slouken@478
   215
  if (ret)
slouken@478
   216
    {
slouken@478
   217
      SetDirectFBerror("IDirectFBSurface::Lock", ret);
slouken@478
   218
      return -1;
slouken@478
   219
    }
slouken@478
   220
slouken@478
   221
  /* Find the pitch and offset values for the overlay */
slouken@478
   222
  overlay->pitches[0] = (Uint16) pitch;
slouken@478
   223
  overlay->pixels[0]  = (Uint8*) data;
slouken@478
   224
slouken@478
   225
  switch (overlay->format)
slouken@478
   226
    {
slouken@478
   227
    case SDL_YV12_OVERLAY:
slouken@478
   228
    case SDL_IYUV_OVERLAY:
slouken@478
   229
      /* Add the two extra planes */
slouken@478
   230
      overlay->pitches[1] = overlay->pitches[0] / 2;
slouken@478
   231
      overlay->pitches[2] = overlay->pitches[0] / 2;
slouken@478
   232
      overlay->pixels[1]  = overlay->pixels[0] + overlay->pitches[0] * overlay->h;
slouken@478
   233
      overlay->pixels[2]  = overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2;
slouken@478
   234
      break;
slouken@478
   235
    default:
slouken@478
   236
      /* Only one plane, no worries */
slouken@478
   237
      break;
slouken@478
   238
    }
slouken@478
   239
slouken@478
   240
  return 0;
slouken@478
   241
}
slouken@478
   242
slouken@478
   243
void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay)
slouken@478
   244
{
slouken@478
   245
  IDirectFBSurface *surface = overlay->hwdata->surface;
slouken@478
   246
slouken@478
   247
  overlay->pixels[0] = overlay->pixels[1] = overlay->pixels[2] = NULL;
slouken@478
   248
slouken@478
   249
  surface->Unlock (surface);
slouken@478
   250
}
slouken@478
   251
slouken@478
   252
int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dst)
slouken@478
   253
{
slouken@478
   254
  DFBResult              ret;
slouken@478
   255
  DFBDisplayLayerConfig  conf;
slouken@478
   256
  IDirectFBDisplayLayer *primary = HIDDEN->layer;
slouken@478
   257
  IDirectFBDisplayLayer *layer   = overlay->hwdata->layer;
slouken@478
   258
slouken@478
   259
  primary->GetConfiguration (primary, &conf);
slouken@478
   260
slouken@478
   261
  ret = layer->SetScreenLocation (layer,
slouken@478
   262
                                  dst->x / (float) conf.width, dst->y / (float) conf.height,
slouken@478
   263
                                  dst->w / (float) conf.width, dst->h / (float) conf.height );
slouken@478
   264
  if (ret)
slouken@478
   265
    {
slouken@478
   266
      SetDirectFBerror("IDirectFBDisplayLayer::SetScreenLocation", ret);
slouken@478
   267
      return -1;
slouken@478
   268
    }
slouken@478
   269
slouken@478
   270
  return 0;
slouken@478
   271
}
slouken@478
   272
slouken@478
   273
void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay *overlay)
slouken@478
   274
{
slouken@478
   275
  struct private_yuvhwdata *hwdata;
slouken@478
   276
slouken@478
   277
  hwdata = overlay->hwdata;
slouken@478
   278
  if (hwdata)
slouken@478
   279
    {
slouken@478
   280
      if (hwdata->surface)
slouken@478
   281
        hwdata->surface->Release (hwdata->surface);
slouken@478
   282
slouken@478
   283
      if (hwdata->layer)
slouken@478
   284
        hwdata->layer->Release (hwdata->layer);
slouken@478
   285
slouken@478
   286
      free (hwdata);
slouken@478
   287
    }
slouken@478
   288
}
slouken@478
   289