From f6b0dfe46e320daa8f59b935372223ba0308b2ce Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Mon, 23 Apr 2012 00:42:44 +0100 Subject: [PATCH] Basic snapshotting in d3dretrace. --- common/os_string.hpp | 2 +- common/trace_parser_flags.cpp | 1 + retrace/CMakeLists.txt | 1 + retrace/d3dretrace.hpp | 9 +++ retrace/d3dretrace.py | 6 ++ retrace/d3dretrace_main.cpp | 11 +++- retrace/d3dstate.hpp | 48 ++++++++++++++++ retrace/d3dstate_images.cpp | 100 ++++++++++++++++++++++++++++++++++ 8 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 retrace/d3dstate.hpp create mode 100644 retrace/d3dstate_images.cpp diff --git a/common/os_string.hpp b/common/os_string.hpp index a277707..78d02f2 100644 --- a/common/os_string.hpp +++ b/common/os_string.hpp @@ -206,7 +206,7 @@ public: va_list args_copy; va_copy(args_copy, args); #ifdef _WIN32 - /* We need to use _vcsprintf to calculate the length as vsnprintf returns -1 + /* We need to use _vscprintf to calculate the length as vsnprintf returns -1 * if the number of characters to write is greater than count. */ length = _vscprintf(format, args_copy); diff --git a/common/trace_parser_flags.cpp b/common/trace_parser_flags.cpp index 304e2a8..98f0e92 100644 --- a/common/trace_parser_flags.cpp +++ b/common/trace_parser_flags.cpp @@ -56,6 +56,7 @@ defaultCallFlags = 0; const Entry callFlagTable[] = { { "CGLFlushDrawable", CALL_FLAG_END_FRAME }, + { "IDirect3DDevice9::Present", CALL_FLAG_END_FRAME }, { "eglGetProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE }, { "eglQueryString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE }, { "eglSwapBuffers", CALL_FLAG_SWAPBUFFERS }, diff --git a/retrace/CMakeLists.txt b/retrace/CMakeLists.txt index b5e89dc..6b5e61a 100644 --- a/retrace/CMakeLists.txt +++ b/retrace/CMakeLists.txt @@ -148,6 +148,7 @@ if (WIN32 AND DirectX_D3DX9_INCLUDE_DIR) retrace_stdc.cpp d3dretrace_main.cpp d3dretrace_d3d9.cpp + d3dstate_images.cpp ) target_link_libraries (d3dretrace retrace_common diff --git a/retrace/d3dretrace.hpp b/retrace/d3dretrace.hpp index cac94cc..91b84fb 100644 --- a/retrace/d3dretrace.hpp +++ b/retrace/d3dretrace.hpp @@ -29,9 +29,18 @@ #include "retrace.hpp" +class IDirect3DDevice9; + + +extern const char *g_szD3D9DllName; + + namespace d3dretrace { +extern IDirect3DDevice9 *pLastDirect3DDevice9; + + extern const retrace::Entry d3d9_callbacks[]; diff --git a/retrace/d3dretrace.py b/retrace/d3dretrace.py index 586335c..9990f1b 100644 --- a/retrace/d3dretrace.py +++ b/retrace/d3dretrace.py @@ -53,6 +53,11 @@ class D3DRetracer(Retracer): Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue) def invokeInterfaceMethod(self, interface, method): + # keep track of the last used device for state dumping + if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): + print r' d3dretrace::pLastDirect3DDevice9 = _this;' + + # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx'): print r' HWND hWnd = createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' hFocusWindow = hWnd;' @@ -60,6 +65,7 @@ class D3DRetracer(Retracer): Retracer.invokeInterfaceMethod(self, interface, method) + # check errors if str(method.type) == 'HRESULT': print r' if (_result != S_OK) {' print r' retrace::warning(call) << "failed\n";' diff --git a/retrace/d3dretrace_main.cpp b/retrace/d3dretrace_main.cpp index 15053e4..6035e77 100644 --- a/retrace/d3dretrace_main.cpp +++ b/retrace/d3dretrace_main.cpp @@ -27,11 +27,14 @@ #include #include "os_string.hpp" + +#include "d3dstate.hpp" #include "retrace.hpp" #include "d3dretrace.hpp" -extern const char *g_szD3D9DllName; +IDirect3DDevice9 * +d3dretrace::pLastDirect3DDevice9 = NULL; void @@ -51,7 +54,11 @@ retrace::addCallbacks(retrace::Retracer &retracer) image::Image * retrace::getSnapshot(void) { - return NULL; + if (!d3dretrace::pLastDirect3DDevice9) { + return NULL; + } + + return d3dstate::getRenderTargetImage(d3dretrace::pLastDirect3DDevice9); } diff --git a/retrace/d3dstate.hpp b/retrace/d3dstate.hpp new file mode 100644 index 0000000..c0ef017 --- /dev/null +++ b/retrace/d3dstate.hpp @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * 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. + * + **************************************************************************/ + +#ifndef _D3DSTATE_HPP_ +#define _D3DSTATE_HPP_ + + +class IDirect3DDevice9; + + +namespace image { + class Image; +} + + +namespace d3dstate { + + +image::Image * +getRenderTargetImage(IDirect3DDevice9 *pDevice); + + +} /* namespace d3dstate */ + + +#endif /* _D3DSTATE_HPP_ */ diff --git a/retrace/d3dstate_images.cpp b/retrace/d3dstate_images.cpp new file mode 100644 index 0000000..855dede --- /dev/null +++ b/retrace/d3dstate_images.cpp @@ -0,0 +1,100 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * 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 "image.hpp" +#include "d3d9imports.hpp" + + +namespace d3dstate { + + +image::Image * +getRenderTargetImage(IDirect3DDevice9 *pDevice) { + image::Image *image = NULL; + IDirect3DSurface9 *pRenderTarget = NULL; + D3DSURFACE_DESC Desc; + IDirect3DSurface9 *pStagingSurface = NULL; + D3DLOCKED_RECT LockedRect; + const unsigned char *src; + unsigned char *dst; + HRESULT hr; + + hr = pDevice->GetRenderTarget(0, &pRenderTarget); + if (FAILED(hr)) { + goto no_rendertarget; + } + assert(pRenderTarget); + + hr = pRenderTarget->GetDesc(&Desc); + assert(SUCCEEDED(hr)); + assert(Desc.Format == D3DFMT_X8R8G8B8 || Desc.Format == D3DFMT_A8R8G8B8); + + hr = pDevice->CreateOffscreenPlainSurface(Desc.Width, Desc.Height, Desc.Format, D3DPOOL_SYSTEMMEM, &pStagingSurface, NULL); + if (FAILED(hr)) { + goto no_staging; + } + + hr = pDevice->GetRenderTargetData(pRenderTarget, pStagingSurface); + 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) { + 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: + pRenderTarget->Release(); +no_rendertarget: + return image; +} + + +} /* namespace d3dstate */ -- 2.43.0