Hi all, Often, when chasing a bug, one does not know where the bug lies (ie is it when uploading the texture to the GL, is the game provided data correct, ...). For this, I implemented a function that enables anyone to dump any surface to disk in a 'pnm' file format. I changed also the texture dumping code to use this new function. Changelog: Added surface dumping function for debug. Lionel -- Lionel Ulmer - http://www.bbrox.org/
--- ../wine_base/dlls/ddraw/d3dtexture.c Tue Dec 17 19:59:05 2002 +++ dlls/ddraw/d3dtexture.c Wed Dec 18 22:47:43 2002 @@ -36,95 +36,26 @@ /* Define this if you want to save to a file all the textures used by a game (can be funny to see how they managed to cram all the pictures in texture memory) */ #undef TEXTURE_SNOOP #ifdef TEXTURE_SNOOP + #include <stdio.h> -#define SNOOP_PALETTED() \ - { \ - FILE *f; \ - char buf[32]; \ - int x, y; \ - \ - sprintf(buf, "%ld.pnm", glThis->tex_name); \ - f = fopen(buf, "wb"); \ - fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight); \ - for (y = 0; y < src_d->dwHeight; y++) { \ - for (x = 0; x < src_d->dwWidth; x++) { \ - unsigned char c = ((unsigned char *) src_d->lpSurface)[y * src_d->dwWidth + x]; \ - fputc(table[c][0], f); \ - fputc(table[c][1], f); \ - fputc(table[c][2], f); \ - } \ - } \ - fclose(f); \ - } - -#define SNOOP_5650() \ - { \ - FILE *f; \ - char buf[32]; \ - int x, y; \ - \ - sprintf(buf, "%ld.pnm", glThis->tex_name); \ - f = fopen(buf, "wb"); \ - fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight); \ - for (y = 0; y < src_d->dwHeight; y++) { \ - for (x = 0; x < src_d->dwWidth; x++) { \ - unsigned short c = ((unsigned short *) src_d->lpSurface)[y * src_d->dwWidth + x]; \ - fputc((c & 0xF800) >> 8, f); \ - fputc((c & 0x07E0) >> 3, f); \ - fputc((c & 0x001F) << 3, f); \ - } \ - } \ - fclose(f); \ - } - -#define SNOOP_5551() \ - { \ - FILE *f; \ - char buf[32]; \ - int x, y; \ - \ - sprintf(buf, "%ld.pnm", glThis->tex_name); \ - f = fopen(buf, "wb"); \ - fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight); \ - for (y = 0; y < src_d->dwHeight; y++) { \ - for (x = 0; x < src_d->dwWidth; x++) { \ - unsigned short c = ((unsigned short *) src_d->lpSurface)[y * src_d->dwWidth + x]; \ - fputc((c & 0xF800) >> 8, f); \ - fputc((c & 0x07C0) >> 3, f); \ - fputc((c & 0x003E) << 2, f); \ - } \ - } \ - fclose(f); \ - } - -#define SNOOP_1555() \ - { \ - FILE *f; \ - char buf[32]; \ - int x, y; \ - \ - sprintf(buf, "%ld.pnm", glThis->tex_name); \ - f = fopen(buf, "wb"); \ - fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight); \ - for (y = 0; y < src_d->dwHeight; y++) { \ - for (x = 0; x < src_d->dwWidth; x++) { \ - unsigned short c = ((unsigned short *) src_d->lpSurface)[y * src_d->dwWidth + x]; \ - fputc((c & 0x7C00) >> 7, f); \ - fputc((c & 0x03E0) >> 2, f); \ - fputc((c & 0x001F) << 3, f); \ - } \ - } \ - fclose(f); \ - } +static void snoop_texture(IDirectDrawSurfaceImpl *This) { + IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private; + char buf[128]; + FILE *f; + + sprintf(buf, "tex_%05d.pnm", glThis->tex_name); + f = fopen(buf, "wb"); + DDRAW_dump_surface_to_disk(This, f); +} + #else -#define SNOOP_PALETTED() -#define SNOOP_5650() -#define SNOOP_5551() -#define SNOOP_1555() + +#define snoop_texture(a) + #endif /******************************************************************************* @@ -224,6 +155,9 @@ glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); glBindTexture(GL_TEXTURE_2D, glThis->tex_name); + /* Texture snooping for the curious :-) */ + snoop_texture(This); + if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { /* **************** Paletted Texture @@ -257,9 +191,6 @@ table[i][3] = 0xFF; } - /* Texture snooping */ - SNOOP_PALETTED(); - if (ptr_ColorTableEXT != NULL) { /* use Paletted Texture Extension */ ptr_ColorTableEXT(GL_TEXTURE_2D, /* target */ @@ -337,9 +268,6 @@ src_d->lpSurface); } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) { if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000) { - /* Texture snooping */ - SNOOP_5650(); - if (init_upload) glTexImage2D(GL_TEXTURE_2D, glThis->mipmap_level, @@ -359,9 +287,6 @@ src_d->lpSurface); } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000001) { - /* Texture snooping */ - SNOOP_5551(); - if (init_upload) glTexImage2D(GL_TEXTURE_2D, glThis->mipmap_level, @@ -439,7 +364,6 @@ ((*src & 0x7FFF) << 1)); src++; } - SNOOP_1555(); if (init_upload) glTexImage2D(GL_TEXTURE_2D, --- ../wine_base/dlls/ddraw/ddraw_private.h Sun Dec 15 12:15:49 2002 +++ dlls/ddraw/ddraw_private.h Tue Dec 17 21:52:22 2002 @@ -21,6 +21,8 @@ /* MAY NOT CONTAIN X11 or DGA specific includes/defines/structs! */ +#include <stdio.h> + #include "winbase.h" #include "wtypes.h" #include "wingdi.h" @@ -371,6 +373,7 @@ extern void DDRAW_dump_lockflag(DWORD lockflag); extern void DDRAW_dump_DDCOLORKEY(const DDCOLORKEY *in); extern void DDRAW_dump_DDCAPS(const DDCAPS *lpcaps); +extern void DDRAW_dump_surface_to_disk(IDirectDrawSurfaceImpl *surface, FILE *f) ; /* Used for generic dumping */ typedef struct --- ../wine_base/dlls/ddraw/helper.c Sat Dec 14 13:51:24 2002 +++ dlls/ddraw/helper.c Wed Dec 18 22:34:27 2002 @@ -24,6 +24,7 @@ #include "wine/port.h" #include <stddef.h> +#include <stdio.h> #include "d3d.h" #include "ddraw.h" @@ -556,4 +557,75 @@ 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 i; + + DDRAW_dump_surface_desc(&(surface->surface_desc)); + + fprintf(f, "P6\n%ld %ld\n255\n", surface->surface_desc.dwWidth, surface->surface_desc.dwHeight); + + if (surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { + unsigned char table[256][3]; + unsigned char *src = (unsigned char *) surface->surface_desc.lpSurface; + 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 (i = 0; i < surface->surface_desc.dwHeight * surface->surface_desc.dwWidth; i++) { + unsigned char color = *src++; + fputc(table[color][0], f); + fputc(table[color][1], f); + fputc(table[color][2], f); + } + } else if (surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) { + int red_shift, green_shift, blue_shift; + 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 (i = 0; i < surface->surface_desc.dwHeight * surface->surface_desc.dwWidth; i++) { + int color; + int comp; + + if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 8) { + color = ((unsigned char *) surface->surface_desc.lpSurface)[i]; + } else if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) { + color = ((unsigned short *) surface->surface_desc.lpSurface)[i]; + } else if (surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) { + color = ((unsigned int *) surface->surface_desc.lpSurface)[i]; + } else { + /* Well, this won't work on platforms without support for non-aligned memory accesses or big endian :-) */ + color = *((unsigned int *) (((char *) surface->surface_desc.lpSurface) + (3 * i))); + } + comp = color & surface->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask; + fputc(red_shift > 0 ? comp >> red_shift : comp << -red_shift, f); + comp = color & surface->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask; + fputc(green_shift > 0 ? comp >> green_shift : comp << -green_shift, f); + comp = color & surface->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask; + fputc(blue_shift > 0 ? comp >> blue_shift : comp << -blue_shift, f); + } + } + fclose(f); }