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