src/video/windx5/SDL_dx5yuv.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. CreateYUVSurface
  2. PrintFOURCC
  3. DX5_CreateYUVOverlay
  4. DX5_LockYUVOverlay
  5. DX5_UnlockYUVOverlay
  6. DX5_DisplayYUVOverlay
  7. DX5_FreeYUVOverlay

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 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     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_dx5yuv.c,v 1.1.2.6 2001/02/10 07:20:09 hercules Exp $";
  26 #endif
  27 
  28 /* This is the DirectDraw implementation of YUV video overlays */
  29 
  30 #include <stdlib.h>
  31 #include <string.h>
  32 
  33 #include "SDL_error.h"
  34 #include "SDL_video.h"
  35 #include "SDL_dx5yuv_c.h"
  36 #include "SDL_yuvfuncs.h"
  37 
  38 #define USE_DIRECTX_OVERLAY
  39 
  40 /* The functions used to manipulate software video overlays */
  41 static struct private_yuvhwfuncs dx5_yuvfuncs = {
  42         DX5_LockYUVOverlay,
  43         DX5_UnlockYUVOverlay,
  44         DX5_DisplayYUVOverlay,
  45         DX5_FreeYUVOverlay
  46 };
  47 
  48 struct private_yuvhwdata {
  49         LPDIRECTDRAWSURFACE3 surface;
  50 
  51         /* These are just so we don't have to allocate them separately */
  52         Uint16 pitches[3];
  53         Uint8 *planes[3];
  54 };
  55 
  56 
  57 static LPDIRECTDRAWSURFACE3 CreateYUVSurface(_THIS,
     /* [<][>][^][v][top][bottom][index][help] */
  58                                          int width, int height, Uint32 format)
  59 {
  60         HRESULT result;
  61         LPDIRECTDRAWSURFACE  dd_surface1;
  62         LPDIRECTDRAWSURFACE3 dd_surface3;
  63         DDSURFACEDESC ddsd;
  64 
  65         /* Set up the surface description */
  66         memset(&ddsd, 0, sizeof(ddsd));
  67         ddsd.dwSize = sizeof(ddsd);
  68         ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT);
  69         ddsd.dwWidth = width;
  70         ddsd.dwHeight= height;
  71 #ifdef USE_DIRECTX_OVERLAY
  72         ddsd.ddsCaps.dwCaps = (DDSCAPS_OVERLAY|DDSCAPS_VIDEOMEMORY);
  73 #else
  74         ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY);
  75 #endif
  76         ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
  77         ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
  78         ddsd.ddpfPixelFormat.dwFourCC = format;
  79 
  80         /* Create the DirectDraw video surface */
  81         result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); 
  82         if ( result != DD_OK ) {
  83                 SetDDerror("DirectDraw2::CreateSurface", result);
  84                 return(NULL);
  85         }
  86         result = IDirectDrawSurface_QueryInterface(dd_surface1,
  87                         &IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3);
  88         IDirectDrawSurface_Release(dd_surface1);
  89         if ( result != DD_OK ) {
  90                 SetDDerror("DirectDrawSurface::QueryInterface", result);
  91                 return(NULL);
  92         }
  93 
  94         /* Make sure the surface format was set properly */
  95         memset(&ddsd, 0, sizeof(ddsd));
  96         ddsd.dwSize = sizeof(ddsd);
  97         result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
  98                                           &ddsd, DDLOCK_NOSYSLOCK, NULL);
  99         if ( result != DD_OK ) {
 100                 SetDDerror("DirectDrawSurface3::Lock", result);
 101                 IDirectDrawSurface_Release(dd_surface3);
 102                 return(NULL);
 103         }
 104         IDirectDrawSurface3_Unlock(dd_surface3, NULL);
 105 
 106         if ( !(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC) ||
 107               (ddsd.ddpfPixelFormat.dwFourCC != format) ) {
 108                 SDL_SetError("DDraw didn't use requested FourCC format");
 109                 IDirectDrawSurface_Release(dd_surface3);
 110                 return(NULL);
 111         }
 112 
 113         /* We're ready to go! */
 114         return(dd_surface3);
 115 }
 116 
 117 #ifdef DEBUG_YUV
 118 static char *PrintFOURCC(Uint32 code)
     /* [<][>][^][v][top][bottom][index][help] */
 119 {
 120         static char buf[5];
 121 
 122         buf[3] = code >> 24;
 123         buf[2] = (code >> 16) & 0xFF;
 124         buf[1] = (code >> 8) & 0xFF;
 125         buf[0] = (code & 0xFF);
 126         return(buf);
 127 }
 128 #endif
 129 
 130 SDL_Overlay *DX5_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display)
     /* [<][>][^][v][top][bottom][index][help] */
 131 {
 132         SDL_Overlay *overlay;
 133         struct private_yuvhwdata *hwdata;
 134 
 135 #ifdef DEBUG_YUV
 136         DWORD numcodes;
 137         DWORD *codes;
 138 
 139         printf("FOURCC format requested: 0x%x\n", PrintFOURCC(format));
 140         IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, NULL);
 141         if ( numcodes ) {
 142                 DWORD i;
 143                 codes = malloc(numcodes*sizeof(*codes));
 144                 if ( codes ) {
 145                         IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, codes);
 146                         for ( i=0; i<numcodes; ++i ) {
 147                                 fprintf(stderr, "Code %d: 0x%x\n", i, PrintFOURCC(codes[i]));
 148                         }
 149                         free(codes);
 150                 }
 151         } else {
 152                 fprintf(stderr, "No FOURCC codes supported\n");
 153         }
 154 #endif
 155 
 156         /* Create the overlay structure */
 157         overlay = (SDL_Overlay *)malloc(sizeof *overlay);
 158         if ( overlay == NULL ) {
 159                 SDL_OutOfMemory();
 160                 return(NULL);
 161         }
 162         memset(overlay, 0, (sizeof *overlay));
 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 = &dx5_yuvfuncs;
 171 
 172         /* Create the pixel data and lookup tables */
 173         hwdata = (struct private_yuvhwdata *)malloc(sizeof *hwdata);
 174         overlay->hwdata = hwdata;
 175         if ( hwdata == NULL ) {
 176                 SDL_OutOfMemory();
 177                 SDL_FreeYUVOverlay(overlay);
 178                 return(NULL);
 179         }
 180         hwdata->surface = CreateYUVSurface(this, width, height, format);
 181         if ( hwdata->surface == NULL ) {
 182                 SDL_FreeYUVOverlay(overlay);
 183                 return(NULL);
 184         }
 185         overlay->hw_overlay = 1;
 186 
 187         /* Set up the plane pointers */
 188         overlay->pitches = hwdata->pitches;
 189         overlay->pixels = hwdata->planes;
 190         switch (format) {
 191             case SDL_YV12_OVERLAY:
 192             case SDL_IYUV_OVERLAY:
 193                 overlay->planes = 3;
 194             default:
 195                 overlay->planes = 1;
 196                 break;
 197         }
 198 
 199         /* We're all done.. */
 200         return(overlay);
 201 }
 202 
 203 int DX5_LockYUVOverlay(_THIS, SDL_Overlay *overlay)
     /* [<][>][^][v][top][bottom][index][help] */
 204 {
 205         HRESULT result;
 206         LPDIRECTDRAWSURFACE3 surface;
 207         DDSURFACEDESC ddsd;
 208 
 209         surface = overlay->hwdata->surface;
 210         memset(&ddsd, 0, sizeof(ddsd));
 211         ddsd.dwSize = sizeof(ddsd);
 212         result = IDirectDrawSurface3_Lock(surface, NULL,
 213                                           &ddsd, DDLOCK_NOSYSLOCK, NULL);
 214         if ( result == DDERR_SURFACELOST ) {
 215                 result = IDirectDrawSurface3_Restore(surface);
 216                 result = IDirectDrawSurface3_Lock(surface, NULL, &ddsd, 
 217                                         (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
 218         }
 219         if ( result != DD_OK ) {
 220                 SetDDerror("DirectDrawSurface3::Lock", result);
 221                 return(-1);
 222         }
 223 
 224         /* Find the pitch and offset values for the overlay */
 225 #if defined(NONAMELESSUNION)
 226         overlay->pitches[0] = (Uint16)ddsd.u1.lPitch;
 227 #else
 228         overlay->pitches[0] = (Uint16)ddsd.lPitch;
 229 #endif
 230         overlay->pixels[0] = (Uint8 *)ddsd.lpSurface;
 231         switch (overlay->format) {
 232             case SDL_YV12_OVERLAY:
 233             case SDL_IYUV_OVERLAY:
 234                 /* Add the two extra planes */
 235                 overlay->pitches[1] = overlay->pitches[0] / 2;
 236                 overlay->pitches[2] = overlay->pitches[0] / 2;
 237                 overlay->pixels[1] = overlay->pixels[0] +
 238                                      overlay->pitches[0] * overlay->h;
 239                 overlay->pixels[2] = overlay->pixels[1] +
 240                                      overlay->pitches[1] * overlay->h / 2;
 241                 break;
 242             default:
 243                 /* Only one plane, no worries */
 244                 break;
 245         }
 246         return(0);
 247 }
 248 
 249 void DX5_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay)
     /* [<][>][^][v][top][bottom][index][help] */
 250 {
 251         LPDIRECTDRAWSURFACE3 surface;
 252 
 253         surface = overlay->hwdata->surface;
 254         IDirectDrawSurface3_Unlock(surface, NULL);
 255 }
 256 
 257 int DX5_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect)
     /* [<][>][^][v][top][bottom][index][help] */
 258 {
 259         HRESULT result;
 260         LPDIRECTDRAWSURFACE3 surface;
 261         RECT src, dst;
 262 
 263         surface = overlay->hwdata->surface;
 264         src.top = 0;
 265         src.bottom = overlay->h;
 266         src.left = 0;
 267         src.right = overlay->w;
 268         dst.top = SDL_bounds.top+dstrect->y;
 269         dst.left = SDL_bounds.left+dstrect->x;
 270         dst.bottom = dst.top+dstrect->h;
 271         dst.right = dst.left+dstrect->w;
 272 #ifdef USE_DIRECTX_OVERLAY
 273         result = IDirectDrawSurface3_UpdateOverlay(surface, &src,
 274                                 SDL_primary, &dst, DDOVER_SHOW, NULL);
 275         if ( result != DD_OK ) {
 276                 SetDDerror("DirectDrawSurface3::UpdateOverlay", result);
 277                 return(-1);
 278         }
 279 #else
 280         result = IDirectDrawSurface3_Blt(SDL_primary, &dst, surface, &src,
 281                                                         DDBLT_WAIT, NULL);
 282         if ( result != DD_OK ) {
 283                 SetDDerror("DirectDrawSurface3::Blt", result);
 284                 return(-1);
 285         }
 286 #endif
 287         return(0);
 288 }
 289 
 290 void DX5_FreeYUVOverlay(_THIS, SDL_Overlay *overlay)
     /* [<][>][^][v][top][bottom][index][help] */
 291 {
 292         struct private_yuvhwdata *hwdata;
 293 
 294         hwdata = overlay->hwdata;
 295         if ( hwdata ) {
 296                 if ( hwdata->surface ) {
 297                         IDirectDrawSurface_Release(hwdata->surface);
 298                 }
 299                 free(hwdata);
 300         }
 301 }
 302 

/* [<][>][^][v][top][bottom][index][help] */