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