From cbb86175e81c2765f14fa01a2dc49d367203ac1f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Wed, 12 Dec 2012 07:38:42 +0000 Subject: [PATCH] d3dretrace: Dump D3D8 images too. --- dispatch/d3d8imports.hpp | 39 +++++++++ retrace/CMakeLists.txt | 4 + retrace/d3d8state.cpp | 134 ++++++++++++++++++++++++++++ retrace/d3d8state_images.cpp | 164 +++++++++++++++++++++++++++++++++++ retrace/d3d9retrace.py | 10 ++- retrace/d3dstate.hpp | 11 +++ wrappers/d3d8trace.py | 3 +- 7 files changed, 360 insertions(+), 5 deletions(-) create mode 100644 dispatch/d3d8imports.hpp create mode 100644 retrace/d3d8state.cpp create mode 100644 retrace/d3d8state_images.cpp diff --git a/dispatch/d3d8imports.hpp b/dispatch/d3d8imports.hpp new file mode 100644 index 0000000..d081379 --- /dev/null +++ b/dispatch/d3d8imports.hpp @@ -0,0 +1,39 @@ +/************************************************************************** + * + * Copyright 2012 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + +/* + * Central place for all D3D8 includes, and respective OS dependent headers. + */ + +#ifndef _D3D8IMPORTS_HPP_ +#define _D3D8IMPORTS_HPP_ + +#include + +#include "compat.h" + +#include + +#endif /* _D3D8IMPORTS_HPP_ */ diff --git a/retrace/CMakeLists.txt b/retrace/CMakeLists.txt index c6a364f..b271727 100644 --- a/retrace/CMakeLists.txt +++ b/retrace/CMakeLists.txt @@ -136,6 +136,10 @@ if (WIN32) if (DirectX_D3D8_INCLUDE_DIR) include_directories (BEFORE SYSTEM ${DirectX_D3D8_INCLUDE_DIR}) set (HAVE_D3D8 1) + set (D3DSTATE_SOURCES ${D3DSTATE_SOURCES} + d3d8state.cpp + d3d8state_images.cpp + ) else () set (HAVE_D3D8 0) endif () diff --git a/retrace/d3d8state.cpp b/retrace/d3d8state.cpp new file mode 100644 index 0000000..60bdb6d --- /dev/null +++ b/retrace/d3d8state.cpp @@ -0,0 +1,134 @@ +/************************************************************************** + * + * Copyright 2011-2012 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include + +#include + +#include "d3d8imports.hpp" +#include "d3dshader.hpp" +#include "d3dstate.hpp" +#include "json.hpp" + + +namespace d3dstate { + + +typedef HRESULT (STDMETHODCALLTYPE IDirect3DDevice8::*GetShaderFunctionMethod)(DWORD Handle, void* pData, DWORD* pSizeOfData); + + +struct VertexShaderGetter +{ + HRESULT GetShader(IDirect3DDevice8 *pDevice, DWORD *pHandle) { + return pDevice->GetVertexShader(pHandle); + } + HRESULT GetShaderFunction(IDirect3DDevice8 *pDevice, DWORD Handle, void* pData, DWORD* pSizeOfData) { + return pDevice->GetVertexShaderFunction(Handle, pData, pSizeOfData); + } +}; + +struct PixelShaderGetter +{ + HRESULT GetShader(IDirect3DDevice8 *pDevice, DWORD *pHandle) { + return pDevice->GetPixelShader(pHandle); + } + HRESULT GetShaderFunction(IDirect3DDevice8 *pDevice, DWORD Handle, void* pData, DWORD* pSizeOfData) { + return pDevice->GetPixelShaderFunction(Handle, pData, pSizeOfData); + } +}; + +template +inline void +dumpShader(JSONWriter &json, IDirect3DDevice8 *pDevice, const char *name) { + Getter getter; + HRESULT hr; + + DWORD dwShader = 0; + hr = getter.GetShader(pDevice, &dwShader); + if (FAILED(hr) || !dwShader) { + return; + } + + DWORD SizeOfData = 0; + + hr = getter.GetShaderFunction(pDevice, dwShader, NULL, &SizeOfData); + if (SUCCEEDED(hr)) { + void *pData; + pData = malloc(SizeOfData); + if (pData) { + hr = getter.GetShaderFunction(pDevice, dwShader, pData, &SizeOfData); + if (SUCCEEDED(hr)) { + IDisassemblyBuffer *pDisassembly = NULL; + hr = DisassembleShader((const DWORD *)pData, &pDisassembly); + if (SUCCEEDED(hr)) { + json.beginMember(name); + json.writeString((const char *)pDisassembly->GetBufferPointer() /*, pDisassembly->GetBufferSize() */); + json.endMember(); + pDisassembly->Release(); + } + + } + free(pData); + } + } +} + +static void +dumpShaders(JSONWriter &json, IDirect3DDevice8 *pDevice) +{ + json.beginMember("shaders"); + json.beginObject(); + + dumpShader(json, pDevice, "vertex"); + dumpShader(json, pDevice, "pixel"); + + json.endObject(); + json.endMember(); // shaders +} + +void +dumpDevice(std::ostream &os, IDirect3DDevice8 *pDevice) +{ + JSONWriter json(os); + + /* TODO */ + json.beginMember("parameters"); + json.beginObject(); + json.endObject(); + json.endMember(); // parameters + + dumpShaders(json, pDevice); + + json.beginMember("textures"); + json.beginObject(); + json.endObject(); + json.endMember(); // textures + + dumpFramebuffer(json, pDevice); +} + + +} /* namespace d3dstate */ diff --git a/retrace/d3d8state_images.cpp b/retrace/d3d8state_images.cpp new file mode 100644 index 0000000..89d4e06 --- /dev/null +++ b/retrace/d3d8state_images.cpp @@ -0,0 +1,164 @@ +/************************************************************************** + * + * Copyright 2011-2012 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include +#include + +#include "image.hpp" +#include "json.hpp" +#include "d3d8imports.hpp" +#include "d3dstate.hpp" + + +namespace d3dstate { + + +static image::Image * +getRenderTargetImage(IDirect3DDevice8 *pDevice, + IDirect3DSurface8 *pRenderTarget) { + image::Image *image = NULL; + D3DSURFACE_DESC Desc; + IDirect3DSurface8 *pStagingSurface = NULL; + D3DLOCKED_RECT LockedRect; + const unsigned char *src; + unsigned char *dst; + HRESULT hr; + + if (!pRenderTarget) { + return NULL; + } + + hr = pRenderTarget->GetDesc(&Desc); + assert(SUCCEEDED(hr)); + + if (Desc.Format != D3DFMT_X8R8G8B8 && + Desc.Format != D3DFMT_A8R8G8B8 && + Desc.Format != D3DFMT_R5G6B5) { + std::cerr << "warning: unsupported D3DFORMAT " << Desc.Format << "\n"; + goto no_staging; + } + + hr = pDevice->CreateImageSurface(Desc.Width, Desc.Height, Desc.Format, &pStagingSurface); + if (FAILED(hr)) { + goto no_staging; + } + + hr = pDevice->CopyRects(pRenderTarget, NULL, 0, pStagingSurface, NULL); + if (FAILED(hr)) { + goto no_rendertargetdata; + } + + hr = pStagingSurface->LockRect(&LockedRect, NULL, D3DLOCK_READONLY); + if (FAILED(hr)) { + goto no_rendertargetdata; + } + + image = new image::Image(Desc.Width, Desc.Height, 3, true); + if (!image) { + goto no_image; + } + + dst = image->start(); + src = (const unsigned char *)LockedRect.pBits; + for (unsigned y = 0; y < Desc.Height; ++y) { + if (Desc.Format == D3DFMT_R5G6B5) { + for (unsigned x = 0; x < Desc.Width; ++x) { + uint32_t pixel = ((const uint16_t *)src)[x]; + dst[3*x + 0] = (( pixel & 0x1f) * (2*0xff) + 0x1f) / (2*0x1f); + dst[3*x + 1] = (((pixel >> 5) & 0x3f) * (2*0xff) + 0x3f) / (2*0x3f); + dst[3*x + 2] = (( pixel >> 11 ) * (2*0xff) + 0x1f) / (2*0x1f); + dst[3*x + 3] = 0xff; + } + } else { + for (unsigned x = 0; x < Desc.Width; ++x) { + dst[3*x + 0] = src[4*x + 2]; + dst[3*x + 1] = src[4*x + 1]; + dst[3*x + 2] = src[4*x + 0]; + } + } + + src += LockedRect.Pitch; + dst += image->stride(); + } + +no_image: + pStagingSurface->UnlockRect(); +no_rendertargetdata: + pStagingSurface->Release(); +no_staging: + return image; +} + + +image::Image * +getRenderTargetImage(IDirect3DDevice8 *pDevice) { + HRESULT hr; + + IDirect3DSurface8 *pRenderTarget = NULL; + hr = pDevice->GetRenderTarget(&pRenderTarget); + if (FAILED(hr)) { + return NULL; + } + assert(pRenderTarget); + + image::Image *image = NULL; + if (pRenderTarget) { + image = getRenderTargetImage(pDevice, pRenderTarget); + pRenderTarget->Release(); + } + + return image; +} + + +void +dumpFramebuffer(JSONWriter &json, IDirect3DDevice8 *pDevice) +{ + HRESULT hr; + + json.beginMember("framebuffer"); + json.beginObject(); + + IDirect3DSurface8 *pRenderTarget = NULL; + hr = pDevice->GetRenderTarget(&pRenderTarget); + if (SUCCEEDED(hr) && pRenderTarget) { + image::Image *image; + image = getRenderTargetImage(pDevice, pRenderTarget); + if (image) { + json.beginMember("RENDER_TARGET_0"); + json.writeImage(image, "UNKNOWN"); + json.endMember(); // RENDER_TARGET_* + } + + pRenderTarget->Release(); + } + + json.endObject(); + json.endMember(); // framebuffer +} + + +} /* namespace d3dstate */ diff --git a/retrace/d3d9retrace.py b/retrace/d3d9retrace.py index 72fc9ef..db92377 100644 --- a/retrace/d3d9retrace.py +++ b/retrace/d3d9retrace.py @@ -62,6 +62,11 @@ class D3DRetracer(Retracer): print r' d3d9Dumper.unbindDevice(_this);' else: print r' d3d9Dumper.bindDevice(_this);' + if interface.name in ('IDirect3DDevice8', 'IDirect3DDevice8Ex'): + if method.name == 'Release': + print r' d3d8Dumper.unbindDevice(_this);' + else: + print r' d3d8Dumper.bindDevice(_this);' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): @@ -161,12 +166,11 @@ def main(): print elif moduleName == 'd3d8': from specs.d3d8 import d3d8 - print r'#include ' - print r'#include ' + print r'#include "d3d8imports.hpp"' print r'#include "d3d8size.hpp"' api.addModule(d3d8) print - #print '''static d3dretrace::D3DDumper d3d8Dumper;''' + print '''static d3dretrace::D3DDumper d3d8Dumper;''' print else: assert False diff --git a/retrace/d3dstate.hpp b/retrace/d3dstate.hpp index 3766a91..eb0e3cd 100644 --- a/retrace/d3dstate.hpp +++ b/retrace/d3dstate.hpp @@ -32,6 +32,7 @@ #include +struct IDirect3DDevice8; struct IDirect3DDevice9; struct ID3D10Device; struct ID3D11DeviceContext; @@ -50,6 +51,16 @@ namespace d3dstate { extern const GUID GUID_D3DSTATE; +image::Image * +getRenderTargetImage(IDirect3DDevice8 *pDevice); + +void +dumpFramebuffer(JSONWriter &json, IDirect3DDevice8 *pDevice); + +void +dumpDevice(std::ostream &os, IDirect3DDevice8 *pDevice); + + image::Image * getRenderTargetImage(IDirect3DDevice9 *pDevice); diff --git a/wrappers/d3d8trace.py b/wrappers/d3d8trace.py index fd2c8f5..9ce3aad 100644 --- a/wrappers/d3d8trace.py +++ b/wrappers/d3d8trace.py @@ -77,8 +77,7 @@ if __name__ == '__main__': print '#include "trace_writer_local.hpp"' print '#include "os.hpp"' print - print '#include ' - print '#include ' + print '#include "d3d8imports.hpp"' print '#include "d3d8size.hpp"' print '#include "d3d9shader.hpp"' print -- 2.43.0