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