src/video/windx5/SDL_dx5video.c

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

FUNCTIONS

This source file includes following functions.
  1. HRESULT
  2. DX5_Available
  3. DX5_Unload
  4. DX5_Load
  5. DX5_DeleteDevice
  6. DX5_CreateDevice
  7. EnumModes2
  8. SetDDerror
  9. DX5_UpdateVideoInfo
  10. DX5_VideoInit
  11. DX5_ListModes
  12. DX5_SetVideoMode
  13. DX5_AllocDDSurface
  14. DX5_AllocHWSurface
  15. PrintSurface
  16. DX5_HWAccelBlit
  17. DX5_CheckHWBlit
  18. DX5_FillHWRect
  19. DX5_SetHWColorKey
  20. DX5_SetHWAlpha
  21. DX5_LockHWSurface
  22. DX5_UnlockHWSurface
  23. DX5_FlipHWSurface
  24. DX5_FreeHWSurface
  25. DX5_WindowUpdate
  26. DX5_DirectUpdate
  27. CS_CS_DIST
  28. DX5_CompressPalette
  29. DX5_SetColors
  30. DX5_SwapGamma
  31. DX5_SetGammaRamp
  32. DX5_GetGammaRamp
  33. DX5_VideoQuit
  34. DX5_RealizePalette
  35. DX5_Recolor8Bit
  36. DX5_PaletteChanged
  37. DX5_WinPAINT

   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_dx5video.c,v 1.11.2.37 2001/02/28 12:35:28 hercules Exp $";
  26 #endif
  27 
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <malloc.h>
  31 #include <windows.h>
  32 #include "directx.h"
  33 
  34 /* Not yet in the mingw32 cross-compile headers */
  35 #ifndef CDS_FULLSCREEN
  36 #define CDS_FULLSCREEN  4
  37 #endif
  38 
  39 #include "SDL_error.h"
  40 #include "SDL_timer.h"
  41 #include "SDL_events.h"
  42 #include "SDL_syswm.h"
  43 #include "SDL_sysvideo.h"
  44 #include "SDL_RLEaccel_c.h"
  45 #include "SDL_blit.h"
  46 #include "SDL_pixels_c.h"
  47 #include "SDL_dx5video.h"
  48 #include "SDL_syswm_c.h"
  49 #include "SDL_sysmouse_c.h"
  50 #include "SDL_dx5events_c.h"
  51 #include "SDL_dx5yuv_c.h"
  52 #include "SDL_wingl_c.h"
  53 
  54 /* Function called to create a GL video mode - use the GDI driver, not DirectX */
  55 extern SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current,
  56                                 int width, int height, int bpp, Uint32 flags);
  57 
  58 /* DirectX function pointers for video and events */
  59 HRESULT (WINAPI *DDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
     /* [<][>][^][v][top][bottom][index][help] */
  60 HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter);
  61 
  62 /* This is the rect EnumModes2 uses */
  63 struct DX5EnumRect {
  64         SDL_Rect r;
  65         struct DX5EnumRect* next;
  66 };
  67 static struct DX5EnumRect *enumlists[NUM_MODELISTS];
  68 
  69 /*
  70  * Experimentally determined values for c_cfDI* constants used in DirectX 5.0
  71  */
  72 
  73 /* Keyboard */
  74 
  75 static DIOBJECTDATAFORMAT KBD_fmt[] = {
  76         { &GUID_Key, 0, 0x8000000C, 0x00000000 },
  77         { &GUID_Key, 1, 0x8000010C, 0x00000000 },
  78         { &GUID_Key, 2, 0x8000020C, 0x00000000 },
  79         { &GUID_Key, 3, 0x8000030C, 0x00000000 },
  80         { &GUID_Key, 4, 0x8000040C, 0x00000000 },
  81         { &GUID_Key, 5, 0x8000050C, 0x00000000 },
  82         { &GUID_Key, 6, 0x8000060C, 0x00000000 },
  83         { &GUID_Key, 7, 0x8000070C, 0x00000000 },
  84         { &GUID_Key, 8, 0x8000080C, 0x00000000 },
  85         { &GUID_Key, 9, 0x8000090C, 0x00000000 },
  86         { &GUID_Key, 10, 0x80000A0C, 0x00000000 },
  87         { &GUID_Key, 11, 0x80000B0C, 0x00000000 },
  88         { &GUID_Key, 12, 0x80000C0C, 0x00000000 },
  89         { &GUID_Key, 13, 0x80000D0C, 0x00000000 },
  90         { &GUID_Key, 14, 0x80000E0C, 0x00000000 },
  91         { &GUID_Key, 15, 0x80000F0C, 0x00000000 },
  92         { &GUID_Key, 16, 0x8000100C, 0x00000000 },
  93         { &GUID_Key, 17, 0x8000110C, 0x00000000 },
  94         { &GUID_Key, 18, 0x8000120C, 0x00000000 },
  95         { &GUID_Key, 19, 0x8000130C, 0x00000000 },
  96         { &GUID_Key, 20, 0x8000140C, 0x00000000 },
  97         { &GUID_Key, 21, 0x8000150C, 0x00000000 },
  98         { &GUID_Key, 22, 0x8000160C, 0x00000000 },
  99         { &GUID_Key, 23, 0x8000170C, 0x00000000 },
 100         { &GUID_Key, 24, 0x8000180C, 0x00000000 },
 101         { &GUID_Key, 25, 0x8000190C, 0x00000000 },
 102         { &GUID_Key, 26, 0x80001A0C, 0x00000000 },
 103         { &GUID_Key, 27, 0x80001B0C, 0x00000000 },
 104         { &GUID_Key, 28, 0x80001C0C, 0x00000000 },
 105         { &GUID_Key, 29, 0x80001D0C, 0x00000000 },
 106         { &GUID_Key, 30, 0x80001E0C, 0x00000000 },
 107         { &GUID_Key, 31, 0x80001F0C, 0x00000000 },
 108         { &GUID_Key, 32, 0x8000200C, 0x00000000 },
 109         { &GUID_Key, 33, 0x8000210C, 0x00000000 },
 110         { &GUID_Key, 34, 0x8000220C, 0x00000000 },
 111         { &GUID_Key, 35, 0x8000230C, 0x00000000 },
 112         { &GUID_Key, 36, 0x8000240C, 0x00000000 },
 113         { &GUID_Key, 37, 0x8000250C, 0x00000000 },
 114         { &GUID_Key, 38, 0x8000260C, 0x00000000 },
 115         { &GUID_Key, 39, 0x8000270C, 0x00000000 },
 116         { &GUID_Key, 40, 0x8000280C, 0x00000000 },
 117         { &GUID_Key, 41, 0x8000290C, 0x00000000 },
 118         { &GUID_Key, 42, 0x80002A0C, 0x00000000 },
 119         { &GUID_Key, 43, 0x80002B0C, 0x00000000 },
 120         { &GUID_Key, 44, 0x80002C0C, 0x00000000 },
 121         { &GUID_Key, 45, 0x80002D0C, 0x00000000 },
 122         { &GUID_Key, 46, 0x80002E0C, 0x00000000 },
 123         { &GUID_Key, 47, 0x80002F0C, 0x00000000 },
 124         { &GUID_Key, 48, 0x8000300C, 0x00000000 },
 125         { &GUID_Key, 49, 0x8000310C, 0x00000000 },
 126         { &GUID_Key, 50, 0x8000320C, 0x00000000 },
 127         { &GUID_Key, 51, 0x8000330C, 0x00000000 },
 128         { &GUID_Key, 52, 0x8000340C, 0x00000000 },
 129         { &GUID_Key, 53, 0x8000350C, 0x00000000 },
 130         { &GUID_Key, 54, 0x8000360C, 0x00000000 },
 131         { &GUID_Key, 55, 0x8000370C, 0x00000000 },
 132         { &GUID_Key, 56, 0x8000380C, 0x00000000 },
 133         { &GUID_Key, 57, 0x8000390C, 0x00000000 },
 134         { &GUID_Key, 58, 0x80003A0C, 0x00000000 },
 135         { &GUID_Key, 59, 0x80003B0C, 0x00000000 },
 136         { &GUID_Key, 60, 0x80003C0C, 0x00000000 },
 137         { &GUID_Key, 61, 0x80003D0C, 0x00000000 },
 138         { &GUID_Key, 62, 0x80003E0C, 0x00000000 },
 139         { &GUID_Key, 63, 0x80003F0C, 0x00000000 },
 140         { &GUID_Key, 64, 0x8000400C, 0x00000000 },
 141         { &GUID_Key, 65, 0x8000410C, 0x00000000 },
 142         { &GUID_Key, 66, 0x8000420C, 0x00000000 },
 143         { &GUID_Key, 67, 0x8000430C, 0x00000000 },
 144         { &GUID_Key, 68, 0x8000440C, 0x00000000 },
 145         { &GUID_Key, 69, 0x8000450C, 0x00000000 },
 146         { &GUID_Key, 70, 0x8000460C, 0x00000000 },
 147         { &GUID_Key, 71, 0x8000470C, 0x00000000 },
 148         { &GUID_Key, 72, 0x8000480C, 0x00000000 },
 149         { &GUID_Key, 73, 0x8000490C, 0x00000000 },
 150         { &GUID_Key, 74, 0x80004A0C, 0x00000000 },
 151         { &GUID_Key, 75, 0x80004B0C, 0x00000000 },
 152         { &GUID_Key, 76, 0x80004C0C, 0x00000000 },
 153         { &GUID_Key, 77, 0x80004D0C, 0x00000000 },
 154         { &GUID_Key, 78, 0x80004E0C, 0x00000000 },
 155         { &GUID_Key, 79, 0x80004F0C, 0x00000000 },
 156         { &GUID_Key, 80, 0x8000500C, 0x00000000 },
 157         { &GUID_Key, 81, 0x8000510C, 0x00000000 },
 158         { &GUID_Key, 82, 0x8000520C, 0x00000000 },
 159         { &GUID_Key, 83, 0x8000530C, 0x00000000 },
 160         { &GUID_Key, 84, 0x8000540C, 0x00000000 },
 161         { &GUID_Key, 85, 0x8000550C, 0x00000000 },
 162         { &GUID_Key, 86, 0x8000560C, 0x00000000 },
 163         { &GUID_Key, 87, 0x8000570C, 0x00000000 },
 164         { &GUID_Key, 88, 0x8000580C, 0x00000000 },
 165         { &GUID_Key, 89, 0x8000590C, 0x00000000 },
 166         { &GUID_Key, 90, 0x80005A0C, 0x00000000 },
 167         { &GUID_Key, 91, 0x80005B0C, 0x00000000 },
 168         { &GUID_Key, 92, 0x80005C0C, 0x00000000 },
 169         { &GUID_Key, 93, 0x80005D0C, 0x00000000 },
 170         { &GUID_Key, 94, 0x80005E0C, 0x00000000 },
 171         { &GUID_Key, 95, 0x80005F0C, 0x00000000 },
 172         { &GUID_Key, 96, 0x8000600C, 0x00000000 },
 173         { &GUID_Key, 97, 0x8000610C, 0x00000000 },
 174         { &GUID_Key, 98, 0x8000620C, 0x00000000 },
 175         { &GUID_Key, 99, 0x8000630C, 0x00000000 },
 176         { &GUID_Key, 100, 0x8000640C, 0x00000000 },
 177         { &GUID_Key, 101, 0x8000650C, 0x00000000 },
 178         { &GUID_Key, 102, 0x8000660C, 0x00000000 },
 179         { &GUID_Key, 103, 0x8000670C, 0x00000000 },
 180         { &GUID_Key, 104, 0x8000680C, 0x00000000 },
 181         { &GUID_Key, 105, 0x8000690C, 0x00000000 },
 182         { &GUID_Key, 106, 0x80006A0C, 0x00000000 },
 183         { &GUID_Key, 107, 0x80006B0C, 0x00000000 },
 184         { &GUID_Key, 108, 0x80006C0C, 0x00000000 },
 185         { &GUID_Key, 109, 0x80006D0C, 0x00000000 },
 186         { &GUID_Key, 110, 0x80006E0C, 0x00000000 },
 187         { &GUID_Key, 111, 0x80006F0C, 0x00000000 },
 188         { &GUID_Key, 112, 0x8000700C, 0x00000000 },
 189         { &GUID_Key, 113, 0x8000710C, 0x00000000 },
 190         { &GUID_Key, 114, 0x8000720C, 0x00000000 },
 191         { &GUID_Key, 115, 0x8000730C, 0x00000000 },
 192         { &GUID_Key, 116, 0x8000740C, 0x00000000 },
 193         { &GUID_Key, 117, 0x8000750C, 0x00000000 },
 194         { &GUID_Key, 118, 0x8000760C, 0x00000000 },
 195         { &GUID_Key, 119, 0x8000770C, 0x00000000 },
 196         { &GUID_Key, 120, 0x8000780C, 0x00000000 },
 197         { &GUID_Key, 121, 0x8000790C, 0x00000000 },
 198         { &GUID_Key, 122, 0x80007A0C, 0x00000000 },
 199         { &GUID_Key, 123, 0x80007B0C, 0x00000000 },
 200         { &GUID_Key, 124, 0x80007C0C, 0x00000000 },
 201         { &GUID_Key, 125, 0x80007D0C, 0x00000000 },
 202         { &GUID_Key, 126, 0x80007E0C, 0x00000000 },
 203         { &GUID_Key, 127, 0x80007F0C, 0x00000000 },
 204         { &GUID_Key, 128, 0x8000800C, 0x00000000 },
 205         { &GUID_Key, 129, 0x8000810C, 0x00000000 },
 206         { &GUID_Key, 130, 0x8000820C, 0x00000000 },
 207         { &GUID_Key, 131, 0x8000830C, 0x00000000 },
 208         { &GUID_Key, 132, 0x8000840C, 0x00000000 },
 209         { &GUID_Key, 133, 0x8000850C, 0x00000000 },
 210         { &GUID_Key, 134, 0x8000860C, 0x00000000 },
 211         { &GUID_Key, 135, 0x8000870C, 0x00000000 },
 212         { &GUID_Key, 136, 0x8000880C, 0x00000000 },
 213         { &GUID_Key, 137, 0x8000890C, 0x00000000 },
 214         { &GUID_Key, 138, 0x80008A0C, 0x00000000 },
 215         { &GUID_Key, 139, 0x80008B0C, 0x00000000 },
 216         { &GUID_Key, 140, 0x80008C0C, 0x00000000 },
 217         { &GUID_Key, 141, 0x80008D0C, 0x00000000 },
 218         { &GUID_Key, 142, 0x80008E0C, 0x00000000 },
 219         { &GUID_Key, 143, 0x80008F0C, 0x00000000 },
 220         { &GUID_Key, 144, 0x8000900C, 0x00000000 },
 221         { &GUID_Key, 145, 0x8000910C, 0x00000000 },
 222         { &GUID_Key, 146, 0x8000920C, 0x00000000 },
 223         { &GUID_Key, 147, 0x8000930C, 0x00000000 },
 224         { &GUID_Key, 148, 0x8000940C, 0x00000000 },
 225         { &GUID_Key, 149, 0x8000950C, 0x00000000 },
 226         { &GUID_Key, 150, 0x8000960C, 0x00000000 },
 227         { &GUID_Key, 151, 0x8000970C, 0x00000000 },
 228         { &GUID_Key, 152, 0x8000980C, 0x00000000 },
 229         { &GUID_Key, 153, 0x8000990C, 0x00000000 },
 230         { &GUID_Key, 154, 0x80009A0C, 0x00000000 },
 231         { &GUID_Key, 155, 0x80009B0C, 0x00000000 },
 232         { &GUID_Key, 156, 0x80009C0C, 0x00000000 },
 233         { &GUID_Key, 157, 0x80009D0C, 0x00000000 },
 234         { &GUID_Key, 158, 0x80009E0C, 0x00000000 },
 235         { &GUID_Key, 159, 0x80009F0C, 0x00000000 },
 236         { &GUID_Key, 160, 0x8000A00C, 0x00000000 },
 237         { &GUID_Key, 161, 0x8000A10C, 0x00000000 },
 238         { &GUID_Key, 162, 0x8000A20C, 0x00000000 },
 239         { &GUID_Key, 163, 0x8000A30C, 0x00000000 },
 240         { &GUID_Key, 164, 0x8000A40C, 0x00000000 },
 241         { &GUID_Key, 165, 0x8000A50C, 0x00000000 },
 242         { &GUID_Key, 166, 0x8000A60C, 0x00000000 },
 243         { &GUID_Key, 167, 0x8000A70C, 0x00000000 },
 244         { &GUID_Key, 168, 0x8000A80C, 0x00000000 },
 245         { &GUID_Key, 169, 0x8000A90C, 0x00000000 },
 246         { &GUID_Key, 170, 0x8000AA0C, 0x00000000 },
 247         { &GUID_Key, 171, 0x8000AB0C, 0x00000000 },
 248         { &GUID_Key, 172, 0x8000AC0C, 0x00000000 },
 249         { &GUID_Key, 173, 0x8000AD0C, 0x00000000 },
 250         { &GUID_Key, 174, 0x8000AE0C, 0x00000000 },
 251         { &GUID_Key, 175, 0x8000AF0C, 0x00000000 },
 252         { &GUID_Key, 176, 0x8000B00C, 0x00000000 },
 253         { &GUID_Key, 177, 0x8000B10C, 0x00000000 },
 254         { &GUID_Key, 178, 0x8000B20C, 0x00000000 },
 255         { &GUID_Key, 179, 0x8000B30C, 0x00000000 },
 256         { &GUID_Key, 180, 0x8000B40C, 0x00000000 },
 257         { &GUID_Key, 181, 0x8000B50C, 0x00000000 },
 258         { &GUID_Key, 182, 0x8000B60C, 0x00000000 },
 259         { &GUID_Key, 183, 0x8000B70C, 0x00000000 },
 260         { &GUID_Key, 184, 0x8000B80C, 0x00000000 },
 261         { &GUID_Key, 185, 0x8000B90C, 0x00000000 },
 262         { &GUID_Key, 186, 0x8000BA0C, 0x00000000 },
 263         { &GUID_Key, 187, 0x8000BB0C, 0x00000000 },
 264         { &GUID_Key, 188, 0x8000BC0C, 0x00000000 },
 265         { &GUID_Key, 189, 0x8000BD0C, 0x00000000 },
 266         { &GUID_Key, 190, 0x8000BE0C, 0x00000000 },
 267         { &GUID_Key, 191, 0x8000BF0C, 0x00000000 },
 268         { &GUID_Key, 192, 0x8000C00C, 0x00000000 },
 269         { &GUID_Key, 193, 0x8000C10C, 0x00000000 },
 270         { &GUID_Key, 194, 0x8000C20C, 0x00000000 },
 271         { &GUID_Key, 195, 0x8000C30C, 0x00000000 },
 272         { &GUID_Key, 196, 0x8000C40C, 0x00000000 },
 273         { &GUID_Key, 197, 0x8000C50C, 0x00000000 },
 274         { &GUID_Key, 198, 0x8000C60C, 0x00000000 },
 275         { &GUID_Key, 199, 0x8000C70C, 0x00000000 },
 276         { &GUID_Key, 200, 0x8000C80C, 0x00000000 },
 277         { &GUID_Key, 201, 0x8000C90C, 0x00000000 },
 278         { &GUID_Key, 202, 0x8000CA0C, 0x00000000 },
 279         { &GUID_Key, 203, 0x8000CB0C, 0x00000000 },
 280         { &GUID_Key, 204, 0x8000CC0C, 0x00000000 },
 281         { &GUID_Key, 205, 0x8000CD0C, 0x00000000 },
 282         { &GUID_Key, 206, 0x8000CE0C, 0x00000000 },
 283         { &GUID_Key, 207, 0x8000CF0C, 0x00000000 },
 284         { &GUID_Key, 208, 0x8000D00C, 0x00000000 },
 285         { &GUID_Key, 209, 0x8000D10C, 0x00000000 },
 286         { &GUID_Key, 210, 0x8000D20C, 0x00000000 },
 287         { &GUID_Key, 211, 0x8000D30C, 0x00000000 },
 288         { &GUID_Key, 212, 0x8000D40C, 0x00000000 },
 289         { &GUID_Key, 213, 0x8000D50C, 0x00000000 },
 290         { &GUID_Key, 214, 0x8000D60C, 0x00000000 },
 291         { &GUID_Key, 215, 0x8000D70C, 0x00000000 },
 292         { &GUID_Key, 216, 0x8000D80C, 0x00000000 },
 293         { &GUID_Key, 217, 0x8000D90C, 0x00000000 },
 294         { &GUID_Key, 218, 0x8000DA0C, 0x00000000 },
 295         { &GUID_Key, 219, 0x8000DB0C, 0x00000000 },
 296         { &GUID_Key, 220, 0x8000DC0C, 0x00000000 },
 297         { &GUID_Key, 221, 0x8000DD0C, 0x00000000 },
 298         { &GUID_Key, 222, 0x8000DE0C, 0x00000000 },
 299         { &GUID_Key, 223, 0x8000DF0C, 0x00000000 },
 300         { &GUID_Key, 224, 0x8000E00C, 0x00000000 },
 301         { &GUID_Key, 225, 0x8000E10C, 0x00000000 },
 302         { &GUID_Key, 226, 0x8000E20C, 0x00000000 },
 303         { &GUID_Key, 227, 0x8000E30C, 0x00000000 },
 304         { &GUID_Key, 228, 0x8000E40C, 0x00000000 },
 305         { &GUID_Key, 229, 0x8000E50C, 0x00000000 },
 306         { &GUID_Key, 230, 0x8000E60C, 0x00000000 },
 307         { &GUID_Key, 231, 0x8000E70C, 0x00000000 },
 308         { &GUID_Key, 232, 0x8000E80C, 0x00000000 },
 309         { &GUID_Key, 233, 0x8000E90C, 0x00000000 },
 310         { &GUID_Key, 234, 0x8000EA0C, 0x00000000 },
 311         { &GUID_Key, 235, 0x8000EB0C, 0x00000000 },
 312         { &GUID_Key, 236, 0x8000EC0C, 0x00000000 },
 313         { &GUID_Key, 237, 0x8000ED0C, 0x00000000 },
 314         { &GUID_Key, 238, 0x8000EE0C, 0x00000000 },
 315         { &GUID_Key, 239, 0x8000EF0C, 0x00000000 },
 316         { &GUID_Key, 240, 0x8000F00C, 0x00000000 },
 317         { &GUID_Key, 241, 0x8000F10C, 0x00000000 },
 318         { &GUID_Key, 242, 0x8000F20C, 0x00000000 },
 319         { &GUID_Key, 243, 0x8000F30C, 0x00000000 },
 320         { &GUID_Key, 244, 0x8000F40C, 0x00000000 },
 321         { &GUID_Key, 245, 0x8000F50C, 0x00000000 },
 322         { &GUID_Key, 246, 0x8000F60C, 0x00000000 },
 323         { &GUID_Key, 247, 0x8000F70C, 0x00000000 },
 324         { &GUID_Key, 248, 0x8000F80C, 0x00000000 },
 325         { &GUID_Key, 249, 0x8000F90C, 0x00000000 },
 326         { &GUID_Key, 250, 0x8000FA0C, 0x00000000 },
 327         { &GUID_Key, 251, 0x8000FB0C, 0x00000000 },
 328         { &GUID_Key, 252, 0x8000FC0C, 0x00000000 },
 329         { &GUID_Key, 253, 0x8000FD0C, 0x00000000 },
 330         { &GUID_Key, 254, 0x8000FE0C, 0x00000000 },
 331         { &GUID_Key, 255, 0x8000FF0C, 0x00000000 },
 332 };
 333 
 334 const DIDATAFORMAT c_dfDIKeyboard = { 24, 16, 0x00000002, 256, 256, KBD_fmt };
 335 
 336 
 337 /* Mouse */
 338 
 339 static DIOBJECTDATAFORMAT PTR_fmt[] = {
 340         { &GUID_XAxis, 0, 0x00FFFF03, 0x00000000 },
 341         { &GUID_YAxis, 4, 0x00FFFF03, 0x00000000 },
 342         { &GUID_ZAxis, 8, 0x80FFFF03, 0x00000000 },
 343         { NULL, 12, 0x00FFFF0C, 0x00000000 },
 344         { NULL, 13, 0x00FFFF0C, 0x00000000 },
 345         { NULL, 14, 0x80FFFF0C, 0x00000000 },
 346         { NULL, 15, 0x80FFFF0C, 0x00000000 },
 347 };
 348 
 349 const DIDATAFORMAT c_dfDIMouse = { 24, 16, 0x00000002, 16, 7, PTR_fmt };
 350 
 351 
 352 /* Joystick */
 353 
 354 static DIOBJECTDATAFORMAT JOY_fmt[] = {
 355         { &GUID_XAxis, 0, 0x80FFFF03, 0x00000100 },
 356         { &GUID_YAxis, 4, 0x80FFFF03, 0x00000100 },
 357         { &GUID_ZAxis, 8, 0x80FFFF03, 0x00000100 },
 358         { &GUID_RxAxis, 12, 0x80FFFF03, 0x00000100 },
 359         { &GUID_RyAxis, 16, 0x80FFFF03, 0x00000100 },
 360         { &GUID_RzAxis, 20, 0x80FFFF03, 0x00000100 },
 361         { &GUID_Slider, 24, 0x80FFFF03, 0x00000100 },
 362         { &GUID_Slider, 28, 0x80FFFF03, 0x00000100 },
 363         { &GUID_POV, 32, 0x80FFFF10, 0x00000000 },
 364         { &GUID_POV, 36, 0x80FFFF10, 0x00000000 },
 365         { &GUID_POV, 40, 0x80FFFF10, 0x00000000 },
 366         { &GUID_POV, 44, 0x80FFFF10, 0x00000000 },
 367         { NULL, 48, 0x80FFFF0C, 0x00000000 },
 368         { NULL, 49, 0x80FFFF0C, 0x00000000 },
 369         { NULL, 50, 0x80FFFF0C, 0x00000000 },
 370         { NULL, 51, 0x80FFFF0C, 0x00000000 },
 371         { NULL, 52, 0x80FFFF0C, 0x00000000 },
 372         { NULL, 53, 0x80FFFF0C, 0x00000000 },
 373         { NULL, 54, 0x80FFFF0C, 0x00000000 },
 374         { NULL, 55, 0x80FFFF0C, 0x00000000 },
 375         { NULL, 56, 0x80FFFF0C, 0x00000000 },
 376         { NULL, 57, 0x80FFFF0C, 0x00000000 },
 377         { NULL, 58, 0x80FFFF0C, 0x00000000 },
 378         { NULL, 59, 0x80FFFF0C, 0x00000000 },
 379         { NULL, 60, 0x80FFFF0C, 0x00000000 },
 380         { NULL, 61, 0x80FFFF0C, 0x00000000 },
 381         { NULL, 62, 0x80FFFF0C, 0x00000000 },
 382         { NULL, 63, 0x80FFFF0C, 0x00000000 },
 383         { NULL, 64, 0x80FFFF0C, 0x00000000 },
 384         { NULL, 65, 0x80FFFF0C, 0x00000000 },
 385         { NULL, 66, 0x80FFFF0C, 0x00000000 },
 386         { NULL, 67, 0x80FFFF0C, 0x00000000 },
 387         { NULL, 68, 0x80FFFF0C, 0x00000000 },
 388         { NULL, 69, 0x80FFFF0C, 0x00000000 },
 389         { NULL, 70, 0x80FFFF0C, 0x00000000 },
 390         { NULL, 71, 0x80FFFF0C, 0x00000000 },
 391         { NULL, 72, 0x80FFFF0C, 0x00000000 },
 392         { NULL, 73, 0x80FFFF0C, 0x00000000 },
 393         { NULL, 74, 0x80FFFF0C, 0x00000000 },
 394         { NULL, 75, 0x80FFFF0C, 0x00000000 },
 395         { NULL, 76, 0x80FFFF0C, 0x00000000 },
 396         { NULL, 77, 0x80FFFF0C, 0x00000000 },
 397         { NULL, 78, 0x80FFFF0C, 0x00000000 },
 398         { NULL, 79, 0x80FFFF0C, 0x00000000 },
 399 };
 400 
 401 const DIDATAFORMAT c_dfDIJoystick = { 24, 16, 0x00000001, 80, 44, JOY_fmt };
 402 
 403 
 404 /* Initialization/Query functions */
 405 static int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat);
 406 static SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
 407 static SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
 408 static int DX5_SetColors(_THIS, int firstcolor, int ncolors,
 409                          SDL_Color *colors);
 410 static void DX5_SwapGamma(_THIS);
 411 #ifdef IID_IDirectDrawGammaControl
 412 static int DX5_SetGammaRamp(_THIS, Uint16 *ramp);
 413 static int DX5_GetGammaRamp(_THIS, Uint16 *ramp);
 414 #endif
 415 static void DX5_VideoQuit(_THIS);
 416 
 417 /* Hardware surface functions */
 418 static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface);
 419 static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst);
 420 static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
 421 static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
 422 static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha);
 423 static int DX5_LockHWSurface(_THIS, SDL_Surface *surface);
 424 static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface);
 425 static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface);
 426 static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface);
 427 
 428 static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
 429                                 LPDIRECTDRAWSURFACE3 requested, Uint32 flag);
 430 
 431 /* Windows message handling functions */
 432 static void DX5_RealizePalette(_THIS);
 433 static void DX5_PaletteChanged(_THIS, HWND window);
 434 static void DX5_WinPAINT(_THIS, HDC hdc);
 435 
 436 /* DX5 driver bootstrap functions */
 437 
 438 static int DX5_Available(void)
     /* [<][>][^][v][top][bottom][index][help] */
 439 {
 440         HINSTANCE DInputDLL;
 441         HINSTANCE DDrawDLL;
 442         int dinput_ok;
 443         int ddraw_ok;
 444 
 445         /* Version check DINPUT.DLL and DDRAW.DLL (Is DirectX okay?) */
 446         dinput_ok = 0;
 447         DInputDLL = LoadLibrary("DINPUT.DLL");
 448         if ( DInputDLL != NULL ) {
 449                 dinput_ok = 1;
 450                 FreeLibrary(DInputDLL);
 451         }
 452         ddraw_ok = 0;
 453         DDrawDLL = LoadLibrary("DDRAW.DLL");
 454         if ( DDrawDLL != NULL ) {
 455           HRESULT (WINAPI *DDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
 456           LPDIRECTDRAW DDraw;
 457 
 458           /* Try to create a valid DirectDraw object */
 459           DDrawCreate = (void *)GetProcAddress(DDrawDLL, "DirectDrawCreate");
 460           if ( (DDrawCreate != NULL)
 461                         && !FAILED(DDrawCreate(NULL, &DDraw, NULL)) ) {
 462             if ( !FAILED(IDirectDraw_SetCooperativeLevel(DDraw,
 463                                                         NULL, DDSCL_NORMAL)) ) {
 464               DDSURFACEDESC desc;
 465               LPDIRECTDRAWSURFACE  DDrawSurf;
 466               LPDIRECTDRAWSURFACE3 DDrawSurf3;
 467 
 468               /* Try to create a DirectDrawSurface3 object */
 469               memset(&desc, 0, sizeof(desc));
 470               desc.dwSize = sizeof(desc);
 471               desc.dwFlags = DDSD_CAPS;
 472               desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY;
 473               if ( !FAILED(IDirectDraw_CreateSurface(DDraw, &desc,
 474                                                         &DDrawSurf, NULL)) ) {
 475                 if ( !FAILED(IDirectDrawSurface_QueryInterface(DDrawSurf,
 476                         &IID_IDirectDrawSurface3, (LPVOID *)&DDrawSurf3)) ) {
 477                   /* Yay! */
 478                   ddraw_ok = 1;
 479 
 480                   /* Clean up.. */
 481                   IDirectDrawSurface3_Release(DDrawSurf3);
 482                 }
 483                 IDirectDrawSurface_Release(DDrawSurf);
 484               }
 485             }
 486             IDirectDraw_Release(DDraw);
 487           }
 488           FreeLibrary(DDrawDLL);
 489         }
 490         return(dinput_ok && ddraw_ok);
 491 }
 492 
 493 /* Functions for loading the DirectX functions dynamically */
 494 static HINSTANCE DDrawDLL = NULL;
 495 static HINSTANCE DInputDLL = NULL;
 496 
 497 static void DX5_Unload(void)
     /* [<][>][^][v][top][bottom][index][help] */
 498 {
 499         if ( DDrawDLL != NULL ) {
 500                 FreeLibrary(DDrawDLL);
 501                 DDrawCreate = NULL;
 502                 DDrawDLL = NULL;
 503         }
 504         if ( DInputDLL != NULL ) {
 505                 FreeLibrary(DInputDLL);
 506                 DInputCreate = NULL;
 507                 DInputDLL = NULL;
 508         }
 509 }
 510 static int DX5_Load(void)
     /* [<][>][^][v][top][bottom][index][help] */
 511 {
 512         int status;
 513 
 514         DX5_Unload();
 515         DDrawDLL = LoadLibrary("DDRAW.DLL");
 516         if ( DDrawDLL != NULL ) {
 517                 DDrawCreate = (void *)GetProcAddress(DDrawDLL,
 518                                         "DirectDrawCreate");
 519         }
 520         DInputDLL = LoadLibrary("DINPUT.DLL");
 521         if ( DInputDLL != NULL ) {
 522                 DInputCreate = (void *)GetProcAddress(DInputDLL,
 523                                         "DirectInputCreateA");
 524         }
 525         if ( DDrawDLL && DDrawCreate && DInputDLL && DInputCreate ) {
 526                 status = 0;
 527         } else {
 528                 DX5_Unload();
 529                 status = -1;
 530         }
 531         return status;
 532 }
 533 
 534 static void DX5_DeleteDevice(SDL_VideoDevice *this)
     /* [<][>][^][v][top][bottom][index][help] */
 535 {
 536         /* Free DirectDraw object */
 537         if ( ddraw2 != NULL ) {
 538                 IDirectDraw2_Release(ddraw2);
 539         }
 540         DX5_Unload();
 541         if ( this ) {
 542                 if ( this->hidden ) {
 543                         free(this->hidden);
 544                 }
 545                 if ( this->gl_data ) {
 546                         free(this->gl_data);
 547                 }
 548                 free(this);
 549         }
 550 }
 551 
 552 static SDL_VideoDevice *DX5_CreateDevice(int devindex)
     /* [<][>][^][v][top][bottom][index][help] */
 553 {
 554         SDL_VideoDevice *device;
 555 
 556         /* Load DirectX */
 557         if ( DX5_Load() < 0 ) {
 558                 return(NULL);
 559         }
 560 
 561         /* Initialize all variables that we clean on shutdown */
 562         device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
 563         if ( device ) {
 564                 memset(device, 0, (sizeof *device));
 565                 device->hidden = (struct SDL_PrivateVideoData *)
 566                                 malloc((sizeof *device->hidden));
 567                 device->gl_data = (struct SDL_PrivateGLData *)
 568                                 malloc((sizeof *device->gl_data));
 569         }
 570         if ( (device == NULL) || (device->hidden == NULL) ||
 571                                  (device->gl_data == NULL) ) {
 572                 SDL_OutOfMemory();
 573                 DX5_DeleteDevice(device);
 574                 return(NULL);
 575         }
 576         memset(device->hidden, 0, (sizeof *device->hidden));
 577         memset(device->gl_data, 0, (sizeof *device->gl_data));
 578 
 579         /* Set the function pointers */
 580         device->VideoInit = DX5_VideoInit;
 581         device->ListModes = DX5_ListModes;
 582         device->SetVideoMode = DX5_SetVideoMode;
 583         device->UpdateMouse = WIN_UpdateMouse;
 584         device->CreateYUVOverlay = DX5_CreateYUVOverlay;
 585         device->SetColors = DX5_SetColors;
 586         device->UpdateRects = NULL;
 587         device->VideoQuit = DX5_VideoQuit;
 588         device->AllocHWSurface = DX5_AllocHWSurface;
 589         device->CheckHWBlit = DX5_CheckHWBlit;
 590         device->FillHWRect = DX5_FillHWRect;
 591         device->SetHWColorKey = DX5_SetHWColorKey;
 592         device->SetHWAlpha = DX5_SetHWAlpha;
 593         device->LockHWSurface = DX5_LockHWSurface;
 594         device->UnlockHWSurface = DX5_UnlockHWSurface;
 595         device->FlipHWSurface = DX5_FlipHWSurface;
 596         device->FreeHWSurface = DX5_FreeHWSurface;
 597 #ifdef IID_IDirectDrawGammaControl
 598         device->SetGammaRamp = DX5_SetGammaRamp;
 599         device->GetGammaRamp = DX5_GetGammaRamp;
 600 #endif
 601 #ifdef HAVE_OPENGL
 602         device->GL_LoadLibrary = WIN_GL_LoadLibrary;
 603         device->GL_GetProcAddress = WIN_GL_GetProcAddress;
 604         device->GL_GetAttribute = WIN_GL_GetAttribute;
 605         device->GL_MakeCurrent = WIN_GL_MakeCurrent;
 606         device->GL_SwapBuffers = WIN_GL_SwapBuffers;
 607 #endif
 608         device->SetCaption = WIN_SetWMCaption;
 609         device->SetIcon = WIN_SetWMIcon;
 610         device->IconifyWindow = WIN_IconifyWindow;
 611         device->GrabInput = WIN_GrabInput;
 612         device->GetWMInfo = WIN_GetWMInfo;
 613         device->FreeWMCursor = WIN_FreeWMCursor;
 614         device->CreateWMCursor = WIN_CreateWMCursor;
 615         device->ShowWMCursor = WIN_ShowWMCursor;
 616         device->WarpWMCursor = WIN_WarpWMCursor;
 617         device->CheckMouseMode = WIN_CheckMouseMode;
 618         device->InitOSKeymap = DX5_InitOSKeymap;
 619         device->PumpEvents = DX5_PumpEvents;
 620 
 621         /* Set up the windows message handling functions */
 622         WIN_RealizePalette = DX5_RealizePalette;
 623         WIN_PaletteChanged = DX5_PaletteChanged;
 624         WIN_SwapGamma = DX5_SwapGamma;
 625         WIN_WinPAINT = DX5_WinPAINT;
 626         HandleMessage = DX5_HandleMessage;
 627 
 628         device->free = DX5_DeleteDevice;
 629 
 630         /* We're finally ready */
 631         return device;
 632 }
 633 
 634 VideoBootStrap DIRECTX_bootstrap = {
 635         "directx", "Win95/98/2000 DirectX",
 636         DX5_Available, DX5_CreateDevice
 637 };
 638 
 639 static HRESULT WINAPI EnumModes2(DDSURFACEDESC *desc, VOID *udata)
     /* [<][>][^][v][top][bottom][index][help] */
 640 {
 641         SDL_VideoDevice *this = (SDL_VideoDevice *)udata;
 642         struct DX5EnumRect *enumrect;
 643 #if defined(NONAMELESSUNION)
 644         int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount;
 645 #else
 646         int bpp = desc->ddpfPixelFormat.dwRGBBitCount;
 647 #endif
 648 
 649         switch (bpp)  {
 650                 case 8:
 651                 case 16:
 652                 case 24:
 653                 case 32:
 654                         bpp /= 8; --bpp;
 655                         ++SDL_nummodes[bpp];
 656                         enumrect = (struct DX5EnumRect*)malloc(sizeof(struct DX5EnumRect));
 657                         if ( !enumrect ) {
 658                                 SDL_OutOfMemory();
 659                                 return(DDENUMRET_CANCEL);
 660                         }
 661                         enumrect->r.x = 0;
 662                         enumrect->r.y = 0;
 663                         enumrect->r.w = (Uint16)desc->dwWidth;
 664                         enumrect->r.h = (Uint16)desc->dwHeight;
 665                         enumrect->next = enumlists[bpp];
 666                         enumlists[bpp] = enumrect;
 667                         break;
 668         }
 669 
 670 
 671         return(DDENUMRET_OK);
 672 }
 673 
 674 void SetDDerror(const char *function, int code)
     /* [<][>][^][v][top][bottom][index][help] */
 675 {
 676         static char *error;
 677         static char  errbuf[BUFSIZ];
 678 
 679         errbuf[0] = 0;
 680         switch (code) {
 681                 case DDERR_GENERIC:
 682                         error = "Undefined error!";
 683                         break;
 684                 case DDERR_EXCEPTION:
 685                         error = "Exception encountered";
 686                         break;
 687                 case DDERR_INVALIDOBJECT:
 688                         error = "Invalid object";
 689                         break;
 690                 case DDERR_INVALIDPARAMS:
 691                         error = "Invalid parameters";
 692                         break;
 693                 case DDERR_NOTFOUND:
 694                         error = "Object not found";
 695                         break;
 696                 case DDERR_INVALIDRECT:
 697                         error = "Invalid rectangle";
 698                         break;
 699                 case DDERR_INVALIDCAPS:
 700                         error = "Invalid caps member";
 701                         break;
 702                 case DDERR_INVALIDPIXELFORMAT:
 703                         error = "Invalid pixel format";
 704                         break;
 705                 case DDERR_OUTOFMEMORY:
 706                         error = "Out of memory";
 707                         break;
 708                 case DDERR_OUTOFVIDEOMEMORY:
 709                         error = "Out of video memory";
 710                         break;
 711                 case DDERR_SURFACEBUSY:
 712                         error = "Surface busy";
 713                         break;
 714                 case DDERR_SURFACELOST:
 715                         error = "Surface was lost";
 716                         break;
 717                 case DDERR_WASSTILLDRAWING:
 718                         error = "DirectDraw is still drawing";
 719                         break;
 720                 case DDERR_INVALIDSURFACETYPE:
 721                         error = "Invalid surface type";
 722                         break;
 723                 case DDERR_NOEXCLUSIVEMODE:
 724                         error = "Not in exclusive access mode";
 725                         break;
 726                 case DDERR_NOPALETTEATTACHED:
 727                         error = "No palette attached";
 728                         break;
 729                 case DDERR_NOPALETTEHW:
 730                         error = "No palette hardware";
 731                         break;
 732                 case DDERR_NOT8BITCOLOR:
 733                         error = "Not 8-bit color";
 734                         break;
 735                 case DDERR_EXCLUSIVEMODEALREADYSET:
 736                         error = "Exclusive mode was already set";
 737                         break;
 738                 case DDERR_HWNDALREADYSET:
 739                         error = "Window handle already set";
 740                         break;
 741                 case DDERR_HWNDSUBCLASSED:
 742                         error = "Window handle is subclassed";
 743                         break;
 744                 case DDERR_NOBLTHW:
 745                         error = "No blit hardware";
 746                         break;
 747                 case DDERR_IMPLICITLYCREATED:
 748                         error = "Surface was implicitly created";
 749                         break;
 750                 case DDERR_INCOMPATIBLEPRIMARY:
 751                         error = "Incompatible primary surface";
 752                         break;
 753                 case DDERR_NOCOOPERATIVELEVELSET:
 754                         error = "No cooperative level set";
 755                         break;
 756                 case DDERR_NODIRECTDRAWHW:
 757                         error = "No DirectDraw hardware";
 758                         break;
 759                 case DDERR_NOEMULATION:
 760                         error = "No emulation available";
 761                         break;
 762                 case DDERR_NOFLIPHW:
 763                         error = "No flip hardware";
 764                         break;
 765                 case DDERR_NOTFLIPPABLE:
 766                         error = "Surface not flippable";
 767                         break;
 768                 case DDERR_PRIMARYSURFACEALREADYEXISTS:
 769                         error = "Primary surface already exists";
 770                         break;
 771                 case DDERR_UNSUPPORTEDMODE:
 772                         error = "Unsupported mode";
 773                         break;
 774                 case DDERR_WRONGMODE:
 775                         error = "Surface created in different mode";
 776                         break;
 777                 case DDERR_UNSUPPORTED:
 778                         error = "Operation not supported";
 779                         break;
 780                 case E_NOINTERFACE:
 781                         error = "Interface not present";
 782                         break;
 783                 default:
 784                         sprintf(errbuf, "%s: Unknown DirectDraw error: 0x%x",
 785                                                                 function, code);
 786                         break;
 787         }
 788         if ( ! errbuf[0] ) {
 789                 sprintf(errbuf, "%s: %s", function, error);
 790         }
 791         SDL_SetError("%s", errbuf);
 792         return;
 793 }
 794 
 795 
 796 static int DX5_UpdateVideoInfo(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 797 {
 798         /* This needs to be DDCAPS_DX5 for the DirectDraw2 interface */
 799 #if DIRECTDRAW_VERSION <= 0x300
 800 #error Your version of DirectX must be greater than or equal to 5.0
 801 #endif
 802 #ifndef IID_IDirectDrawGammaControl
 803         /*if gamma is undefined then we really have directx <= 0x500*/
 804         DDCAPS DDCaps;
 805 #else
 806         DDCAPS_DX5 DDCaps;
 807 #endif
 808         HRESULT result;
 809 
 810         /* Fill in our hardware acceleration capabilities */
 811         memset(&DDCaps, 0, sizeof(DDCaps));
 812         DDCaps.dwSize = sizeof(DDCaps);
 813         result = IDirectDraw2_GetCaps(ddraw2, (DDCAPS *)&DDCaps, NULL);
 814         if ( result != DD_OK ) {
 815                 SetDDerror("DirectDraw2::GetCaps", result);
 816                 return(-1);
 817         }
 818         this->info.hw_available = 1;
 819         if ( (DDCaps.dwCaps & DDCAPS_BLT) == DDCAPS_BLT ) {
 820                 this->info.blit_hw = 1;
 821         }
 822         if ( ((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) &&
 823              ((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT) ) {
 824                 this->info.blit_hw_CC = 1;
 825         }
 826         if ( (DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA ) {
 827                 /* This is only for alpha channel, and DirectX 6
 828                    doesn't support 2D alpha blits yet, so set it 0
 829                  */
 830                 this->info.blit_hw_A = 0;
 831         }
 832         if ( (DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM ) {
 833                 this->info.blit_sw = 1;
 834                 /* This isn't necessarily true, but the HEL will cover us */
 835                 this->info.blit_sw_CC = this->info.blit_hw_CC;
 836                 this->info.blit_sw_A = this->info.blit_hw_A;
 837         }
 838         if ( (DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL ) {
 839                 this->info.blit_fill = 1;
 840         }
 841 
 842         /* Find out how much video memory is available */
 843         { DDSCAPS ddsCaps;
 844           DWORD total_mem;
 845                 ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
 846                 result = IDirectDraw2_GetAvailableVidMem(ddraw2,
 847                                                 &ddsCaps, &total_mem, NULL);
 848                 if ( result != DD_OK ) {
 849                         total_mem = DDCaps.dwVidMemTotal; 
 850                 }
 851                 this->info.video_mem = total_mem/1024;
 852         }
 853         return(0);
 854 }
 855 
 856 int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat)
     /* [<][>][^][v][top][bottom][index][help] */
 857 {
 858         HRESULT result;
 859         LPDIRECTDRAW ddraw;
 860         int i, j;
 861         HDC hdc;
 862 
 863         /* Intialize everything */
 864         ddraw2 = NULL;
 865         SDL_primary = NULL;
 866         SDL_clipper = NULL;
 867         SDL_palette = NULL;
 868         for ( i=0; i<NUM_MODELISTS; ++i ) {
 869                 SDL_nummodes[i] = 0;
 870                 SDL_modelist[i] = NULL;
 871                 SDL_modeindex[i] = 0;
 872         }
 873         colorchange_expected = 0;
 874 
 875         /* Create the window */
 876         if ( DX5_CreateWindow(this) < 0 ) {
 877                 return(-1);
 878         }
 879         DX5_SoundFocus(SDL_Window);
 880 
 881         /* Create the DirectDraw object */
 882         result = DDrawCreate(NULL, &ddraw, NULL);
 883         if ( result != DD_OK ) {
 884                 SetDDerror("DirectDrawCreate", result);
 885                 return(-1);
 886         }
 887         result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2,
 888                                                         (LPVOID *)&ddraw2);
 889         IDirectDraw_Release(ddraw);
 890         if ( result != DD_OK ) {
 891                 SetDDerror("DirectDraw::QueryInterface", result);
 892                 return(-1);
 893         }
 894 
 895         /* Determine the screen depth */
 896         hdc = GetDC(SDL_Window);
 897         vformat->BitsPerPixel = GetDeviceCaps(hdc,PLANES) *
 898                                         GetDeviceCaps(hdc,BITSPIXEL);
 899         ReleaseDC(SDL_Window, hdc);
 900 
 901         /* Enumerate the available fullscreen modes */
 902         for ( i=0; i<NUM_MODELISTS; ++i )
 903                 enumlists[i] = NULL;
 904 
 905         result = IDirectDraw2_EnumDisplayModes(ddraw2,0,NULL,this,EnumModes2);
 906         if ( result != DD_OK ) {
 907                 SetDDerror("DirectDraw2::EnumDisplayModes", result);
 908                 return(-1);
 909         }
 910         for ( i=0; i<NUM_MODELISTS; ++i ) {
 911                 struct DX5EnumRect *rect;
 912                 SDL_modelist[i] = (SDL_Rect **)
 913                                 malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *));
 914                 if ( SDL_modelist[i] == NULL ) {
 915                         SDL_OutOfMemory();
 916                         return(-1);
 917                 }
 918                 for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next ) {
 919                         SDL_modelist[i][j]=(SDL_Rect *)rect;
 920                 }
 921                 SDL_modelist[i][j] = NULL;
 922         }
 923         
 924         /* Fill in some window manager capabilities */
 925         this->info.wm_available = 1;
 926 
 927         /* Fill in the video hardware capabilities */
 928         DX5_UpdateVideoInfo(this);
 929 
 930         return(0);
 931 }
 932 
 933 SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
     /* [<][>][^][v][top][bottom][index][help] */
 934 {
 935         int bpp;
 936 
 937         bpp = format->BitsPerPixel;
 938         if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
 939                 /* FIXME:  No support for 1 bpp or 4 bpp formats */
 940                 switch (bpp) {  /* Does windows support other BPP? */
 941                         case 8:
 942                         case 16:
 943                         case 24:
 944                         case 32:
 945                                 bpp = (bpp/8)-1;
 946                                 if ( SDL_nummodes[bpp] > 0 )
 947                                         return(SDL_modelist[bpp]);
 948                                 /* Fall through */
 949                         default:
 950                                 return((SDL_Rect **)0);
 951                 }
 952         } else {
 953                 if ( this->screen->format->BitsPerPixel == bpp ) {
 954                         return((SDL_Rect **)-1);
 955                 } else {
 956                         return((SDL_Rect **)0);
 957                 }
 958         }
 959 }
 960 
 961 /* Various screen update functions available */
 962 static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects);
 963 static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
 964 
 965 SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current,
     /* [<][>][^][v][top][bottom][index][help] */
 966                                 int width, int height, int bpp, Uint32 flags)
 967 {
 968         SDL_Surface *video;
 969         HRESULT result;
 970         DWORD sharemode;
 971         DWORD style;
 972         const DWORD directstyle =
 973                         (WS_POPUP);
 974         const DWORD windowstyle = 
 975                         (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
 976         const DWORD resizestyle =
 977                         (WS_THICKFRAME|WS_MAXIMIZEBOX);
 978         DDSURFACEDESC ddsd;
 979         LPDIRECTDRAWSURFACE  dd_surface1;
 980         LPDIRECTDRAWSURFACE3 dd_surface3;
 981         BOOL was_visible;
 982 
 983 #ifdef DDRAW_DEBUG
 984  fprintf(stderr, "Setting %dx%dx%d video mode\n", width, height, bpp);
 985 #endif
 986         /* See whether or not we should center the window */
 987         was_visible = IsWindowVisible(SDL_Window);
 988 
 989         /* Clean up any previous DirectDraw surfaces */
 990         if ( current->hwdata ) {
 991                 this->FreeHWSurface(this, current);
 992                 current->hwdata = NULL;
 993         }
 994         if ( SDL_primary != NULL ) {
 995                 IDirectDrawSurface3_Release(SDL_primary);
 996                 SDL_primary = NULL;
 997         }
 998 
 999         /* Unset any previous OpenGL fullscreen mode */
1000         if ( (current->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
1001                                (SDL_OPENGL|SDL_FULLSCREEN) ) {
1002                 ChangeDisplaySettings(NULL, 0);
1003         }
1004 
1005         /* Clean up any GL context that may be hanging around */
1006         if ( current->flags & SDL_OPENGL ) {
1007                 WIN_GL_ShutDown(this);
1008         }
1009 
1010         /* If we are setting a GL mode, use GDI, not DirectX (yuck) */
1011         if ( flags & SDL_OPENGL ) {
1012                 RECT bounds;
1013                 int x, y;
1014                 Uint32 Rmask, Gmask, Bmask;
1015 
1016                 /* Recalculate the bitmasks if necessary */
1017                 if ( bpp == current->format->BitsPerPixel ) {
1018                         video = current;
1019                 } else {
1020                         switch (bpp) {
1021                             case 15:
1022                             case 16:
1023                                 if ( 0 /*DIB_SussScreenDepth() == 15*/ ) {
1024                                         /* 5-5-5 */
1025                                         Rmask = 0x00007c00;
1026                                         Gmask = 0x000003e0;
1027                                         Bmask = 0x0000001f;
1028                                 } else {
1029                                         /* 5-6-5 */
1030                                         Rmask = 0x0000f800;
1031                                         Gmask = 0x000007e0;
1032                                         Bmask = 0x0000001f;
1033                                 }
1034                                 break;
1035                             case 24:
1036                             case 32:
1037                                 /* GDI defined as 8-8-8 */
1038                                 Rmask = 0x00ff0000;
1039                                 Gmask = 0x0000ff00;
1040                                 Bmask = 0x000000ff;
1041                                 break;
1042                             default:
1043                                 Rmask = 0x00000000;
1044                                 Gmask = 0x00000000;
1045                                 Bmask = 0x00000000;
1046                                 break;
1047                         }
1048                         video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp,
1049                                                      Rmask, Gmask, Bmask, 0);
1050                         if ( video == NULL ) {
1051                                 SDL_OutOfMemory();
1052                                 return(NULL);
1053                         }
1054                 }
1055 
1056                 /* Fill in part of the video surface */
1057                 video->flags = 0;       /* Clear flags */
1058                 video->w = width;
1059                 video->h = height;
1060                 video->pitch = SDL_CalculatePitch(video);
1061 
1062                 /* Set fullscreen mode if appropriate.
1063                    Ugh, since our list of valid video modes comes from
1064                    the DirectX driver, we may not actually be able to
1065                    change to the desired resolution here.
1066                    FIXME: Should we do a closest match?
1067                  */
1068                 if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
1069                         DEVMODE settings;
1070 
1071                         memset(&settings, 0, sizeof(DEVMODE));
1072                         settings.dmSize = sizeof(DEVMODE);
1073                         settings.dmBitsPerPel = video->format->BitsPerPixel;
1074                         settings.dmPelsWidth = width;
1075                         settings.dmPelsHeight = height;
1076                         settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
1077                         if ( ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) {
1078                                 video->flags |= SDL_FULLSCREEN;
1079                         }
1080                 }
1081 
1082                 style = GetWindowLong(SDL_Window, GWL_STYLE);
1083                 style &= ~(resizestyle|WS_MAXIMIZE);
1084                 if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
1085                         style &= ~windowstyle;
1086                         style |= directstyle;
1087                 } else {
1088                         if ( flags & SDL_NOFRAME ) {
1089                                 style &= ~windowstyle;
1090                                 style |= directstyle;
1091                                 video->flags |= SDL_NOFRAME;
1092                         } else {
1093                                 style &= ~directstyle;
1094                                 style |= windowstyle;
1095                                 if ( flags & SDL_RESIZABLE ) {
1096                                         style |= resizestyle;
1097                                         video->flags |= SDL_RESIZABLE;
1098                                 }
1099                         }
1100                         if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
1101                 }
1102                 SetWindowLong(SDL_Window, GWL_STYLE, style);
1103 
1104                 /* Resize the window (copied from SDL WinDIB driver) */
1105                 if ( SDL_windowid == NULL ) {
1106                         UINT swp_flags;
1107 
1108                         SDL_resizing = 1;
1109                         bounds.left = 0;
1110                         bounds.top = 0;
1111                         bounds.right = video->w;
1112                         bounds.bottom = video->h;
1113                         AdjustWindowRect(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE);
1114                         width = bounds.right-bounds.left;
1115                         height = bounds.bottom-bounds.top;
1116                         x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
1117                         y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
1118                         if ( y < 0 ) { /* Cover up title bar for more client area */
1119                                 y -= GetSystemMetrics(SM_CYCAPTION)/2;
1120                         }
1121                         swp_flags = (SWP_NOCOPYBITS | SWP_NOZORDER | SWP_SHOWWINDOW);
1122                         if ( was_visible && !(flags & SDL_FULLSCREEN) ) {
1123                                 swp_flags |= SWP_NOMOVE;
1124                         }
1125                         SetWindowPos(SDL_Window, NULL, x, y, width, height, swp_flags);
1126                         SDL_resizing = 0;
1127                         SetForegroundWindow(SDL_Window);
1128                 }
1129 
1130                 /* Set up for OpenGL */
1131                 if ( WIN_GL_SetupWindow(this) < 0 ) {
1132                         return(NULL);
1133                 }
1134                 video->flags |= SDL_OPENGL;
1135                 return(video);
1136         }
1137 
1138         /* Set the appropriate window style */
1139         style = GetWindowLong(SDL_Window, GWL_STYLE);
1140         style &= ~(resizestyle|WS_MAXIMIZE);
1141         if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
1142                 style &= ~windowstyle;
1143                 style |= directstyle;
1144         } else {
1145                 if ( flags & SDL_NOFRAME ) {
1146                         style &= ~windowstyle;
1147                         style |= directstyle;
1148                 } else {
1149                         style &= ~directstyle;
1150                         style |= windowstyle;
1151                         if ( flags & SDL_RESIZABLE ) {
1152                                 style |= resizestyle;
1153                         }
1154                 }
1155                 if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
1156         }
1157         SetWindowLong(SDL_Window, GWL_STYLE, style);
1158 
1159         /* Set DirectDraw sharing mode.. exclusive when fullscreen */
1160         if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
1161                 sharemode = DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT;
1162         } else {
1163                 sharemode = DDSCL_NORMAL;
1164         }
1165         result = IDirectDraw2_SetCooperativeLevel(ddraw2,SDL_Window,sharemode);
1166         if ( result != DD_OK ) {
1167                 SetDDerror("DirectDraw2::SetCooperativeLevel", result);
1168                 return(NULL);
1169         }
1170 
1171         /* Set the display mode, if we are in fullscreen mode */
1172         if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
1173                 /* Cover up desktop during mode change */
1174                 SDL_resizing = 1;
1175                 SetWindowPos(SDL_Window, NULL, 0, 0, 
1176                         GetSystemMetrics(SM_CXSCREEN),
1177                         GetSystemMetrics(SM_CYSCREEN),
1178                         (SWP_NOCOPYBITS | SWP_NOZORDER));
1179                 SDL_resizing = 0;
1180                 ShowWindow(SDL_Window, SW_SHOW);
1181                 while ( GetForegroundWindow() != SDL_Window ) {
1182                         SetForegroundWindow(SDL_Window);
1183                         SDL_Delay(100);
1184                 }
1185                 result = IDirectDraw2_SetDisplayMode(ddraw2, width, height,
1186                                                                 bpp, 0, 0);
1187                 if ( result != DD_OK ) {
1188                         /* We couldn't set fullscreen mode, try window */
1189                         return(DX5_SetVideoMode(this, current,
1190                                 width, height, bpp, flags & ~SDL_FULLSCREEN)); 
1191                 }
1192                 DX5_DInputReset(this, 1);
1193         } else {
1194                 DX5_DInputReset(this, 0);
1195         }
1196         DX5_UpdateVideoInfo(this);
1197 
1198         /* Create a primary DirectDraw surface */
1199         memset(&ddsd, 0, sizeof(ddsd));
1200         ddsd.dwSize = sizeof(ddsd);
1201         ddsd.dwFlags = DDSD_CAPS;
1202         ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY);
1203         if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
1204                 /* There's no windowed double-buffering */
1205                 flags &= ~SDL_DOUBLEBUF;
1206         }
1207         if ( (flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
1208                 ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
1209                 ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP);
1210                 ddsd.dwBackBufferCount = 1;
1211         }
1212         result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); 
1213         if ( (result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) ) {
1214                 ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
1215                 ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX|DDSCAPS_FLIP);
1216                 ddsd.dwBackBufferCount = 0;
1217                 result = IDirectDraw2_CreateSurface(ddraw2,
1218                                                 &ddsd, &dd_surface1, NULL); 
1219         }
1220         if ( result != DD_OK ) {
1221                 SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result);
1222                 return(NULL);
1223         }
1224         result = IDirectDrawSurface_QueryInterface(dd_surface1,
1225                         &IID_IDirectDrawSurface3, (LPVOID *)&SDL_primary);
1226         if ( result != DD_OK ) {
1227                 SetDDerror("DirectDrawSurface::QueryInterface", result);
1228                 return(NULL);
1229         }
1230         result = IDirectDrawSurface_Release(dd_surface1);
1231         if ( result != DD_OK ) {
1232                 SetDDerror("DirectDrawSurface::Release", result);
1233                 return(NULL);
1234         }
1235 
1236         /* Get the format of the primary DirectDraw surface */
1237         memset(&ddsd, 0, sizeof(ddsd));
1238         ddsd.dwSize = sizeof(ddsd);
1239         ddsd.dwFlags = DDSD_PIXELFORMAT|DDSD_CAPS;
1240         result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd);
1241         if ( result != DD_OK ) {
1242                 SetDDerror("DirectDrawSurface::Release", result);
1243                 return(NULL);
1244         }
1245         if ( ! (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) ) {
1246                 SDL_SetError("Primary DDRAW surface is not RGB format");
1247                 return(NULL);
1248         }
1249 
1250         /* Free old palette and create a new one if we're in 8-bit mode */
1251         if ( SDL_palette != NULL ) {
1252                 IDirectDrawPalette_Release(SDL_palette);
1253                 SDL_palette = NULL;
1254         }
1255 #if defined(NONAMELESSUNION)
1256         if ( ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8 ) {
1257 #else
1258         if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
1259 #endif
1260                 int i;
1261 
1262                 if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
1263                         /* We have access to the entire palette */
1264                         for ( i=0; i<256; ++i ) {
1265                                 SDL_colors[i].peFlags =
1266                                                 (PC_NOCOLLAPSE|PC_RESERVED);
1267                                 SDL_colors[i].peRed = 0;
1268                                 SDL_colors[i].peGreen = 0;
1269                                 SDL_colors[i].peBlue = 0;
1270                         }
1271                 } else {
1272                         /* First 10 colors are reserved by Windows */
1273                         for ( i=0; i<10; ++i ) {
1274                                 SDL_colors[i].peFlags = PC_EXPLICIT;
1275                                 SDL_colors[i].peRed = i;
1276                                 SDL_colors[i].peGreen = 0;
1277                                 SDL_colors[i].peBlue = 0;
1278                         }
1279                         for ( i=10; i<(10+236); ++i ) {
1280                                 SDL_colors[i].peFlags = PC_NOCOLLAPSE;
1281                                 SDL_colors[i].peRed = 0;
1282                                 SDL_colors[i].peGreen = 0;
1283                                 SDL_colors[i].peBlue = 0;
1284                         }
1285                         /* Last 10 colors are reserved by Windows */
1286                         for ( i=246; i<256; ++i ) {
1287                                 SDL_colors[i].peFlags = PC_EXPLICIT;
1288                                 SDL_colors[i].peRed = i;
1289                                 SDL_colors[i].peGreen = 0;
1290                                 SDL_colors[i].peBlue = 0;
1291                         }
1292                 }
1293                 result = IDirectDraw2_CreatePalette(ddraw2,
1294                                         (DDPCAPS_8BIT|DDPCAPS_ALLOW256),
1295                                                 SDL_colors, &SDL_palette, NULL);
1296                 if ( result != DD_OK ) {
1297                         SetDDerror("DirectDraw2::CreatePalette", result);
1298                         return(NULL);
1299                 }
1300                 result = IDirectDrawSurface3_SetPalette(SDL_primary,
1301                                                                 SDL_palette);
1302                 if ( result != DD_OK ) {
1303                         SetDDerror("DirectDrawSurface3::SetPalette", result);
1304                         return(NULL);
1305                 }
1306         }
1307 
1308         /* Create our video surface using the same pixel format */
1309         video = current;
1310         if ( (width != video->w) || (height != video->h)
1311                         || (video->format->BitsPerPixel != 
1312 #if defined(NONAMELESSUNION)
1313                                 ddsd.ddpfPixelFormat.u1.dwRGBBitCount) ) {
1314 #else
1315                                 ddsd.ddpfPixelFormat.dwRGBBitCount) ) {
1316 #endif
1317                 SDL_FreeSurface(video);
1318                 video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0,
1319 #if defined(NONAMELESSUNION)
1320                                 ddsd.ddpfPixelFormat.u1.dwRGBBitCount,
1321                                         ddsd.ddpfPixelFormat.u2.dwRBitMask,
1322                                         ddsd.ddpfPixelFormat.u3.dwGBitMask,
1323                                         ddsd.ddpfPixelFormat.u4.dwBBitMask,
1324 #else
1325                                 ddsd.ddpfPixelFormat.dwRGBBitCount,
1326                                         ddsd.ddpfPixelFormat.dwRBitMask,
1327                                         ddsd.ddpfPixelFormat.dwGBitMask,
1328                                         ddsd.ddpfPixelFormat.dwBBitMask,
1329 #endif
1330                                                                 0);
1331                 if ( video == NULL ) {
1332                         SDL_OutOfMemory();
1333                         return(NULL);
1334                 }
1335                 video->w = width;
1336                 video->h = height;
1337                 video->pitch = 0;
1338         }
1339         video->flags = 0;       /* Clear flags */
1340 
1341         /* If not fullscreen, locking is possible, but it doesn't do what 
1342            the caller really expects -- if the locked surface is written to,
1343            the appropriate portion of the entire screen is modified, not 
1344            the application window, as we would like.
1345            Note that it is still possible to write directly to display
1346            memory, but the application must respect the clip list of
1347            the surface.  There might be some odd timing interactions
1348            involving clip list updates and background refreshing as
1349            Windows moves other windows across our window.
1350            We currently don't support this, even though it might be a
1351            good idea since BeOS has an implementation of BDirectWindow
1352            that does the same thing.  This would be most useful for
1353            applications that do complete screen updates every frame.
1354             -- Fixme?
1355         */
1356         if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
1357                 /* Necessary if we're going from fullscreen to window */
1358                 if ( video->pixels == NULL ) {
1359                         video->pitch = (width*video->format->BytesPerPixel);
1360                         /* Pitch needs to be QWORD (8-byte) aligned */
1361                         video->pitch = (video->pitch + 7) & ~7;
1362                         video->pixels = (void *)malloc(video->h*video->pitch);
1363                         if ( video->pixels == NULL ) {
1364                                 if ( video != current ) {
1365                                         SDL_FreeSurface(video);
1366                                 }
1367                                 SDL_OutOfMemory();
1368                                 return(NULL);
1369                         }
1370                 }
1371                 dd_surface3 = NULL;
1372                 video->flags |= SDL_SWSURFACE;
1373                 if ( (flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME) ) {
1374                         video->flags |= SDL_RESIZABLE;
1375                 }
1376                 if ( flags & SDL_NOFRAME ) {
1377                         video->flags |= SDL_NOFRAME;
1378                 }
1379         } else {
1380                 /* Necessary if we're going from window to fullscreen */
1381                 if ( video->pixels != NULL ) {
1382                         free(video->pixels);
1383                         video->pixels = NULL;
1384                 }
1385                 dd_surface3 = SDL_primary;
1386                 video->flags |= SDL_HWSURFACE;
1387         }
1388 
1389         /* See if the primary surface has double-buffering enabled */
1390         if ( (ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP ) {
1391                 video->flags |= SDL_DOUBLEBUF;
1392         }
1393 
1394         /* Allocate the SDL surface associated with the primary surface */
1395         if ( DX5_AllocDDSurface(this, video, dd_surface3,
1396                                 video->flags&SDL_HWSURFACE) < 0 ) {
1397                 if ( video != current ) {
1398                         SDL_FreeSurface(video);
1399                 }
1400                 return(NULL);
1401         }
1402 
1403         /* Use the appropriate blitting function */
1404         if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
1405                 video->flags |= SDL_FULLSCREEN;
1406                 if ( video->format->palette != NULL ) {
1407                         video->flags |= SDL_HWPALETTE;
1408                 }
1409                 this->UpdateRects = DX5_DirectUpdate;
1410         } else {
1411                 this->UpdateRects = DX5_WindowUpdate;
1412         }
1413 
1414         /* Make our window the proper size, set the clipper, then show it */
1415         if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
1416                 RECT bounds;
1417                 int  x, y;
1418                 UINT swp_flags;
1419 
1420                 /* Create and set a clipper on our primary surface */
1421                 if ( SDL_clipper == NULL ) {
1422                         result = IDirectDraw2_CreateClipper(ddraw2,
1423                                                         0, &SDL_clipper, NULL);
1424                         if ( result != DD_OK ) {
1425                                 if ( video != current ) {
1426                                         SDL_FreeSurface(video);
1427                                 }
1428                                 SetDDerror("DirectDraw2::CreateClipper",result);
1429                                 return(NULL);
1430                         }
1431                 }
1432                 result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window);
1433                 if ( result != DD_OK ) {
1434                         if ( video != current ) {
1435                                 SDL_FreeSurface(video);
1436                         }
1437                         SetDDerror("DirectDrawClipper::SetHWnd", result);
1438                         return(NULL);
1439                 }
1440                 result = IDirectDrawSurface3_SetClipper(SDL_primary,
1441                                                                 SDL_clipper);
1442                 if ( result != DD_OK ) {
1443                         if ( video != current ) {
1444                                 SDL_FreeSurface(video);
1445                         }
1446                         SetDDerror("DirectDrawSurface3::SetClipper", result);
1447                         return(NULL);
1448                 }
1449 
1450                 /* Set the size of the window, centering and adjusting */
1451                 SDL_resizing = 1;
1452                 bounds.left = 0;
1453                 bounds.top = 0;
1454                 bounds.right = video->w;
1455                 bounds.bottom = video->h;
1456                 AdjustWindowRect(&bounds, GetWindowLong(SDL_Window, GWL_STYLE),
1457                                                                         FALSE);
1458                 width = bounds.right-bounds.left;
1459                 height = bounds.bottom-bounds.top;
1460                 x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
1461                 y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
1462                 if ( y < 0 ) { /* Cover up title bar for more client area */
1463                         y -= GetSystemMetrics(SM_CYCAPTION)/2;
1464                 }
1465                 swp_flags = (SWP_NOCOPYBITS | SWP_NOZORDER);
1466                 if ( was_visible ) {
1467                         swp_flags |= SWP_NOMOVE;
1468                 }
1469                 SetWindowPos(SDL_Window, NULL, x, y, width, height, swp_flags);
1470                 SDL_resizing = 0;
1471         }
1472         ShowWindow(SDL_Window, SW_SHOW);
1473         SetForegroundWindow(SDL_Window);
1474 
1475         /* We're live! */
1476         return(video);
1477 }
1478 
1479 struct private_hwdata {
1480         LPDIRECTDRAWSURFACE3 dd_surface;
1481         LPDIRECTDRAWSURFACE3 dd_writebuf;
1482 };
1483 
1484 static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
     /* [<][>][^][v][top][bottom][index][help] */
1485                                 LPDIRECTDRAWSURFACE3 requested, Uint32 flag)
1486 {
1487         LPDIRECTDRAWSURFACE  dd_surface1;
1488         LPDIRECTDRAWSURFACE3 dd_surface3;
1489         DDSURFACEDESC ddsd;
1490         HRESULT result;
1491 
1492         /* Clear the hardware flag, in case we fail */
1493         surface->flags &= ~flag;
1494 
1495         /* Allocate the hardware acceleration data */
1496         surface->hwdata = (struct private_hwdata *)
1497                                         malloc(sizeof(*surface->hwdata));
1498         if ( surface->hwdata == NULL ) {
1499                 SDL_OutOfMemory();
1500                 return(-1);
1501         }
1502         dd_surface3 = NULL;
1503 
1504         /* Set up the surface description */
1505         memset(&ddsd, 0, sizeof(ddsd));
1506         ddsd.dwSize = sizeof(ddsd);
1507         ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|
1508                                         DDSD_PITCH|DDSD_PIXELFORMAT);
1509         ddsd.dwWidth = surface->w;
1510         ddsd.dwHeight= surface->h;
1511 #if defined(NONAMELESSUNION)
1512         ddsd.u1.lPitch = surface->pitch;
1513 #else
1514         ddsd.lPitch = surface->pitch;
1515 #endif
1516         if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
1517                 ddsd.ddsCaps.dwCaps =
1518                                 (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY);
1519         } else {
1520                 ddsd.ddsCaps.dwCaps =
1521                                 (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
1522         }
1523         ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1524         ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
1525         if ( surface->format->palette ) {
1526                 ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
1527         }
1528 #if defined(NONAMELESSUNION)
1529         ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel;
1530         ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask;
1531         ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask;
1532         ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;
1533 #else
1534         ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel;
1535         ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask;
1536         ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask;
1537         ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;
1538 #endif
1539 
1540         /* Create the DirectDraw video surface */
1541         if ( requested != NULL ) {
1542                 dd_surface3 = requested;
1543         } else {
1544                 result = IDirectDraw2_CreateSurface(ddraw2,
1545                                                 &ddsd, &dd_surface1, NULL); 
1546                 if ( result != DD_OK ) {
1547                         SetDDerror("DirectDraw2::CreateSurface", result);
1548                         goto error_end;
1549                 }
1550                 result = IDirectDrawSurface_QueryInterface(dd_surface1,
1551                         &IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3);
1552                 IDirectDrawSurface_Release(dd_surface1);
1553                 if ( result != DD_OK ) {
1554                         SetDDerror("DirectDrawSurface::QueryInterface", result);
1555                         goto error_end;
1556                 }
1557         }
1558 
1559         if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
1560                 /* Check to see whether the surface actually ended up
1561                    in video memory, and fail if not.  We expect the
1562                    surfaces we create here to actually be in hardware!
1563                 */
1564                 result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps);
1565                 if ( result != DD_OK ) {
1566                         SetDDerror("DirectDrawSurface3::GetCaps", result);
1567                         goto error_end;
1568                 }
1569                 if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) !=
1570                                                         DDSCAPS_VIDEOMEMORY ) {
1571                         SDL_SetError("No room in video memory");
1572                         goto error_end;
1573                 }
1574         } else {
1575                 /* Try to hook our surface memory */
1576                 ddsd.dwFlags = DDSD_LPSURFACE;
1577                 ddsd.lpSurface = surface->pixels;
1578                 result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3,
1579                                                                 &ddsd, 0);
1580                 if ( result != DD_OK ) {
1581                         SetDDerror("DirectDraw2::SetSurfaceDesc", result);
1582                         goto error_end;
1583                 }
1584         
1585         }
1586 
1587         /* Make sure the surface format was set properly */
1588         memset(&ddsd, 0, sizeof(ddsd));
1589         ddsd.dwSize = sizeof(ddsd);
1590         result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
1591                                         &ddsd, DDLOCK_NOSYSLOCK, NULL);
1592         if ( result != DD_OK ) {
1593                 SetDDerror("DirectDrawSurface3::Lock", result);
1594                 goto error_end;
1595         }
1596         IDirectDrawSurface3_Unlock(dd_surface3, NULL);
1597 
1598         if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) {
1599                 if ( ddsd.lpSurface != surface->pixels ) {
1600                         SDL_SetError("DDraw didn't use SDL surface memory");
1601                         goto error_end;
1602                 }
1603                 if (
1604 #if defined(NONAMELESSUNION)
1605                         ddsd.u1.lPitch
1606 #else
1607                         ddsd.lPitch
1608 #endif
1609                                  != (LONG)surface->pitch ) {
1610                         SDL_SetError("DDraw created surface with wrong pitch");
1611                         goto error_end;
1612                 }
1613         } else {
1614 #if defined(NONAMELESSUNION)
1615                 surface->pitch = (Uint16)ddsd.u1.lPitch;
1616 #else
1617                 surface->pitch = (Uint16)ddsd.lPitch;
1618 #endif
1619         }
1620 #if defined(NONAMELESSUNION)
1621         if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount != 
1622                                         surface->format->BitsPerPixel) ||
1623              (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) ||
1624              (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) ||
1625              (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){
1626 #else
1627         if ( (ddsd.ddpfPixelFormat.dwRGBBitCount != 
1628                                         surface->format->BitsPerPixel) ||
1629              (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) ||
1630              (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) ||
1631              (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){
1632 #endif
1633                 SDL_SetError("DDraw didn't use SDL surface description");
1634                 goto error_end;
1635         }
1636         if ( (ddsd.dwWidth != (DWORD)surface->w) ||
1637                 (ddsd.dwHeight != (DWORD)surface->h) ) {
1638                 SDL_SetError("DDraw created surface with wrong size");
1639                 goto error_end;
1640         }
1641 
1642         /* Set the surface private data */
1643         surface->flags |= flag;
1644         surface->hwdata->dd_surface = dd_surface3;
1645         if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
1646                 LPDIRECTDRAWSURFACE3 dd_writebuf;
1647 
1648                 ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
1649                 result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3,
1650                                                 &ddsd.ddsCaps, &dd_writebuf);
1651                 if ( result != DD_OK ) {
1652                         SetDDerror("DirectDrawSurface3::GetAttachedSurface",
1653                                                                 result);
1654                 } else {
1655                         dd_surface3 = dd_writebuf;
1656                 }
1657         }
1658         surface->hwdata->dd_writebuf = dd_surface3;
1659 
1660         /* We're ready to go! */
1661         return(0);
1662 
1663         /* Okay, so goto's are cheesy, but there are so many possible
1664            errors in this function, and the cleanup is the same in 
1665            every single case.  Is there a better way, other than deeply
1666            nesting the code?
1667         */
1668 error_end:
1669         if ( (dd_surface3 != NULL) && (dd_surface3 != requested) ) {
1670                 IDirectDrawSurface_Release(dd_surface3);
1671         }
1672         free(surface->hwdata);
1673         surface->hwdata = NULL;
1674         return(-1);
1675 }
1676 
1677 static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
1678 {
1679         /* DDraw limitation -- you need to set cooperative level first */
1680         if ( SDL_primary == NULL ) {
1681                 SDL_SetError("You must set a non-GL video mode first");
1682                 return(-1);
1683         }
1684         return(DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE));
1685 }
1686 
1687 void PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags)
     /* [<][>][^][v][top][bottom][index][help] */
1688 {
1689         DDSURFACEDESC ddsd;
1690 
1691         /* Lock and load! */
1692         memset(&ddsd, 0, sizeof(ddsd));
1693         ddsd.dwSize = sizeof(ddsd);
1694         if ( IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
1695                         (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL) != DD_OK ) {
1696                 return;
1697         }
1698         IDirectDrawSurface3_Unlock(surface, NULL);
1699         
1700         fprintf(stderr, "%s:\n", title);
1701         fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n",
1702                 ddsd.dwWidth, ddsd.dwHeight,
1703                 (flags & SDL_HWSURFACE) ? "hardware" : "software",
1704 #if defined(NONAMELESSUNION)
1705                 ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch);
1706 #else
1707                 ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch);
1708 #endif
1709         fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n", 
1710 #if defined(NONAMELESSUNION)
1711                         ddsd.ddpfPixelFormat.u2.dwRBitMask,
1712                         ddsd.ddpfPixelFormat.u3.dwGBitMask,
1713                         ddsd.ddpfPixelFormat.u4.dwBBitMask);
1714 #else
1715                         ddsd.ddpfPixelFormat.dwRBitMask,
1716                         ddsd.ddpfPixelFormat.dwGBitMask,
1717                         ddsd.ddpfPixelFormat.dwBBitMask);
1718 #endif
1719 }
1720 
1721 static int DX5_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
     /* [<][>][^][v][top][bottom][index][help] */
1722                                         SDL_Surface *dst, SDL_Rect *dstrect)
1723 {
1724         LPDIRECTDRAWSURFACE3 src_surface;
1725         LPDIRECTDRAWSURFACE3 dst_surface;
1726         DWORD flags;
1727         RECT rect;
1728         HRESULT result;
1729 
1730         /* Set it up.. the desination must have a DDRAW surface */
1731         src_surface = src->hwdata->dd_writebuf;
1732         dst_surface = dst->hwdata->dd_writebuf;
1733         rect.top    = srcrect->y;
1734         rect.bottom = srcrect->y+srcrect->h;
1735         rect.left   = srcrect->x;
1736         rect.right  = srcrect->x+srcrect->w;
1737         if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY )
1738                 flags = DDBLTFAST_SRCCOLORKEY;
1739         else
1740                 flags = DDBLTFAST_NOCOLORKEY;
1741         /* FIXME:  We can remove this flag for _really_ fast blit queuing,
1742                    but it will affect the return values of locks and flips.
1743          */
1744         flags |= DDBLTFAST_WAIT;
1745 
1746         /* Do the blit! */
1747         result = IDirectDrawSurface3_BltFast(dst_surface,
1748                         dstrect->x, dstrect->y, src_surface, &rect, flags);
1749         if ( result != DD_OK ) {
1750                 if ( result == DDERR_SURFACELOST ) {
1751                         result = IDirectDrawSurface3_Restore(src_surface);
1752                         result = IDirectDrawSurface3_Restore(dst_surface);
1753                         /* The surfaces need to be reloaded with artwork */
1754                         SDL_SetError("Blit surfaces were lost, reload them");
1755                         return(-2);
1756                 }
1757                 SetDDerror("IDirectDrawSurface3::BltFast", result);
1758 #ifdef DDRAW_DEBUG
1759  fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w, dstrect->h, dstrect->x, dstrect->y);
1760  fprintf(stderr, "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n",
1761                 (src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src, dst,
1762                                         dstrect->x, dstrect->y);
1763   PrintSurface("SRC", src_surface, src->flags);
1764   PrintSurface("DST", dst_surface, dst->flags);
1765  fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n",
1766                 rect.left, rect.top, rect.right, rect.bottom);
1767 #endif
1768                 /* Unexpected error, fall back to software blit */
1769                 return(src->map->sw_blit(src, srcrect, dst, dstrect));
1770         }
1771         return(0);
1772 }
1773 
1774 static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
     /* [<][>][^][v][top][bottom][index][help] */
1775 {
1776         int accelerated;
1777 
1778         /* We need to have a DDraw surface for HW blits */
1779         if ( (src->flags & SDL_HWSURFACE) == SDL_SWSURFACE ) {
1780                 /* Allocate a DDraw surface for the blit */
1781                 if ( src->hwdata == NULL ) {
1782                         DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE);
1783                 }
1784         }
1785         if ( src->hwdata == NULL ) {
1786                 return(0);
1787         }
1788 
1789         /* Set initial acceleration on */
1790         src->flags |= SDL_HWACCEL;
1791 
1792         /* Set the surface attributes */
1793         if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
1794                 if ( DX5_SetHWColorKey(this, src, src->format->colorkey) < 0 ) {
1795                         src->flags &= ~SDL_HWACCEL;
1796                 }
1797         }
1798         if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
1799                 if ( DX5_SetHWAlpha(this, src, src->format->alpha) < 0 ) {
1800                         src->flags &= ~SDL_HWACCEL;
1801                 }
1802         }
1803 
1804         /* Check to see if final surface blit is accelerated */
1805         accelerated = !!(src->flags & SDL_HWACCEL);
1806         if ( accelerated ) {
1807 #ifdef DDRAW_DEBUG
1808   fprintf(stderr, "Setting accelerated blit on 0x%p\n", src);
1809 #endif
1810                 src->map->hw_blit = DX5_HWAccelBlit;
1811         }
1812         return(accelerated);
1813 }
1814 
1815 static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
     /* [<][>][^][v][top][bottom][index][help] */
1816 {
1817         LPDIRECTDRAWSURFACE3 dst_surface;
1818         RECT area;
1819         DDBLTFX bltfx;
1820         HRESULT result;
1821 
1822 #ifdef DDRAW_DEBUG
1823  fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x, dstrect->y);
1824 #endif
1825         dst_surface = dst->hwdata->dd_writebuf;
1826         area.top = dstrect->y;
1827         area.bottom = dstrect->y+dstrect->h;
1828         area.left = dstrect->x;
1829         area.right = dstrect->x+dstrect->w;
1830         bltfx.dwSize = sizeof(bltfx);
1831 #if defined(NONAMELESSUNION)
1832         bltfx.u5.dwFillColor = color;
1833 #else
1834         bltfx.dwFillColor = color;
1835 #endif
1836         result = IDirectDrawSurface3_Blt(dst_surface,
1837                         &area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
1838         if ( result == DDERR_SURFACELOST ) {
1839                 IDirectDrawSurface3_Restore(dst_surface);
1840                 result = IDirectDrawSurface3_Blt(dst_surface,
1841                         &area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
1842         }
1843         if ( result != DD_OK ) {
1844                 SetDDerror("IDirectDrawSurface3::Blt", result);
1845                 return(-1);
1846         }
1847         return(0);
1848 }
1849 
1850 static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
     /* [<][>][^][v][top][bottom][index][help] */
1851 {
1852         DDCOLORKEY colorkey;
1853         HRESULT result;
1854 
1855         /* Set the surface colorkey */
1856         colorkey.dwColorSpaceLowValue = key;
1857         colorkey.dwColorSpaceHighValue = key;
1858         result = IDirectDrawSurface3_SetColorKey(
1859                         surface->hwdata->dd_surface, DDCKEY_SRCBLT, &colorkey);
1860         if ( result != DD_OK ) {
1861                 SetDDerror("IDirectDrawSurface3::SetColorKey", result);
1862                 return(-1);
1863         }
1864         return(0);
1865 }
1866 static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
     /* [<][>][^][v][top][bottom][index][help] */
1867 {
1868         return(-1);
1869 }
1870 
1871 static int DX5_LockHWSurface(_THIS, SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
1872 {
1873         HRESULT result;
1874         LPDIRECTDRAWSURFACE3 dd_surface;
1875         DDSURFACEDESC ddsd;
1876 
1877         /* Lock and load! */
1878         dd_surface = surface->hwdata->dd_writebuf;
1879         memset(&ddsd, 0, sizeof(ddsd));
1880         ddsd.dwSize = sizeof(ddsd);
1881         result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
1882                                         (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
1883         if ( result == DDERR_SURFACELOST ) {
1884                 result = IDirectDrawSurface3_Restore(
1885                                                 surface->hwdata->dd_surface);
1886                 result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, 
1887                                         (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
1888         }
1889         if ( result != DD_OK ) {
1890                 SetDDerror("DirectDrawSurface3::Lock", result);
1891                 return(-1);
1892         }
1893         /* Pitch might have changed -- recalculate pitch and offset */
1894 #if defined(NONAMELESSUNION)
1895         if ( surface->pitch != ddsd.u1.lPitch ) {
1896                 surface->pitch = ddsd.u1.lPitch;
1897 #else
1898         if ( surface->pitch != ddsd.lPitch ) {
1899                 surface->pitch = (Uint16)ddsd.lPitch;
1900 #endif
1901                 surface->offset =
1902                         ((ddsd.dwHeight-surface->h)/2)*surface->pitch +
1903                         ((ddsd.dwWidth-surface->w)/2)*
1904                                         surface->format->BytesPerPixel;
1905         }
1906         surface->pixels = ddsd.lpSurface;
1907         return(0);
1908 }
1909 
1910 static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
1911 {
1912         IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
1913         surface->pixels = NULL;
1914 }
1915 
1916 static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
1917 {
1918         HRESULT result;
1919         LPDIRECTDRAWSURFACE3 dd_surface;
1920 
1921         dd_surface = surface->hwdata->dd_surface;
1922         result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
1923         if ( result == DDERR_SURFACELOST ) {
1924                 result = IDirectDrawSurface3_Restore(
1925                                                 surface->hwdata->dd_surface);
1926                 result = IDirectDrawSurface3_Flip(dd_surface,NULL,DDFLIP_WAIT);
1927         }
1928         if ( result != DD_OK ) {
1929                 SetDDerror("DirectDrawSurface3::Flip", result);
1930                 return(-1);
1931         }
1932         return(0);
1933 }
1934 
1935 static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface)
     /* [<][>][^][v][top][bottom][index][help] */
1936 {
1937         if ( surface->hwdata ) {
1938                 if ( surface->hwdata->dd_surface != SDL_primary ) {
1939                         IDirectDrawSurface3_Release(surface->hwdata->dd_surface);
1940                 }
1941                 free(surface->hwdata);
1942                 surface->hwdata = NULL;
1943         }
1944 }
1945 
1946 void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects)
     /* [<][>][^][v][top][bottom][index][help] */
1947 {
1948         HRESULT result;
1949         int i;
1950         RECT src, dst;
1951 
1952         for ( i=0; i<numrects; ++i ) {
1953                 src.top = rects[i].y;
1954                 src.bottom = rects[i].y+rects[i].h;
1955                 src.left = rects[i].x;
1956                 src.right = rects[i].x+rects[i].w;
1957                 dst.top = SDL_bounds.top+src.top;
1958                 dst.left = SDL_bounds.left+src.left;
1959                 dst.bottom = SDL_bounds.top+src.bottom;
1960                 dst.right = SDL_bounds.left+src.right;
1961                 result = IDirectDrawSurface3_Blt(SDL_primary, &dst, 
1962                                         this->screen->hwdata->dd_surface, &src,
1963                                                         DDBLT_WAIT, NULL);
1964                 /* Doh!  Check for lost surface and restore it */
1965                 if ( result == DDERR_SURFACELOST ) {
1966                         IDirectDrawSurface3_Restore(SDL_primary);
1967                         IDirectDrawSurface3_Blt(SDL_primary, &dst, 
1968                                         this->screen->hwdata->dd_surface, &src,
1969                                                         DDBLT_WAIT, NULL);
1970                 }
1971         }
1972 }
1973 
1974 void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
     /* [<][>][^][v][top][bottom][index][help] */
1975 {
1976 }
1977 
1978 /* Compress a full palette into the limited number of colors given to us
1979    by windows.
1980 
1981    The "best" way to do this is to sort the colors by diversity and place
1982    the most diverse colors into the limited palette.  Unfortunately this
1983    results in widely varying colors being displayed in the interval during
1984    which the windows palette has been set, and the mapping of the shadow
1985    surface to the new palette.  This is especially noticeable during fades.
1986 
1987    To deal with this problem, we can copy a predetermined portion of the
1988    full palette, and use that as the limited palette.  This allows colors
1989    to fade smoothly as the remapping is very similar on each palette change.
1990    Unfortunately, this breaks applications which partition the palette into
1991    distinct and widely varying areas, expecting all colors to be available.
1992 
1993    I'm making them both available, chosen at compile time.
1994    If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION,
1995    otherwise the sort-by-diversity algorithm will be used.
1996 */
1997 #define SIMPLE_COMPRESSION
1998 #define CS_CS_DIST(A, B) ({                                             \
     /* [<][>][^][v][top][bottom][index][help] */
1999         int r = (A.r - B.r);                                            \
2000         int g = (A.g - B.g);                                            \
2001         int b = (A.b - B.b);                                            \
2002         (r*r + g*g + b*b);                                              \
2003 })
2004 static void DX5_CompressPalette(_THIS, SDL_Color *colors, int ncolors, int maxcolors)
     /* [<][>][^][v][top][bottom][index][help] */
2005 {
2006 #ifdef SIMPLE_COMPRESSION
2007         int i, j;
2008 #else
2009         static SDL_Color zero = { 0, 0, 0, 0 };
2010         int i, j;
2011         int max, dist;
2012         int prev, next;
2013         int *pool;
2014         int *seen, *order;
2015 #endif
2016 
2017         /* Does this happen? */
2018         if ( maxcolors > ncolors ) {
2019                 maxcolors = ncolors;
2020         }
2021 
2022 #ifdef SIMPLE_COMPRESSION
2023         /* Just copy the first "maxcolors" colors */
2024         for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
2025                 SDL_colors[j].peRed = colors[i].r;
2026                 SDL_colors[j].peGreen = colors[i].g;
2027                 SDL_colors[j].peBlue = colors[i].b;
2028         }
2029 #else
2030         /* Allocate memory for the arrays we use */
2031         pool = (int *)alloca(2*ncolors*sizeof(int));
2032         if ( pool == NULL ) {
2033                 /* No worries, just return */;
2034                 return;
2035         }
2036         seen = pool;
2037         memset(seen, 0, ncolors*sizeof(int));
2038         order = pool+ncolors;
2039 
2040         /* Start with the brightest color */
2041         max = 0;
2042         for ( i=0; i<ncolors; ++i ) {
2043                 dist = CS_CS_DIST(zero, colors[i]);
2044                 if ( dist >= max ) {
2045                         max = dist;
2046                         next = i;
2047                 }
2048         }
2049         j = 0;
2050         order[j++] = next;
2051         seen[next] = 1;
2052         prev = next;
2053 
2054         /* Keep going through all the colors */
2055         while ( j < maxcolors ) {
2056                 max = 0;
2057                 for ( i=0; i<ncolors; ++i ) {
2058                         if ( seen[i] ) {
2059                                 continue;
2060                         }
2061                         dist = CS_CS_DIST(colors[i], colors[prev]);
2062                         if ( dist >= max ) {
2063                                 max = dist;
2064                                 next = i;
2065                         }
2066                 }
2067                 order[j++] = next;
2068                 seen[next] = 1;
2069                 prev = next;
2070         }
2071 
2072         /* Compress the colors to the palette */
2073         for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
2074                 SDL_colors[j].peRed = colors[order[i]].r;
2075                 SDL_colors[j].peGreen = colors[order[i]].g;
2076                 SDL_colors[j].peBlue = colors[order[i]].b;
2077         }
2078 #endif /* SIMPLE_COMPRESSION */
2079 }
2080 
2081 /* Set the system colormap in both fullscreen and windowed modes */
2082 int DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
     /* [<][>][^][v][top][bottom][index][help] */
2083 {
2084         int i;
2085         int alloct_all;
2086 
2087         /* Copy palette colors into display palette */
2088         alloct_all = 0;
2089         if ( SDL_palette != NULL ) {
2090                 if ( (this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
2091                         /* We can set all entries explicitly */
2092                         for ( i=0; i< ncolors; ++i ) {
2093                                 int j = firstcolor + i;
2094                                 SDL_colors[j].peRed = colors[i].r;
2095                                 SDL_colors[j].peGreen = colors[i].g;
2096                                 SDL_colors[j].peBlue = colors[i].b;
2097                         }
2098                         IDirectDrawPalette_SetEntries(SDL_palette, 0,
2099                                 firstcolor, ncolors, &SDL_colors[firstcolor]);
2100                         alloct_all = 1;
2101                 } else {
2102                         /* Grab the 236 most diverse colors in the palette */
2103                         DX5_CompressPalette(this, colors, ncolors, 236);
2104                         /* This sends an WM_PALETTECHANGED message to us */
2105                         colorchange_expected = 1;
2106                         IDirectDrawPalette_SetEntries(SDL_palette, 0,
2107                                                         0, 256, SDL_colors);
2108                 }
2109         }
2110         return(alloct_all);
2111 }
2112 
2113 static void DX5_SwapGamma(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
2114 {
2115         return;
2116 }
2117 
2118 /* Gamma code is only available on DirectX 7 and newer */
2119 #ifdef IID_IDirectDrawGammaControl
2120 
2121 static int DX5_SetGammaRamp(_THIS, Uint16 *ramp)
     /* [<][>][^][v][top][bottom][index][help] */
2122 {
2123         LPDIRECTDRAWGAMMACONTROL gamma;
2124         DDGAMMARAMP gamma_ramp;
2125         HRESULT result;
2126 
2127         /* Check for a video mode! */
2128         if ( ! SDL_primary ) {
2129                 SDL_SetError("A video mode must be set for gamma correction");
2130                 return(-1);
2131         }
2132 
2133         /* Get the gamma control object */
2134         result = IDirectDrawSurface3_QueryInterface(SDL_primary,
2135                         &IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
2136         if ( result != DD_OK ) {
2137                 SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
2138                 return(-1);
2139         }
2140 
2141         /* Set up the gamma ramp */
2142         memcpy(gamma_ramp.red, &ramp[0*256], 256*sizeof(*ramp));
2143         memcpy(gamma_ramp.green, &ramp[1*256], 256*sizeof(*ramp));
2144         memcpy(gamma_ramp.blue, &ramp[2*256], 256*sizeof(*ramp));
2145         result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp);
2146         if ( result != DD_OK ) {
2147                 SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result);
2148         }
2149 
2150         /* Release the interface and return */
2151         IDirectDrawGammaControl_Release(gamma);
2152         return (result == DD_OK) ? 0 : -1;
2153 }
2154 
2155 static int DX5_GetGammaRamp(_THIS, Uint16 *ramp)
     /* [<][>][^][v][top][bottom][index][help] */
2156 {
2157         LPDIRECTDRAWGAMMACONTROL gamma;
2158         DDGAMMARAMP gamma_ramp;
2159         HRESULT result;
2160 
2161         /* Check for a video mode! */
2162         if ( ! SDL_primary ) {
2163                 SDL_SetError("A video mode must be set for gamma correction");
2164                 return(-1);
2165         }
2166 
2167         /* Get the gamma control object */
2168         result = IDirectDrawSurface3_QueryInterface(SDL_primary,
2169                         &IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
2170         if ( result != DD_OK ) {
2171                 SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
2172                 return(-1);
2173         }
2174 
2175         /* Set up the gamma ramp */
2176         result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp);
2177         if ( result == DD_OK ) {
2178                 memcpy(&ramp[0*256], gamma_ramp.red, 256*sizeof(*ramp));
2179                 memcpy(&ramp[1*256], gamma_ramp.green, 256*sizeof(*ramp));
2180                 memcpy(&ramp[2*256], gamma_ramp.blue, 256*sizeof(*ramp));
2181         } else {
2182                 SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result);
2183         }
2184 
2185         /* Release the interface and return */
2186         IDirectDrawGammaControl_Release(gamma);
2187         return (result == DD_OK) ? 0 : -1;
2188 }
2189 
2190 #endif /* IID_IDirectDrawGammaControl */
2191 
2192 void DX5_VideoQuit(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
2193 {
2194         int i, j;
2195 
2196         /* If we're fullscreen GL, we need to reset the display */
2197         if ( this->screen != NULL ) {
2198                 if ( (this->screen->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
2199                                             (SDL_OPENGL|SDL_FULLSCREEN) ) {
2200                         ChangeDisplaySettings(NULL, 0);
2201                 }
2202                 if ( this->screen->flags & SDL_OPENGL ) {
2203                         WIN_GL_ShutDown(this);
2204                 }
2205         }
2206 
2207         /* Free any palettes we used */
2208         if ( SDL_palette != NULL ) {
2209                 IDirectDrawPalette_Release(SDL_palette);
2210                 SDL_palette = NULL;
2211         }
2212 
2213         /* Allow the primary surface to be freed */
2214         if ( SDL_primary != NULL ) {
2215                 SDL_primary = NULL;
2216         }
2217 
2218         /* Free video mode lists */
2219         for ( i=0; i<NUM_MODELISTS; ++i ) {
2220                 if ( SDL_modelist[i] != NULL ) {
2221                         for ( j=0; SDL_modelist[i][j]; ++j )
2222                                 free(SDL_modelist[i][j]);
2223                         free(SDL_modelist[i]);
2224                         SDL_modelist[i] = NULL;
2225                 }
2226         }
2227 
2228         /* Free the window */
2229         if ( SDL_Window ) {
2230                 DX5_DestroyWindow(this);
2231         }
2232 
2233         /* Free our window icon */
2234         if ( screen_icn ) {
2235                 DestroyIcon(screen_icn);
2236                 screen_icn = NULL;
2237         }
2238 }
2239 
2240 /* Exported for the windows message loop only */
2241 void DX5_RealizePalette(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
2242 {
2243         if ( SDL_palette ) {
2244                 IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
2245         }
2246 }
2247 static void DX5_Recolor8Bit(_THIS, SDL_Surface *surface, Uint8 *mapping)
     /* [<][>][^][v][top][bottom][index][help] */
2248 {
2249         int row, col;
2250         Uint8 *pixels;
2251 
2252         if ( surface->w && surface->h ) {
2253                 if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
2254                         if ( this->LockHWSurface(this, surface) < 0 ) {
2255                                 return;
2256                         }
2257                 }
2258                 for ( row=0; row<surface->h; ++row ) {
2259                         pixels = (Uint8 *)surface->pixels+row*surface->pitch;
2260                         for ( col=0; col<surface->w; ++col, ++pixels ) {
2261                                 *pixels = mapping[*pixels];
2262                         }
2263                 }
2264                 if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
2265                         this->UnlockHWSurface(this, surface);
2266                 }
2267                 SDL_UpdateRect(surface, 0, 0, 0, 0);
2268         }
2269 }
2270 void DX5_PaletteChanged(_THIS, HWND window)
     /* [<][>][^][v][top][bottom][index][help] */
2271 {
2272         SDL_Palette *palette;
2273         SDL_Color *saved = NULL;
2274         HDC hdc;
2275         int i;
2276         PALETTEENTRY *entries;
2277 
2278         /* This is true when the window is closing */
2279         if ( (SDL_primary == NULL) || (SDL_VideoSurface == NULL) )
2280                 return;
2281 
2282         /* We need to get the colors as they were set */
2283         palette = this->physpal;
2284         if(!palette)
2285                 palette = SDL_VideoSurface->format->palette;
2286         if ( palette == NULL ) { /* Sometimes we don't have a palette */
2287                 return;
2288         }
2289         entries = (PALETTEENTRY *)alloca(palette->ncolors*sizeof(*entries));
2290         hdc = GetDC(window);
2291         GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries);
2292         ReleaseDC(window, hdc);
2293         if ( ! colorchange_expected ) {
2294                 saved = (SDL_Color *)alloca(palette->ncolors*sizeof(SDL_Color));
2295                 memcpy(saved, palette->colors, 
2296                                         palette->ncolors*sizeof(SDL_Color));
2297         }
2298         for ( i=0; i<palette->ncolors; ++i ) {
2299                 palette->colors[i].r = entries[i].peRed;
2300                 palette->colors[i].g = entries[i].peGreen;
2301                 palette->colors[i].b = entries[i].peBlue;
2302         }
2303         if ( ! colorchange_expected ) {
2304                 Uint8 mapping[256];
2305 
2306                 memset(mapping, 0, sizeof(mapping));
2307                 for ( i=0; i<palette->ncolors; ++i ) {
2308                         mapping[i] = SDL_FindColor(palette,
2309                                         saved[i].r, saved[i].g, saved[i].b);
2310                 }
2311                 DX5_Recolor8Bit(this, SDL_VideoSurface, mapping);
2312         }
2313         colorchange_expected = 0;
2314 
2315         /* Notify all mapped surfaces of the change */
2316         SDL_FormatChanged(SDL_VideoSurface);
2317 }
2318 
2319 /* Exported for the windows message loop only */
2320 void DX5_WinPAINT(_THIS, HDC hdc)
     /* [<][>][^][v][top][bottom][index][help] */
2321 {
2322         SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
2323 }

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