Fix order of texture enumeration to fix yet another set of dumb games.
[wine] / dlls / ddraw / helper.c
1
2 /*              DirectDraw Base Functions
3  *
4  * Copyright 1997-1999 Marcus Meissner
5  * Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
6  * Copyright 2000 TransGaming Technologies Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stddef.h>
27 #include <stdio.h>
28
29 #include "d3d.h"
30 #include "ddraw.h"
31 #include "winerror.h"
32
33 #include "wine/exception.h"
34 #include "ddraw_private.h"
35
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
39
40 /******************************************************************************
41  *              debug output functions
42  */
43 void DDRAW_dump_flags_(DWORD flags, const flag_info* names,
44                        size_t num_names, int newline)
45 {
46     unsigned int        i;
47
48     for (i=0; i < num_names; i++)
49         if ((flags & names[i].val) ||      /* standard flag value */
50             ((!flags) && (!names[i].val))) /* zero value only */
51             DPRINTF("%s ", names[i].name);
52
53     if (newline)
54         DPRINTF("\n");
55 }
56
57 void DDRAW_dump_members(DWORD flags, const void* data,
58                         const member_info* mems, size_t num_mems)
59 {
60     unsigned int i;
61
62     for (i=0; i < num_mems; i++)
63     {
64         if (mems[i].val & flags)
65         {
66             DPRINTF(" - %s : ", mems[i].name);
67             mems[i].func((const char *)data + mems[i].offset);
68             DPRINTF("\n");
69         }
70     }
71 }
72
73 void DDRAW_dump_DDBLTFX(DWORD flagmask)
74 {
75     static const flag_info flags[] =
76         {
77             FE(DDBLTFX_ARITHSTRETCHY),
78             FE(DDBLTFX_MIRRORLEFTRIGHT),
79             FE(DDBLTFX_MIRRORUPDOWN),
80             FE(DDBLTFX_NOTEARING),
81             FE(DDBLTFX_ROTATE180),
82             FE(DDBLTFX_ROTATE270),
83             FE(DDBLTFX_ROTATE90),
84             FE(DDBLTFX_ZBUFFERRANGE),
85             FE(DDBLTFX_ZBUFFERBASEDEST)
86         };
87
88     DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
89 }
90
91 void DDRAW_dump_DDBLTFAST(DWORD flagmask)
92 {
93     static const flag_info flags[] =
94         {
95             FE(DDBLTFAST_NOCOLORKEY),
96             FE(DDBLTFAST_SRCCOLORKEY),
97             FE(DDBLTFAST_DESTCOLORKEY),
98             FE(DDBLTFAST_WAIT)
99         };
100
101     DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
102 }
103
104 void DDRAW_dump_DDBLT(DWORD flagmask)
105 {
106     static const flag_info flags[] =
107         {
108             FE(DDBLT_ALPHADEST),
109             FE(DDBLT_ALPHADESTCONSTOVERRIDE),
110             FE(DDBLT_ALPHADESTNEG),
111             FE(DDBLT_ALPHADESTSURFACEOVERRIDE),
112             FE(DDBLT_ALPHAEDGEBLEND),
113             FE(DDBLT_ALPHASRC),
114             FE(DDBLT_ALPHASRCCONSTOVERRIDE),
115             FE(DDBLT_ALPHASRCNEG),
116             FE(DDBLT_ALPHASRCSURFACEOVERRIDE),
117             FE(DDBLT_ASYNC),
118             FE(DDBLT_COLORFILL),
119             FE(DDBLT_DDFX),
120             FE(DDBLT_DDROPS),
121             FE(DDBLT_KEYDEST),
122             FE(DDBLT_KEYDESTOVERRIDE),
123             FE(DDBLT_KEYSRC),
124             FE(DDBLT_KEYSRCOVERRIDE),
125             FE(DDBLT_ROP),
126             FE(DDBLT_ROTATIONANGLE),
127             FE(DDBLT_ZBUFFER),
128             FE(DDBLT_ZBUFFERDESTCONSTOVERRIDE),
129             FE(DDBLT_ZBUFFERDESTOVERRIDE),
130             FE(DDBLT_ZBUFFERSRCCONSTOVERRIDE),
131             FE(DDBLT_ZBUFFERSRCOVERRIDE),
132             FE(DDBLT_WAIT),
133             FE(DDBLT_DEPTHFILL)
134     };
135
136     DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
137 }
138
139 void DDRAW_dump_DDSCAPS2(const DDSCAPS2 *in)
140 {
141     static const flag_info flags[] = {
142         FE(DDSCAPS_RESERVED1),
143         FE(DDSCAPS_ALPHA),
144         FE(DDSCAPS_BACKBUFFER),
145         FE(DDSCAPS_COMPLEX),
146         FE(DDSCAPS_FLIP),
147         FE(DDSCAPS_FRONTBUFFER),
148         FE(DDSCAPS_OFFSCREENPLAIN),
149         FE(DDSCAPS_OVERLAY),
150         FE(DDSCAPS_PALETTE),
151         FE(DDSCAPS_PRIMARYSURFACE),
152         FE(DDSCAPS_PRIMARYSURFACELEFT),
153         FE(DDSCAPS_SYSTEMMEMORY),
154         FE(DDSCAPS_TEXTURE),
155         FE(DDSCAPS_3DDEVICE),
156         FE(DDSCAPS_VIDEOMEMORY),
157         FE(DDSCAPS_VISIBLE),
158         FE(DDSCAPS_WRITEONLY),
159         FE(DDSCAPS_ZBUFFER),
160         FE(DDSCAPS_OWNDC),
161         FE(DDSCAPS_LIVEVIDEO),
162         FE(DDSCAPS_HWCODEC),
163         FE(DDSCAPS_MODEX),
164         FE(DDSCAPS_MIPMAP),
165         FE(DDSCAPS_RESERVED2),
166         FE(DDSCAPS_ALLOCONLOAD),
167         FE(DDSCAPS_VIDEOPORT),
168         FE(DDSCAPS_LOCALVIDMEM),
169         FE(DDSCAPS_NONLOCALVIDMEM),
170         FE(DDSCAPS_STANDARDVGAMODE),
171         FE(DDSCAPS_OPTIMIZED)
172     };
173     static const flag_info flags2[] = {
174         FE(DDSCAPS2_HARDWAREDEINTERLACE),
175         FE(DDSCAPS2_HINTDYNAMIC),
176         FE(DDSCAPS2_HINTSTATIC),
177         FE(DDSCAPS2_TEXTUREMANAGE),
178         FE(DDSCAPS2_RESERVED1),
179         FE(DDSCAPS2_RESERVED2),
180         FE(DDSCAPS2_OPAQUE),
181         FE(DDSCAPS2_HINTANTIALIASING),
182         FE(DDSCAPS2_CUBEMAP),
183         FE(DDSCAPS2_CUBEMAP_POSITIVEX),
184         FE(DDSCAPS2_CUBEMAP_NEGATIVEX),
185         FE(DDSCAPS2_CUBEMAP_POSITIVEY),
186         FE(DDSCAPS2_CUBEMAP_NEGATIVEY),
187         FE(DDSCAPS2_CUBEMAP_POSITIVEZ),
188         FE(DDSCAPS2_CUBEMAP_NEGATIVEZ),
189         FE(DDSCAPS2_MIPMAPSUBLEVEL),
190         FE(DDSCAPS2_D3DTEXTUREMANAGE),
191         FE(DDSCAPS2_DONOTPERSIST),
192         FE(DDSCAPS2_STEREOSURFACELEFT)
193     };
194  
195     DDRAW_dump_flags_(in->dwCaps, flags, sizeof(flags)/sizeof(flags[0]), 0);
196     DDRAW_dump_flags_(in->dwCaps2, flags2, sizeof(flags2)/sizeof(flags2[0]), 0);
197 }
198
199 void DDRAW_dump_DDSCAPS(const DDSCAPS *in) {
200     DDSCAPS2 in_bis;
201
202     in_bis.dwCaps = in->dwCaps;
203     in_bis.dwCaps2 = 0;
204     in_bis.dwCaps3 = 0;
205     in_bis.dwCaps4 = 0;
206
207     DDRAW_dump_DDSCAPS2(&in_bis);
208 }
209
210 void DDRAW_dump_pixelformat_flag(DWORD flagmask)
211 {
212     static const flag_info flags[] =
213         {
214             FE(DDPF_ALPHAPIXELS),
215             FE(DDPF_ALPHA),
216             FE(DDPF_FOURCC),
217             FE(DDPF_PALETTEINDEXED4),
218             FE(DDPF_PALETTEINDEXEDTO8),
219             FE(DDPF_PALETTEINDEXED8),
220             FE(DDPF_RGB),
221             FE(DDPF_COMPRESSED),
222             FE(DDPF_RGBTOYUV),
223             FE(DDPF_YUV),
224             FE(DDPF_ZBUFFER),
225             FE(DDPF_PALETTEINDEXED1),
226             FE(DDPF_PALETTEINDEXED2),
227             FE(DDPF_ZPIXELS)
228     };
229
230     DDRAW_dump_flags_(flagmask, flags, sizeof(flags)/sizeof(flags[0]), 0);
231 }
232
233 void DDRAW_dump_paletteformat(DWORD dwFlags)
234 {
235     static const flag_info flags[] =
236         {
237             FE(DDPCAPS_4BIT),
238             FE(DDPCAPS_8BITENTRIES),
239             FE(DDPCAPS_8BIT),
240             FE(DDPCAPS_INITIALIZE),
241             FE(DDPCAPS_PRIMARYSURFACE),
242             FE(DDPCAPS_PRIMARYSURFACELEFT),
243             FE(DDPCAPS_ALLOW256),
244             FE(DDPCAPS_VSYNC),
245             FE(DDPCAPS_1BIT),
246             FE(DDPCAPS_2BIT),
247             FE(DDPCAPS_ALPHA)
248     };
249
250     DDRAW_dump_flags(dwFlags, flags, sizeof(flags)/sizeof(flags[0]));
251 }
252
253 void DDRAW_dump_pixelformat(const DDPIXELFORMAT *pf) {
254     DPRINTF("( ");
255     DDRAW_dump_pixelformat_flag(pf->dwFlags);
256     if (pf->dwFlags & DDPF_FOURCC) {
257         DPRINTF(", dwFourCC code '%c%c%c%c' (0x%08lx) - %ld bits per pixel",
258                 (unsigned char)( pf->dwFourCC     &0xff),
259                 (unsigned char)((pf->dwFourCC>> 8)&0xff),
260                 (unsigned char)((pf->dwFourCC>>16)&0xff),
261                 (unsigned char)((pf->dwFourCC>>24)&0xff),
262                 pf->dwFourCC,
263                 pf->u1.dwYUVBitCount
264         );
265     }
266     if (pf->dwFlags & DDPF_RGB) {
267         char *cmd;
268         DPRINTF(", RGB bits: %ld, ", pf->u1.dwRGBBitCount);
269         switch (pf->u1.dwRGBBitCount) {
270         case 4: cmd = "%1lx"; break;
271         case 8: cmd = "%02lx"; break;
272         case 16: cmd = "%04lx"; break;
273         case 24: cmd = "%06lx"; break;
274         case 32: cmd = "%08lx"; break;
275         default: ERR("Unexpected bit depth !\n"); cmd = "%d"; break;
276         }
277         DPRINTF(" R "); DPRINTF(cmd, pf->u2.dwRBitMask);
278         DPRINTF(" G "); DPRINTF(cmd, pf->u3.dwGBitMask);
279         DPRINTF(" B "); DPRINTF(cmd, pf->u4.dwBBitMask);
280         if (pf->dwFlags & DDPF_ALPHAPIXELS) {
281             DPRINTF(" A "); DPRINTF(cmd, pf->u5.dwRGBAlphaBitMask);
282         }
283         if (pf->dwFlags & DDPF_ZPIXELS) {
284             DPRINTF(" Z "); DPRINTF(cmd, pf->u5.dwRGBZBitMask);
285         }
286     }
287     if (pf->dwFlags & DDPF_ZBUFFER) {
288         DPRINTF(", Z bits : %ld", pf->u1.dwZBufferBitDepth);
289     }
290     if (pf->dwFlags & DDPF_ALPHA) {
291         DPRINTF(", Alpha bits : %ld", pf->u1.dwAlphaBitDepth);
292     }
293     DPRINTF(")");
294 }
295
296 void DDRAW_dump_colorkeyflag(DWORD ck)
297 {
298     static const flag_info flags[] =
299         {
300             FE(DDCKEY_COLORSPACE),
301             FE(DDCKEY_DESTBLT),
302             FE(DDCKEY_DESTOVERLAY),
303             FE(DDCKEY_SRCBLT),
304             FE(DDCKEY_SRCOVERLAY)
305     };
306
307     DDRAW_dump_flags(ck, flags, sizeof(flags)/sizeof(flags[0]));
308 }
309
310 void DDRAW_dump_lockflag(DWORD lockflag)
311 {
312     static const flag_info flags[] =
313         {
314             FE(DDLOCK_SURFACEMEMORYPTR),
315             FE(DDLOCK_WAIT),
316             FE(DDLOCK_EVENT),
317             FE(DDLOCK_READONLY),
318             FE(DDLOCK_WRITEONLY),
319             FE(DDLOCK_NOSYSLOCK),
320             FE(DDLOCK_DISCARDCONTENTS),
321             FE(DDLOCK_NOOVERWRITE)
322         };
323
324     DDRAW_dump_flags(lockflag, flags, sizeof(flags)/sizeof(flags[0]));
325 }
326
327 static void DDRAW_dump_DWORD(const void *in) {
328     DPRINTF("%ld", *((const DWORD *) in));
329 }
330 static void DDRAW_dump_PTR(const void *in) {
331     DPRINTF("%p", *((const void **) in));
332 }
333 void DDRAW_dump_DDCOLORKEY(const DDCOLORKEY *ddck) {
334     DPRINTF(" Low : %ld  - High : %ld", ddck->dwColorSpaceLowValue, ddck->dwColorSpaceHighValue);
335 }
336
337 void DDRAW_dump_surface_desc(const DDSURFACEDESC2 *lpddsd)
338 {
339 #define STRUCT DDSURFACEDESC2
340     static const member_info members[] =
341         {
342             ME(DDSD_HEIGHT, DDRAW_dump_DWORD, dwHeight),
343             ME(DDSD_WIDTH, DDRAW_dump_DWORD, dwWidth),
344             ME(DDSD_PITCH, DDRAW_dump_DWORD, u1.lPitch),
345             ME(DDSD_LINEARSIZE, DDRAW_dump_DWORD, u1.dwLinearSize),
346             ME(DDSD_BACKBUFFERCOUNT, DDRAW_dump_DWORD, dwBackBufferCount),
347             ME(DDSD_MIPMAPCOUNT, DDRAW_dump_DWORD, u2.dwMipMapCount),
348             ME(DDSD_REFRESHRATE, DDRAW_dump_DWORD, u2.dwRefreshRate),
349             ME(DDSD_ALPHABITDEPTH, DDRAW_dump_DWORD, dwAlphaBitDepth),
350             ME(DDSD_LPSURFACE, DDRAW_dump_PTR, lpSurface),
351             ME(DDSD_CKDESTOVERLAY, DDRAW_dump_DDCOLORKEY, u3.ddckCKDestOverlay),
352             ME(DDSD_CKDESTBLT, DDRAW_dump_DDCOLORKEY, ddckCKDestBlt),
353             ME(DDSD_CKSRCOVERLAY, DDRAW_dump_DDCOLORKEY, ddckCKSrcOverlay),
354             ME(DDSD_CKSRCBLT, DDRAW_dump_DDCOLORKEY, ddckCKSrcBlt),
355             ME(DDSD_PIXELFORMAT, DDRAW_dump_pixelformat, u4.ddpfPixelFormat)
356         };
357     static const member_info members_caps[] =
358         {
359             ME(DDSD_CAPS, DDRAW_dump_DDSCAPS, ddsCaps)
360         };
361     static const member_info members_caps2[] =
362         {
363             ME(DDSD_CAPS, DDRAW_dump_DDSCAPS2, ddsCaps)
364         };
365 #undef STRUCT
366
367     if (lpddsd->dwSize >= sizeof(DDSURFACEDESC2)) {
368         DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members_caps2, 1);
369     } else {
370         DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members_caps, 1);
371     }
372                                                   
373     DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members,
374                        sizeof(members)/sizeof(members[0]));
375 }
376
377 void DDRAW_dump_cooperativelevel(DWORD cooplevel)
378 {
379     static const flag_info flags[] =
380         {
381             FE(DDSCL_FULLSCREEN),
382             FE(DDSCL_ALLOWREBOOT),
383             FE(DDSCL_NOWINDOWCHANGES),
384             FE(DDSCL_NORMAL),
385             FE(DDSCL_ALLOWMODEX),
386             FE(DDSCL_EXCLUSIVE),
387             FE(DDSCL_SETFOCUSWINDOW),
388             FE(DDSCL_SETDEVICEWINDOW),
389             FE(DDSCL_CREATEDEVICEWINDOW)
390     };
391
392     if (TRACE_ON(ddraw))
393     {
394         DPRINTF(" - ");
395         DDRAW_dump_flags(cooplevel, flags, sizeof(flags)/sizeof(flags[0]));
396     }
397 }
398
399 void DDRAW_dump_DDCAPS(const DDCAPS *lpcaps) {
400     static const flag_info flags1[] = {
401       FE(DDCAPS_3D),
402       FE(DDCAPS_ALIGNBOUNDARYDEST),
403       FE(DDCAPS_ALIGNSIZEDEST),
404       FE(DDCAPS_ALIGNBOUNDARYSRC),
405       FE(DDCAPS_ALIGNSIZESRC),
406       FE(DDCAPS_ALIGNSTRIDE),
407       FE(DDCAPS_BLT),
408       FE(DDCAPS_BLTQUEUE),
409       FE(DDCAPS_BLTFOURCC),
410       FE(DDCAPS_BLTSTRETCH),
411       FE(DDCAPS_GDI),
412       FE(DDCAPS_OVERLAY),
413       FE(DDCAPS_OVERLAYCANTCLIP),
414       FE(DDCAPS_OVERLAYFOURCC),
415       FE(DDCAPS_OVERLAYSTRETCH),
416       FE(DDCAPS_PALETTE),
417       FE(DDCAPS_PALETTEVSYNC),
418       FE(DDCAPS_READSCANLINE),
419       FE(DDCAPS_STEREOVIEW),
420       FE(DDCAPS_VBI),
421       FE(DDCAPS_ZBLTS),
422       FE(DDCAPS_ZOVERLAYS),
423       FE(DDCAPS_COLORKEY),
424       FE(DDCAPS_ALPHA),
425       FE(DDCAPS_COLORKEYHWASSIST),
426       FE(DDCAPS_NOHARDWARE),
427       FE(DDCAPS_BLTCOLORFILL),
428       FE(DDCAPS_BANKSWITCHED),
429       FE(DDCAPS_BLTDEPTHFILL),
430       FE(DDCAPS_CANCLIP),
431       FE(DDCAPS_CANCLIPSTRETCHED),
432       FE(DDCAPS_CANBLTSYSMEM)
433     };
434     static const flag_info flags2[] = {
435       FE(DDCAPS2_CERTIFIED),
436       FE(DDCAPS2_NO2DDURING3DSCENE),
437       FE(DDCAPS2_VIDEOPORT),
438       FE(DDCAPS2_AUTOFLIPOVERLAY),
439       FE(DDCAPS2_CANBOBINTERLEAVED),
440       FE(DDCAPS2_CANBOBNONINTERLEAVED),
441       FE(DDCAPS2_COLORCONTROLOVERLAY),
442       FE(DDCAPS2_COLORCONTROLPRIMARY),
443       FE(DDCAPS2_CANDROPZ16BIT),
444       FE(DDCAPS2_NONLOCALVIDMEM),
445       FE(DDCAPS2_NONLOCALVIDMEMCAPS),
446       FE(DDCAPS2_NOPAGELOCKREQUIRED),
447       FE(DDCAPS2_WIDESURFACES),
448       FE(DDCAPS2_CANFLIPODDEVEN),
449       FE(DDCAPS2_CANBOBHARDWARE),
450       FE(DDCAPS2_COPYFOURCC),
451       FE(DDCAPS2_PRIMARYGAMMA),
452       FE(DDCAPS2_CANRENDERWINDOWED),
453       FE(DDCAPS2_CANCALIBRATEGAMMA),
454       FE(DDCAPS2_FLIPINTERVAL),
455       FE(DDCAPS2_FLIPNOVSYNC),
456       FE(DDCAPS2_CANMANAGETEXTURE),
457       FE(DDCAPS2_TEXMANINNONLOCALVIDMEM),
458       FE(DDCAPS2_STEREO),
459       FE(DDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL)
460     };
461     static const flag_info flags3[] = {
462       FE(DDCKEYCAPS_DESTBLT),
463       FE(DDCKEYCAPS_DESTBLTCLRSPACE),
464       FE(DDCKEYCAPS_DESTBLTCLRSPACEYUV),
465       FE(DDCKEYCAPS_DESTBLTYUV),
466       FE(DDCKEYCAPS_DESTOVERLAY),
467       FE(DDCKEYCAPS_DESTOVERLAYCLRSPACE),
468       FE(DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV),
469       FE(DDCKEYCAPS_DESTOVERLAYONEACTIVE),
470       FE(DDCKEYCAPS_DESTOVERLAYYUV),
471       FE(DDCKEYCAPS_SRCBLT),
472       FE(DDCKEYCAPS_SRCBLTCLRSPACE),
473       FE(DDCKEYCAPS_SRCBLTCLRSPACEYUV),
474       FE(DDCKEYCAPS_SRCBLTYUV),
475       FE(DDCKEYCAPS_SRCOVERLAY),
476       FE(DDCKEYCAPS_SRCOVERLAYCLRSPACE),
477       FE(DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV),
478       FE(DDCKEYCAPS_SRCOVERLAYONEACTIVE),
479       FE(DDCKEYCAPS_SRCOVERLAYYUV),
480       FE(DDCKEYCAPS_NOCOSTOVERLAY)
481     };
482     static const flag_info flags4[] = {
483       FE(DDFXCAPS_BLTALPHA),
484       FE(DDFXCAPS_OVERLAYALPHA),
485       FE(DDFXCAPS_BLTARITHSTRETCHYN),
486       FE(DDFXCAPS_BLTARITHSTRETCHY),
487       FE(DDFXCAPS_BLTMIRRORLEFTRIGHT),
488       FE(DDFXCAPS_BLTMIRRORUPDOWN),
489       FE(DDFXCAPS_BLTROTATION),
490       FE(DDFXCAPS_BLTROTATION90),
491       FE(DDFXCAPS_BLTSHRINKX),
492       FE(DDFXCAPS_BLTSHRINKXN),
493       FE(DDFXCAPS_BLTSHRINKY),
494       FE(DDFXCAPS_BLTSHRINKYN),
495       FE(DDFXCAPS_BLTSTRETCHX),
496       FE(DDFXCAPS_BLTSTRETCHXN),
497       FE(DDFXCAPS_BLTSTRETCHY),
498       FE(DDFXCAPS_BLTSTRETCHYN),
499       FE(DDFXCAPS_OVERLAYARITHSTRETCHY),
500       FE(DDFXCAPS_OVERLAYARITHSTRETCHYN),
501       FE(DDFXCAPS_OVERLAYSHRINKX),
502       FE(DDFXCAPS_OVERLAYSHRINKXN),
503       FE(DDFXCAPS_OVERLAYSHRINKY),
504       FE(DDFXCAPS_OVERLAYSHRINKYN),
505       FE(DDFXCAPS_OVERLAYSTRETCHX),
506       FE(DDFXCAPS_OVERLAYSTRETCHXN),
507       FE(DDFXCAPS_OVERLAYSTRETCHY),
508       FE(DDFXCAPS_OVERLAYSTRETCHYN),
509       FE(DDFXCAPS_OVERLAYMIRRORLEFTRIGHT),
510       FE(DDFXCAPS_OVERLAYMIRRORUPDOWN)
511     };
512     static const flag_info flags5[] = {
513       FE(DDFXALPHACAPS_BLTALPHAEDGEBLEND),
514       FE(DDFXALPHACAPS_BLTALPHAPIXELS),
515       FE(DDFXALPHACAPS_BLTALPHAPIXELSNEG),
516       FE(DDFXALPHACAPS_BLTALPHASURFACES),
517       FE(DDFXALPHACAPS_BLTALPHASURFACESNEG),
518       FE(DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND),
519       FE(DDFXALPHACAPS_OVERLAYALPHAPIXELS),
520       FE(DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG),
521       FE(DDFXALPHACAPS_OVERLAYALPHASURFACES),
522       FE(DDFXALPHACAPS_OVERLAYALPHASURFACESNEG)
523     };
524     static const flag_info flags6[] = {
525       FE(DDPCAPS_4BIT),
526       FE(DDPCAPS_8BITENTRIES),
527       FE(DDPCAPS_8BIT),
528       FE(DDPCAPS_INITIALIZE),
529       FE(DDPCAPS_PRIMARYSURFACE),
530       FE(DDPCAPS_PRIMARYSURFACELEFT),
531       FE(DDPCAPS_ALLOW256),
532       FE(DDPCAPS_VSYNC),
533       FE(DDPCAPS_1BIT),
534       FE(DDPCAPS_2BIT),
535       FE(DDPCAPS_ALPHA),
536     };
537     static const flag_info flags7[] = {
538       FE(DDSVCAPS_RESERVED1),
539       FE(DDSVCAPS_RESERVED2),
540       FE(DDSVCAPS_RESERVED3),
541       FE(DDSVCAPS_RESERVED4),
542       FE(DDSVCAPS_STEREOSEQUENTIAL),
543     };
544
545     DPRINTF(" - dwSize : %ld\n", lpcaps->dwSize);
546     DPRINTF(" - dwCaps : "); DDRAW_dump_flags(lpcaps->dwCaps, flags1, sizeof(flags1)/sizeof(flags1[0]));
547     DPRINTF(" - dwCaps2 : "); DDRAW_dump_flags(lpcaps->dwCaps2, flags2, sizeof(flags2)/sizeof(flags2[0]));
548     DPRINTF(" - dwCKeyCaps : "); DDRAW_dump_flags(lpcaps->dwCKeyCaps, flags3, sizeof(flags3)/sizeof(flags3[0]));
549     DPRINTF(" - dwFXCaps : "); DDRAW_dump_flags(lpcaps->dwFXCaps, flags4, sizeof(flags4)/sizeof(flags4[0]));
550     DPRINTF(" - dwFXAlphaCaps : "); DDRAW_dump_flags(lpcaps->dwFXAlphaCaps, flags5, sizeof(flags5)/sizeof(flags5[0]));
551     DPRINTF(" - dwPalCaps : "); DDRAW_dump_flags(lpcaps->dwPalCaps, flags6, sizeof(flags6)/sizeof(flags6[0]));
552     DPRINTF(" - dwSVCaps : "); DDRAW_dump_flags(lpcaps->dwSVCaps, flags7, sizeof(flags7)/sizeof(flags7[0]));
553     DPRINTF("...\n");
554     DPRINTF(" - dwNumFourCCCodes : %ld\n", lpcaps->dwNumFourCCCodes);
555     DPRINTF(" - dwCurrVisibleOverlays : %ld\n", lpcaps->dwCurrVisibleOverlays);
556     DPRINTF(" - dwMinOverlayStretch : %ld\n", lpcaps->dwMinOverlayStretch);
557     DPRINTF(" - dwMaxOverlayStretch : %ld\n", lpcaps->dwMaxOverlayStretch);
558     DPRINTF("...\n");
559     DPRINTF(" - ddsCaps : "); DDRAW_dump_DDSCAPS2(&lpcaps->ddsCaps); DPRINTF("\n");
560 }
561
562 /* Debug function that can be helpful to debug various surface-related problems */
563 static int get_shift(DWORD color_mask) {
564     int shift = 0;
565     while (color_mask > 0xFF) {
566         color_mask >>= 1;
567         shift += 1;
568     }
569     while ((color_mask & 0x80) == 0) {
570         color_mask <<= 1;
571         shift -= 1;
572     }
573     return shift;
574 }
575
576 void DDRAW_dump_surface_to_disk(IDirectDrawSurfaceImpl *surface, FILE *f)
577 {
578     int i;
579
580     if (TRACE_ON(ddraw)) {
581         DPRINTF("Dumping surface : \n");
582         DDRAW_dump_surface_desc(&(surface->surface_desc));
583     }
584     
585     fprintf(f, "P6\n%ld %ld\n255\n", surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
586
587     if (surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
588         unsigned char table[256][3];
589         unsigned char *src = (unsigned char *) surface->surface_desc.lpSurface;
590         if (surface->palette == NULL) {
591             fclose(f);
592             return;
593         }
594         for (i = 0; i < 256; i++) {
595             table[i][0] = surface->palette->palents[i].peRed;
596             table[i][1] = surface->palette->palents[i].peGreen;
597             table[i][2] = surface->palette->palents[i].peBlue;
598         }
599         for (i = 0; i < surface->surface_desc.dwHeight * surface->surface_desc.dwWidth; i++) {
600             unsigned char color = *src++;
601             fputc(table[color][0], f);
602             fputc(table[color][1], f);
603             fputc(table[color][2], f);
604         }
605     } else if (surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) {
606         int red_shift, green_shift, blue_shift;
607         red_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask);
608         green_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask);
609         blue_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask);
610
611         for (i = 0; i < surface->surface_desc.dwHeight * surface->surface_desc.dwWidth; i++) {
612             int color;
613             int comp;
614             
615             if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 8) {
616                 color = ((unsigned char *) surface->surface_desc.lpSurface)[i];
617             } else if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
618                 color = ((unsigned short *) surface->surface_desc.lpSurface)[i];
619             } else if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) {
620                 color = ((unsigned int *) surface->surface_desc.lpSurface)[i];
621             } else {
622                 /* Well, this won't work on platforms without support for non-aligned memory accesses or big endian :-) */
623                 color = *((unsigned int *) (((char *) surface->surface_desc.lpSurface) + (3 * i)));
624             }
625             comp = color & surface->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask;
626             fputc(red_shift > 0 ? comp >> red_shift : comp << -red_shift, f);
627             comp = color & surface->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask;
628             fputc(green_shift > 0 ? comp >> green_shift : comp << -green_shift, f);
629             comp = color & surface->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask;
630             fputc(blue_shift > 0 ? comp >> blue_shift : comp << -blue_shift, f);
631         }
632     }
633     fclose(f);
634 }