ntdll: Implement DVD_ReadStructure.
[wine] / dlls / ddraw / ddraw_utils.c
1 /*
2  * DirectDraw helper functions
3  *
4  * Copyright 1997-2000 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 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
25
26 #include "wine/debug.h"
27
28 #include <stddef.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "wingdi.h"
36 #include "ddraw.h"
37
38 #include "ddraw_private.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
41
42 /* *************************************
43       16 / 15 bpp to palettized 8 bpp
44    ************************************* */
45 static void pixel_convert_16_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, IDirectDrawPaletteImpl* palette) {
46     unsigned char  *c_src = (unsigned char  *) src;
47     unsigned short *c_dst = (unsigned short *) dst;
48     int y;
49
50     if (palette != NULL) {
51         const unsigned int * pal = (unsigned int *) palette->screen_palents;
52
53         for (y = height; y--; ) {
54 #if defined(__i386__) && defined(__GNUC__)
55             /* gcc generates slightly inefficient code for the the copy/lookup,
56              * it generates one excess memory access (to pal) per pixel. Since
57              * we know that pal is not modified by the memory write we can
58              * put it into a register and reduce the number of memory accesses
59              * from 4 to 3 pp. There are two xor eax,eax to avoid pipeline
60              * stalls. (This is not guaranteed to be the fastest method.)
61              */
62             __asm__ __volatile__(
63             "xor %%eax,%%eax\n"
64             "1:\n"
65             "    lodsb\n"
66             "    movw (%%edx,%%eax,4),%%ax\n"
67             "    stosw\n"
68             "      xor %%eax,%%eax\n"
69             "    loop 1b\n"
70             : "=S" (c_src), "=D" (c_dst)
71             : "S" (c_src), "D" (c_dst) , "c" (width), "d" (pal)
72             : "eax", "cc", "memory"
73             );
74             c_src+=(pitch-width);
75 #else
76             unsigned char * srclineend = c_src+width;
77             while (c_src < srclineend)
78                 *c_dst++ = pal[*c_src++];
79             c_src+=(pitch-width);
80 #endif
81         }
82     } else {
83         FIXME("No palette set...\n");
84         memset(dst, 0, width * height * 2);
85     }
86 }
87 static void palette_convert_16_to_8(
88         LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count
89 ) {
90     unsigned int i;
91     unsigned int *pal = (unsigned int *) screen_palette;
92
93     for (i = 0; i < count; i++)
94         pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 8) |
95                           ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
96                           ((((unsigned short) palent[i].peGreen) & 0xFC) << 3));
97 }
98
99 static void palette_convert_15_to_8(
100         LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count
101 ) {
102     unsigned int i;
103     unsigned int *pal = (unsigned int *) screen_palette;
104
105     for (i = 0; i < count; i++)
106         pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 7) |
107                           ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
108                           ((((unsigned short) palent[i].peGreen) & 0xF8) << 2));
109 }
110
111 /* *************************************
112       24 to palettized 8 bpp
113    ************************************* */
114 static void pixel_convert_24_to_8(
115         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
116         IDirectDrawPaletteImpl* palette
117 ) {
118     unsigned char  *c_src = (unsigned char  *) src;
119     unsigned char *c_dst = (unsigned char *) dst;
120     int y;
121
122     if (palette != NULL) {
123         const unsigned int *pal = (unsigned int *) palette->screen_palents;
124
125         for (y = height; y--; ) {
126             unsigned char * srclineend = c_src+width;
127             while (c_src < srclineend ) {
128                 register long pixel = pal[*c_src++];
129                 *c_dst++ = pixel;
130                 *c_dst++ = pixel>>8;
131                 *c_dst++ = pixel>>16;
132             }
133             c_src+=(pitch-width);
134         }
135     } else {
136         FIXME("No palette set...\n");
137         memset(dst, 0, width * height * 3);
138     }
139 }
140
141 /* *************************************
142       32 bpp to palettized 8 bpp
143    ************************************* */
144 static void pixel_convert_32_to_8(
145         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
146         IDirectDrawPaletteImpl* palette
147 ) {
148     unsigned char  *c_src = (unsigned char  *) src;
149     unsigned int *c_dst = (unsigned int *) dst;
150     int y;
151
152     if (palette != NULL) {
153         const unsigned int *pal = (unsigned int *) palette->screen_palents;
154
155         for (y = height; y--; ) {
156 #if defined(__i386__) && defined(__GNUC__)
157             /* See comment in pixel_convert_16_to_8 */
158             __asm__ __volatile__(
159             "xor %%eax,%%eax\n"
160             "1:\n"
161             "    lodsb\n"
162             "    movl (%%edx,%%eax,4),%%eax\n"
163             "    stosl\n"
164             "      xor %%eax,%%eax\n"
165             "    loop 1b\n"
166             : "=S" (c_src), "=D" (c_dst)
167             : "S" (c_src), "D" (c_dst) , "c" (width), "d" (pal)
168             : "eax", "cc", "memory"
169             );
170             c_src+=(pitch-width);
171 #else
172             unsigned char * srclineend = c_src+width;
173             while (c_src < srclineend )
174                 *c_dst++ = pal[*c_src++];
175             c_src+=(pitch-width);
176 #endif
177         }
178     } else {
179         FIXME("No palette set...\n");
180         memset(dst, 0, width * height * 4);
181     }
182 }
183
184 static void palette_convert_24_to_8(
185         LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count
186 ) {
187     unsigned int i;
188     unsigned int *pal = (unsigned int *) screen_palette;
189
190     for (i = 0; i < count; i++)
191         pal[start + i] = ((((unsigned int) palent[i].peRed) << 16) |
192                           (((unsigned int) palent[i].peGreen) << 8) |
193                            ((unsigned int) palent[i].peBlue));
194 }
195
196 /* *************************************
197       16 bpp to 15 bpp
198    ************************************* */
199 static void pixel_convert_15_to_16(
200         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
201         IDirectDrawPaletteImpl* palette
202 ) {
203     unsigned short *c_src = (unsigned short *) src;
204     unsigned short *c_dst = (unsigned short *) dst;
205     int y;
206
207     for (y = height; y--; ) {
208         unsigned short * srclineend = c_src+width;
209         while (c_src < srclineend ) {
210             unsigned short val = *c_src++;
211             *c_dst++=((val&0xFFC0)>>1)|(val&0x001f);
212         }
213         c_src+=((pitch/2)-width);
214     }
215 }
216
217 /* *************************************
218       32 bpp to 16 bpp
219    ************************************* */
220 static void pixel_convert_32_to_16(
221         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
222         IDirectDrawPaletteImpl* palette
223 ) {
224     unsigned short *c_src = (unsigned short *) src;
225     unsigned int *c_dst = (unsigned int *) dst;
226     int y;
227
228     for (y = height; y--; ) {
229         unsigned short * srclineend = c_src+width;
230         while (c_src < srclineend ) {
231             *c_dst++ = (((*c_src & 0xF800) << 8) |
232                         ((*c_src & 0x07E0) << 5) |
233                         ((*c_src & 0x001F) << 3));
234             c_src++;
235         }
236         c_src+=((pitch/2)-width);
237     }
238 }
239
240 /* *************************************
241       32 bpp to 24 bpp
242    ************************************* */
243 static void pixel_convert_32_to_24(
244         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
245         IDirectDrawPaletteImpl* palette
246 ) {
247     unsigned char *c_src = (unsigned char *) src;
248     unsigned int *c_dst = (unsigned int *) dst;
249     int y;
250
251     for (y = height; y--; ) {
252         unsigned char * srclineend = c_src+width*3;
253         while (c_src < srclineend ) {
254             /* FIXME: wrong for big endian */
255             memcpy(c_dst,c_src,3);
256             c_src+=3;
257             c_dst++;
258         }
259         c_src+=pitch-width*3;
260     }
261 }
262
263 /* *************************************
264       16 bpp to 32 bpp
265    ************************************* */
266 static void pixel_convert_16_to_32(
267         void *src, void *dst, DWORD width, DWORD height, LONG pitch,
268         IDirectDrawPaletteImpl* palette
269 ) {
270     unsigned int *c_src = (unsigned int *) src;
271     unsigned short *c_dst = (unsigned short *) dst;
272     int y;
273
274     for (y = height; y--; ) {
275         unsigned int * srclineend = c_src+width;
276         while (c_src < srclineend ) {
277             *c_dst++ = (((*c_src & 0xF80000) >> 8) |
278                         ((*c_src & 0x00FC00) >> 5) |
279                         ((*c_src & 0x0000F8) >> 3));
280             c_src++;
281         }
282         c_src+=((pitch/4)-width);
283     }
284 }
285
286 Convert ModeEmulations[8] = {
287   { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  24, 24, 0xFF0000, 0x00FF00, 0x0000FF }, { pixel_convert_32_to_24, NULL } },
288   { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  16, 16, 0xF800, 0x07E0, 0x001F }, { pixel_convert_32_to_16, NULL } },
289   { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_32_to_8,  palette_convert_24_to_8 } },
290   { { 24, 24,   0xFF0000,   0x00FF00,   0x0000FF }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_24_to_8,  palette_convert_24_to_8 } },
291   { { 16, 15,     0x7C00,     0x03E0,     0x001F }, {  16,16, 0xf800, 0x07e0, 0x001f }, { pixel_convert_15_to_16,  NULL } },
292   { { 16, 16,     0xF800,     0x07E0,     0x001F }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_16_to_8,  palette_convert_16_to_8 } },
293   { { 16, 15,     0x7C00,     0x03E0,     0x001F }, {  8,  8, 0x00, 0x00, 0x00 }, { pixel_convert_16_to_8,  palette_convert_15_to_8 } },
294   { { 16, 16,     0xF800,     0x07E0,     0x001F }, {  32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, { pixel_convert_16_to_32, NULL } }
295 };
296
297 void DDRAW_Convert_DDSCAPS_1_To_2(const DDSCAPS* pIn, DDSCAPS2* pOut)
298 {
299     /* 2 adds three additional caps fields to the end. Both versions
300      * are unversioned. */
301     pOut->dwCaps = pIn->dwCaps;
302     pOut->dwCaps2 = 0;
303     pOut->dwCaps3 = 0;
304     pOut->dwCaps4 = 0;
305 }
306
307 void DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(const DDDEVICEIDENTIFIER2* pIn,
308                                              DDDEVICEIDENTIFIER* pOut)
309 {
310     /* 2 adds a dwWHQLLevel field to the end. Both structures are
311      * unversioned. */
312     memcpy(pOut, pIn, sizeof(*pOut));
313 }
314
315 /******************************************************************************
316  *              debug output functions
317  */
318 void DDRAW_dump_flags_(DWORD flags, const flag_info* names,
319                        size_t num_names, int newline)
320 {
321     unsigned int        i;
322
323     for (i=0; i < num_names; i++)
324         if ((flags & names[i].val) ||      /* standard flag value */
325             ((!flags) && (!names[i].val))) /* zero value only */
326             DPRINTF("%s ", names[i].name);
327
328     if (newline)
329         DPRINTF("\n");
330 }
331
332 void DDRAW_dump_members(DWORD flags, const void* data,
333                         const member_info* mems, size_t num_mems)
334 {
335     unsigned int i;
336
337     for (i=0; i < num_mems; i++)
338     {
339         if (mems[i].val & flags)
340         {
341             DPRINTF(" - %s : ", mems[i].name);
342             mems[i].func((const char *)data + mems[i].offset);
343             DPRINTF("\n");
344         }
345     }
346 }
347
348 void DDRAW_dump_DDBLTFX(DWORD flagmask)
349 {
350     static const flag_info flags[] =
351         {
352             FE(DDBLTFX_ARITHSTRETCHY),
353             FE(DDBLTFX_MIRRORLEFTRIGHT),
354             FE(DDBLTFX_MIRRORUPDOWN),
355             FE(DDBLTFX_NOTEARING),
356             FE(DDBLTFX_ROTATE180),
357             FE(DDBLTFX_ROTATE270),
358             FE(DDBLTFX_ROTATE90),
359             FE(DDBLTFX_ZBUFFERRANGE),
360             FE(DDBLTFX_ZBUFFERBASEDEST)
361         };
362
363     DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
364 }
365
366 void DDRAW_dump_DDBLTFAST(DWORD flagmask)
367 {
368     static const flag_info flags[] =
369         {
370             FE(DDBLTFAST_NOCOLORKEY),
371             FE(DDBLTFAST_SRCCOLORKEY),
372             FE(DDBLTFAST_DESTCOLORKEY),
373             FE(DDBLTFAST_WAIT)
374         };
375
376     DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
377 }
378
379 void DDRAW_dump_DDBLT(DWORD flagmask)
380 {
381     static const flag_info flags[] =
382         {
383             FE(DDBLT_ALPHADEST),
384             FE(DDBLT_ALPHADESTCONSTOVERRIDE),
385             FE(DDBLT_ALPHADESTNEG),
386             FE(DDBLT_ALPHADESTSURFACEOVERRIDE),
387             FE(DDBLT_ALPHAEDGEBLEND),
388             FE(DDBLT_ALPHASRC),
389             FE(DDBLT_ALPHASRCCONSTOVERRIDE),
390             FE(DDBLT_ALPHASRCNEG),
391             FE(DDBLT_ALPHASRCSURFACEOVERRIDE),
392             FE(DDBLT_ASYNC),
393             FE(DDBLT_COLORFILL),
394             FE(DDBLT_DDFX),
395             FE(DDBLT_DDROPS),
396             FE(DDBLT_KEYDEST),
397             FE(DDBLT_KEYDESTOVERRIDE),
398             FE(DDBLT_KEYSRC),
399             FE(DDBLT_KEYSRCOVERRIDE),
400             FE(DDBLT_ROP),
401             FE(DDBLT_ROTATIONANGLE),
402             FE(DDBLT_ZBUFFER),
403             FE(DDBLT_ZBUFFERDESTCONSTOVERRIDE),
404             FE(DDBLT_ZBUFFERDESTOVERRIDE),
405             FE(DDBLT_ZBUFFERSRCCONSTOVERRIDE),
406             FE(DDBLT_ZBUFFERSRCOVERRIDE),
407             FE(DDBLT_WAIT),
408             FE(DDBLT_DEPTHFILL),
409             FE(DDBLT_DONOTWAIT)
410     };
411
412     DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
413 }
414
415 void DDRAW_dump_DDSCAPS2(const DDSCAPS2 *in)
416 {
417     static const flag_info flags[] = {
418         FE(DDSCAPS_RESERVED1),
419         FE(DDSCAPS_ALPHA),
420         FE(DDSCAPS_BACKBUFFER),
421         FE(DDSCAPS_COMPLEX),
422         FE(DDSCAPS_FLIP),
423         FE(DDSCAPS_FRONTBUFFER),
424         FE(DDSCAPS_OFFSCREENPLAIN),
425         FE(DDSCAPS_OVERLAY),
426         FE(DDSCAPS_PALETTE),
427         FE(DDSCAPS_PRIMARYSURFACE),
428         FE(DDSCAPS_PRIMARYSURFACELEFT),
429         FE(DDSCAPS_SYSTEMMEMORY),
430         FE(DDSCAPS_TEXTURE),
431         FE(DDSCAPS_3DDEVICE),
432         FE(DDSCAPS_VIDEOMEMORY),
433         FE(DDSCAPS_VISIBLE),
434         FE(DDSCAPS_WRITEONLY),
435         FE(DDSCAPS_ZBUFFER),
436         FE(DDSCAPS_OWNDC),
437         FE(DDSCAPS_LIVEVIDEO),
438         FE(DDSCAPS_HWCODEC),
439         FE(DDSCAPS_MODEX),
440         FE(DDSCAPS_MIPMAP),
441         FE(DDSCAPS_RESERVED2),
442         FE(DDSCAPS_ALLOCONLOAD),
443         FE(DDSCAPS_VIDEOPORT),
444         FE(DDSCAPS_LOCALVIDMEM),
445         FE(DDSCAPS_NONLOCALVIDMEM),
446         FE(DDSCAPS_STANDARDVGAMODE),
447         FE(DDSCAPS_OPTIMIZED)
448     };
449     static const flag_info flags2[] = {
450         FE(DDSCAPS2_HARDWAREDEINTERLACE),
451         FE(DDSCAPS2_HINTDYNAMIC),
452         FE(DDSCAPS2_HINTSTATIC),
453         FE(DDSCAPS2_TEXTUREMANAGE),
454         FE(DDSCAPS2_RESERVED1),
455         FE(DDSCAPS2_RESERVED2),
456         FE(DDSCAPS2_OPAQUE),
457         FE(DDSCAPS2_HINTANTIALIASING),
458         FE(DDSCAPS2_CUBEMAP),
459         FE(DDSCAPS2_CUBEMAP_POSITIVEX),
460         FE(DDSCAPS2_CUBEMAP_NEGATIVEX),
461         FE(DDSCAPS2_CUBEMAP_POSITIVEY),
462         FE(DDSCAPS2_CUBEMAP_NEGATIVEY),
463         FE(DDSCAPS2_CUBEMAP_POSITIVEZ),
464         FE(DDSCAPS2_CUBEMAP_NEGATIVEZ),
465         FE(DDSCAPS2_MIPMAPSUBLEVEL),
466         FE(DDSCAPS2_D3DTEXTUREMANAGE),
467         FE(DDSCAPS2_DONOTPERSIST),
468         FE(DDSCAPS2_STEREOSURFACELEFT)
469     };
470  
471     DDRAW_dump_flags_(in->dwCaps, flags, sizeof(flags)/sizeof(flags[0]), 0);
472     DDRAW_dump_flags_(in->dwCaps2, flags2, sizeof(flags2)/sizeof(flags2[0]), 0);
473 }
474
475 void DDRAW_dump_DDSCAPS(const DDSCAPS *in) {
476     DDSCAPS2 in_bis;
477
478     in_bis.dwCaps = in->dwCaps;
479     in_bis.dwCaps2 = 0;
480     in_bis.dwCaps3 = 0;
481     in_bis.dwCaps4 = 0;
482
483     DDRAW_dump_DDSCAPS2(&in_bis);
484 }
485
486 void DDRAW_dump_pixelformat_flag(DWORD flagmask)
487 {
488     static const flag_info flags[] =
489         {
490             FE(DDPF_ALPHAPIXELS),
491             FE(DDPF_ALPHA),
492             FE(DDPF_FOURCC),
493             FE(DDPF_PALETTEINDEXED4),
494             FE(DDPF_PALETTEINDEXEDTO8),
495             FE(DDPF_PALETTEINDEXED8),
496             FE(DDPF_RGB),
497             FE(DDPF_COMPRESSED),
498             FE(DDPF_RGBTOYUV),
499             FE(DDPF_YUV),
500             FE(DDPF_ZBUFFER),
501             FE(DDPF_PALETTEINDEXED1),
502             FE(DDPF_PALETTEINDEXED2),
503             FE(DDPF_ZPIXELS)
504     };
505
506     DDRAW_dump_flags_(flagmask, flags, sizeof(flags)/sizeof(flags[0]), 0);
507 }
508
509 void DDRAW_dump_paletteformat(DWORD dwFlags)
510 {
511     static const flag_info flags[] =
512         {
513             FE(DDPCAPS_4BIT),
514             FE(DDPCAPS_8BITENTRIES),
515             FE(DDPCAPS_8BIT),
516             FE(DDPCAPS_INITIALIZE),
517             FE(DDPCAPS_PRIMARYSURFACE),
518             FE(DDPCAPS_PRIMARYSURFACELEFT),
519             FE(DDPCAPS_ALLOW256),
520             FE(DDPCAPS_VSYNC),
521             FE(DDPCAPS_1BIT),
522             FE(DDPCAPS_2BIT),
523             FE(DDPCAPS_ALPHA)
524     };
525
526     DDRAW_dump_flags(dwFlags, flags, sizeof(flags)/sizeof(flags[0]));
527 }
528
529 void DDRAW_dump_pixelformat(const DDPIXELFORMAT *pf) {
530     DPRINTF("( ");
531     DDRAW_dump_pixelformat_flag(pf->dwFlags);
532     if (pf->dwFlags & DDPF_FOURCC) {
533         DPRINTF(", dwFourCC code '%c%c%c%c' (0x%08lx) - %ld bits per pixel",
534                 (unsigned char)( pf->dwFourCC     &0xff),
535                 (unsigned char)((pf->dwFourCC>> 8)&0xff),
536                 (unsigned char)((pf->dwFourCC>>16)&0xff),
537                 (unsigned char)((pf->dwFourCC>>24)&0xff),
538                 pf->dwFourCC,
539                 pf->u1.dwYUVBitCount
540         );
541     }
542     if (pf->dwFlags & DDPF_RGB) {
543         const char *cmd;
544         DPRINTF(", RGB bits: %ld, ", pf->u1.dwRGBBitCount);
545         switch (pf->u1.dwRGBBitCount) {
546         case 4: cmd = "%1lx"; break;
547         case 8: cmd = "%02lx"; break;
548         case 16: cmd = "%04lx"; break;
549         case 24: cmd = "%06lx"; break;
550         case 32: cmd = "%08lx"; break;
551         default: ERR("Unexpected bit depth !\n"); cmd = "%d"; break;
552         }
553         DPRINTF(" R "); DPRINTF(cmd, pf->u2.dwRBitMask);
554         DPRINTF(" G "); DPRINTF(cmd, pf->u3.dwGBitMask);
555         DPRINTF(" B "); DPRINTF(cmd, pf->u4.dwBBitMask);
556         if (pf->dwFlags & DDPF_ALPHAPIXELS) {
557             DPRINTF(" A "); DPRINTF(cmd, pf->u5.dwRGBAlphaBitMask);
558         }
559         if (pf->dwFlags & DDPF_ZPIXELS) {
560             DPRINTF(" Z "); DPRINTF(cmd, pf->u5.dwRGBZBitMask);
561         }
562     }
563     if (pf->dwFlags & DDPF_ZBUFFER) {
564         DPRINTF(", Z bits : %ld", pf->u1.dwZBufferBitDepth);
565     }
566     if (pf->dwFlags & DDPF_ALPHA) {
567         DPRINTF(", Alpha bits : %ld", pf->u1.dwAlphaBitDepth);
568     }
569     DPRINTF(")");
570 }
571
572 void DDRAW_dump_colorkeyflag(DWORD ck)
573 {
574     static const flag_info flags[] =
575         {
576             FE(DDCKEY_COLORSPACE),
577             FE(DDCKEY_DESTBLT),
578             FE(DDCKEY_DESTOVERLAY),
579             FE(DDCKEY_SRCBLT),
580             FE(DDCKEY_SRCOVERLAY)
581     };
582
583     DDRAW_dump_flags(ck, flags, sizeof(flags)/sizeof(flags[0]));
584 }
585
586 void DDRAW_dump_lockflag(DWORD lockflag)
587 {
588     static const flag_info flags[] =
589         {
590             FE(DDLOCK_SURFACEMEMORYPTR),
591             FE(DDLOCK_WAIT),
592             FE(DDLOCK_EVENT),
593             FE(DDLOCK_READONLY),
594             FE(DDLOCK_WRITEONLY),
595             FE(DDLOCK_NOSYSLOCK),
596             FE(DDLOCK_DISCARDCONTENTS),
597             FE(DDLOCK_NOOVERWRITE)
598         };
599
600     DDRAW_dump_flags(lockflag, flags, sizeof(flags)/sizeof(flags[0]));
601 }
602
603 static void DDRAW_dump_DWORD(const void *in) {
604     DPRINTF("%ld", *((const DWORD *) in));
605 }
606 static void DDRAW_dump_PTR(const void *in) {
607     DPRINTF("%p", *((const void * const*) in));
608 }
609 void DDRAW_dump_DDCOLORKEY(const DDCOLORKEY *ddck) {
610     DPRINTF(" Low : %ld  - High : %ld", ddck->dwColorSpaceLowValue, ddck->dwColorSpaceHighValue);
611 }
612
613 void DDRAW_dump_surface_desc(const DDSURFACEDESC2 *lpddsd)
614 {
615 #define STRUCT DDSURFACEDESC2
616     static const member_info members[] =
617         {
618             ME(DDSD_HEIGHT, DDRAW_dump_DWORD, dwHeight),
619             ME(DDSD_WIDTH, DDRAW_dump_DWORD, dwWidth),
620             ME(DDSD_PITCH, DDRAW_dump_DWORD, u1.lPitch),
621             ME(DDSD_LINEARSIZE, DDRAW_dump_DWORD, u1.dwLinearSize),
622             ME(DDSD_BACKBUFFERCOUNT, DDRAW_dump_DWORD, dwBackBufferCount),
623             ME(DDSD_MIPMAPCOUNT, DDRAW_dump_DWORD, u2.dwMipMapCount),
624             ME(DDSD_ZBUFFERBITDEPTH, DDRAW_dump_DWORD, u2.dwMipMapCount), /* This is for 'old-style' D3D */
625             ME(DDSD_REFRESHRATE, DDRAW_dump_DWORD, u2.dwRefreshRate),
626             ME(DDSD_ALPHABITDEPTH, DDRAW_dump_DWORD, dwAlphaBitDepth),
627             ME(DDSD_LPSURFACE, DDRAW_dump_PTR, lpSurface),
628             ME(DDSD_CKDESTOVERLAY, DDRAW_dump_DDCOLORKEY, u3.ddckCKDestOverlay),
629             ME(DDSD_CKDESTBLT, DDRAW_dump_DDCOLORKEY, ddckCKDestBlt),
630             ME(DDSD_CKSRCOVERLAY, DDRAW_dump_DDCOLORKEY, ddckCKSrcOverlay),
631             ME(DDSD_CKSRCBLT, DDRAW_dump_DDCOLORKEY, ddckCKSrcBlt),
632             ME(DDSD_PIXELFORMAT, DDRAW_dump_pixelformat, u4.ddpfPixelFormat)
633         };
634     static const member_info members_caps[] =
635         {
636             ME(DDSD_CAPS, DDRAW_dump_DDSCAPS, ddsCaps)
637         };
638     static const member_info members_caps2[] =
639         {
640             ME(DDSD_CAPS, DDRAW_dump_DDSCAPS2, ddsCaps)
641         };
642 #undef STRUCT
643
644     if (NULL == lpddsd) {
645         DPRINTF("(null)\n");
646     } else {
647       if (lpddsd->dwSize >= sizeof(DDSURFACEDESC2)) {
648           DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members_caps2, 1);
649       } else {
650           DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members_caps, 1);
651       }
652       DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members,
653                          sizeof(members)/sizeof(members[0]));
654     }
655 }
656
657 void DDRAW_dump_cooperativelevel(DWORD cooplevel)
658 {
659     static const flag_info flags[] =
660         {
661             FE(DDSCL_FULLSCREEN),
662             FE(DDSCL_ALLOWREBOOT),
663             FE(DDSCL_NOWINDOWCHANGES),
664             FE(DDSCL_NORMAL),
665             FE(DDSCL_ALLOWMODEX),
666             FE(DDSCL_EXCLUSIVE),
667             FE(DDSCL_SETFOCUSWINDOW),
668             FE(DDSCL_SETDEVICEWINDOW),
669             FE(DDSCL_CREATEDEVICEWINDOW)
670     };
671
672     if (TRACE_ON(ddraw))
673     {
674         DPRINTF(" - ");
675         DDRAW_dump_flags(cooplevel, flags, sizeof(flags)/sizeof(flags[0]));
676     }
677 }
678
679 void DDRAW_dump_DDCAPS(const DDCAPS *lpcaps) {
680     static const flag_info flags1[] = {
681       FE(DDCAPS_3D),
682       FE(DDCAPS_ALIGNBOUNDARYDEST),
683       FE(DDCAPS_ALIGNSIZEDEST),
684       FE(DDCAPS_ALIGNBOUNDARYSRC),
685       FE(DDCAPS_ALIGNSIZESRC),
686       FE(DDCAPS_ALIGNSTRIDE),
687       FE(DDCAPS_BLT),
688       FE(DDCAPS_BLTQUEUE),
689       FE(DDCAPS_BLTFOURCC),
690       FE(DDCAPS_BLTSTRETCH),
691       FE(DDCAPS_GDI),
692       FE(DDCAPS_OVERLAY),
693       FE(DDCAPS_OVERLAYCANTCLIP),
694       FE(DDCAPS_OVERLAYFOURCC),
695       FE(DDCAPS_OVERLAYSTRETCH),
696       FE(DDCAPS_PALETTE),
697       FE(DDCAPS_PALETTEVSYNC),
698       FE(DDCAPS_READSCANLINE),
699       FE(DDCAPS_STEREOVIEW),
700       FE(DDCAPS_VBI),
701       FE(DDCAPS_ZBLTS),
702       FE(DDCAPS_ZOVERLAYS),
703       FE(DDCAPS_COLORKEY),
704       FE(DDCAPS_ALPHA),
705       FE(DDCAPS_COLORKEYHWASSIST),
706       FE(DDCAPS_NOHARDWARE),
707       FE(DDCAPS_BLTCOLORFILL),
708       FE(DDCAPS_BANKSWITCHED),
709       FE(DDCAPS_BLTDEPTHFILL),
710       FE(DDCAPS_CANCLIP),
711       FE(DDCAPS_CANCLIPSTRETCHED),
712       FE(DDCAPS_CANBLTSYSMEM)
713     };
714     static const flag_info flags2[] = {
715       FE(DDCAPS2_CERTIFIED),
716       FE(DDCAPS2_NO2DDURING3DSCENE),
717       FE(DDCAPS2_VIDEOPORT),
718       FE(DDCAPS2_AUTOFLIPOVERLAY),
719       FE(DDCAPS2_CANBOBINTERLEAVED),
720       FE(DDCAPS2_CANBOBNONINTERLEAVED),
721       FE(DDCAPS2_COLORCONTROLOVERLAY),
722       FE(DDCAPS2_COLORCONTROLPRIMARY),
723       FE(DDCAPS2_CANDROPZ16BIT),
724       FE(DDCAPS2_NONLOCALVIDMEM),
725       FE(DDCAPS2_NONLOCALVIDMEMCAPS),
726       FE(DDCAPS2_NOPAGELOCKREQUIRED),
727       FE(DDCAPS2_WIDESURFACES),
728       FE(DDCAPS2_CANFLIPODDEVEN),
729       FE(DDCAPS2_CANBOBHARDWARE),
730       FE(DDCAPS2_COPYFOURCC),
731       FE(DDCAPS2_PRIMARYGAMMA),
732       FE(DDCAPS2_CANRENDERWINDOWED),
733       FE(DDCAPS2_CANCALIBRATEGAMMA),
734       FE(DDCAPS2_FLIPINTERVAL),
735       FE(DDCAPS2_FLIPNOVSYNC),
736       FE(DDCAPS2_CANMANAGETEXTURE),
737       FE(DDCAPS2_TEXMANINNONLOCALVIDMEM),
738       FE(DDCAPS2_STEREO),
739       FE(DDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL)
740     };
741     static const flag_info flags3[] = {
742       FE(DDCKEYCAPS_DESTBLT),
743       FE(DDCKEYCAPS_DESTBLTCLRSPACE),
744       FE(DDCKEYCAPS_DESTBLTCLRSPACEYUV),
745       FE(DDCKEYCAPS_DESTBLTYUV),
746       FE(DDCKEYCAPS_DESTOVERLAY),
747       FE(DDCKEYCAPS_DESTOVERLAYCLRSPACE),
748       FE(DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV),
749       FE(DDCKEYCAPS_DESTOVERLAYONEACTIVE),
750       FE(DDCKEYCAPS_DESTOVERLAYYUV),
751       FE(DDCKEYCAPS_SRCBLT),
752       FE(DDCKEYCAPS_SRCBLTCLRSPACE),
753       FE(DDCKEYCAPS_SRCBLTCLRSPACEYUV),
754       FE(DDCKEYCAPS_SRCBLTYUV),
755       FE(DDCKEYCAPS_SRCOVERLAY),
756       FE(DDCKEYCAPS_SRCOVERLAYCLRSPACE),
757       FE(DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV),
758       FE(DDCKEYCAPS_SRCOVERLAYONEACTIVE),
759       FE(DDCKEYCAPS_SRCOVERLAYYUV),
760       FE(DDCKEYCAPS_NOCOSTOVERLAY)
761     };
762     static const flag_info flags4[] = {
763       FE(DDFXCAPS_BLTALPHA),
764       FE(DDFXCAPS_OVERLAYALPHA),
765       FE(DDFXCAPS_BLTARITHSTRETCHYN),
766       FE(DDFXCAPS_BLTARITHSTRETCHY),
767       FE(DDFXCAPS_BLTMIRRORLEFTRIGHT),
768       FE(DDFXCAPS_BLTMIRRORUPDOWN),
769       FE(DDFXCAPS_BLTROTATION),
770       FE(DDFXCAPS_BLTROTATION90),
771       FE(DDFXCAPS_BLTSHRINKX),
772       FE(DDFXCAPS_BLTSHRINKXN),
773       FE(DDFXCAPS_BLTSHRINKY),
774       FE(DDFXCAPS_BLTSHRINKYN),
775       FE(DDFXCAPS_BLTSTRETCHX),
776       FE(DDFXCAPS_BLTSTRETCHXN),
777       FE(DDFXCAPS_BLTSTRETCHY),
778       FE(DDFXCAPS_BLTSTRETCHYN),
779       FE(DDFXCAPS_OVERLAYARITHSTRETCHY),
780       FE(DDFXCAPS_OVERLAYARITHSTRETCHYN),
781       FE(DDFXCAPS_OVERLAYSHRINKX),
782       FE(DDFXCAPS_OVERLAYSHRINKXN),
783       FE(DDFXCAPS_OVERLAYSHRINKY),
784       FE(DDFXCAPS_OVERLAYSHRINKYN),
785       FE(DDFXCAPS_OVERLAYSTRETCHX),
786       FE(DDFXCAPS_OVERLAYSTRETCHXN),
787       FE(DDFXCAPS_OVERLAYSTRETCHY),
788       FE(DDFXCAPS_OVERLAYSTRETCHYN),
789       FE(DDFXCAPS_OVERLAYMIRRORLEFTRIGHT),
790       FE(DDFXCAPS_OVERLAYMIRRORUPDOWN)
791     };
792     static const flag_info flags5[] = {
793       FE(DDFXALPHACAPS_BLTALPHAEDGEBLEND),
794       FE(DDFXALPHACAPS_BLTALPHAPIXELS),
795       FE(DDFXALPHACAPS_BLTALPHAPIXELSNEG),
796       FE(DDFXALPHACAPS_BLTALPHASURFACES),
797       FE(DDFXALPHACAPS_BLTALPHASURFACESNEG),
798       FE(DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND),
799       FE(DDFXALPHACAPS_OVERLAYALPHAPIXELS),
800       FE(DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG),
801       FE(DDFXALPHACAPS_OVERLAYALPHASURFACES),
802       FE(DDFXALPHACAPS_OVERLAYALPHASURFACESNEG)
803     };
804     static const flag_info flags6[] = {
805       FE(DDPCAPS_4BIT),
806       FE(DDPCAPS_8BITENTRIES),
807       FE(DDPCAPS_8BIT),
808       FE(DDPCAPS_INITIALIZE),
809       FE(DDPCAPS_PRIMARYSURFACE),
810       FE(DDPCAPS_PRIMARYSURFACELEFT),
811       FE(DDPCAPS_ALLOW256),
812       FE(DDPCAPS_VSYNC),
813       FE(DDPCAPS_1BIT),
814       FE(DDPCAPS_2BIT),
815       FE(DDPCAPS_ALPHA),
816     };
817     static const flag_info flags7[] = {
818       FE(DDSVCAPS_RESERVED1),
819       FE(DDSVCAPS_RESERVED2),
820       FE(DDSVCAPS_RESERVED3),
821       FE(DDSVCAPS_RESERVED4),
822       FE(DDSVCAPS_STEREOSEQUENTIAL),
823     };
824
825     DPRINTF(" - dwSize : %ld\n", lpcaps->dwSize);
826     DPRINTF(" - dwCaps : "); DDRAW_dump_flags(lpcaps->dwCaps, flags1, sizeof(flags1)/sizeof(flags1[0]));
827     DPRINTF(" - dwCaps2 : "); DDRAW_dump_flags(lpcaps->dwCaps2, flags2, sizeof(flags2)/sizeof(flags2[0]));
828     DPRINTF(" - dwCKeyCaps : "); DDRAW_dump_flags(lpcaps->dwCKeyCaps, flags3, sizeof(flags3)/sizeof(flags3[0]));
829     DPRINTF(" - dwFXCaps : "); DDRAW_dump_flags(lpcaps->dwFXCaps, flags4, sizeof(flags4)/sizeof(flags4[0]));
830     DPRINTF(" - dwFXAlphaCaps : "); DDRAW_dump_flags(lpcaps->dwFXAlphaCaps, flags5, sizeof(flags5)/sizeof(flags5[0]));
831     DPRINTF(" - dwPalCaps : "); DDRAW_dump_flags(lpcaps->dwPalCaps, flags6, sizeof(flags6)/sizeof(flags6[0]));
832     DPRINTF(" - dwSVCaps : "); DDRAW_dump_flags(lpcaps->dwSVCaps, flags7, sizeof(flags7)/sizeof(flags7[0]));
833     DPRINTF("...\n");
834     DPRINTF(" - dwNumFourCCCodes : %ld\n", lpcaps->dwNumFourCCCodes);
835     DPRINTF(" - dwCurrVisibleOverlays : %ld\n", lpcaps->dwCurrVisibleOverlays);
836     DPRINTF(" - dwMinOverlayStretch : %ld\n", lpcaps->dwMinOverlayStretch);
837     DPRINTF(" - dwMaxOverlayStretch : %ld\n", lpcaps->dwMaxOverlayStretch);
838     DPRINTF("...\n");
839     DPRINTF(" - ddsCaps : "); DDRAW_dump_DDSCAPS2(&lpcaps->ddsCaps); DPRINTF("\n");
840 }
841
842 void DDRAW_dump_DDENUMSURFACES(DWORD flagmask)
843 {
844     static const flag_info flags[] =
845         {
846             FE(DDENUMSURFACES_ALL),
847             FE(DDENUMSURFACES_MATCH),
848             FE(DDENUMSURFACES_NOMATCH),
849             FE(DDENUMSURFACES_CANBECREATED),
850             FE(DDENUMSURFACES_DOESEXIST)
851         };
852     DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
853 }
854
855 /* Debug function that can be helpful to debug various surface-related problems */
856 static int get_shift(DWORD color_mask) {
857     int shift = 0;
858     while (color_mask > 0xFF) {
859         color_mask >>= 1;
860         shift += 1;
861     }
862     while ((color_mask & 0x80) == 0) {
863         color_mask <<= 1;
864         shift -= 1;
865     }
866     return shift;
867 }
868
869 void DDRAW_dump_surface_to_disk(IDirectDrawSurfaceImpl *surface, FILE *f, int scale)
870 {
871     int rwidth, rheight, x, y;
872     static char *output = NULL;
873     static int size = 0;
874
875     rwidth  = (surface->surface_desc.dwWidth  + scale - 1) / scale;
876     rheight = (surface->surface_desc.dwHeight + scale - 1) / scale;
877
878     if (rwidth > size) {
879         output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, rwidth * 3);
880         size = rwidth;
881     }
882     
883     fprintf(f, "P6\n%d %d\n255\n", rwidth, rheight);
884
885     if (surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
886         unsigned char table[256][3];
887         int i;
888         
889         if (surface->palette == NULL) {
890             fclose(f);
891             return;
892         }
893         for (i = 0; i < 256; i++) {
894             table[i][0] = surface->palette->palents[i].peRed;
895             table[i][1] = surface->palette->palents[i].peGreen;
896             table[i][2] = surface->palette->palents[i].peBlue;
897         }
898         for (y = 0; y < rheight; y++) {
899             unsigned char *src = (unsigned char *) surface->surface_desc.lpSurface + (y * scale * surface->surface_desc.u1.lPitch);
900             for (x = 0; x < rwidth; x++) {
901                 unsigned char color = *src;
902                 src += scale;
903
904                 output[3 * x + 0] = table[color][0];
905                 output[3 * x + 1] = table[color][1];
906                 output[3 * x + 2] = table[color][2];
907             }
908             fwrite(output, 3 * rwidth, 1, f);
909         }
910     } else if (surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) {
911         int red_shift, green_shift, blue_shift, pix_width;
912         
913         if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 8) {
914             pix_width = 1;
915         } else if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
916             pix_width = 2;
917         } else if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) {
918             pix_width = 4;
919         } else {
920             pix_width = 3;
921         }
922         
923         red_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask);
924         green_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask);
925         blue_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask);
926
927         for (y = 0; y < rheight; y++) {
928             unsigned char *src = (unsigned char *) surface->surface_desc.lpSurface + (y * scale * surface->surface_desc.u1.lPitch);
929             for (x = 0; x < rwidth; x++) {          
930                 unsigned int color;
931                 unsigned int comp;
932                 int i;
933
934                 color = 0;
935                 for (i = 0; i < pix_width; i++) {
936                     color |= src[i] << (8 * i);
937                 }
938                 src += scale * pix_width;
939                 
940                 comp = color & surface->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask;
941                 output[3 * x + 0] = red_shift > 0 ? comp >> red_shift : comp << -red_shift;
942                 comp = color & surface->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask;
943                 output[3 * x + 1] = green_shift > 0 ? comp >> green_shift : comp << -green_shift;
944                 comp = color & surface->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask;
945                 output[3 * x + 2] = blue_shift > 0 ? comp >> blue_shift : comp << -blue_shift;
946             }
947             fwrite(output, 3 * rwidth, 1, f);
948         }
949     }
950     fclose(f);
951 }