X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=retrace%2Fd3d9state_images.cpp;h=c21573cd327fb402619e8c7807c4c44f1b41c558;hb=3747d74bb1630cbe6d006252543a97460ef8b3ba;hp=855dede27801251ac4c935c8f425ce3095129f8f;hpb=2b46364c974c95b8e2568f1e3f13e888c46c9d04;p=apitrace diff --git a/retrace/d3d9state_images.cpp b/retrace/d3d9state_images.cpp index 855dede..c21573c 100644 --- a/retrace/d3d9state_images.cpp +++ b/retrace/d3d9state_images.cpp @@ -25,18 +25,21 @@ #include +#include #include "image.hpp" +#include "json.hpp" #include "d3d9imports.hpp" +#include "d3dstate.hpp" namespace d3dstate { -image::Image * -getRenderTargetImage(IDirect3DDevice9 *pDevice) { +static image::Image * +getRenderTargetImage(IDirect3DDevice9 *pDevice, + IDirect3DSurface9 *pRenderTarget) { image::Image *image = NULL; - IDirect3DSurface9 *pRenderTarget = NULL; D3DSURFACE_DESC Desc; IDirect3DSurface9 *pStagingSurface = NULL; D3DLOCKED_RECT LockedRect; @@ -44,15 +47,19 @@ getRenderTargetImage(IDirect3DDevice9 *pDevice) { unsigned char *dst; HRESULT hr; - hr = pDevice->GetRenderTarget(0, &pRenderTarget); - if (FAILED(hr)) { - goto no_rendertarget; + if (!pRenderTarget) { + return NULL; } - assert(pRenderTarget); hr = pRenderTarget->GetDesc(&Desc); assert(SUCCEEDED(hr)); - assert(Desc.Format == D3DFMT_X8R8G8B8 || Desc.Format == D3DFMT_A8R8G8B8); + + 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->CreateOffscreenPlainSurface(Desc.Width, Desc.Height, Desc.Format, D3DPOOL_SYSTEMMEM, &pStagingSurface, NULL); if (FAILED(hr)) { @@ -77,11 +84,22 @@ getRenderTargetImage(IDirect3DDevice9 *pDevice) { 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]; + 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(); } @@ -91,10 +109,69 @@ no_image: no_rendertargetdata: pStagingSurface->Release(); no_staging: - pRenderTarget->Release(); -no_rendertarget: return image; } +image::Image * +getRenderTargetImage(IDirect3DDevice9 *pDevice) { + HRESULT hr; + + IDirect3DSurface9 *pRenderTarget = NULL; + hr = pDevice->GetRenderTarget(0, &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, IDirect3DDevice9 *pDevice) +{ + HRESULT hr; + + json.beginMember("framebuffer"); + json.beginObject(); + + D3DCAPS9 Caps; + pDevice->GetDeviceCaps(&Caps); + + for (UINT i = 0; i < Caps.NumSimultaneousRTs; ++i) { + IDirect3DSurface9 *pRenderTarget = NULL; + hr = pDevice->GetRenderTarget(i, &pRenderTarget); + if (FAILED(hr)) { + continue; + } + + if (!pRenderTarget) { + continue; + } + + image::Image *image; + image = getRenderTargetImage(pDevice, pRenderTarget); + if (image) { + char label[64]; + _snprintf(label, sizeof label, "RENDER_TARGET_%u", i); + json.beginMember(label); + json.writeImage(image, "UNKNOWN"); + json.endMember(); // RENDER_TARGET_* + } + + pRenderTarget->Release(); + } + + json.endObject(); + json.endMember(); // framebuffer +} + + } /* namespace d3dstate */