diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 877cd69f216..b4b67240f91 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -28,6 +28,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw); WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info +#ifdef SHOW_FRAME_MAKEUP +#include +#endif + #if 0 /* TODO */ extern IWineD3DVertexShaderImpl* VertexShaders[64]; extern IWineD3DVertexDeclarationImpl* VertexShaderDeclarations[64]; @@ -2058,34 +2062,42 @@ void drawPrimitive(IWineD3DDevice *iface, TRACE("Done all gl drawing\n"); /* Diagnostics */ -#if defined(SHOW_FRAME_MAKEUP) +#ifdef SHOW_FRAME_MAKEUP { - if (isDumpingFrames) { + static long int primCounter = 0; + /* NOTE: set primCounter to the value reported by drawprim + before you want to to write frame makeup to /tmp */ + if (primCounter >= 0) { D3DLOCKED_RECT r; char buffer[80]; IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY); - sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter); + sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter); TRACE("Saving screenshot %s\n", buffer); IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer); IWineD3DSurface_UnlockRect(This->renderTarget); -#if defined(SHOW_TEXTURE_MAKEUP) +#ifdef SHOW_TEXTURE_MAKEUP { IWineD3DSurface *pSur; int textureNo; for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) { if (This->stateBlock->textures[textureNo] != NULL) { - sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo); + sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo); TRACE("Saving texture %s\n", buffer); - IWineD3DTexture_GetSurfaceLevel(This->stateBlock->textures[textureNo], 0, &pSur); - IWineD3DSurface_SaveSnapshot(pSur, buffer); - IWineD3DSurface_Release(pSur); + if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == D3DRTYPE_TEXTURE) { + IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur); + IWineD3DSurface_SaveSnapshot(pSur, buffer); + IWineD3DSurface_Release(pSur); + } else { + FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo])); + } } } } #endif - ++primCounter; } + TRACE("drawprim #%ld\n", primCounter); + ++primCounter; } #endif } diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index b0efbaaa36d..eaba9499d99 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1116,80 +1116,141 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) { #include HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) { FILE* f = NULL; - ULONG i; + UINT i, y; IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; + char *allocatedMemory; + char *textureRow; + IWineD3DSwapChain *swapChain = NULL; + int width, height; + GLuint tmpTexture; + DWORD color; + /*FIXME: + Textures my not be stored in ->allocatedgMemory and a GlTexture + so we should lock the surface before saving a snapshot, or atleast check that + */ + /* TODO: Compressed texture images can be obtained from the GL in uncompressed form + by calling GetTexImage and in compressed form by calling + GetCompressedTexImageARB. Queried compressed images can be saved and + later reused by calling CompressedTexImage[123]DARB. Pre-compressed + texture images do not need to be processed by the GL and should + significantly improve texture loading performance relative to uncompressed + images. */ + +/* Setup the width and height to be the internal texture width and height. */ + width = This->pow2Width; + height = This->pow2Height; +/* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/ + IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain); + + if (swapChain || This->inPBuffer) { /* if were not a real texture then read the back buffer into a real texture*/ +/* we don't want to interfere with the back buffer so read the data into a tempory texture and then save the data out of the tempory texture */ + GLint prevRead; + ENTER_GL(); + FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This); + glEnable(GL_TEXTURE_2D); + + glGenTextures(1, &tmpTexture); + glBindTexture(GL_TEXTURE_2D, tmpTexture); + + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + width, + height, + 0/*border*/, + GL_RGBA, + GL_UNSIGNED_INT_8_8_8_8_REV, + NULL); + + glGetIntegerv(GL_READ_BUFFER, &prevRead); + vcheckGLcall("glGetIntegerv"); + glReadBuffer(GL_BACK); + vcheckGLcall("glReadBuffer"); + glCopyTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + 0, + 0, + width, + height, + 0); + + checkGLcall("glCopyTexImage2D"); + glReadBuffer(prevRead); + LEAVE_GL(); + + } else { /* bind the real texture */ + IWineD3DSurface_PreLoad(iface); + } + allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width * height * 4); + ENTER_GL(); + FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height); + glGetTexImage(GL_TEXTURE_2D, + This->glDescription.level, + GL_RGBA, + GL_UNSIGNED_INT_8_8_8_8_REV, + allocatedMemory); + checkGLcall("glTexImage2D"); + if (tmpTexture) { + glBindTexture(GL_TEXTURE_2D, 0); + glDeleteTextures(1, &tmpTexture); + } + LEAVE_GL(); f = fopen(filename, "w+"); if (NULL == f) { ERR("opening of %s failed with: %s\n", filename, strerror(errno)); return D3DERR_INVALIDCALL; } +/* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/ + TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format)); +/* TGA header */ + fputc(0,f); + fputc(0,f); + fputc(2,f); + fputc(0,f); + fputc(0,f); + fputc(0,f); + fputc(0,f); + fputc(0,f); + fputc(0,f); + fputc(0,f); + fputc(0,f); + fputc(0,f); +/* short width*/ + fwrite(&width,2,1,f); +/* short height */ + fwrite(&height,2,1,f); +/* format rgba */ + fputc(0x20,f); + fputc(0x28,f); +/* raw data */ + /* if the data is upside down if we've fetched it from a back buffer, so it needs flipping again to make it the correct way up*/ + if(swapChain) + textureRow = allocatedMemory + (width * (height - 1) *4); + else + textureRow = allocatedMemory; + for (y = 0 ; y < height; y++) { + for (i = 0; i < width; i++) { + color = *((DWORD*)textureRow); + fputc((color >> 16) & 0xFF, f); /* B */ + fputc((color >> 8) & 0xFF, f); /* G */ + fputc((color >> 0) & 0xFF, f); /* R */ + fputc((color >> 24) & 0xFF, f); /* A */ + textureRow += 4; + } + /* take two rows of the pointer to the texture memory */ + if(swapChain) + (textureRow-= width << 3); - TRACE("opened %s with format %s\n", filename, debug_d3dformat(This->resource.format)); - - fprintf(f, "P6\n%u %u\n255\n", This->currentDesc.Width, This->currentDesc.Height); - switch (This->resource.format) { - case WINED3DFMT_X8R8G8B8: - case WINED3DFMT_A8R8G8B8: - { - DWORD color; - for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) { - color = ((DWORD*) This->resource.allocatedMemory)[i]; - fputc((color >> 16) & 0xFF, f); - fputc((color >> 8) & 0xFF, f); - fputc((color >> 0) & 0xFF, f); - } - } - break; - case WINED3DFMT_R8G8B8: - { - BYTE* color; - for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) { - color = ((BYTE*) This->resource.allocatedMemory) + (3 * i); - fputc((color[0]) & 0xFF, f); - fputc((color[1]) & 0xFF, f); - fputc((color[2]) & 0xFF, f); - } - } - break; - case WINED3DFMT_A1R5G5B5: - { - WORD color; - for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) { - color = ((WORD*) This->resource.allocatedMemory)[i]; - fputc(((color >> 10) & 0x1F) * 255 / 31, f); - fputc(((color >> 5) & 0x1F) * 255 / 31, f); - fputc(((color >> 0) & 0x1F) * 255 / 31, f); - } - } - break; - case WINED3DFMT_A4R4G4B4: - { - WORD color; - for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) { - color = ((WORD*) This->resource.allocatedMemory)[i]; - fputc(((color >> 8) & 0x0F) * 255 / 15, f); - fputc(((color >> 4) & 0x0F) * 255 / 15, f); - fputc(((color >> 0) & 0x0F) * 255 / 15, f); - } - } - break; - - case WINED3DFMT_R5G6B5: - { - WORD color; - for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) { - color = ((WORD*) This->resource.allocatedMemory)[i]; - fputc(((color >> 11) & 0x1F) * 255 / 31, f); - fputc(((color >> 5) & 0x3F) * 255 / 63, f); - fputc(((color >> 0) & 0x1F) * 255 / 31, f); - } - } - break; - default: - FIXME("Unimplemented dump mode format(%u,%s)\n", This->resource.format, debug_d3dformat(This->resource.format)); } + TRACE("Closing file\n"); fclose(f); + + if(swapChain) { + IWineD3DSwapChain_Release(swapChain); + } + HeapFree(GetProcessHeap(), 0, allocatedMemory); return D3D_OK; }