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