| /* |
| * DirectDraw helper functions |
| * |
| * Copyright 1997-2000 Marcus Meissner |
| * Copyright 1998 Lionel Ulmer (most of Direct3D stuff) |
| * Copyright 2000 TransGaming Technologies Inc. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #define NONAMELESSUNION |
| #define NONAMELESSSTRUCT |
| |
| #include "wine/debug.h" |
| |
| #include <stddef.h> |
| #include <stdarg.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "wingdi.h" |
| #include "ddraw.h" |
| |
| #include "ddraw_private.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(ddraw); |
| |
| /* ************************************* |
| 16 / 15 bpp to palettized 8 bpp |
| ************************************* */ |
| static void pixel_convert_16_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, IDirectDrawPaletteImpl* palette) { |
| unsigned char *c_src = (unsigned char *) src; |
| unsigned short *c_dst = (unsigned short *) dst; |
| int y; |
| |
| if (palette != NULL) { |
| const unsigned int * pal = (unsigned int *) palette->screen_palents; |
| |
| for (y = height; y--; ) { |
| #if defined(__i386__) && defined(__GNUC__) |
| /* gcc generates slightly inefficient code for the the copy/lookup, |
| * it generates one excess memory access (to pal) per pixel. Since |
| * we know that pal is not modified by the memory write we can |
| * put it into a register and reduce the number of memory accesses |
| * from 4 to 3 pp. There are two xor eax,eax to avoid pipeline |
| * stalls. (This is not guaranteed to be the fastest method.) |
| */ |
| __asm__ __volatile__( |
| "xor %%eax,%%eax\n" |
| "1:\n" |
| " lodsb\n" |
| " movw (%%edx,%%eax,4),%%ax\n" |
| " stosw\n" |
| " xor %%eax,%%eax\n" |
| " loop 1b\n" |
| : "=S" (c_src), "=D" (c_dst) |
| : "S" (c_src), "D" (c_dst) , "c" (width), "d" (pal) |
| : "eax", "cc", "memory" |
| ); |
| c_src+=(pitch-width); |
| #else |
| unsigned char * srclineend = c_src+width; |
| while (c_src < srclineend) |
| *c_dst++ = pal[*c_src++]; |
| c_src+=(pitch-width); |
| #endif |
| } |
| } else { |
| FIXME("No palette set...\n"); |
| memset(dst, 0, width * height * 2); |
| } |
| } |
| static void palette_convert_16_to_8( |
| LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count |
| ) { |
| unsigned int i; |
| unsigned int *pal = (unsigned int *) screen_palette; |
| |
| for (i = 0; i < count; i++) |
| pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 8) | |
| ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) | |
| ((((unsigned short) palent[i].peGreen) & 0xFC) << 3)); |
| } |
| |
| static void palette_convert_15_to_8( |
| LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count |
| ) { |
| unsigned int i; |
| unsigned int *pal = (unsigned int *) screen_palette; |
| |
| for (i = 0; i < count; i++) |
| pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 7) | |
| ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) | |
| ((((unsigned short) palent[i].peGreen) & 0xF8) << 2)); |
| } |
| |
| /* ************************************* |
| 24 to palettized 8 bpp |
| ************************************* */ |
| static void pixel_convert_24_to_8( |
| void *src, void *dst, DWORD width, DWORD height, LONG pitch, |
| IDirectDrawPaletteImpl* palette |
| ) { |
| unsigned char *c_src = (unsigned char *) src; |
| unsigned char *c_dst = (unsigned char *) dst; |
| int y; |
| |
| if (palette != NULL) { |
| const unsigned int *pal = (unsigned int *) palette->screen_palents; |
| |
| for (y = height; y--; ) { |
| unsigned char * srclineend = c_src+width; |
| while (c_src < srclineend ) { |
| register long pixel = pal[*c_src++]; |
| *c_dst++ = pixel; |
| *c_dst++ = pixel>>8; |
| *c_dst++ = pixel>>16; |
| } |
| c_src+=(pitch-width); |
| } |
| } else { |
| FIXME("No palette set...\n"); |
| memset(dst, 0, width * height * 3); |
| } |
| } |
| |
| /* ************************************* |
| 32 bpp to palettized 8 bpp |
| ************************************* */ |
| static void pixel_convert_32_to_8( |
| void *src, void *dst, DWORD width, DWORD height, LONG pitch, |
| IDirectDrawPaletteImpl* palette |
| ) { |
| unsigned char *c_src = (unsigned char *) src; |
| unsigned int *c_dst = (unsigned int *) dst; |
| int y; |
| |
| if (palette != NULL) { |
| const unsigned int *pal = (unsigned int *) palette->screen_palents; |
| |
| for (y = height; y--; ) { |
| #if defined(__i386__) && defined(__GNUC__) |
| /* See comment in pixel_convert_16_to_8 */ |
| __asm__ __volatile__( |
| "xor %%eax,%%eax\n" |
| "1:\n" |
| " lodsb\n" |
| " movl (%%edx,%%eax,4),%%eax\n" |
| " stosl\n" |
| " xor %%eax,%%eax\n" |
| " loop 1b\n" |
| : "=S" (c_src), "=D" (c_dst) |
| : "S" (c_src), "D" (c_dst) , "c" (width), "d" (pal) |
| : "eax", "cc", "memory" |
| ); |
| c_src+=(pitch-width); |
| #else |
| unsigned char * srclineend = c_src+width; |
| while (c_src < srclineend ) |
| *c_dst++ = pal[*c_src++]; |
| c_src+=(pitch-width); |
| #endif |
| } |
| } else { |
| FIXME("No palette set...\n"); |
| memset(dst, 0, width * height * 4); |
| } |
| } |
| |
| static void palette_convert_24_to_8( |
| LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count |
| ) { |
| unsigned int i; |
| unsigned int *pal = (unsigned int *) screen_palette; |
| |
| for (i = 0; i < count; i++) |
| pal[start + i] = ((((unsigned int) palent[i].peRed) << 16) | |
| (((unsigned int) palent[i].peGreen) << 8) | |
| ((unsigned int) palent[i].peBlue)); |
| } |
| |
| /* ************************************* |
| 16 bpp to 15 bpp |
| ************************************* */ |
| static void pixel_convert_15_to_16( |
| void *src, void *dst, DWORD width, DWORD height, LONG pitch, |
| IDirectDrawPaletteImpl* palette |
| ) { |
| unsigned short *c_src = (unsigned short *) src; |
| unsigned short *c_dst = (unsigned short *) dst; |
| int y; |
| |
| for (y = height; y--; ) { |
| unsigned short * srclineend = c_src+width; |
| while (c_src < srclineend ) { |
| unsigned short val = *c_src++; |
| *c_dst++=((val&0xFFC0)>>1)|(val&0x001f); |
| } |
| c_src+=((pitch/2)-width); |
| } |
| } |
| |
| /* ************************************* |
| 32 bpp to 16 bpp |
| ************************************* */ |
| static void pixel_convert_32_to_16( |
| void *src, void *dst, DWORD width, DWORD height, LONG pitch, |
| IDirectDrawPaletteImpl* palette |
| ) { |
| unsigned short *c_src = (unsigned short *) src; |
| unsigned int *c_dst = (unsigned int *) dst; |
| int y; |
| |
| for (y = height; y--; ) { |
| unsigned short * srclineend = c_src+width; |
| while (c_src < srclineend ) { |
| *c_dst++ = (((*c_src & 0xF800) << 8) | |
| ((*c_src & 0x07E0) << 5) | |
| ((*c_src & 0x001F) << 3)); |
| c_src++; |
| } |
| c_src+=((pitch/2)-width); |
| } |
| } |
| |
| /* ************************************* |
| 32 bpp to 24 bpp |
| ************************************* */ |
| static void pixel_convert_32_to_24( |
| void *src, void *dst, DWORD width, DWORD height, LONG pitch, |
| IDirectDrawPaletteImpl* palette |
| ) { |
| unsigned char *c_src = (unsigned char *) src; |
| unsigned int *c_dst = (unsigned int *) dst; |
| int y; |
| |
| for (y = height; y--; ) { |
| unsigned char * srclineend = c_src+width*3; |
| while (c_src < srclineend ) { |
| /* FIXME: wrong for big endian */ |
| memcpy(c_dst,c_src,3); |
| c_src+=3; |
| c_dst++; |
| } |
| c_src+=pitch-width*3; |
| } |
| } |
| |
| /* ************************************* |
| 16 bpp to 32 bpp |
| ************************************* */ |
| static void pixel_convert_16_to_32( |
| void *src, void *dst, DWORD width, DWORD height, LONG pitch, |
| IDirectDrawPaletteImpl* palette |
| ) { |
| unsigned int *c_src = (unsigned int *) src; |
| unsigned short *c_dst = (unsigned short *) dst; |
| int y; |
| |
| for (y = height; y--; ) { |
| unsigned int * srclineend = c_src+width; |
| while (c_src < srclineend ) { |
| *c_dst++ = (((*c_src & 0xF80000) >> 8) | |
| ((*c_src & 0x00FC00) >> 5) | |
| ((*c_src & 0x0000F8) >> 3)); |
| c_src++; |
| } |
| c_src+=((pitch/4)-width); |
| } |
| } |
| |
| Convert ModeEmulations[8] = { |
| { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, { 24, 24, 0xFF0000, 0x00FF00, 0x0000FF }, { pixel_convert_32_to_24, NULL } }, |
| { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, { 16, 16, 0xF800, 0x07E0, 0x001F }, { pixel_convert_32_to_16, NULL } }, |
| { { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, { 8, 8, 0x00, 0x00, 0x00 }, { pixel_convert_32_to_8, palette_convert_24_to_8 } }, |
| { { 24, 24, 0xFF0000, 0x00FF00, 0x0000FF }, { 8, 8, 0x00, 0x00, 0x00 }, { pixel_convert_24_to_8, palette_convert_24_to_8 } }, |
| { { 16, 15, 0x7C00, 0x03E0, 0x001F }, { 16,16, 0xf800, 0x07e0, 0x001f }, { pixel_convert_15_to_16, NULL } }, |
| { { 16, 16, 0xF800, 0x07E0, 0x001F }, { 8, 8, 0x00, 0x00, 0x00 }, { pixel_convert_16_to_8, palette_convert_16_to_8 } }, |
| { { 16, 15, 0x7C00, 0x03E0, 0x001F }, { 8, 8, 0x00, 0x00, 0x00 }, { pixel_convert_16_to_8, palette_convert_15_to_8 } }, |
| { { 16, 16, 0xF800, 0x07E0, 0x001F }, { 32, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, { pixel_convert_16_to_32, NULL } } |
| }; |
| |
| void DDRAW_Convert_DDSCAPS_1_To_2(const DDSCAPS* pIn, DDSCAPS2* pOut) |
| { |
| /* 2 adds three additional caps fields to the end. Both versions |
| * are unversioned. */ |
| pOut->dwCaps = pIn->dwCaps; |
| pOut->dwCaps2 = 0; |
| pOut->dwCaps3 = 0; |
| pOut->dwCaps4 = 0; |
| } |
| |
| void DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(const DDDEVICEIDENTIFIER2* pIn, |
| DDDEVICEIDENTIFIER* pOut) |
| { |
| /* 2 adds a dwWHQLLevel field to the end. Both structures are |
| * unversioned. */ |
| memcpy(pOut, pIn, sizeof(*pOut)); |
| } |
| |
| /****************************************************************************** |
| * debug output functions |
| */ |
| void DDRAW_dump_flags_(DWORD flags, const flag_info* names, |
| size_t num_names, int newline) |
| { |
| unsigned int i; |
| |
| for (i=0; i < num_names; i++) |
| if ((flags & names[i].val) || /* standard flag value */ |
| ((!flags) && (!names[i].val))) /* zero value only */ |
| DPRINTF("%s ", names[i].name); |
| |
| if (newline) |
| DPRINTF("\n"); |
| } |
| |
| void DDRAW_dump_members(DWORD flags, const void* data, |
| const member_info* mems, size_t num_mems) |
| { |
| unsigned int i; |
| |
| for (i=0; i < num_mems; i++) |
| { |
| if (mems[i].val & flags) |
| { |
| DPRINTF(" - %s : ", mems[i].name); |
| mems[i].func((const char *)data + mems[i].offset); |
| DPRINTF("\n"); |
| } |
| } |
| } |
| |
| void DDRAW_dump_DDBLTFX(DWORD flagmask) |
| { |
| static const flag_info flags[] = |
| { |
| FE(DDBLTFX_ARITHSTRETCHY), |
| FE(DDBLTFX_MIRRORLEFTRIGHT), |
| FE(DDBLTFX_MIRRORUPDOWN), |
| FE(DDBLTFX_NOTEARING), |
| FE(DDBLTFX_ROTATE180), |
| FE(DDBLTFX_ROTATE270), |
| FE(DDBLTFX_ROTATE90), |
| FE(DDBLTFX_ZBUFFERRANGE), |
| FE(DDBLTFX_ZBUFFERBASEDEST) |
| }; |
| |
| DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0])); |
| } |
| |
| void DDRAW_dump_DDBLTFAST(DWORD flagmask) |
| { |
| static const flag_info flags[] = |
| { |
| FE(DDBLTFAST_NOCOLORKEY), |
| FE(DDBLTFAST_SRCCOLORKEY), |
| FE(DDBLTFAST_DESTCOLORKEY), |
| FE(DDBLTFAST_WAIT) |
| }; |
| |
| DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0])); |
| } |
| |
| void DDRAW_dump_DDBLT(DWORD flagmask) |
| { |
| static const flag_info flags[] = |
| { |
| FE(DDBLT_ALPHADEST), |
| FE(DDBLT_ALPHADESTCONSTOVERRIDE), |
| FE(DDBLT_ALPHADESTNEG), |
| FE(DDBLT_ALPHADESTSURFACEOVERRIDE), |
| FE(DDBLT_ALPHAEDGEBLEND), |
| FE(DDBLT_ALPHASRC), |
| FE(DDBLT_ALPHASRCCONSTOVERRIDE), |
| FE(DDBLT_ALPHASRCNEG), |
| FE(DDBLT_ALPHASRCSURFACEOVERRIDE), |
| FE(DDBLT_ASYNC), |
| FE(DDBLT_COLORFILL), |
| FE(DDBLT_DDFX), |
| FE(DDBLT_DDROPS), |
| FE(DDBLT_KEYDEST), |
| FE(DDBLT_KEYDESTOVERRIDE), |
| FE(DDBLT_KEYSRC), |
| FE(DDBLT_KEYSRCOVERRIDE), |
| FE(DDBLT_ROP), |
| FE(DDBLT_ROTATIONANGLE), |
| FE(DDBLT_ZBUFFER), |
| FE(DDBLT_ZBUFFERDESTCONSTOVERRIDE), |
| FE(DDBLT_ZBUFFERDESTOVERRIDE), |
| FE(DDBLT_ZBUFFERSRCCONSTOVERRIDE), |
| FE(DDBLT_ZBUFFERSRCOVERRIDE), |
| FE(DDBLT_WAIT), |
| FE(DDBLT_DEPTHFILL) |
| }; |
| |
| DDRAW_dump_flags(flagmask, flags, sizeof(flags)/sizeof(flags[0])); |
| } |
| |
| void DDRAW_dump_DDSCAPS2(const DDSCAPS2 *in) |
| { |
| static const flag_info flags[] = { |
| FE(DDSCAPS_RESERVED1), |
| FE(DDSCAPS_ALPHA), |
| FE(DDSCAPS_BACKBUFFER), |
| FE(DDSCAPS_COMPLEX), |
| FE(DDSCAPS_FLIP), |
| FE(DDSCAPS_FRONTBUFFER), |
| FE(DDSCAPS_OFFSCREENPLAIN), |
| FE(DDSCAPS_OVERLAY), |
| FE(DDSCAPS_PALETTE), |
| FE(DDSCAPS_PRIMARYSURFACE), |
| FE(DDSCAPS_PRIMARYSURFACELEFT), |
| FE(DDSCAPS_SYSTEMMEMORY), |
| FE(DDSCAPS_TEXTURE), |
| FE(DDSCAPS_3DDEVICE), |
| FE(DDSCAPS_VIDEOMEMORY), |
| FE(DDSCAPS_VISIBLE), |
| FE(DDSCAPS_WRITEONLY), |
| FE(DDSCAPS_ZBUFFER), |
| FE(DDSCAPS_OWNDC), |
| FE(DDSCAPS_LIVEVIDEO), |
| FE(DDSCAPS_HWCODEC), |
| FE(DDSCAPS_MODEX), |
| FE(DDSCAPS_MIPMAP), |
| FE(DDSCAPS_RESERVED2), |
| FE(DDSCAPS_ALLOCONLOAD), |
| FE(DDSCAPS_VIDEOPORT), |
| FE(DDSCAPS_LOCALVIDMEM), |
| FE(DDSCAPS_NONLOCALVIDMEM), |
| FE(DDSCAPS_STANDARDVGAMODE), |
| FE(DDSCAPS_OPTIMIZED) |
| }; |
| static const flag_info flags2[] = { |
| FE(DDSCAPS2_HARDWAREDEINTERLACE), |
| FE(DDSCAPS2_HINTDYNAMIC), |
| FE(DDSCAPS2_HINTSTATIC), |
| FE(DDSCAPS2_TEXTUREMANAGE), |
| FE(DDSCAPS2_RESERVED1), |
| FE(DDSCAPS2_RESERVED2), |
| FE(DDSCAPS2_OPAQUE), |
| FE(DDSCAPS2_HINTANTIALIASING), |
| FE(DDSCAPS2_CUBEMAP), |
| FE(DDSCAPS2_CUBEMAP_POSITIVEX), |
| FE(DDSCAPS2_CUBEMAP_NEGATIVEX), |
| FE(DDSCAPS2_CUBEMAP_POSITIVEY), |
| FE(DDSCAPS2_CUBEMAP_NEGATIVEY), |
| FE(DDSCAPS2_CUBEMAP_POSITIVEZ), |
| FE(DDSCAPS2_CUBEMAP_NEGATIVEZ), |
| FE(DDSCAPS2_MIPMAPSUBLEVEL), |
| FE(DDSCAPS2_D3DTEXTUREMANAGE), |
| FE(DDSCAPS2_DONOTPERSIST), |
| FE(DDSCAPS2_STEREOSURFACELEFT) |
| }; |
| |
| DDRAW_dump_flags_(in->dwCaps, flags, sizeof(flags)/sizeof(flags[0]), 0); |
| DDRAW_dump_flags_(in->dwCaps2, flags2, sizeof(flags2)/sizeof(flags2[0]), 0); |
| } |
| |
| void DDRAW_dump_DDSCAPS(const DDSCAPS *in) { |
| DDSCAPS2 in_bis; |
| |
| in_bis.dwCaps = in->dwCaps; |
| in_bis.dwCaps2 = 0; |
| in_bis.dwCaps3 = 0; |
| in_bis.dwCaps4 = 0; |
| |
| DDRAW_dump_DDSCAPS2(&in_bis); |
| } |
| |
| void DDRAW_dump_pixelformat_flag(DWORD flagmask) |
| { |
| static const flag_info flags[] = |
| { |
| FE(DDPF_ALPHAPIXELS), |
| FE(DDPF_ALPHA), |
| FE(DDPF_FOURCC), |
| FE(DDPF_PALETTEINDEXED4), |
| FE(DDPF_PALETTEINDEXEDTO8), |
| FE(DDPF_PALETTEINDEXED8), |
| FE(DDPF_RGB), |
| FE(DDPF_COMPRESSED), |
| FE(DDPF_RGBTOYUV), |
| FE(DDPF_YUV), |
| FE(DDPF_ZBUFFER), |
| FE(DDPF_PALETTEINDEXED1), |
| FE(DDPF_PALETTEINDEXED2), |
| FE(DDPF_ZPIXELS) |
| }; |
| |
| DDRAW_dump_flags_(flagmask, flags, sizeof(flags)/sizeof(flags[0]), 0); |
| } |
| |
| void DDRAW_dump_paletteformat(DWORD dwFlags) |
| { |
| static const flag_info flags[] = |
| { |
| FE(DDPCAPS_4BIT), |
| FE(DDPCAPS_8BITENTRIES), |
| FE(DDPCAPS_8BIT), |
| FE(DDPCAPS_INITIALIZE), |
| FE(DDPCAPS_PRIMARYSURFACE), |
| FE(DDPCAPS_PRIMARYSURFACELEFT), |
| FE(DDPCAPS_ALLOW256), |
| FE(DDPCAPS_VSYNC), |
| FE(DDPCAPS_1BIT), |
| FE(DDPCAPS_2BIT), |
| FE(DDPCAPS_ALPHA) |
| }; |
| |
| DDRAW_dump_flags(dwFlags, flags, sizeof(flags)/sizeof(flags[0])); |
| } |
| |
| void DDRAW_dump_pixelformat(const DDPIXELFORMAT *pf) { |
| DPRINTF("( "); |
| DDRAW_dump_pixelformat_flag(pf->dwFlags); |
| if (pf->dwFlags & DDPF_FOURCC) { |
| DPRINTF(", dwFourCC code '%c%c%c%c' (0x%08lx) - %ld bits per pixel", |
| (unsigned char)( pf->dwFourCC &0xff), |
| (unsigned char)((pf->dwFourCC>> 8)&0xff), |
| (unsigned char)((pf->dwFourCC>>16)&0xff), |
| (unsigned char)((pf->dwFourCC>>24)&0xff), |
| pf->dwFourCC, |
| pf->u1.dwYUVBitCount |
| ); |
| } |
| if (pf->dwFlags & DDPF_RGB) { |
| const char *cmd; |
| DPRINTF(", RGB bits: %ld, ", pf->u1.dwRGBBitCount); |
| switch (pf->u1.dwRGBBitCount) { |
| case 4: cmd = "%1lx"; break; |
| case 8: cmd = "%02lx"; break; |
| case 16: cmd = "%04lx"; break; |
| case 24: cmd = "%06lx"; break; |
| case 32: cmd = "%08lx"; break; |
| default: ERR("Unexpected bit depth !\n"); cmd = "%d"; break; |
| } |
| DPRINTF(" R "); DPRINTF(cmd, pf->u2.dwRBitMask); |
| DPRINTF(" G "); DPRINTF(cmd, pf->u3.dwGBitMask); |
| DPRINTF(" B "); DPRINTF(cmd, pf->u4.dwBBitMask); |
| if (pf->dwFlags & DDPF_ALPHAPIXELS) { |
| DPRINTF(" A "); DPRINTF(cmd, pf->u5.dwRGBAlphaBitMask); |
| } |
| if (pf->dwFlags & DDPF_ZPIXELS) { |
| DPRINTF(" Z "); DPRINTF(cmd, pf->u5.dwRGBZBitMask); |
| } |
| } |
| if (pf->dwFlags & DDPF_ZBUFFER) { |
| DPRINTF(", Z bits : %ld", pf->u1.dwZBufferBitDepth); |
| } |
| if (pf->dwFlags & DDPF_ALPHA) { |
| DPRINTF(", Alpha bits : %ld", pf->u1.dwAlphaBitDepth); |
| } |
| DPRINTF(")"); |
| } |
| |
| void DDRAW_dump_colorkeyflag(DWORD ck) |
| { |
| static const flag_info flags[] = |
| { |
| FE(DDCKEY_COLORSPACE), |
| FE(DDCKEY_DESTBLT), |
| FE(DDCKEY_DESTOVERLAY), |
| FE(DDCKEY_SRCBLT), |
| FE(DDCKEY_SRCOVERLAY) |
| }; |
| |
| DDRAW_dump_flags(ck, flags, sizeof(flags)/sizeof(flags[0])); |
| } |
| |
| void DDRAW_dump_lockflag(DWORD lockflag) |
| { |
| static const flag_info flags[] = |
| { |
| FE(DDLOCK_SURFACEMEMORYPTR), |
| FE(DDLOCK_WAIT), |
| FE(DDLOCK_EVENT), |
| FE(DDLOCK_READONLY), |
| FE(DDLOCK_WRITEONLY), |
| FE(DDLOCK_NOSYSLOCK), |
| FE(DDLOCK_DISCARDCONTENTS), |
| FE(DDLOCK_NOOVERWRITE) |
| }; |
| |
| DDRAW_dump_flags(lockflag, flags, sizeof(flags)/sizeof(flags[0])); |
| } |
| |
| static void DDRAW_dump_DWORD(const void *in) { |
| DPRINTF("%ld", *((const DWORD *) in)); |
| } |
| static void DDRAW_dump_PTR(const void *in) { |
| DPRINTF("%p", *((const void * const*) in)); |
| } |
| void DDRAW_dump_DDCOLORKEY(const DDCOLORKEY *ddck) { |
| DPRINTF(" Low : %ld - High : %ld", ddck->dwColorSpaceLowValue, ddck->dwColorSpaceHighValue); |
| } |
| |
| void DDRAW_dump_surface_desc(const DDSURFACEDESC2 *lpddsd) |
| { |
| #define STRUCT DDSURFACEDESC2 |
| static const member_info members[] = |
| { |
| ME(DDSD_HEIGHT, DDRAW_dump_DWORD, dwHeight), |
| ME(DDSD_WIDTH, DDRAW_dump_DWORD, dwWidth), |
| ME(DDSD_PITCH, DDRAW_dump_DWORD, u1.lPitch), |
| ME(DDSD_LINEARSIZE, DDRAW_dump_DWORD, u1.dwLinearSize), |
| ME(DDSD_BACKBUFFERCOUNT, DDRAW_dump_DWORD, dwBackBufferCount), |
| ME(DDSD_MIPMAPCOUNT, DDRAW_dump_DWORD, u2.dwMipMapCount), |
| ME(DDSD_ZBUFFERBITDEPTH, DDRAW_dump_DWORD, u2.dwMipMapCount), /* This is for 'old-style' D3D */ |
| ME(DDSD_REFRESHRATE, DDRAW_dump_DWORD, u2.dwRefreshRate), |
| ME(DDSD_ALPHABITDEPTH, DDRAW_dump_DWORD, dwAlphaBitDepth), |
| ME(DDSD_LPSURFACE, DDRAW_dump_PTR, lpSurface), |
| ME(DDSD_CKDESTOVERLAY, DDRAW_dump_DDCOLORKEY, u3.ddckCKDestOverlay), |
| ME(DDSD_CKDESTBLT, DDRAW_dump_DDCOLORKEY, ddckCKDestBlt), |
| ME(DDSD_CKSRCOVERLAY, DDRAW_dump_DDCOLORKEY, ddckCKSrcOverlay), |
| ME(DDSD_CKSRCBLT, DDRAW_dump_DDCOLORKEY, ddckCKSrcBlt), |
| ME(DDSD_PIXELFORMAT, DDRAW_dump_pixelformat, u4.ddpfPixelFormat) |
| }; |
| static const member_info members_caps[] = |
| { |
| ME(DDSD_CAPS, DDRAW_dump_DDSCAPS, ddsCaps) |
| }; |
| static const member_info members_caps2[] = |
| { |
| ME(DDSD_CAPS, DDRAW_dump_DDSCAPS2, ddsCaps) |
| }; |
| #undef STRUCT |
| |
| if (lpddsd->dwSize >= sizeof(DDSURFACEDESC2)) { |
| DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members_caps2, 1); |
| } else { |
| DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members_caps, 1); |
| } |
| |
| DDRAW_dump_members(lpddsd->dwFlags, lpddsd, members, |
| sizeof(members)/sizeof(members[0])); |
| } |
| |
| void DDRAW_dump_cooperativelevel(DWORD cooplevel) |
| { |
| static const flag_info flags[] = |
| { |
| FE(DDSCL_FULLSCREEN), |
| FE(DDSCL_ALLOWREBOOT), |
| FE(DDSCL_NOWINDOWCHANGES), |
| FE(DDSCL_NORMAL), |
| FE(DDSCL_ALLOWMODEX), |
| FE(DDSCL_EXCLUSIVE), |
| FE(DDSCL_SETFOCUSWINDOW), |
| FE(DDSCL_SETDEVICEWINDOW), |
| FE(DDSCL_CREATEDEVICEWINDOW) |
| }; |
| |
| if (TRACE_ON(ddraw)) |
| { |
| DPRINTF(" - "); |
| DDRAW_dump_flags(cooplevel, flags, sizeof(flags)/sizeof(flags[0])); |
| } |
| } |
| |
| void DDRAW_dump_DDCAPS(const DDCAPS *lpcaps) { |
| static const flag_info flags1[] = { |
| FE(DDCAPS_3D), |
| FE(DDCAPS_ALIGNBOUNDARYDEST), |
| FE(DDCAPS_ALIGNSIZEDEST), |
| FE(DDCAPS_ALIGNBOUNDARYSRC), |
| FE(DDCAPS_ALIGNSIZESRC), |
| FE(DDCAPS_ALIGNSTRIDE), |
| FE(DDCAPS_BLT), |
| FE(DDCAPS_BLTQUEUE), |
| FE(DDCAPS_BLTFOURCC), |
| FE(DDCAPS_BLTSTRETCH), |
| FE(DDCAPS_GDI), |
| FE(DDCAPS_OVERLAY), |
| FE(DDCAPS_OVERLAYCANTCLIP), |
| FE(DDCAPS_OVERLAYFOURCC), |
| FE(DDCAPS_OVERLAYSTRETCH), |
| FE(DDCAPS_PALETTE), |
| FE(DDCAPS_PALETTEVSYNC), |
| FE(DDCAPS_READSCANLINE), |
| FE(DDCAPS_STEREOVIEW), |
| FE(DDCAPS_VBI), |
| FE(DDCAPS_ZBLTS), |
| FE(DDCAPS_ZOVERLAYS), |
| FE(DDCAPS_COLORKEY), |
| FE(DDCAPS_ALPHA), |
| FE(DDCAPS_COLORKEYHWASSIST), |
| FE(DDCAPS_NOHARDWARE), |
| FE(DDCAPS_BLTCOLORFILL), |
| FE(DDCAPS_BANKSWITCHED), |
| FE(DDCAPS_BLTDEPTHFILL), |
| FE(DDCAPS_CANCLIP), |
| FE(DDCAPS_CANCLIPSTRETCHED), |
| FE(DDCAPS_CANBLTSYSMEM) |
| }; |
| static const flag_info flags2[] = { |
| FE(DDCAPS2_CERTIFIED), |
| FE(DDCAPS2_NO2DDURING3DSCENE), |
| FE(DDCAPS2_VIDEOPORT), |
| FE(DDCAPS2_AUTOFLIPOVERLAY), |
| FE(DDCAPS2_CANBOBINTERLEAVED), |
| FE(DDCAPS2_CANBOBNONINTERLEAVED), |
| FE(DDCAPS2_COLORCONTROLOVERLAY), |
| FE(DDCAPS2_COLORCONTROLPRIMARY), |
| FE(DDCAPS2_CANDROPZ16BIT), |
| FE(DDCAPS2_NONLOCALVIDMEM), |
| FE(DDCAPS2_NONLOCALVIDMEMCAPS), |
| FE(DDCAPS2_NOPAGELOCKREQUIRED), |
| FE(DDCAPS2_WIDESURFACES), |
| FE(DDCAPS2_CANFLIPODDEVEN), |
| FE(DDCAPS2_CANBOBHARDWARE), |
| FE(DDCAPS2_COPYFOURCC), |
| FE(DDCAPS2_PRIMARYGAMMA), |
| FE(DDCAPS2_CANRENDERWINDOWED), |
| FE(DDCAPS2_CANCALIBRATEGAMMA), |
| FE(DDCAPS2_FLIPINTERVAL), |
| FE(DDCAPS2_FLIPNOVSYNC), |
| FE(DDCAPS2_CANMANAGETEXTURE), |
| FE(DDCAPS2_TEXMANINNONLOCALVIDMEM), |
| FE(DDCAPS2_STEREO), |
| FE(DDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL) |
| }; |
| static const flag_info flags3[] = { |
| FE(DDCKEYCAPS_DESTBLT), |
| FE(DDCKEYCAPS_DESTBLTCLRSPACE), |
| FE(DDCKEYCAPS_DESTBLTCLRSPACEYUV), |
| FE(DDCKEYCAPS_DESTBLTYUV), |
| FE(DDCKEYCAPS_DESTOVERLAY), |
| FE(DDCKEYCAPS_DESTOVERLAYCLRSPACE), |
| FE(DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV), |
| FE(DDCKEYCAPS_DESTOVERLAYONEACTIVE), |
| FE(DDCKEYCAPS_DESTOVERLAYYUV), |
| FE(DDCKEYCAPS_SRCBLT), |
| FE(DDCKEYCAPS_SRCBLTCLRSPACE), |
| FE(DDCKEYCAPS_SRCBLTCLRSPACEYUV), |
| FE(DDCKEYCAPS_SRCBLTYUV), |
| FE(DDCKEYCAPS_SRCOVERLAY), |
| FE(DDCKEYCAPS_SRCOVERLAYCLRSPACE), |
| FE(DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV), |
| FE(DDCKEYCAPS_SRCOVERLAYONEACTIVE), |
| FE(DDCKEYCAPS_SRCOVERLAYYUV), |
| FE(DDCKEYCAPS_NOCOSTOVERLAY) |
| }; |
| static const flag_info flags4[] = { |
| FE(DDFXCAPS_BLTALPHA), |
| FE(DDFXCAPS_OVERLAYALPHA), |
| FE(DDFXCAPS_BLTARITHSTRETCHYN), |
| FE(DDFXCAPS_BLTARITHSTRETCHY), |
| FE(DDFXCAPS_BLTMIRRORLEFTRIGHT), |
| FE(DDFXCAPS_BLTMIRRORUPDOWN), |
| FE(DDFXCAPS_BLTROTATION), |
| FE(DDFXCAPS_BLTROTATION90), |
| FE(DDFXCAPS_BLTSHRINKX), |
| FE(DDFXCAPS_BLTSHRINKXN), |
| FE(DDFXCAPS_BLTSHRINKY), |
| FE(DDFXCAPS_BLTSHRINKYN), |
| FE(DDFXCAPS_BLTSTRETCHX), |
| FE(DDFXCAPS_BLTSTRETCHXN), |
| FE(DDFXCAPS_BLTSTRETCHY), |
| FE(DDFXCAPS_BLTSTRETCHYN), |
| FE(DDFXCAPS_OVERLAYARITHSTRETCHY), |
| FE(DDFXCAPS_OVERLAYARITHSTRETCHYN), |
| FE(DDFXCAPS_OVERLAYSHRINKX), |
| FE(DDFXCAPS_OVERLAYSHRINKXN), |
| FE(DDFXCAPS_OVERLAYSHRINKY), |
| FE(DDFXCAPS_OVERLAYSHRINKYN), |
| FE(DDFXCAPS_OVERLAYSTRETCHX), |
| FE(DDFXCAPS_OVERLAYSTRETCHXN), |
| FE(DDFXCAPS_OVERLAYSTRETCHY), |
| FE(DDFXCAPS_OVERLAYSTRETCHYN), |
| FE(DDFXCAPS_OVERLAYMIRRORLEFTRIGHT), |
| FE(DDFXCAPS_OVERLAYMIRRORUPDOWN) |
| }; |
| static const flag_info flags5[] = { |
| FE(DDFXALPHACAPS_BLTALPHAEDGEBLEND), |
| FE(DDFXALPHACAPS_BLTALPHAPIXELS), |
| FE(DDFXALPHACAPS_BLTALPHAPIXELSNEG), |
| FE(DDFXALPHACAPS_BLTALPHASURFACES), |
| FE(DDFXALPHACAPS_BLTALPHASURFACESNEG), |
| FE(DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND), |
| FE(DDFXALPHACAPS_OVERLAYALPHAPIXELS), |
| FE(DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG), |
| FE(DDFXALPHACAPS_OVERLAYALPHASURFACES), |
| FE(DDFXALPHACAPS_OVERLAYALPHASURFACESNEG) |
| }; |
| static const flag_info flags6[] = { |
| FE(DDPCAPS_4BIT), |
| FE(DDPCAPS_8BITENTRIES), |
| FE(DDPCAPS_8BIT), |
| FE(DDPCAPS_INITIALIZE), |
| FE(DDPCAPS_PRIMARYSURFACE), |
| FE(DDPCAPS_PRIMARYSURFACELEFT), |
| FE(DDPCAPS_ALLOW256), |
| FE(DDPCAPS_VSYNC), |
| FE(DDPCAPS_1BIT), |
| FE(DDPCAPS_2BIT), |
| FE(DDPCAPS_ALPHA), |
| }; |
| static const flag_info flags7[] = { |
| FE(DDSVCAPS_RESERVED1), |
| FE(DDSVCAPS_RESERVED2), |
| FE(DDSVCAPS_RESERVED3), |
| FE(DDSVCAPS_RESERVED4), |
| FE(DDSVCAPS_STEREOSEQUENTIAL), |
| }; |
| |
| DPRINTF(" - dwSize : %ld\n", lpcaps->dwSize); |
| DPRINTF(" - dwCaps : "); DDRAW_dump_flags(lpcaps->dwCaps, flags1, sizeof(flags1)/sizeof(flags1[0])); |
| DPRINTF(" - dwCaps2 : "); DDRAW_dump_flags(lpcaps->dwCaps2, flags2, sizeof(flags2)/sizeof(flags2[0])); |
| DPRINTF(" - dwCKeyCaps : "); DDRAW_dump_flags(lpcaps->dwCKeyCaps, flags3, sizeof(flags3)/sizeof(flags3[0])); |
| DPRINTF(" - dwFXCaps : "); DDRAW_dump_flags(lpcaps->dwFXCaps, flags4, sizeof(flags4)/sizeof(flags4[0])); |
| DPRINTF(" - dwFXAlphaCaps : "); DDRAW_dump_flags(lpcaps->dwFXAlphaCaps, flags5, sizeof(flags5)/sizeof(flags5[0])); |
| DPRINTF(" - dwPalCaps : "); DDRAW_dump_flags(lpcaps->dwPalCaps, flags6, sizeof(flags6)/sizeof(flags6[0])); |
| DPRINTF(" - dwSVCaps : "); DDRAW_dump_flags(lpcaps->dwSVCaps, flags7, sizeof(flags7)/sizeof(flags7[0])); |
| DPRINTF("...\n"); |
| DPRINTF(" - dwNumFourCCCodes : %ld\n", lpcaps->dwNumFourCCCodes); |
| DPRINTF(" - dwCurrVisibleOverlays : %ld\n", lpcaps->dwCurrVisibleOverlays); |
| DPRINTF(" - dwMinOverlayStretch : %ld\n", lpcaps->dwMinOverlayStretch); |
| DPRINTF(" - dwMaxOverlayStretch : %ld\n", lpcaps->dwMaxOverlayStretch); |
| DPRINTF("...\n"); |
| DPRINTF(" - ddsCaps : "); DDRAW_dump_DDSCAPS2(&lpcaps->ddsCaps); DPRINTF("\n"); |
| } |
| |
| /* Debug function that can be helpful to debug various surface-related problems */ |
| static int get_shift(DWORD color_mask) { |
| int shift = 0; |
| while (color_mask > 0xFF) { |
| color_mask >>= 1; |
| shift += 1; |
| } |
| while ((color_mask & 0x80) == 0) { |
| color_mask <<= 1; |
| shift -= 1; |
| } |
| return shift; |
| } |
| |
| void DDRAW_dump_surface_to_disk(IDirectDrawSurfaceImpl *surface, FILE *f, int scale) |
| { |
| int rwidth, rheight, x, y; |
| static char *output = NULL; |
| static int size = 0; |
| |
| rwidth = (surface->surface_desc.dwWidth + scale - 1) / scale; |
| rheight = (surface->surface_desc.dwHeight + scale - 1) / scale; |
| |
| if (rwidth > size) { |
| output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, rwidth * 3); |
| size = rwidth; |
| } |
| |
| fprintf(f, "P6\n%d %d\n255\n", rwidth, rheight); |
| |
| if (surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { |
| unsigned char table[256][3]; |
| int i; |
| |
| if (surface->palette == NULL) { |
| fclose(f); |
| return; |
| } |
| for (i = 0; i < 256; i++) { |
| table[i][0] = surface->palette->palents[i].peRed; |
| table[i][1] = surface->palette->palents[i].peGreen; |
| table[i][2] = surface->palette->palents[i].peBlue; |
| } |
| for (y = 0; y < rheight; y++) { |
| unsigned char *src = (unsigned char *) surface->surface_desc.lpSurface + (y * scale * surface->surface_desc.u1.lPitch); |
| for (x = 0; x < rwidth; x++) { |
| unsigned char color = *src; |
| src += scale; |
| |
| output[3 * x + 0] = table[color][0]; |
| output[3 * x + 1] = table[color][1]; |
| output[3 * x + 2] = table[color][2]; |
| } |
| fwrite(output, 3 * rwidth, 1, f); |
| } |
| } else if (surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) { |
| int red_shift, green_shift, blue_shift, pix_width; |
| |
| if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 8) { |
| pix_width = 1; |
| } else if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) { |
| pix_width = 2; |
| } else if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) { |
| pix_width = 4; |
| } else { |
| pix_width = 3; |
| } |
| |
| red_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask); |
| green_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask); |
| blue_shift = get_shift(surface->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask); |
| |
| for (y = 0; y < rheight; y++) { |
| unsigned char *src = (unsigned char *) surface->surface_desc.lpSurface + (y * scale * surface->surface_desc.u1.lPitch); |
| for (x = 0; x < rwidth; x++) { |
| unsigned int color; |
| unsigned int comp; |
| int i; |
| |
| color = 0; |
| for (i = 0; i < pix_width; i++) { |
| color |= src[i] << (8 * i); |
| } |
| src += scale * pix_width; |
| |
| comp = color & surface->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask; |
| output[3 * x + 0] = red_shift > 0 ? comp >> red_shift : comp << -red_shift; |
| comp = color & surface->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask; |
| output[3 * x + 1] = green_shift > 0 ? comp >> green_shift : comp << -green_shift; |
| comp = color & surface->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask; |
| output[3 * x + 2] = blue_shift > 0 ? comp >> blue_shift : comp << -blue_shift; |
| } |
| fwrite(output, 3 * rwidth, 1, f); |
| } |
| } |
| fclose(f); |
| } |