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