src/video/windx5/SDL_dx5video.c
author Sam Lantinga <slouken@lokigames.com>
Thu, 26 Apr 2001 16:45:43 +0000
changeset 0 74212992fb08
child 1 cf2af46e9e2a
permissions -rw-r--r--
Initial revision
     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$";
    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 );
    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)
   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)
   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)
   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)
   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)
   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)
   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)
   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)
   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)
   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)
   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,
   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, 
  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)
  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)
  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,
  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)
  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)
  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)
  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)
  1867 {
  1868 	return(-1);
  1869 }
  1870 
  1871 static int DX5_LockHWSurface(_THIS, SDL_Surface *surface)
  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)
  1911 {
  1912 	IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
  1913 	surface->pixels = NULL;
  1914 }
  1915 
  1916 static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
  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)
  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)
  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)
  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) ({						\
  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)
  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)
  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)
  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)
  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)
  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)
  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)
  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)
  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)
  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)
  2321 {
  2322 	SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
  2323 }