Moved the implementation of a couple of system.drv entry points to
[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     };
410
411     DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0]));
412 }
413
414 void DDRAW_dump_DDSCAPS2(const DDSCAPS2 *in)
415 {
416     static const flag_info flags[] = {
417         FE(DDSCAPS_RESERVED1),
418         FE(DDSCAPS_ALPHA),
419         FE(DDSCAPS_BACKBUFFER),
420         FE(DDSCAPS_COMPLEX),
421         FE(DDSCAPS_FLIP),
422         FE(DDSCAPS_FRONTBUFFER),
423         FE(DDSCAPS_OFFSCREENPLAIN),
424         FE(DDSCAPS_OVERLAY),
425         FE(DDSCAPS_PALETTE),
426         FE(DDSCAPS_PRIMARYSURFACE),
427         FE(DDSCAPS_PRIMARYSURFACELEFT),
428         FE(DDSCAPS_SYSTEMMEMORY),
429         FE(DDSCAPS_TEXTURE),
430         FE(DDSCAPS_3DDEVICE),
431         FE(DDSCAPS_VIDEOMEMORY),
432         FE(DDSCAPS_VISIBLE),
433         FE(DDSCAPS_WRITEONLY),
434         FE(DDSCAPS_ZBUFFER),
435         FE(DDSCAPS_OWNDC),
436         FE(DDSCAPS_LIVEVIDEO),
437         FE(DDSCAPS_HWCODEC),
438         FE(DDSCAPS_MODEX),
439         FE(DDSCAPS_MIPMAP),
440         FE(DDSCAPS_RESERVED2),
441         FE(DDSCAPS_ALLOCONLOAD),
442         FE(DDSCAPS_VIDEOPORT),
443         FE(DDSCAPS_LOCALVIDMEM),
444         FE(DDSCAPS_NONLOCALVIDMEM),
445         FE(DDSCAPS_STANDARDVGAMODE),
446         FE(DDSCAPS_OPTIMIZED)
447     };
448     static const flag_info flags2[] = {
449         FE(DDSCAPS2_HARDWAREDEINTERLACE),
450         FE(DDSCAPS2_HINTDYNAMIC),
451         FE(DDSCAPS2_HINTSTATIC),
452         FE(DDSCAPS2_TEXTUREMANAGE),
453         FE(DDSCAPS2_RESERVED1),
454         FE(DDSCAPS2_RESERVED2),
455         FE(DDSCAPS2_OPAQUE),
456         FE(DDSCAPS2_HINTANTIALIASING),
457         FE(DDSCAPS2_CUBEMAP),
458         FE(DDSCAPS2_CUBEMAP_POSITIVEX),
459         FE(DDSCAPS2_CUBEMAP_NEGATIVEX),
460         FE(DDSCAPS2_CUBEMAP_POSITIVEY),
461         FE(DDSCAPS2_CUBEMAP_NEGATIVEY),
462         FE(DDSCAPS2_CUBEMAP_POSITIVEZ),
463         FE(DDSCAPS2_CUBEMAP_NEGATIVEZ),
464         FE(DDSCAPS2_MIPMAPSUBLEVEL),
465         FE(DDSCAPS2_D3DTEXTUREMANAGE),
466         FE(DDSCAPS2_DONOTPERSIST),
467         FE(DDSCAPS2_STEREOSURFACELEFT)
468     };
469  
470     DDRAW_dump_flags_(in->dwCaps, flags, sizeof(flags)/sizeof(flags[0]), 0);
471     DDRAW_dump_flags_(in->dwCaps2, flags2, sizeof(flags2)/sizeof(flags2[0]), 0);
472 }
473
474 void DDRAW_dump_DDSCAPS(const DDSCAPS *in) {
475     DDSCAPS2 in_bis;
476
477     in_bis.dwCaps = in->dwCaps;
478     in_bis.dwCaps2 = 0;
479     in_bis.dwCaps3 = 0;
480     in_bis.dwCaps4 = 0;
481
482     DDRAW_dump_DDSCAPS2(&in_bis);
483 }
484
485 void DDRAW_dump_pixelformat_flag(DWORD flagmask)
486 {
487     static const flag_info flags[] =
488         {
489             FE(DDPF_ALPHAPIXELS),
490             FE(DDPF_ALPHA),
491             FE(DDPF_FOURCC),
492             FE(DDPF_PALETTEINDEXED4),
493             FE(DDPF_PALETTEINDEXEDTO8),
494             FE(DDPF_PALETTEINDEXED8),
495             FE(DDPF_RGB),
496             FE(DDPF_COMPRESSED),
497             FE(DDPF_RGBTOYUV),
498             FE(DDPF_YUV),
499             FE(DDPF_ZBUFFER),
500             FE(DDPF_PALETTEINDEXED1),
501             FE(DDPF_PALETTEINDEXED2),
502             FE(DDPF_ZPIXELS)
503     };
504
505     DDRAW_dump_flags_(flagmask, flags, sizeof(flags)/sizeof(flags[0]), 0);
506 }
507
508 void DDRAW_dump_paletteformat(DWORD dwFlags)
509 {
510     static const flag_info flags[] =
511         {
512             FE(DDPCAPS_4BIT),
513             FE(DDPCAPS_8BITENTRIES),
514             FE(DDPCAPS_8BIT),
515             FE(DDPCAPS_INITIALIZE),
516             FE(DDPCAPS_PRIMARYSURFACE),
517             FE(DDPCAPS_PRIMARYSURFACELEFT),
518             FE(DDPCAPS_ALLOW256),
519             FE(DDPCAPS_VSYNC),
520             FE(DDPCAPS_1BIT),
521             FE(DDPCAPS_2BIT),
522             FE(DDPCAPS_ALPHA)
523     };
524
525     DDRAW_dump_flags(dwFlags, flags, sizeof(flags)/sizeof(flags[0]));
526 }
527
528 void DDRAW_dump_pixelformat(const DDPIXELFORMAT *pf) {
529     DPRINTF("( ");
530     DDRAW_dump_pixelformat_flag(pf->dwFlags);
531     if (pf->dwFlags & DDPF_FOURCC) {
532         DPRINTF(", dwFourCC code '%c%c%c%c' (0x%08lx) - %ld bits per pixel",
533                 (unsigned char)( pf->dwFourCC     &0xff),
534                 (unsigned char)((pf->dwFourCC>> 8)&0xff),
535                 (unsigned char)((pf->dwFourCC>>16)&0xff),
536                 (unsigned char)((pf->dwFourCC>>24)&0xff),
537                 pf->dwFourCC,
538                 pf->u1.dwYUVBitCount
539         );
540     }
541     if (pf->dwFlags & DDPF_RGB) {
542         const char *cmd;
543         DPRINTF(", RGB bits: %ld, ", pf->u1.dwRGBBitCount);
544         switch (pf->u1.dwRGBBitCount) {
545         case 4: cmd = "%1lx"; break;
546         case 8: cmd = "%02lx"; break;
547         case 16: cmd = "%04lx"; break;
548         case 24: cmd = "%06lx"; break;
549         case 32: cmd = "%08lx"; break;
550         default: ERR("Unexpected bit depth !\n"); cmd = "%d"; break;
551         }
552         DPRINTF(" R "); DPRINTF(cmd, pf->u2.dwRBitMask);
553         DPRINTF(" G "); DPRINTF(cmd, pf->u3.dwGBitMask);
554         DPRINTF(" B "); DPRINTF(cmd, pf->u4.dwBBitMask);
555         if (pf->dwFlags & DDPF_ALPHAPIXELS) {
556             DPRINTF(" A "); DPRINTF(cmd, pf->u5.dwRGBAlphaBitMask);
557         }
558         if (pf->dwFlags & DDPF_ZPIXELS) {
559             DPRINTF(" Z "); DPRINTF(cmd, pf->u5.dwRGBZBitMask);
560         }
561     }
562     if (pf->dwFlags & DDPF_ZBUFFER) {
563         DPRINTF(", Z bits : %ld", pf->u1.dwZBufferBitDepth);
564     }
565     if (pf->dwFlags & DDPF_ALPHA) {
566         DPRINTF(", Alpha bits : %ld", pf->u1.dwAlphaBitDepth);
567     }
568     DPRINTF(")");
569 }
570
571 void DDRAW_dump_colorkeyflag(DWORD ck)
572 {
573     static const flag_info flags[] =
574         {
575             FE(DDCKEY_COLORSPACE),
576             FE(DDCKEY_DESTBLT),
577             FE(DDCKEY_DESTOVERLAY),
578             FE(DDCKEY_SRCBLT),
579             FE(DDCKEY_SRCOVERLAY)
580     };
581
582     DDRAW_dump_flags(ck, flags, sizeof(flags)/sizeof(flags[0]));
583 }
584
585 void DDRAW_dump_lockflag(DWORD lockflag)
586 {
587     static const flag_info flags[] =
588         {
589             FE(DDLOCK_SURFACEMEMORYPTR),
590             FE(DDLOCK_WAIT),
591             FE(DDLOCK_EVENT),
592             FE(DDLOCK_READONLY),
593             FE(DDLOCK_WRITEONLY),
594             FE(DDLOCK_NOSYSLOCK),
595             FE(DDLOCK_DISCARDCONTENTS),
596             FE(DDLOCK_NOOVERWRITE)
597         };
598
599     DDRAW_dump_flags(lockflag, flags, sizeof(flags)/sizeof(flags[0]));
600 }
601
602 static void DDRAW_dump_DWORD(const void *in) {
603     DPRINTF("%ld", *((const DWORD *) in));
604 }
605 static void DDRAW_dump_PTR(const void *in) {
606     DPRINTF("%p", *((const void * const*) in));
607 }
608 void DDRAW_dump_DDCOLORKEY(const DDCOLORKEY *ddck) {
609     DPRINTF(" Low : %ld  - High : %ld", ddck->dwColorSpaceLowValue, ddck->dwColorSpaceHighValue);
610 }
611
612 void DDRAW_dump_surface_desc(const DDSURFACEDESC2 *lpddsd)
613 {
614 #define STRUCT DDSURFACEDESC2
615     static const member_info members[] =
616         {
617             ME(DDSD_HEIGHT, DDRAW_dump_DWORD, dwHeight),
618             ME(DDSD_WIDTH, DDRAW_dump_DWORD, dwWidth),
619             ME(DDSD_PITCH, DDRAW_dump_DWORD, u1.lPitch),
620             ME(DDSD_LINEARSIZE, DDRAW_dump_DWORD, u1.dwLinearSize),
621             ME(DDSD_BACKBUFFERCOUNT, DDRAW_dump_DWORD, dwBackBufferCount),
622             ME(DDSD_MIPMAPCOUNT, DDRAW_dump_DWORD, u2.dwMipMapCount),
623             ME(DDSD_ZBUFFERBITDEPTH, DDRAW_dump_DWORD, u2.dwMipMapCount), /* This is for 'old-style' D3D */
624             ME(DDSD_REFRESHRATE, DDRAW_dump_DWORD, u2.dwRefreshRate),
625             ME(DDSD_ALPHABITDEPTH, DDRAW_dump_DWORD, dwAlphaBitDepth),
626             ME(DDSD_LPSURFACE, DDRAW_dump_PTR, lpSurface),
627             ME(DDSD_CKDESTOVERLAY, DDRAW_dump_DDCOLORKEY, u3.ddckCKDestOverlay),
628             ME(DDSD_CKDESTBLT, DDRAW_dump_DDCOLORKEY, ddckCKDestBlt),
629             ME(DDSD_CKSRCOVERLAY, DDRAW_dump_DDCOLORKEY, ddckCKSrcOverlay),
630             ME(DDSD_CKSRCBLT, DDRAW_dump_DDCOLORKEY, ddckCKSrcBlt),
631             ME(DDSD_PIXELFORMAT, DDRAW_dump_pixelformat, u4.ddpfPixelFormat)
632         };
633     static const member_info members_caps[] =
634         {
635             ME(DDSD_CAPS, DDRAW_dump_DDSCAPS, ddsCaps)
636         };
637     static const member_info members_caps2[] =
638         {
639             ME(DDSD_CAPS, DDRAW_dump_DDSCAPS2, ddsCaps)
640         };
641 #undef STRUCT
642
643     if (lpddsd->dwSize >= sizeof(DDSURFACEDESC2)) {
644         DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members_caps2, 1);
645     } else {
646         DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members_caps, 1);
647     }
648                                                   
649     DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members,
650                        sizeof(members)/sizeof(members[0]));
651 }
652
653 void DDRAW_dump_cooperativelevel(DWORD cooplevel)
654 {
655     static const flag_info flags[] =
656         {
657             FE(DDSCL_FULLSCREEN),
658             FE(DDSCL_ALLOWREBOOT),
659             FE(DDSCL_NOWINDOWCHANGES),
660             FE(DDSCL_NORMAL),
661             FE(DDSCL_ALLOWMODEX),
662             FE(DDSCL_EXCLUSIVE),
663             FE(DDSCL_SETFOCUSWINDOW),
664             FE(DDSCL_SETDEVICEWINDOW),
665             FE(DDSCL_CREATEDEVICEWINDOW)
666     };
667
668     if (TRACE_ON(ddraw))
669     {
670         DPRINTF(" - ");
671         DDRAW_dump_flags(cooplevel, flags, sizeof(flags)/sizeof(flags[0]));
672     }
673 }
674
675 void DDRAW_dump_DDCAPS(const DDCAPS *lpcaps) {
676     static const flag_info flags1[] = {
677       FE(DDCAPS_3D),
678       FE(DDCAPS_ALIGNBOUNDARYDEST),
679       FE(DDCAPS_ALIGNSIZEDEST),
680       FE(DDCAPS_ALIGNBOUNDARYSRC),
681       FE(DDCAPS_ALIGNSIZESRC),
682       FE(DDCAPS_ALIGNSTRIDE),
683       FE(DDCAPS_BLT),
684       FE(DDCAPS_BLTQUEUE),
685       FE(DDCAPS_BLTFOURCC),
686       FE(DDCAPS_BLTSTRETCH),
687       FE(DDCAPS_GDI),
688       FE(DDCAPS_OVERLAY),
689       FE(DDCAPS_OVERLAYCANTCLIP),
690       FE(DDCAPS_OVERLAYFOURCC),
691       FE(DDCAPS_OVERLAYSTRETCH),
692       FE(DDCAPS_PALETTE),
693       FE(DDCAPS_PALETTEVSYNC),
694       FE(DDCAPS_READSCANLINE),
695       FE(DDCAPS_STEREOVIEW),
696       FE(DDCAPS_VBI),
697       FE(DDCAPS_ZBLTS),
698       FE(DDCAPS_ZOVERLAYS),
699       FE(DDCAPS_COLORKEY),
700       FE(DDCAPS_ALPHA),
701       FE(DDCAPS_COLORKEYHWASSIST),
702       FE(DDCAPS_NOHARDWARE),
703       FE(DDCAPS_BLTCOLORFILL),
704       FE(DDCAPS_BANKSWITCHED),
705       FE(DDCAPS_BLTDEPTHFILL),
706       FE(DDCAPS_CANCLIP),
707       FE(DDCAPS_CANCLIPSTRETCHED),
708       FE(DDCAPS_CANBLTSYSMEM)
709     };
710     static const flag_info flags2[] = {
711       FE(DDCAPS2_CERTIFIED),
712       FE(DDCAPS2_NO2DDURING3DSCENE),
713       FE(DDCAPS2_VIDEOPORT),
714       FE(DDCAPS2_AUTOFLIPOVERLAY),
715       FE(DDCAPS2_CANBOBINTERLEAVED),
716       FE(DDCAPS2_CANBOBNONINTERLEAVED),
717       FE(DDCAPS2_COLORCONTROLOVERLAY),
718       FE(DDCAPS2_COLORCONTROLPRIMARY),
719       FE(DDCAPS2_CANDROPZ16BIT),
720       FE(DDCAPS2_NONLOCALVIDMEM),
721       FE(DDCAPS2_NONLOCALVIDMEMCAPS),
722       FE(DDCAPS2_NOPAGELOCKREQUIRED),
723       FE(DDCAPS2_WIDESURFACES),
724       FE(DDCAPS2_CANFLIPODDEVEN),
725       FE(DDCAPS2_CANBOBHARDWARE),
726       FE(DDCAPS2_COPYFOURCC),
727       FE(DDCAPS2_PRIMARYGAMMA),
728       FE(DDCAPS2_CANRENDERWINDOWED),
729       FE(DDCAPS2_CANCALIBRATEGAMMA),
730       FE(DDCAPS2_FLIPINTERVAL),
731       FE(DDCAPS2_FLIPNOVSYNC),
732       FE(DDCAPS2_CANMANAGETEXTURE),
733       FE(DDCAPS2_TEXMANINNONLOCALVIDMEM),
734       FE(DDCAPS2_STEREO),
735       FE(DDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL)
736     };
737     static const flag_info flags3[] = {
738       FE(DDCKEYCAPS_DESTBLT),
739       FE(DDCKEYCAPS_DESTBLTCLRSPACE),
740       FE(DDCKEYCAPS_DESTBLTCLRSPACEYUV),
741       FE(DDCKEYCAPS_DESTBLTYUV),
742       FE(DDCKEYCAPS_DESTOVERLAY),
743       FE(DDCKEYCAPS_DESTOVERLAYCLRSPACE),
744       FE(DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV),
745       FE(DDCKEYCAPS_DESTOVERLAYONEACTIVE),
746       FE(DDCKEYCAPS_DESTOVERLAYYUV),
747       FE(DDCKEYCAPS_SRCBLT),
748       FE(DDCKEYCAPS_SRCBLTCLRSPACE),
749       FE(DDCKEYCAPS_SRCBLTCLRSPACEYUV),
750       FE(DDCKEYCAPS_SRCBLTYUV),
751       FE(DDCKEYCAPS_SRCOVERLAY),
752       FE(DDCKEYCAPS_SRCOVERLAYCLRSPACE),
753       FE(DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV),
754       FE(DDCKEYCAPS_SRCOVERLAYONEACTIVE),
755       FE(DDCKEYCAPS_SRCOVERLAYYUV),
756       FE(DDCKEYCAPS_NOCOSTOVERLAY)
757     };
758     static const flag_info flags4[] = {
759       FE(DDFXCAPS_BLTALPHA),
760       FE(DDFXCAPS_OVERLAYALPHA),
761       FE(DDFXCAPS_BLTARITHSTRETCHYN),
762       FE(DDFXCAPS_BLTARITHSTRETCHY),
763       FE(DDFXCAPS_BLTMIRRORLEFTRIGHT),
764       FE(DDFXCAPS_BLTMIRRORUPDOWN),
765       FE(DDFXCAPS_BLTROTATION),
766       FE(DDFXCAPS_BLTROTATION90),
767       FE(DDFXCAPS_BLTSHRINKX),
768       FE(DDFXCAPS_BLTSHRINKXN),
769       FE(DDFXCAPS_BLTSHRINKY),
770       FE(DDFXCAPS_BLTSHRINKYN),
771       FE(DDFXCAPS_BLTSTRETCHX),
772       FE(DDFXCAPS_BLTSTRETCHXN),
773       FE(DDFXCAPS_BLTSTRETCHY),
774       FE(DDFXCAPS_BLTSTRETCHYN),
775       FE(DDFXCAPS_OVERLAYARITHSTRETCHY),
776       FE(DDFXCAPS_OVERLAYARITHSTRETCHYN),
777       FE(DDFXCAPS_OVERLAYSHRINKX),
778       FE(DDFXCAPS_OVERLAYSHRINKXN),
779       FE(DDFXCAPS_OVERLAYSHRINKY),
780       FE(DDFXCAPS_OVERLAYSHRINKYN),
781       FE(DDFXCAPS_OVERLAYSTRETCHX),
782       FE(DDFXCAPS_OVERLAYSTRETCHXN),
783       FE(DDFXCAPS_OVERLAYSTRETCHY),
784       FE(DDFXCAPS_OVERLAYSTRETCHYN),
785       FE(DDFXCAPS_OVERLAYMIRRORLEFTRIGHT),
786       FE(DDFXCAPS_OVERLAYMIRRORUPDOWN)
787     };
788     static const flag_info flags5[] = {
789       FE(DDFXALPHACAPS_BLTALPHAEDGEBLEND),
790       FE(DDFXALPHACAPS_BLTALPHAPIXELS),
791       FE(DDFXALPHACAPS_BLTALPHAPIXELSNEG),
792       FE(DDFXALPHACAPS_BLTALPHASURFACES),
793       FE(DDFXALPHACAPS_BLTALPHASURFACESNEG),
794       FE(DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND),
795       FE(DDFXALPHACAPS_OVERLAYALPHAPIXELS),
796       FE(DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG),
797       FE(DDFXALPHACAPS_OVERLAYALPHASURFACES),
798       FE(DDFXALPHACAPS_OVERLAYALPHASURFACESNEG)
799     };
800     static const flag_info flags6[] = {
801       FE(DDPCAPS_4BIT),
802       FE(DDPCAPS_8BITENTRIES),
803       FE(DDPCAPS_8BIT),
804       FE(DDPCAPS_INITIALIZE),
805       FE(DDPCAPS_PRIMARYSURFACE),
806       FE(DDPCAPS_PRIMARYSURFACELEFT),
807       FE(DDPCAPS_ALLOW256),
808       FE(DDPCAPS_VSYNC),
809       FE(DDPCAPS_1BIT),
810       FE(DDPCAPS_2BIT),
811       FE(DDPCAPS_ALPHA),
812     };
813     static const flag_info flags7[] = {
814       FE(DDSVCAPS_RESERVED1),
815       FE(DDSVCAPS_RESERVED2),
816       FE(DDSVCAPS_RESERVED3),
817       FE(DDSVCAPS_RESERVED4),
818       FE(DDSVCAPS_STEREOSEQUENTIAL),
819     };
820
821     DPRINTF(" - dwSize : %ld\n", lpcaps->dwSize);
822     DPRINTF(" - dwCaps : "); DDRAW_dump_flags(lpcaps->dwCaps, flags1, sizeof(flags1)/sizeof(flags1[0]));
823     DPRINTF(" - dwCaps2 : "); DDRAW_dump_flags(lpcaps->dwCaps2, flags2, sizeof(flags2)/sizeof(flags2[0]));
824     DPRINTF(" - dwCKeyCaps : "); DDRAW_dump_flags(lpcaps->dwCKeyCaps, flags3, sizeof(flags3)/sizeof(flags3[0]));
825     DPRINTF(" - dwFXCaps : "); DDRAW_dump_flags(lpcaps->dwFXCaps, flags4, sizeof(flags4)/sizeof(flags4[0]));
826     DPRINTF(" - dwFXAlphaCaps : "); DDRAW_dump_flags(lpcaps->dwFXAlphaCaps, flags5, sizeof(flags5)/sizeof(flags5[0]));
827     DPRINTF(" - dwPalCaps : "); DDRAW_dump_flags(lpcaps->dwPalCaps, flags6, sizeof(flags6)/sizeof(flags6[0]));
828     DPRINTF(" - dwSVCaps : "); DDRAW_dump_flags(lpcaps->dwSVCaps, flags7, sizeof(flags7)/sizeof(flags7[0]));
829     DPRINTF("...\n");
830     DPRINTF(" - dwNumFourCCCodes : %ld\n", lpcaps->dwNumFourCCCodes);
831     DPRINTF(" - dwCurrVisibleOverlays : %ld\n", lpcaps->dwCurrVisibleOverlays);
832     DPRINTF(" - dwMinOverlayStretch : %ld\n", lpcaps->dwMinOverlayStretch);
833     DPRINTF(" - dwMaxOverlayStretch : %ld\n", lpcaps->dwMaxOverlayStretch);
834     DPRINTF("...\n");
835     DPRINTF(" - ddsCaps : "); DDRAW_dump_DDSCAPS2(&lpcaps->ddsCaps); DPRINTF("\n");
836 }
837
838 /* Debug function that can be helpful to debug various surface-related problems */
839 static int get_shift(DWORD color_mask) {
840     int shift = 0;
841     while (color_mask > 0xFF) {
842         color_mask >>= 1;
843         shift += 1;
844     }
845     while ((color_mask & 0x80) == 0) {
846         color_mask <<= 1;
847         shift -= 1;
848     }
849     return shift;
850 }
851
852 void DDRAW_dump_surface_to_disk(IDirectDrawSurfaceImpl *surface, FILE *f, int scale)
853 {
854     int rwidth, rheight, x, y;
855     static char *output = NULL;
856     static int size = 0;
857
858     rwidth  = (surface->surface_desc.dwWidth  + scale - 1) / scale;
859     rheight = (surface->surface_desc.dwHeight + scale - 1) / scale;
860
861     if (rwidth > size) {
862         output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, rwidth * 3);
863         size = rwidth;
864     }
865     
866     fprintf(f, "P6\n%d %d\n255\n", rwidth, rheight);
867
868     if (surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
869         unsigned char table[256][3];
870         int i;
871         
872         if (surface->palette == NULL) {
873             fclose(f);
874             return;
875         }
876         for (i = 0; i < 256; i++) {
877             table[i][0] = surface->palette->palents[i].peRed;
878             table[i][1] = surface->palette->palents[i].peGreen;
879             table[i][2] = surface->palette->palents[i].peBlue;
880         }
881         for (y = 0; y < rheight; y++) {
882             unsigned char *src = (unsigned char *) surface->surface_desc.lpSurface + (y * scale * surface->surface_desc.u1.lPitch);
883             for (x = 0; x < rwidth; x++) {
884                 unsigned char color = *src;
885                 src += scale;
886
887                 output[3 * x + 0] = table[color][0];
888                 output[3 * x + 1] = table[color][1];
889                 output[3 * x + 2] = table[color][2];
890             }
891             fwrite(output, 3 * rwidth, 1, f);
892         }
893     } else if (surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) {
894         int red_shift, green_shift, blue_shift, pix_width;
895         
896         if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 8) {
897             pix_width = 1;
898         } else if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
899             pix_width = 2;
900         } else if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) {
901             pix_width = 4;
902         } else {
903             pix_width = 3;
904         }
905         
906         red_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask);
907         green_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask);
908         blue_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask);
909
910         for (y = 0; y < rheight; y++) {
911             unsigned char *src = (unsigned char *) surface->surface_desc.lpSurface + (y * scale * surface->surface_desc.u1.lPitch);
912             for (x = 0; x < rwidth; x++) {          
913                 unsigned int color;
914                 unsigned int comp;
915                 int i;
916
917                 color = 0;
918                 for (i = 0; i < pix_width; i++) {
919                     color |= src[i] << (8 * i);
920                 }
921                 src += scale * pix_width;
922                 
923                 comp = color & surface->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask;
924                 output[3 * x + 0] = red_shift > 0 ? comp >> red_shift : comp << -red_shift;
925                 comp = color & surface->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask;
926                 output[3 * x + 1] = green_shift > 0 ? comp >> green_shift : comp << -green_shift;
927                 comp = color & surface->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask;
928                 output[3 * x + 2] = blue_shift > 0 ? comp >> blue_shift : comp << -blue_shift;
929             }
930             fwrite(output, 3 * rwidth, 1, f);
931         }
932     }
933     fclose(f);
934 }