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