#include "d3d9_device.h" #include #include #include "avs/game.h" #include "hooks/graphics/graphics.h" #include "overlay/overlay.h" #include "util/flags_helper.h" #include "cfg/screen_resize.h" #include "d3d9_backend.h" #include "d3d9_texture.h" #ifndef SPICE64 #include "shaders/vertex_shader.h" #endif #define CHECK_RESULT_FMT(x, fmt, ...) \ HRESULT __ret = (x); \ if (GRAPHICS_LOG_HRESULT && FAILED(__ret)) [[unlikely]] { \ log_warning("graphics::d3d9", "{} failed, hr={} " fmt, __FUNCTION__, FMT_HRESULT(__ret), ## __VA_ARGS__); \ } \ return __ret #define CHECK_RESULT(x) \ HRESULT __ret = (x); \ if (GRAPHICS_LOG_HRESULT && FAILED(__ret)) [[unlikely]] { \ log_warning("graphics::d3d9", "{} failed, hr={}", __FUNCTION__, FMT_HRESULT(__ret)); \ } \ return __ret // TODO: At some point, support a manual `Reset` call by reloading all textures constexpr bool CUSTOM_RESET = false; constexpr D3DFORMAT D3DFMT_DF24 = static_cast(MAKEFOURCC('D', 'F', '2', '4')); std::string usage2s(DWORD dwUsage) { FLAGS_START(dwUsage); FLAG(dwUsage, D3DUSAGE_RENDERTARGET); FLAG(dwUsage, D3DUSAGE_DEPTHSTENCIL); FLAG(dwUsage, D3DUSAGE_WRITEONLY); FLAG(dwUsage, D3DUSAGE_SOFTWAREPROCESSING); FLAG(dwUsage, D3DUSAGE_DONOTCLIP); FLAG(dwUsage, D3DUSAGE_POINTS); FLAG(dwUsage, D3DUSAGE_RTPATCHES); FLAG(dwUsage, D3DUSAGE_NPATCHES); FLAG(dwUsage, D3DUSAGE_DYNAMIC); FLAG(dwUsage, D3DUSAGE_AUTOGENMIPMAP); FLAG(dwUsage, D3DUSAGE_DMAP); FLAGS_END(dwUsage); } std::string pool2s(D3DPOOL Pool) { switch (Pool) { ENUM_VARIANT(D3DPOOL_DEFAULT); ENUM_VARIANT(D3DPOOL_MANAGED); ENUM_VARIANT(D3DPOOL_SYSTEMMEM); ENUM_VARIANT(D3DPOOL_SCRATCH); default: return fmt::format("Pool(0x{:08x})", Pool); } } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::QueryInterface( REFIID riid, void **ppvObj) { if (ppvObj == nullptr) { return E_POINTER; } if (riid == IID_WrappedIDirect3DDevice9 || riid == IID_IDirect3DDevice9 || riid == IID_IDirect3DDevice9Ex) { // update to IDirect3DDevice9Ex interface if (!is_d3d9ex && riid == IID_IDirect3DDevice9Ex) { IDirect3DDevice9Ex *deviceex = nullptr; HRESULT ret = pReal->QueryInterface(IID_PPV_ARGS(&deviceex)); if (FAILED(ret) || deviceex == nullptr) { if (ret != E_NOINTERFACE) { log_warning("graphics::d3d9", "failed to upgrade to IDirect3DDevice9Ex, hr={}", FMT_HRESULT(ret)); } return E_NOINTERFACE; } pReal->Release(); pReal = deviceex; is_d3d9ex = true; } this->AddRef(); *ppvObj = this; return S_OK; } return pReal->QueryInterface(riid, ppvObj); } ULONG STDMETHODCALLTYPE WrappedIDirect3DDevice9::AddRef() { this->refs++; return pReal->AddRef(); } ULONG STDMETHODCALLTYPE WrappedIDirect3DDevice9::Release() { // get what this thread thinks the reference count is auto local_refs = --this->refs; // release owned objects if there are no more references if (local_refs == 0) { if (this->main_swapchain) { this->main_swapchain->Release(); this->main_swapchain = nullptr; } if (this->sub_swapchain) { this->sub_swapchain->Release(); this->sub_swapchain = nullptr; } if (this->fake_sub_swapchain) { this->fake_sub_swapchain->Release(); this->fake_sub_swapchain = nullptr; } if (overlay::ENABLED) { const std::lock_guard lock(overlay::OVERLAY_MUTEX); // release overlay if we are the backing device which will release its owned references if (overlay::OVERLAY && overlay::OVERLAY->uses_device(this->pReal)) { overlay::OVERLAY.reset(); } } } // get reference count of underlying interface ULONG refs = this->pReal != nullptr ? this->pReal->Release() : 0; // the reference counts should be equivalent at this point, so log if they are not if (local_refs == 0 && refs != 0) { log_warning("graphics::d3d9", "reference count for `IDirect3DDevice9` object {} wrapping {} " "is inconsistent: {}, but expected 0", fmt::ptr(this), fmt::ptr(this->pReal), refs); refs = 0; } if (refs == 0) { delete this; } return refs; } /* * IDirect3DDevice9 */ HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::TestCooperativeLevel() { WRAP_VERBOSE; CHECK_RESULT(pReal->TestCooperativeLevel()); } UINT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetAvailableTextureMem() { WRAP_DEBUG; return pReal->GetAvailableTextureMem(); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::EvictManagedResources() { WRAP_VERBOSE; CHECK_RESULT(pReal->EvictManagedResources()); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetDirect3D( IDirect3D9 **ppD3D9) { WRAP_VERBOSE; CHECK_RESULT(pReal->GetDirect3D(ppD3D9)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetDeviceCaps( D3DCAPS9 *pCaps) { WRAP_VERBOSE; CHECK_RESULT(pReal->GetDeviceCaps(pCaps)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetDisplayMode( UINT iSwapChain, D3DDISPLAYMODE *pMode) { WRAP_VERBOSE; CHECK_RESULT(pReal->GetDisplayMode(iSwapChain, pMode)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetCreationParameters( D3DDEVICE_CREATION_PARAMETERS *pParameters) { WRAP_VERBOSE; CHECK_RESULT(pReal->GetCreationParameters(pParameters)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetCursorProperties( UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9 *pCursorBitmap) { WRAP_VERBOSE; CHECK_RESULT(pReal->SetCursorProperties(XHotSpot, YHotSpot, pCursorBitmap)); } void STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetCursorPosition( int X, int Y, DWORD Flags) { WRAP_VERBOSE; return pReal->SetCursorPosition(X, Y, Flags); } BOOL STDMETHODCALLTYPE WrappedIDirect3DDevice9::ShowCursor( BOOL bShow) { WRAP_VERBOSE; return pReal->ShowCursor(bShow); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateAdditionalSwapChain( D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DSwapChain9 **ppSwapChain) { WRAP_VERBOSE; HRESULT hr = pReal->CreateAdditionalSwapChain(pPresentationParameters, ppSwapChain); if (avs::game::is_model({"LDJ", "KFC"})) { if (SUCCEEDED(hr) && !sub_swapchain) { sub_swapchain = new WrappedIDirect3DSwapChain9(this, *ppSwapChain); sub_swapchain->should_run_hooks = false; } else if (FAILED(hr) && !fake_sub_swapchain) { log_warning("graphics::d3d9", "failed to create sub swap chain, hr={}, using fake swap chain", FMT_HRESULT(hr)); fake_sub_swapchain = new FakeIDirect3DSwapChain9(this, pPresentationParameters, false); fake_sub_swapchain->AddRef(); *ppSwapChain = static_cast(fake_sub_swapchain); return D3D_OK; } } CHECK_RESULT(hr); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetSwapChain( UINT iSwapChain, IDirect3DSwapChain9 **ppSwapChain) { WRAP_VERBOSE_FMT("GetSwapChain({})", iSwapChain); if (iSwapChain == 0) { if (!main_swapchain) { HRESULT ret = pReal->GetSwapChain(iSwapChain, ppSwapChain); if (FAILED(ret)) { log_warning("graphics::d3d9", "failed to get swapchain {}, hr={}", iSwapChain, FMT_HRESULT(ret)); return ret; } main_swapchain = new WrappedIDirect3DSwapChain9(this, *ppSwapChain); } main_swapchain->AddRef(); *ppSwapChain = static_cast(main_swapchain); graphics_screens_register(iSwapChain); return D3D_OK; } if (iSwapChain == 1 && avs::game::is_model({"LDJ", "KFC"})) { if (sub_swapchain) { sub_swapchain->AddRef(); *ppSwapChain = static_cast(sub_swapchain); graphics_screens_register(iSwapChain); return D3D_OK; } else if (fake_sub_swapchain) { fake_sub_swapchain->AddRef(); *ppSwapChain = static_cast(fake_sub_swapchain); graphics_screens_register(iSwapChain); return D3D_OK; } } HRESULT ret = pReal->GetSwapChain(iSwapChain, ppSwapChain); if (GRAPHICS_LOG_HRESULT && FAILED(ret)) { log_warning("graphics::d3d9", "{} failed, hr={}", __FUNCTION__, FMT_HRESULT(ret)); } else { graphics_screens_register(iSwapChain); } return ret; } UINT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetNumberOfSwapChains() { WRAP_VERBOSE; UINT n = pReal->GetNumberOfSwapChains(); if (sub_swapchain && avs::game::is_model({"LDJ", "KFC"})) { n += 1; } return n; } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::Reset( D3DPRESENT_PARAMETERS *pPresentationParameters) { log_misc("graphics::d3d9", "WrappedIDirect3DDevice9::Reset"); if (pPresentationParameters) { if (GRAPHICS_WINDOWED) { pPresentationParameters->Windowed = true; pPresentationParameters->FullScreen_RefreshRateInHz = 0; } else if (GRAPHICS_FORCE_REFRESH > 0) { pPresentationParameters->FullScreen_RefreshRateInHz = GRAPHICS_FORCE_REFRESH; } } // reset overlay if (overlay::OVERLAY && overlay::OVERLAY->uses_device(pReal)) { overlay::OVERLAY->reset_invalidate(); } HRESULT res = pReal->Reset(pPresentationParameters); // recreate overlay if (overlay::OVERLAY && overlay::OVERLAY->uses_device(pReal) && SUCCEEDED(res)) { overlay::OVERLAY->reset_recreate(); } CHECK_RESULT(res); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::Present( const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion) { WRAP_DEBUG; static std::once_flag printed; std::call_once(printed, []() { log_misc("graphics::d3d9", "WrappedIDirect3DDevice9::Present"); }); graphics_d3d9_on_present(hFocusWindow, pReal, this); CHECK_RESULT(pReal->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetBackBuffer( UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer) { WRAP_VERBOSE; CHECK_RESULT(pReal->GetBackBuffer(iSwapChain, iBackBuffer, Type, ppBackBuffer)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetRasterStatus( UINT iSwapChain, D3DRASTER_STATUS *pRasterStatus) { WRAP_DEBUG; CHECK_RESULT(pReal->GetRasterStatus(iSwapChain, pRasterStatus)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetDialogBoxMode( BOOL bEnableDialogs) { WRAP_DEBUG; CHECK_RESULT(pReal->SetDialogBoxMode(bEnableDialogs)); } void STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetGammaRamp( UINT iSwapChain, DWORD Flags, const D3DGAMMARAMP *pRamp) { WRAP_DEBUG; pReal->SetGammaRamp(iSwapChain, Flags, pRamp); } void STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetGammaRamp( UINT iSwapChain, D3DGAMMARAMP *pRamp) { WRAP_DEBUG; pReal->GetGammaRamp(iSwapChain, pRamp); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateTexture( UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9 **ppTexture, HANDLE *pSharedHandle) { WRAP_VERBOSE_FMT("CreateTexture({}, {}, {}, {}, {}, {})", Width, Height, Levels, usage2s(Usage), Format, pool2s(Pool)); // fix nvidia proprietary depthstencil texture format if (avs::game::is_model("I36") && (Usage & D3DUSAGE_DEPTHSTENCIL) && Format == D3DFMT_DF24) { HRESULT ret = pReal->CreateTexture(Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle); if (FAILED(ret)) { Format = D3DFMT_D24S8; } else { return ret; } } #ifndef SPICE64 // texture fix for iidx (iix18 resort anthem, iidx19 lincle) if (avs::game::is_model({ "JDZ", "KDZ" })) { // patch texture format type from 15-bit+alpha to 32-bit. if (Width == 256 && Height == 256 && Levels == 1 && Usage == D3DUSAGE_RENDERTARGET && Format == D3DFMT_A1R5G5B5 && Pool == D3DPOOL_DEFAULT && !pSharedHandle) { Format = D3DFMT_A8R8G8B8; } } #endif HRESULT res = pReal->CreateTexture(Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle); if (CUSTOM_RESET && ppTexture && Pool == D3DPOOL_MANAGED && SUCCEEDED(res)) { *ppTexture = new WrappedIDirect3DTexture9(this, *ppTexture); } CHECK_RESULT_FMT(res, "({}, {}, {}, {}, {}, {})", Width, Height, Levels, usage2s(Usage), Format, pool2s(Pool)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateVolumeTexture( UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9 **ppVolumeTexture, HANDLE *pSharedHandle) { WRAP_VERBOSE_FMT("CreateVolumeTexture({}, {}, {}, {}, {}, {}, {})", Width, Height, Depth, Levels, usage2s(Usage), Format, pool2s(Pool)); CHECK_RESULT(pReal->CreateVolumeTexture(Width, Height, Depth, Levels, Usage, Format, Pool, ppVolumeTexture, pSharedHandle)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateCubeTexture( UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9 **ppCubeTexture, HANDLE *pSharedHandle) { WRAP_VERBOSE_FMT("CreateCubeTexture({}, {}, {}, {}, {})", EdgeLength, Levels, usage2s(Usage), Format, pool2s(Pool)); CHECK_RESULT(pReal->CreateCubeTexture( EdgeLength, Levels, Usage, Format, Pool, ppCubeTexture, pSharedHandle)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateVertexBuffer( UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9 **ppVertexBuffer, HANDLE *pSharedHandle) { WRAP_VERBOSE_FMT("CreateVertexBuffer({}, {}, {}, {})", Length, usage2s(Usage), FVF, pool2s(Pool)); CHECK_RESULT(pReal->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateIndexBuffer( UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9 **ppIndexBuffer, HANDLE *pSharedHandle) { WRAP_VERBOSE_FMT("CreateIndexBuffer({}, {}, {}, {})", Length, usage2s(Usage), Format, pool2s(Pool)); CHECK_RESULT(pReal->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, pSharedHandle)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateRenderTarget( UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) { WRAP_VERBOSE_FMT("CreateRenderTarget({}, {}, {}, {}, {}, {})", Width, Height, Format, MultiSample, MultisampleQuality, Lockable); CHECK_RESULT(pReal->CreateRenderTarget(Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateDepthStencilSurface( UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) { WRAP_DEBUG; CHECK_RESULT(pReal->CreateDepthStencilSurface(Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::UpdateSurface( IDirect3DSurface9 *pSourceSurface, const RECT *pSourceRect, IDirect3DSurface9 *pDestinationSurface, const POINT *pDestPoint) { WRAP_DEBUG; CHECK_RESULT(pReal->UpdateSurface(pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::UpdateTexture( IDirect3DBaseTexture9 *pSourceTexture, IDirect3DBaseTexture9 *pDestinationTexture) { WRAP_DEBUG; if (CUSTOM_RESET) { #ifdef __GNUC__ // Do a pointer compare rather than `QueryInterface` because it is a lot cheaper than incrementing // the reference count if (pSourceTexture && (&pSourceTexture->QueryInterface) == WrappedIDirect3DTexture9::QueryInterface) { pSourceTexture = static_cast(pSourceTexture)->pReal; } if (pDestinationTexture && (&pDestinationTexture->QueryInterface) == WrappedIDirect3DTexture9::QueryInterface) { pDestinationTexture = static_cast(pDestinationTexture)->pReal; } #else void *dummy = nullptr; if (pSourceTexture && SUCCEEDED(pSourceTexture->QueryInterface( IID_WrappedIDirect3DTexture9, &dummy))) { pSourceTexture = static_cast(pSourceTexture)->pReal; } if (pDestinationTexture && SUCCEEDED(pDestinationTexture->QueryInterface( IID_WrappedIDirect3DTexture9, &dummy))) { pDestinationTexture = static_cast(pDestinationTexture)->pReal; } #endif } CHECK_RESULT(pReal->UpdateTexture(pSourceTexture, pDestinationTexture)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetRenderTargetData( IDirect3DSurface9 *pRenderTarget, IDirect3DSurface9 *pDestSurface) { WRAP_DEBUG; CHECK_RESULT(pReal->GetRenderTargetData(pRenderTarget, pDestSurface)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetFrontBufferData( UINT iSwapChain, IDirect3DSurface9 *pDestSurface) { WRAP_DEBUG; CHECK_RESULT(pReal->GetFrontBufferData(iSwapChain, pDestSurface)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::StretchRect( IDirect3DSurface9 *pSourceSurface, const RECT *pSourceRect, IDirect3DSurface9 *pDestSurface, const RECT *pDestRect, D3DTEXTUREFILTERTYPE Filter) { WRAP_DEBUG; CHECK_RESULT(pReal->StretchRect(pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::ColorFill( IDirect3DSurface9 *pSurface, const RECT *pRect, D3DCOLOR color) { WRAP_DEBUG; CHECK_RESULT(pReal->ColorFill(pSurface, pRect, color)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateOffscreenPlainSurface( UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) { WRAP_VERBOSE_FMT("CreateOffscreenPlainSurface({}, {}, {}, {})", Width, Height, Format, pool2s(Pool)); CHECK_RESULT(pReal->CreateOffscreenPlainSurface( Width, Height, Format, Pool, ppSurface, pSharedHandle)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetRenderTarget( DWORD RenderTargetIndex, IDirect3DSurface9 *pRenderTarget) { WRAP_DEBUG; CHECK_RESULT(pReal->SetRenderTarget(RenderTargetIndex, pRenderTarget)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetRenderTarget( DWORD RenderTargetIndex, IDirect3DSurface9 **ppRenderTarget) { WRAP_DEBUG; return pReal->GetRenderTarget(RenderTargetIndex, ppRenderTarget); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetDepthStencilSurface( IDirect3DSurface9 *pNewZStencil) { WRAP_DEBUG; CHECK_RESULT(pReal->SetDepthStencilSurface(pNewZStencil)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetDepthStencilSurface( IDirect3DSurface9 **ppZStencilSurface) { WRAP_DEBUG; CHECK_RESULT(pReal->GetDepthStencilSurface(ppZStencilSurface)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::BeginScene() { WRAP_DEBUG; static std::once_flag printed; std::call_once(printed, []() { log_misc("graphics::d3d9", "WrappedIDirect3DDevice9::BeginScene"); }); return pReal->BeginScene(); } static IDirect3DSurface9 *topSurface = nullptr; static IDirect3DSurface9 *backbuffer = nullptr; static LPDIRECT3DSWAPCHAIN9 mSwapChain = nullptr; static IDirect3DTexture9* tex; void SurfaceHook(IDirect3DDevice9 *pReal) { // log_misc("graphics::d3d9", "SurfaceHook called"); D3DPRESENT_PARAMETERS param {}; pReal->GetSwapChain(0, &mSwapChain); mSwapChain->GetPresentParameters(¶m); if (!topSurface) { if (pReal->CreateTexture(4096, 4096, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL) != D3D_OK) { log_misc("graphics::d3d9", "create texture failed"); } log_misc("graphics::d3d9", "Backbuffer: {} {} {}", param.BackBufferWidth, param.BackBufferHeight, param.BackBufferCount); tex->GetSurfaceLevel(0, &topSurface); if (mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer) != D3D_OK) { log_misc("graphics::d3d9", "GetBackBuffer failed"); } } const int rectLeft = 1024; const int rectTop = 576; const int w = param.BackBufferWidth; const int h = param.BackBufferHeight; D3DLOCKED_RECT rect; RECT targetRect { rectLeft, rectTop, (LONG)(rectLeft + w), (LONG)(rectTop + h), }; // stretch to add top/left offset to avoid going negative topSurface->LockRect(&rect, NULL, D3DLOCK_DONOTWAIT); auto hr = pReal->StretchRect( backbuffer, nullptr, topSurface, &targetRect, D3DTEXF_LINEAR); if (hr != D3D_OK) { log_misc("graphics::d3d9", "StretchRect backbuffer failed"); } topSurface->UnlockRect(); // do the actual zoom / offset math if (cfg::SCREENRESIZE->centered) { targetRect.right = (w + rectLeft) / cfg::SCREENRESIZE->scale_x; targetRect.bottom = (h + rectTop) / cfg::SCREENRESIZE->scale_y; const LONG deltaH = ((targetRect.bottom - targetRect.top) - h) / 2; const LONG deltaW = ((targetRect.right - targetRect.left) - w) / 2; targetRect.top -= deltaH; targetRect.bottom -= deltaH; targetRect.left -= deltaW; targetRect.right -= deltaW; } else { targetRect.left -= cfg::SCREENRESIZE->offset_x; targetRect.top += cfg::SCREENRESIZE->offset_y; targetRect.right = -cfg::SCREENRESIZE->offset_x; targetRect.right += (w + rectLeft) / cfg::SCREENRESIZE->scale_x; targetRect.bottom = cfg::SCREENRESIZE->offset_y; targetRect.bottom += (h + rectTop) / cfg::SCREENRESIZE->scale_y; } // draw to back buffer backbuffer->LockRect(&rect, NULL, D3DLOCK_DONOTWAIT); hr = pReal->StretchRect( topSurface, &targetRect, backbuffer, nullptr, cfg::SCREENRESIZE->enable_linear_filter ? D3DTEXF_LINEAR : D3DTEXF_NONE); backbuffer->UnlockRect(); if (hr != D3D_OK) { log_misc("graphics::d3d9", "StretchRect targetRect failed"); } } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::EndScene() { WRAP_DEBUG; if (cfg::SCREENRESIZE->enable_screen_resize) { SurfaceHook(pReal); } static std::once_flag printed; std::call_once(printed, []() { log_misc("graphics::d3d9", "WrappedIDirect3DDevice9::EndScene"); }); return pReal->EndScene(); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::Clear( DWORD Count, const D3DRECT *pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) { WRAP_DEBUG; CHECK_RESULT(pReal->Clear(Count, pRects, Flags, Color, Z, Stencil)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetTransform( D3DTRANSFORMSTATETYPE State, const D3DMATRIX *pMatrix) { WRAP_DEBUG; CHECK_RESULT(pReal->SetTransform(State, pMatrix)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetTransform( D3DTRANSFORMSTATETYPE State, D3DMATRIX *pMatrix) { WRAP_DEBUG; CHECK_RESULT(pReal->GetTransform(State, pMatrix)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::MultiplyTransform( D3DTRANSFORMSTATETYPE State, const D3DMATRIX *pMatrix) { WRAP_DEBUG; CHECK_RESULT(pReal->MultiplyTransform(State, pMatrix)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetViewport( const D3DVIEWPORT9 *pViewport) { WRAP_DEBUG; #ifndef SPICE64 if (avs::game::is_model({ "JDZ", "KDZ", "K39", "L39", "LBR" })) { // Set vertex shader constant to half pixel viewport offset const float ConstantHalfTexelFixupOffset[2] = {-1.0F / (float)pViewport->Width, 1.0F / (float)pViewport->Height}; HRESULT ret = pReal->SetVertexShaderConstantF(63, ConstantHalfTexelFixupOffset, sizeof(ConstantHalfTexelFixupOffset) / sizeof(ConstantHalfTexelFixupOffset[0])); CHECK_RESULT(ret); } #endif CHECK_RESULT(pReal->SetViewport(pViewport)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetViewport( D3DVIEWPORT9 *pViewport) { WRAP_DEBUG; CHECK_RESULT(pReal->GetViewport(pViewport)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetMaterial( const D3DMATERIAL9 *pMaterial) { WRAP_DEBUG; CHECK_RESULT(pReal->SetMaterial(pMaterial)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetMaterial( D3DMATERIAL9 *pMaterial) { WRAP_DEBUG; CHECK_RESULT(pReal->GetMaterial(pMaterial)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetLight( DWORD Index, const D3DLIGHT9 *pLight) { WRAP_DEBUG; CHECK_RESULT(pReal->SetLight(Index, pLight)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetLight( DWORD Index, D3DLIGHT9 *pLight) { WRAP_DEBUG; CHECK_RESULT(pReal->GetLight(Index, pLight)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::LightEnable( DWORD Index, BOOL Enable) { WRAP_DEBUG; CHECK_RESULT(pReal->LightEnable(Index, Enable)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetLightEnable( DWORD Index, BOOL *pEnable) { WRAP_DEBUG; CHECK_RESULT(pReal->GetLightEnable(Index, pEnable)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetClipPlane( DWORD Index, const float *pPlane) { WRAP_DEBUG; CHECK_RESULT(pReal->SetClipPlane(Index, pPlane)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetClipPlane( DWORD Index, float *pPlane) { WRAP_DEBUG; CHECK_RESULT(pReal->GetClipPlane(Index, pPlane)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetRenderState( D3DRENDERSTATETYPE State, DWORD Value) { WRAP_DEBUG; CHECK_RESULT(pReal->SetRenderState(State, Value)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetRenderState( D3DRENDERSTATETYPE State, DWORD *pValue) { WRAP_DEBUG; CHECK_RESULT(pReal->GetRenderState(State, pValue)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateStateBlock( D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9 **ppSB) { WRAP_DEBUG; CHECK_RESULT(pReal->CreateStateBlock(Type, ppSB)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::BeginStateBlock() { WRAP_DEBUG; return pReal->BeginStateBlock(); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::EndStateBlock( IDirect3DStateBlock9 **ppSB) { WRAP_DEBUG; CHECK_RESULT(pReal->EndStateBlock(ppSB)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetClipStatus( const D3DCLIPSTATUS9 *pClipStatus) { WRAP_DEBUG; CHECK_RESULT(pReal->SetClipStatus(pClipStatus)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetClipStatus( D3DCLIPSTATUS9 *pClipStatus) { WRAP_DEBUG; CHECK_RESULT(pReal->GetClipStatus(pClipStatus)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetTexture( DWORD Stage, IDirect3DBaseTexture9 **ppTexture) { WRAP_DEBUG; CHECK_RESULT(pReal->GetTexture(Stage, ppTexture)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetTexture( DWORD Stage, IDirect3DBaseTexture9 *pTexture) { WRAP_DEBUG_FMT("SetTexture({}, {})", Stage, fmt::ptr(pTexture)); if (CUSTOM_RESET) { void *dummy = nullptr; if (pTexture && SUCCEEDED(pTexture->QueryInterface( IID_WrappedIDirect3DTexture9, &dummy))) { pTexture = static_cast(pTexture)->pReal; } } CHECK_RESULT(pReal->SetTexture(Stage, pTexture)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pValue) { WRAP_DEBUG; CHECK_RESULT(pReal->GetTextureStageState(Stage, Type, pValue)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) { WRAP_DEBUG; CHECK_RESULT(pReal->SetTextureStageState(Stage, Type, Value)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD *pValue) { WRAP_DEBUG; CHECK_RESULT(pReal->GetSamplerState(Sampler, Type, pValue)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) { WRAP_DEBUG; CHECK_RESULT(pReal->SetSamplerState(Sampler, Type, Value)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::ValidateDevice( DWORD *pNumPasses) { WRAP_VERBOSE; CHECK_RESULT(pReal->ValidateDevice(pNumPasses)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetPaletteEntries( UINT PaletteNumber, const PALETTEENTRY *pEntries) { WRAP_DEBUG; CHECK_RESULT(pReal->SetPaletteEntries(PaletteNumber, pEntries)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetPaletteEntries( UINT PaletteNumber, PALETTEENTRY *pEntries) { WRAP_DEBUG; CHECK_RESULT(pReal->GetPaletteEntries(PaletteNumber, pEntries)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetCurrentTexturePalette( UINT PaletteNumber) { WRAP_DEBUG; CHECK_RESULT(pReal->SetCurrentTexturePalette(PaletteNumber)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetCurrentTexturePalette( UINT *PaletteNumber) { WRAP_DEBUG; CHECK_RESULT(pReal->GetCurrentTexturePalette(PaletteNumber)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetScissorRect( const RECT *pRect) { WRAP_DEBUG; CHECK_RESULT(pReal->SetScissorRect(pRect)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetScissorRect( RECT *pRect) { WRAP_DEBUG; CHECK_RESULT(pReal->GetScissorRect(pRect)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetSoftwareVertexProcessing( BOOL bSoftware) { WRAP_VERBOSE; CHECK_RESULT(pReal->SetSoftwareVertexProcessing(bSoftware)); } BOOL STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetSoftwareVertexProcessing() { WRAP_VERBOSE; return pReal->GetSoftwareVertexProcessing(); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetNPatchMode(float nSegments) { WRAP_DEBUG; CHECK_RESULT(pReal->SetNPatchMode(nSegments)); } float STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetNPatchMode() { WRAP_DEBUG; return pReal->GetNPatchMode(); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) { WRAP_DEBUG; CHECK_RESULT(pReal->DrawPrimitive(PrimitiveType, StartVertex, PrimitiveCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::DrawIndexedPrimitive( D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount) { WRAP_DEBUG; CHECK_RESULT(pReal->DrawIndexedPrimitive( PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, StartIndex, PrimitiveCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::DrawPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void *pVertexStreamZeroData, UINT VertexStreamZeroStride) { WRAP_DEBUG_FMT("DrawPrimitiveUP({}, {}, {}, {})", PrimitiveType, PrimitiveCount, fmt::ptr(pVertexStreamZeroData), VertexStreamZeroStride); CHECK_RESULT(pReal->DrawPrimitiveUP( PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::DrawIndexedPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount, const void *pIndexData, D3DFORMAT IndexDataFormat, const void *pVertexStreamZeroData, UINT VertexStreamZeroStride) { WRAP_DEBUG; CHECK_RESULT(pReal->DrawIndexedPrimitiveUP( PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::ProcessVertices( UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9 *pDestBuffer, IDirect3DVertexDeclaration9 *pVertexDecl, DWORD Flags) { WRAP_DEBUG; CHECK_RESULT(pReal->ProcessVertices(SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateVertexDeclaration( const D3DVERTEXELEMENT9 *pVertexElements, IDirect3DVertexDeclaration9 **ppDecl) { WRAP_DEBUG; CHECK_RESULT(pReal->CreateVertexDeclaration(pVertexElements, ppDecl)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetVertexDeclaration( IDirect3DVertexDeclaration9 *pDecl) { WRAP_DEBUG; CHECK_RESULT(pReal->SetVertexDeclaration(pDecl)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetVertexDeclaration( IDirect3DVertexDeclaration9 **ppDecl) { WRAP_DEBUG; CHECK_RESULT(pReal->GetVertexDeclaration(ppDecl)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetFVF( DWORD FVF) { WRAP_DEBUG; CHECK_RESULT(pReal->SetFVF(FVF)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetFVF( DWORD *pFVF) { WRAP_DEBUG; CHECK_RESULT(pReal->GetFVF(pFVF)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateVertexShader( const DWORD *pFunction, IDirect3DVertexShader9 **ppShader) { WRAP_VERBOSE_FMT("CreateVertexShader({})", fmt::ptr(pFunction)); CHECK_RESULT(pReal->CreateVertexShader(pFunction, ppShader)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetVertexShader( IDirect3DVertexShader9 *pShader) { WRAP_DEBUG_FMT("SetVertexShader({})", fmt::ptr(pShader)); #ifndef SPICE64 // diagonal line fix if (avs::game::is_model({ "JDZ", "KDZ", "K39", "L39", "LBR" })) { if (!vertex_shader) { log_info("graphics::d3d9", "initializing and setting up vertex shaders"); // create and set up the vertex shader shim HRESULT ret = pReal->CreateVertexShader((const DWORD *) g_vs11_vs_main, &vertex_shader); if (FAILED(ret)) { log_warning("graphics::d3d9", "CreateVertexShader failed, hr={}", FMT_HRESULT(ret)); } } if (pShader != nullptr) { pShader = vertex_shader; } } #endif CHECK_RESULT(pReal->SetVertexShader(pShader)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetVertexShader( IDirect3DVertexShader9 **ppShader) { WRAP_DEBUG; CHECK_RESULT(pReal->GetVertexShader(ppShader)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetVertexShaderConstantF( UINT StartRegister, const float *pConstantData, UINT Vector4fCount) { WRAP_DEBUG; CHECK_RESULT(pReal->SetVertexShaderConstantF( StartRegister, pConstantData, Vector4fCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetVertexShaderConstantF( UINT StartRegister, float *pConstantData, UINT Vector4fCount) { WRAP_DEBUG; CHECK_RESULT(pReal->GetVertexShaderConstantF( StartRegister, pConstantData, Vector4fCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetVertexShaderConstantI( UINT StartRegister, const int *pConstantData, UINT Vector4iCount) { WRAP_DEBUG; CHECK_RESULT(pReal->SetVertexShaderConstantI( StartRegister, pConstantData, Vector4iCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetVertexShaderConstantI( UINT StartRegister, int *pConstantData, UINT Vector4iCount) { WRAP_DEBUG; CHECK_RESULT(pReal->GetVertexShaderConstantI( StartRegister, pConstantData, Vector4iCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetVertexShaderConstantB( UINT StartRegister, const BOOL *pConstantData, UINT BoolCount) { WRAP_DEBUG; CHECK_RESULT(pReal->SetVertexShaderConstantB( StartRegister, pConstantData, BoolCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetVertexShaderConstantB( UINT StartRegister, BOOL *pConstantData, UINT BoolCount) { WRAP_DEBUG; CHECK_RESULT(pReal->GetVertexShaderConstantB( StartRegister, pConstantData, BoolCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetStreamSource( UINT StreamNumber, IDirect3DVertexBuffer9 *pStreamData, UINT OffsetInBytes, UINT Stride) { WRAP_DEBUG; CHECK_RESULT(pReal->SetStreamSource( StreamNumber, pStreamData, OffsetInBytes, Stride)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetStreamSource( UINT StreamNumber, IDirect3DVertexBuffer9 **ppStreamData, UINT *OffsetInBytes, UINT *pStride) { WRAP_DEBUG; CHECK_RESULT(pReal->GetStreamSource( StreamNumber, ppStreamData, OffsetInBytes, pStride)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetStreamSourceFreq( UINT StreamNumber, UINT Divider) { WRAP_DEBUG; return pReal->SetStreamSourceFreq(StreamNumber, Divider); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetStreamSourceFreq( UINT StreamNumber, UINT *Divider) { WRAP_DEBUG; CHECK_RESULT(pReal->GetStreamSourceFreq(StreamNumber, Divider)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetIndices( IDirect3DIndexBuffer9 *pIndexData) { WRAP_DEBUG; CHECK_RESULT(pReal->SetIndices(pIndexData)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetIndices( IDirect3DIndexBuffer9 **ppIndexData) { WRAP_DEBUG; CHECK_RESULT(pReal->GetIndices(ppIndexData)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreatePixelShader( const DWORD *pFunction, IDirect3DPixelShader9 **ppShader) { WRAP_VERBOSE_FMT("CreatePixelShader({})", fmt::ptr(pFunction)); CHECK_RESULT(pReal->CreatePixelShader(pFunction, ppShader)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetPixelShader( IDirect3DPixelShader9 *pShader) { WRAP_DEBUG_FMT("SetPixelShader({})", fmt::ptr(pShader)); CHECK_RESULT(pReal->SetPixelShader(pShader)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetPixelShader( IDirect3DPixelShader9 **ppShader) { WRAP_DEBUG; CHECK_RESULT(pReal->GetPixelShader(ppShader)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetPixelShaderConstantF( UINT StartRegister, const float *pConstantData, UINT Vector4fCount) { WRAP_DEBUG; CHECK_RESULT(pReal->SetPixelShaderConstantF( StartRegister, pConstantData, Vector4fCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetPixelShaderConstantF( UINT StartRegister, float *pConstantData, UINT Vector4fCount) { WRAP_DEBUG; CHECK_RESULT(pReal->GetPixelShaderConstantF( StartRegister, pConstantData, Vector4fCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetPixelShaderConstantI( UINT StartRegister, const int *pConstantData, UINT Vector4iCount) { WRAP_DEBUG; CHECK_RESULT(pReal->SetPixelShaderConstantI( StartRegister, pConstantData, Vector4iCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetPixelShaderConstantI( UINT StartRegister, int *pConstantData, UINT Vector4iCount) { WRAP_DEBUG; CHECK_RESULT(pReal->GetPixelShaderConstantI( StartRegister, pConstantData, Vector4iCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetPixelShaderConstantB( UINT StartRegister, const BOOL *pConstantData, UINT BoolCount) { WRAP_DEBUG; CHECK_RESULT(pReal->SetPixelShaderConstantB( StartRegister, pConstantData, BoolCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetPixelShaderConstantB( UINT StartRegister, BOOL *pConstantData, UINT BoolCount) { WRAP_DEBUG; CHECK_RESULT(pReal->GetPixelShaderConstantB( StartRegister, pConstantData, BoolCount)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::DrawRectPatch( UINT Handle, const float *pNumSegs, const D3DRECTPATCH_INFO *pRectPatchInfo) { WRAP_DEBUG; CHECK_RESULT(pReal->DrawRectPatch(Handle, pNumSegs, pRectPatchInfo)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::DrawTriPatch( UINT Handle, const float *pNumSegs, const D3DTRIPATCH_INFO *pTriPatchInfo) { WRAP_DEBUG; CHECK_RESULT(pReal->DrawTriPatch(Handle, pNumSegs, pTriPatchInfo)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::DeletePatch(UINT Handle) { WRAP_VERBOSE; CHECK_RESULT(pReal->DeletePatch(Handle)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateQuery( D3DQUERYTYPE Type, IDirect3DQuery9 **ppQuery) { WRAP_DEBUG; CHECK_RESULT(pReal->CreateQuery(Type, ppQuery)); } /* * IDirect3DDevice9Ex */ HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetConvolutionMonoKernel( UINT width, UINT height, float *rows, float *columns) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->SetConvolutionMonoKernel( width, height, rows, columns)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::ComposeRects( IDirect3DSurface9 *pSrc, IDirect3DSurface9 *pDst, IDirect3DVertexBuffer9 *pSrcRectDescs, UINT NumRects, IDirect3DVertexBuffer9 *pDstRectDescs, D3DCOMPOSERECTSOP Operation, int Xoffset, int Yoffset) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->ComposeRects( pSrc, pDst, pSrcRectDescs, NumRects, pDstRectDescs, Operation, Xoffset, Yoffset)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::PresentEx( const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags) { WRAP_DEBUG; assert(is_d3d9ex); static std::once_flag printed; std::call_once(printed, []() { log_misc("graphics::d3d9", "WrappedIDirect3DDevice9::PresentEx"); }); graphics_d3d9_on_present(hFocusWindow, pReal, this); CHECK_RESULT(static_cast(pReal)->PresentEx( pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetGPUThreadPriority( INT *pPriority) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->GetGPUThreadPriority(pPriority)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetGPUThreadPriority( INT Priority) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->SetGPUThreadPriority(Priority)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::WaitForVBlank( UINT iSwapChain) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->WaitForVBlank(iSwapChain)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CheckResourceResidency( IDirect3DResource9 **pResourceArray, UINT32 NumResources) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->CheckResourceResidency( pResourceArray, NumResources)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::SetMaximumFrameLatency( UINT MaxLatency) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->SetMaximumFrameLatency(MaxLatency)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetMaximumFrameLatency( UINT *pMaxLatency) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->GetMaximumFrameLatency(pMaxLatency)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CheckDeviceState(HWND hDestinationWindow) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->CheckDeviceState(hDestinationWindow)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateRenderTargetEx( UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->CreateRenderTargetEx( Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle, Usage)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateOffscreenPlainSurfaceEx( UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->CreateOffscreenPlainSurfaceEx( Width, Height, Format, Pool, ppSurface, pSharedHandle, Usage)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::CreateDepthStencilSurfaceEx( UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->CreateDepthStencilSurfaceEx( Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle, Usage)); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::ResetEx( D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX *pFullscreenDisplayMode) { WRAP_DEBUG; assert(is_d3d9ex); log_misc("graphics::d3d9", "WrappedIDirect3DDevice9::ResetEx"); if (GRAPHICS_WINDOWED) { if (pPresentationParameters) { pPresentationParameters->Windowed = true; pPresentationParameters->FullScreen_RefreshRateInHz = 0; } pFullscreenDisplayMode = nullptr; } else if (GRAPHICS_FORCE_REFRESH > 0) { if (pPresentationParameters) { pPresentationParameters->FullScreen_RefreshRateInHz = GRAPHICS_FORCE_REFRESH; } if (pFullscreenDisplayMode) { pFullscreenDisplayMode->RefreshRate = GRAPHICS_FORCE_REFRESH; } } // reset overlay if (overlay::OVERLAY && overlay::OVERLAY->uses_device(pReal)) { overlay::OVERLAY->reset_invalidate(); } HRESULT res = static_cast(pReal)->ResetEx( pPresentationParameters, pFullscreenDisplayMode); // recreate overlay if (overlay::OVERLAY && overlay::OVERLAY->uses_device(pReal) && SUCCEEDED(res)) { overlay::OVERLAY->reset_recreate(); } CHECK_RESULT(res); } HRESULT STDMETHODCALLTYPE WrappedIDirect3DDevice9::GetDisplayModeEx( UINT iSwapChain, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) { WRAP_DEBUG; assert(is_d3d9ex); CHECK_RESULT(static_cast(pReal)->GetDisplayModeEx( iSwapChain, pMode, pRotation)); }