Fix build errors with RageDisplay_D3D using Windows SDK

Also: Implement d3d9 screenshots without d3dx9

This only implements the two most likely surface formats. Does anybody
actually use 16-bit rendering anymore? (If yes, I'll do the slower path
through StretchRect to convert)

(backport from master, where it was two commits)
This commit is contained in:
Tracy Ward
2019-10-04 09:35:44 -04:00
parent 6aedffabf3
commit 2bce815a1a
+30 -23
View File
@@ -13,28 +13,20 @@
#include "DisplaySpec.h" #include "DisplaySpec.h"
#include "LocalizedString.h" #include "LocalizedString.h"
#include <D3dx9tex.h>
#include <d3d9.h> #include <d3d9.h>
#include <dxerr.h>
#include "archutils/Win32/GraphicsWindow.h" #include "archutils/Win32/GraphicsWindow.h"
#include "archutils/Win32/DirectXHelpers.h"
// Static libraries // Static libraries
// load Windows D3D9 dynamically // load Windows D3D9 dynamically
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "DxErr.lib")
#endif #endif
#include <math.h> #include <math.h>
#include <list> #include <list>
RString GetErrorString( HRESULT hr )
{
return DXGetErrorString(hr);
}
// Globals // Globals
HMODULE g_D3D9_Module = nullptr; HMODULE g_D3D9_Module = nullptr;
LPDIRECT3D9 g_pd3d = nullptr; LPDIRECT3D9 g_pd3d = nullptr;
@@ -644,22 +636,23 @@ RageSurface* RageDisplay_D3D::CreateScreenshot()
{ {
RageSurface * result = nullptr; RageSurface * result = nullptr;
// Get the back buffer. // get the render target
IDirect3DSurface9* pSurface; IDirect3DSurface9* pSurface;
if( SUCCEEDED( g_pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface ) ) ) if (SUCCEEDED(g_pd3dDevice->GetRenderTarget(0, &pSurface)))
{ {
// Get the back buffer description. // get the render target surface description
D3DSURFACE_DESC desc; D3DSURFACE_DESC desc;
pSurface->GetDesc( &desc ); pSurface->GetDesc(&desc);
// Copy the back buffer into a surface of a type we support. // create an offscreen plain surface of the same format in the SYSTEMMEM pool
IDirect3DSurface9* pCopy; IDirect3DSurface9* pCopy;
if( SUCCEEDED( g_pd3dDevice->CreateOffscreenPlainSurface( desc.Width, desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pCopy, nullptr ) ) ) if (SUCCEEDED(g_pd3dDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pCopy, nullptr)))
{ {
if( SUCCEEDED( D3DXLoadSurfaceFromSurface( pCopy, nullptr, nullptr, pSurface, nullptr, nullptr, D3DX_FILTER_NONE, 0) ) ) // copy the data from the render target into the offscreen plain surface
if (SUCCEEDED(g_pd3dDevice->GetRenderTargetData(pSurface, pCopy)))
{ {
// Update desc from the copy. // Update desc from the copy.
pCopy->GetDesc( &desc ); pCopy->GetDesc(&desc);
D3DLOCKED_RECT lr; D3DLOCKED_RECT lr;
@@ -670,19 +663,33 @@ RageSurface* RageDisplay_D3D::CreateScreenshot()
rect.right = desc.Width; rect.right = desc.Width;
rect.bottom = desc.Height; rect.bottom = desc.Height;
pCopy->LockRect( &lr, &rect, D3DLOCK_READONLY ); pCopy->LockRect(&lr, &rect, D3DLOCK_READONLY);
} }
RageSurface *surface = CreateSurfaceFromPixfmt( RagePixelFormat_RGBA8, lr.pBits, desc.Width, desc.Height, lr.Pitch); // since we no longer have an easy function to force a conversion to A8R8G8B8, we need to figure out our pixel format.
ASSERT( surface != nullptr ); // (yes, we could create a couple of surfaces in the default pool, copy the bits into the one matching our source,
// then use IDirect3DDevice::StretchRect to convert it without stretching into our desired format. This would mean
// a copy to device memory and a copy back again, though.)
// possible formats are found in FindBackBufferType
RagePixelFormat pf;
switch (desc.Format)
{
default: pf = RagePixelFormat_Invalid; FAIL_M("Unknown pixel format"); break;
case D3DFMT_X8R8G8B8: pf = RagePixelFormat_RGBA8; break;
case D3DFMT_A8R8G8B8: pf = RagePixelFormat_RGBA8; break;
// 16-bit formats are not here. Does anybody actually use them?
}
RageSurface *surface = CreateSurfaceFromPixfmt(pf, lr.pBits, desc.Width, desc.Height, lr.Pitch);
ASSERT(nullptr != surface);
// We need to make a copy, since lr.pBits will go away when we call UnlockRect(). // We need to make a copy, since lr.pBits will go away when we call UnlockRect().
result = result =
CreateSurface( surface->w, surface->h, CreateSurface(surface->w, surface->h,
surface->format->BitsPerPixel, surface->format->BitsPerPixel,
surface->format->Rmask, surface->format->Gmask, surface->format->Rmask, surface->format->Gmask,
surface->format->Bmask, surface->format->Amask ); surface->format->Bmask, surface->format->Amask);
RageSurfaceUtils::CopySurface( surface, result ); RageSurfaceUtils::CopySurface(surface, result);
delete surface; delete surface;
pCopy->UnlockRect(); pCopy->UnlockRect();