mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-24 13:54:17 +01:00
312 lines
9.8 KiB
C++
312 lines
9.8 KiB
C++
#pragma once
|
|
|
|
#include "dxgi_swapchain.h"
|
|
|
|
namespace dxvk {
|
|
|
|
class DxgiSwapChainDispatcher : public IDXGISwapChain4 {
|
|
|
|
public:
|
|
|
|
DxgiSwapChainDispatcher(IDXGISwapChain4* dispatch, IUnknown* device)
|
|
: m_device(device),
|
|
m_dispatch(dispatch) {
|
|
}
|
|
|
|
virtual ~DxgiSwapChainDispatcher() {
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE AddRef() {
|
|
if (likely(m_dispatch != nullptr))
|
|
return m_dispatch->AddRef();
|
|
|
|
return 0;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE Release() {
|
|
if (likely(m_dispatch != nullptr)) {
|
|
ULONG refCount = m_dispatch->Release();
|
|
|
|
if (unlikely(!refCount)) {
|
|
// Clear the underlying swap chain pointer. Helps in
|
|
// use-after-free situations encountered in Divinity
|
|
// Original Sin Enhanced Edition.
|
|
m_dispatch = nullptr;
|
|
delete this;
|
|
}
|
|
|
|
return refCount;
|
|
}
|
|
|
|
return ~0u;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
|
REFIID riid,
|
|
void** ppvObject) final {
|
|
if (ppvObject == nullptr)
|
|
return E_POINTER;
|
|
|
|
*ppvObject = nullptr;
|
|
|
|
if (riid == __uuidof(IUnknown)
|
|
|| riid == __uuidof(IDXGIObject)
|
|
|| riid == __uuidof(IDXGIDeviceSubObject)
|
|
|| riid == __uuidof(IDXGISwapChain)
|
|
|| riid == __uuidof(IDXGISwapChain1)
|
|
|| riid == __uuidof(IDXGISwapChain2)
|
|
|| riid == __uuidof(IDXGISwapChain3)
|
|
|| riid == __uuidof(IDXGISwapChain4)) {
|
|
*ppvObject = ref(this);
|
|
return S_OK;
|
|
}
|
|
|
|
if (logQueryInterfaceError(__uuidof(IDXGISwapChain), riid)) {
|
|
Logger::warn("DxgiSwapChainDispatcher::QueryInterface: Unknown interface query");
|
|
Logger::warn(str::format(riid));
|
|
}
|
|
|
|
return m_dispatch->QueryInterface(riid, ppvObject);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetPrivateData(
|
|
REFGUID Name,
|
|
UINT* pDataSize,
|
|
void* pData) final {
|
|
return m_dispatch->GetPrivateData(Name, pDataSize, pData);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE SetPrivateData(
|
|
REFGUID Name,
|
|
UINT DataSize,
|
|
const void* pData) final {
|
|
return m_dispatch->SetPrivateData(Name, DataSize, pData);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
|
|
REFGUID Name,
|
|
const IUnknown* pUnknown) final {
|
|
return m_dispatch->SetPrivateDataInterface(Name, pUnknown);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetParent(
|
|
REFIID riid,
|
|
void** ppParent) final {
|
|
return m_dispatch->GetParent(riid, ppParent);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetDevice(
|
|
REFIID riid,
|
|
void** ppDevice) final {
|
|
return m_dispatch->GetDevice(riid, ppDevice);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetBuffer(
|
|
UINT Buffer,
|
|
REFIID riid,
|
|
void** ppSurface) final {
|
|
return m_dispatch->GetBuffer(Buffer, riid, ppSurface);
|
|
}
|
|
|
|
UINT STDMETHODCALLTYPE GetCurrentBackBufferIndex() final {
|
|
return m_dispatch->GetCurrentBackBufferIndex();
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetContainingOutput(
|
|
IDXGIOutput** ppOutput) final {
|
|
return m_dispatch->GetContainingOutput(ppOutput);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetDesc(
|
|
DXGI_SWAP_CHAIN_DESC* pDesc) final {
|
|
return m_dispatch->GetDesc(pDesc);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetDesc1(
|
|
DXGI_SWAP_CHAIN_DESC1* pDesc) final {
|
|
return m_dispatch->GetDesc1(pDesc);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetFullscreenState(
|
|
BOOL* pFullscreen,
|
|
IDXGIOutput** ppTarget) final {
|
|
if (likely(m_dispatch != nullptr))
|
|
return m_dispatch->GetFullscreenState(pFullscreen, ppTarget);
|
|
|
|
if (pFullscreen)
|
|
*pFullscreen = FALSE;
|
|
|
|
if (ppTarget)
|
|
*ppTarget = nullptr;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetFullscreenDesc(
|
|
DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc) final {
|
|
return m_dispatch->GetFullscreenDesc(pDesc);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetHwnd(
|
|
HWND* pHwnd) final {
|
|
return m_dispatch->GetHwnd(pHwnd);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetCoreWindow(
|
|
REFIID refiid,
|
|
void** ppUnk) final {
|
|
return m_dispatch->GetCoreWindow(refiid, ppUnk);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetBackgroundColor(
|
|
DXGI_RGBA* pColor) final {
|
|
return m_dispatch->GetBackgroundColor(pColor);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetRotation(
|
|
DXGI_MODE_ROTATION* pRotation) final {
|
|
return m_dispatch->GetRotation(pRotation);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetRestrictToOutput(
|
|
IDXGIOutput** ppRestrictToOutput) final {
|
|
return m_dispatch->GetRestrictToOutput(ppRestrictToOutput);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetFrameStatistics(
|
|
DXGI_FRAME_STATISTICS* pStats) final {
|
|
return m_dispatch->GetFrameStatistics(pStats);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetLastPresentCount(
|
|
UINT* pLastPresentCount) final {
|
|
return m_dispatch->GetLastPresentCount(pLastPresentCount);
|
|
}
|
|
|
|
BOOL STDMETHODCALLTYPE IsTemporaryMonoSupported() final {
|
|
return m_dispatch->IsTemporaryMonoSupported();
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE Present(
|
|
UINT SyncInterval,
|
|
UINT Flags) final {
|
|
return m_dispatch->Present(SyncInterval, Flags);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE Present1(
|
|
UINT SyncInterval,
|
|
UINT PresentFlags,
|
|
const DXGI_PRESENT_PARAMETERS* pPresentParameters) final {
|
|
return m_dispatch->Present1(SyncInterval, PresentFlags, pPresentParameters);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE ResizeBuffers(
|
|
UINT BufferCount,
|
|
UINT Width,
|
|
UINT Height,
|
|
DXGI_FORMAT NewFormat,
|
|
UINT SwapChainFlags) final {
|
|
return m_dispatch->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE ResizeBuffers1(
|
|
UINT BufferCount,
|
|
UINT Width,
|
|
UINT Height,
|
|
DXGI_FORMAT Format,
|
|
UINT SwapChainFlags,
|
|
const UINT* pCreationNodeMask,
|
|
IUnknown* const* ppPresentQueue) final {
|
|
return m_dispatch->ResizeBuffers1(BufferCount, Width, Height, Format, SwapChainFlags, pCreationNodeMask, ppPresentQueue);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE ResizeTarget(
|
|
const DXGI_MODE_DESC* pNewTargetParameters) final {
|
|
return m_dispatch->ResizeTarget(pNewTargetParameters);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE SetFullscreenState(
|
|
BOOL Fullscreen,
|
|
IDXGIOutput* pTarget) final {
|
|
if (likely(m_dispatch != nullptr))
|
|
return m_dispatch->SetFullscreenState(Fullscreen, pTarget);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE SetBackgroundColor(
|
|
const DXGI_RGBA* pColor) final {
|
|
return m_dispatch->SetBackgroundColor(pColor);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE SetRotation(
|
|
DXGI_MODE_ROTATION Rotation) final {
|
|
return m_dispatch->SetRotation(Rotation);
|
|
}
|
|
|
|
HANDLE STDMETHODCALLTYPE GetFrameLatencyWaitableObject() final {
|
|
return m_dispatch->GetFrameLatencyWaitableObject();
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetMatrixTransform(
|
|
DXGI_MATRIX_3X2_F* pMatrix) final {
|
|
return m_dispatch->GetMatrixTransform(pMatrix);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(
|
|
UINT* pMaxLatency) final {
|
|
return m_dispatch->GetMaximumFrameLatency(pMaxLatency);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE GetSourceSize(
|
|
UINT* pWidth,
|
|
UINT* pHeight) final {
|
|
return m_dispatch->GetSourceSize(pWidth, pHeight);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE SetMatrixTransform(
|
|
const DXGI_MATRIX_3X2_F* pMatrix) final {
|
|
return m_dispatch->SetMatrixTransform(pMatrix);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(
|
|
UINT MaxLatency) final {
|
|
return m_dispatch->SetMaximumFrameLatency(MaxLatency);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE SetSourceSize(
|
|
UINT Width,
|
|
UINT Height) final {
|
|
return m_dispatch->SetSourceSize(Width, Height);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CheckColorSpaceSupport(
|
|
DXGI_COLOR_SPACE_TYPE ColorSpace,
|
|
UINT* pColorSpaceSupport) final {
|
|
return m_dispatch->CheckColorSpaceSupport(ColorSpace, pColorSpaceSupport);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE SetColorSpace1(
|
|
DXGI_COLOR_SPACE_TYPE ColorSpace) final {
|
|
return m_dispatch->SetColorSpace1(ColorSpace);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE SetHDRMetaData(
|
|
DXGI_HDR_METADATA_TYPE Type,
|
|
UINT Size,
|
|
void* pMetaData) final {
|
|
return m_dispatch->SetHDRMetaData(Type, Size, pMetaData);
|
|
}
|
|
|
|
private:
|
|
|
|
// m_device is not used or reference counted, provided for compatibility with mod engines
|
|
// which expect to find device pointer in the memory after swapchain interface.
|
|
IUnknown* m_device;
|
|
|
|
IDXGISwapChain4* m_dispatch;
|
|
|
|
};
|
|
|
|
}
|