Change the format of surface_SaveSnapshot to TGA from PPM and add

support for compressed textures and an alpha channel.
This commit is contained in:
Oliver Stieber 2005-09-27 10:49:59 +00:00 committed by Alexandre Julliard
parent 0ec183cfe3
commit c99a3fafef
2 changed files with 146 additions and 73 deletions

View File

@ -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 <stdio.h>
#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
}

View File

@ -1116,80 +1116,141 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
#include <stdio.h>
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;
}