comparison src/video/windx5/SDL_dx5video.c @ 0:74212992fb08

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