#include "d3d9_fake_swapchain.h" #include #include #include "util/logging.h" #if 1 #define WRAP_VERBOSE log_misc("graphics::d3d9", "FakeIDirect3DSwapChain9::{}", __FUNCTION__) #define WRAP_VERBOSE_FMT(format, ...) log_misc("graphics::d3d9", format, __VA_ARGS__) #else #define WRAP_VERBOSE #define WRAP_VERBOSE_FMT(format, ...) #endif // IDirect3DSwapChain9 HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::QueryInterface(REFIID riid, void **ppvObj) { if (ppvObj == nullptr) { return E_POINTER; } if (riid == IID_IUnknown || riid == IID_IDirect3DSwapChain9 || riid == IID_IDirect3DSwapChain9Ex) { #pragma region Update to IDirect3DSwapChain9Ex interface if (!is_d3d9ex && riid == IID_IDirect3DSwapChain9Ex) { is_d3d9ex = true; } #pragma endregion AddRef(); *ppvObj = this; return S_OK; } return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE FakeIDirect3DSwapChain9::AddRef(void) { return ++this->ref_cnt; } ULONG STDMETHODCALLTYPE FakeIDirect3DSwapChain9::Release(void) { ULONG refs = --this->ref_cnt; if (refs == 0) { delete this; } return refs; } HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::Present(const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags) { static std::once_flag printed; std::call_once(printed, []() { log_misc("graphics::d3d9", "FakeIDirect3DSwapChain9::Present"); }); if (!is_hidden) { return D3DERR_INVALIDCALL; } present_count.fetch_add(1, std::memory_order_relaxed); return D3D_OK; } HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetFrontBufferData(IDirect3DSurface9 *pDestSurface) { WRAP_VERBOSE; return D3DERR_INVALIDCALL; } HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetBackBuffer(UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer) { static std::once_flag printed; std::call_once(printed, []() { log_misc("graphics::d3d9", "FakeIDirect3DSwapChain9::GetBackBuffer"); }); if (iBackBuffer >= render_targets.size() || Type != D3DBACKBUFFER_TYPE_MONO || !ppBackBuffer) { return D3DERR_INVALIDCALL; } auto &render_target = render_targets[iBackBuffer]; render_target->AddRef(); *ppBackBuffer = render_target; return D3D_OK; } HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetRasterStatus(D3DRASTER_STATUS *pRasterStatus) { WRAP_VERBOSE; if (!is_hidden) { return D3DERR_INVALIDCALL; } if (pRasterStatus == nullptr) { return D3DERR_INVALIDCALL; } *pRasterStatus = {}; return D3D_OK; } HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetDisplayMode(D3DDISPLAYMODE *pMode) { WRAP_VERBOSE; if (!is_hidden) { return D3DERR_INVALIDCALL; } if (pMode == nullptr) { return D3DERR_INVALIDCALL; } pMode->Width = present_params.BackBufferWidth; pMode->Height = present_params.BackBufferHeight; pMode->RefreshRate = present_params.FullScreen_RefreshRateInHz; pMode->Format = present_params.BackBufferFormat; return D3D_OK; } HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetDevice(IDirect3DDevice9 **ppDevice) { WRAP_VERBOSE; if (ppDevice == nullptr) { return D3DERR_INVALIDCALL; } pDev->AddRef(); *ppDevice = pDev; return D3D_OK; } HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetPresentParameters( D3DPRESENT_PARAMETERS *pPresentationParameters) { WRAP_VERBOSE; if (!is_hidden) { return D3DERR_INVALIDCALL; } if (pPresentationParameters == nullptr) { return D3DERR_INVALIDCALL; } *pPresentationParameters = present_params; return D3D_OK; } // IDirect3DSwapChain9Ex HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetLastPresentCount(UINT *pLastPresentCount) { assert(is_d3d9ex); if (!is_hidden) { return D3DERR_INVALIDCALL; } if (pLastPresentCount == nullptr) { return D3DERR_INVALIDCALL; } *pLastPresentCount = present_count.load(std::memory_order_relaxed); return D3D_OK; } HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetPresentStats(D3DPRESENTSTATS *pPresentationStatistics) { assert(is_d3d9ex); if (!is_hidden) { return D3DERR_INVALIDCALL; } if (pPresentationStatistics == nullptr) { return D3DERR_INVALIDCALL; } *pPresentationStatistics = {}; pPresentationStatistics->PresentCount = present_count.load(std::memory_order_relaxed); return D3D_OK; } HRESULT STDMETHODCALLTYPE FakeIDirect3DSwapChain9::GetDisplayModeEx(D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) { WRAP_VERBOSE; assert(is_d3d9ex); if (!is_hidden) { return D3DERR_INVALIDCALL; } if (pMode == nullptr) { return D3DERR_INVALIDCALL; } pMode->Size = sizeof(*pMode); pMode->Width = present_params.BackBufferWidth; pMode->Height = present_params.BackBufferHeight; pMode->RefreshRate = present_params.FullScreen_RefreshRateInHz; pMode->Format = present_params.BackBufferFormat; pMode->ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE; if (pRotation != nullptr) { *pRotation = D3DDISPLAYROTATION_IDENTITY; } return D3D_OK; }