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