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