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