gsdx-d3d9: Save screenshots as PNG files

v2: Avoid unnecessary memory copy
This commit is contained in:
Jonathan Li 2016-02-19 18:05:39 +00:00
parent d865efceb9
commit a97cbf038c
1 changed files with 49 additions and 37 deletions

View File

@ -21,6 +21,7 @@
#include "stdafx.h"
#include "GSTexture9.h"
#include "GSPng.h"
GSTexture9::GSTexture9(IDirect3DSurface9* surface)
{
@ -143,56 +144,67 @@ void GSTexture9::Unmap()
bool GSTexture9::Save(const string& fn, bool dds)
{
bool rb_swapped = true;
CComPtr<IDirect3DSurface9> surface;
if(m_desc.Usage & D3DUSAGE_DEPTHSTENCIL)
{
HRESULT hr;
D3DSURFACE_DESC desc;
m_surface->GetDesc(&desc);
if(desc.Format != D3DFMT_D32F_LOCKABLE)
if (m_desc.Usage & D3DUSAGE_DEPTHSTENCIL && desc.Format != D3DFMT_D32F_LOCKABLE)
{
return false;
hr = m_dev->CreateOffscreenPlainSurface(desc.Width, desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
D3DLOCKED_RECT slr, dlr;
hr = m_surface->LockRect(&slr, NULL, 0);
hr = surface->LockRect(&dlr, NULL, 0);
uint8* s = (uint8*)slr.pBits;
uint8* d = (uint8*)dlr.pBits;
for(uint32 y = 0; y < desc.Height; y++, s += slr.Pitch, d += dlr.Pitch)
{
for(uint32 x = 0; x < desc.Width; x++)
{
((float*)d)[x] = ((float*)s)[x];
}
}
m_surface->UnlockRect();
surface->UnlockRect();
if (desc.Format == D3DFMT_A8 || desc.Pool == D3DPOOL_MANAGED || desc.Usage == D3DUSAGE_DEPTHSTENCIL)
{
surface = m_surface;
rb_swapped = false;
}
else
{
surface = m_surface;
HRESULT hr;
hr = m_dev->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, nullptr);
if (FAILED(hr))
{
return false;
}
if(surface != NULL)
hr = m_dev->GetRenderTargetData(m_surface, surface);
if (FAILED(hr))
{
return SUCCEEDED(D3DXSaveSurfaceToFile(fn.c_str(), dds ? D3DXIFF_DDS : D3DXIFF_BMP, surface, NULL, NULL));
}
/*
if(CComQIPtr<IDirect3DTexture9> texture = surface)
{
return SUCCEEDED(D3DXSaveTextureToFile(fn.c_str(), dds ? D3DXIFF_DDS : D3DXIFF_BMP, texture, NULL));
}
*/
return false;
}
}
GSPng::Format format;
switch (desc.Format)
{
case D3DFMT_A8:
format = GSPng::R8I_PNG;
break;
case D3DFMT_A8R8G8B8:
format = dds? GSPng::RGBA_PNG : GSPng::RGB_PNG;
break;
case D3DFMT_D32F_LOCKABLE:
format = GSPng::RGB_A_PNG;
break;
default:
fprintf(stderr, "D3DFMT %d not saved to image\n", desc.Format);
return false;
}
D3DLOCKED_RECT slr;
HRESULT hr = surface->LockRect(&slr, nullptr, 0);
if (FAILED(hr))
{
return false;
}
bool success = GSPng::Save(format, fn, static_cast<uint8*>(slr.pBits), desc.Width, desc.Height, slr.Pitch, rb_swapped);
surface->UnlockRect();
return success;
}
GSTexture9::operator IDirect3DSurface9*()