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