src/video/windx5/SDL_dx5video.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 15 Mar 2006 17:46:41 +0000
changeset 1545 8d9bb0cf2c2a
parent 1523 21b1fbb53f4a
child 1658 e49147870aac
child 1771 8d3ca155c396
permissions -rw-r--r--
Added current_w and current_h to the SDL_VideoInfo structure, which is set to the desktop resolution during video intialization, and then set to the current resolution when a video mode is set.

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