| /************************************************************************** |
| * |
| * Copyright 2015 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 <assert.h> |
| #include <stdint.h> |
| |
| #include "image.hpp" |
| #include "state_writer.hpp" |
| #include "com_ptr.hpp" |
| #include "d3dimports.hpp" |
| #include "d3dstate.hpp" |
| |
| |
| typedef enum _D3DFORMAT |
| { |
| D3DFMT_UNKNOWN = 0, |
| |
| D3DFMT_R8G8B8 = 20, |
| D3DFMT_A8R8G8B8 = 21, |
| D3DFMT_X8R8G8B8 = 22, |
| D3DFMT_R5G6B5 = 23, |
| D3DFMT_X1R5G5B5 = 24, |
| D3DFMT_A1R5G5B5 = 25, |
| D3DFMT_A4R4G4B4 = 26, |
| D3DFMT_R3G3B2 = 27, |
| D3DFMT_A8 = 28, |
| D3DFMT_A8R3G3B2 = 29, |
| D3DFMT_X4R4G4B4 = 30, |
| D3DFMT_A2B10G10R10 = 31, |
| |
| D3DFMT_D16_LOCKABLE = 70, |
| D3DFMT_D32 = 71, |
| D3DFMT_D15S1 = 73, |
| D3DFMT_D24S8 = 75, |
| D3DFMT_D24X8 = 77, |
| D3DFMT_D24X4S4 = 79, |
| D3DFMT_D16 = 80, |
| |
| D3DFMT_D32F_LOCKABLE = 82, |
| D3DFMT_D24FS8 = 83, |
| |
| D3DFMT_FORCE_DWORD = 0x7fffffff |
| } D3DFORMAT; |
| |
| |
| namespace d3dstate { |
| |
| |
| image::Image * |
| ConvertImage(D3DFORMAT SrcFormat, |
| void *SrcData, |
| INT SrcPitch, |
| UINT Width, UINT Height); |
| |
| |
| static D3DFORMAT |
| convertFormat(const DDPIXELFORMAT & ddpfPixelFormat) |
| { |
| if (ddpfPixelFormat.dwSize != sizeof ddpfPixelFormat) { |
| return D3DFMT_UNKNOWN; |
| } |
| |
| switch (ddpfPixelFormat.dwFlags) { |
| case DDPF_RGB: |
| switch (ddpfPixelFormat.dwRGBBitCount) { |
| case 32: |
| if (ddpfPixelFormat.dwRBitMask == 0xff0000 && |
| ddpfPixelFormat.dwGBitMask == 0x00ff00 && |
| ddpfPixelFormat.dwBBitMask == 0x0000ff) { |
| return D3DFMT_X8R8G8B8; |
| } |
| break; |
| } |
| break; |
| case DDPF_ZBUFFER: |
| case DDPF_ZBUFFER | DDPF_STENCILBUFFER: |
| switch (ddpfPixelFormat.dwZBufferBitDepth) { |
| case 16: |
| if (ddpfPixelFormat.dwZBitMask == 0x0000ffff) { |
| return D3DFMT_D16; |
| } |
| break; |
| case 32: |
| if (ddpfPixelFormat.dwZBitMask == 0x00ffffff) { |
| return D3DFMT_D24X8; |
| } |
| break; |
| } |
| break; |
| } |
| |
| return D3DFMT_UNKNOWN; |
| } |
| |
| static image::Image * |
| getSurfaceImage(IDirect3DDevice7 *pDevice, |
| IDirectDrawSurface7 *pSurface) |
| { |
| HRESULT hr; |
| |
| DDSURFACEDESC2 Desc; |
| ZeroMemory(&Desc, sizeof Desc); |
| Desc.dwSize = sizeof Desc; |
| |
| hr = pSurface->Lock(NULL, &Desc, DDLOCK_WAIT | DDLOCK_READONLY | DDLOCK_SURFACEMEMORYPTR | DDLOCK_NOSYSLOCK, NULL); |
| if (FAILED(hr)) { |
| std::cerr << "warning: IDirectDrawSurface7::Lock failed\n"; |
| return NULL; |
| } |
| |
| image::Image *image = NULL; |
| D3DFORMAT Format = convertFormat(Desc.ddpfPixelFormat); |
| if (Format == D3DFMT_UNKNOWN) { |
| std::cerr << "warning: unsupported DDPIXELFORMAT\n"; |
| } else { |
| image = ConvertImage(Format, Desc.lpSurface, Desc.lPitch, Desc.dwWidth, Desc.dwHeight); |
| } |
| |
| pSurface->Unlock(NULL); |
| |
| return image; |
| } |
| |
| |
| image::Image * |
| getRenderTargetImage(IDirect3DDevice7 *pDevice) { |
| HRESULT hr; |
| |
| com_ptr<IDirectDrawSurface7> pRenderTarget; |
| hr = pDevice->GetRenderTarget(&pRenderTarget); |
| if (FAILED(hr)) { |
| return NULL; |
| } |
| assert(pRenderTarget); |
| |
| return getSurfaceImage(pDevice, pRenderTarget); |
| } |
| |
| |
| void |
| dumpTextures(StateWriter &writer, IDirect3DDevice7 *pDevice) |
| { |
| writer.beginMember("textures"); |
| writer.beginObject(); |
| writer.endObject(); |
| writer.endMember(); // textures |
| } |
| |
| |
| void |
| dumpFramebuffer(StateWriter &writer, IDirect3DDevice7 *pDevice) |
| { |
| HRESULT hr; |
| |
| writer.beginMember("framebuffer"); |
| writer.beginObject(); |
| |
| com_ptr<IDirectDrawSurface7> pRenderTarget; |
| hr = pDevice->GetRenderTarget(&pRenderTarget); |
| if (SUCCEEDED(hr) && pRenderTarget) { |
| image::Image *image; |
| image = getSurfaceImage(pDevice, pRenderTarget); |
| if (image) { |
| writer.beginMember("RENDER_TARGET_0"); |
| writer.writeImage(image); |
| writer.endMember(); // RENDER_TARGET_* |
| delete image; |
| } |
| |
| // Search for a depth-stencil attachment |
| DDSCAPS2 ddsCaps; |
| ZeroMemory(&ddsCaps, sizeof ddsCaps); |
| ddsCaps.dwCaps = DDSCAPS_ZBUFFER; |
| com_ptr<IDirectDrawSurface7> pDepthStencil; |
| hr = pRenderTarget->GetAttachedSurface(&ddsCaps, &pDepthStencil); |
| if (SUCCEEDED(hr) && pDepthStencil) { |
| std::cerr << "found ZS!!\n"; |
| image = getSurfaceImage(pDevice, pDepthStencil); |
| if (image) { |
| writer.beginMember("DEPTH_STENCIL"); |
| writer.writeImage(image); |
| writer.endMember(); // DEPTH_STENCIL |
| delete image; |
| } |
| } |
| } |
| |
| writer.endObject(); |
| writer.endMember(); // framebuffer |
| } |
| |
| |
| } /* namespace d3dstate */ |