Skip to content

Commit

Permalink
[dxgi] Implement swapchain dispatcher
Browse files Browse the repository at this point in the history
Some overlays and hooks check if the vtable funcs reside in the dxgi.dll module.

Fixes: #1996
  • Loading branch information
misyltoad authored and doitsujin committed Mar 30, 2021
1 parent 9e646a3 commit a690210
Show file tree
Hide file tree
Showing 2 changed files with 292 additions and 2 deletions.
14 changes: 12 additions & 2 deletions src/dxgi/dxgi_factory.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "dxgi_factory.h"
#include "dxgi_swapchain.h"
#include "dxgi_swapchain_dispatcher.h"

namespace dxvk {

Expand Down Expand Up @@ -130,9 +131,18 @@ namespace dxvk {
if (SUCCEEDED(pDevice->QueryInterface(
__uuidof(IWineDXGISwapChainFactory),
reinterpret_cast<void**>(&wineDevice)))) {
return wineDevice->CreateSwapChainForHwnd(
IDXGISwapChain4* frontendSwapChain;

HRESULT hr = wineDevice->CreateSwapChainForHwnd(
this, hWnd, pDesc, pFullscreenDesc,
pRestrictToOutput, ppSwapChain);
pRestrictToOutput, reinterpret_cast<IDXGISwapChain1**>(&frontendSwapChain));

// No ref as that's handled by the object we're wrapping
// which was ref'ed on creation.
if (SUCCEEDED(hr))
*ppSwapChain = new DxgiSwapChainDispatcher(frontendSwapChain);

return hr;
}

Logger::err("DXGI: CreateSwapChainForHwnd: Unsupported device type");
Expand Down
280 changes: 280 additions & 0 deletions src/dxgi/dxgi_swapchain_dispatcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
#pragma once

#include "dxgi_swapchain.h"

namespace dxvk {

class DxgiSwapChainDispatcher : public IDXGISwapChain4 {

public:

DxgiSwapChainDispatcher(IDXGISwapChain4* dispatch)
: m_dispatch(dispatch) {
}

virtual ~DxgiSwapChainDispatcher() {
}

ULONG STDMETHODCALLTYPE AddRef() {
return m_dispatch->AddRef();
}

ULONG STDMETHODCALLTYPE Release() {
ULONG refCount = m_dispatch->Release();

if (unlikely(!refCount))
delete this;

return refCount;
}

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;
}

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 {
return m_dispatch->GetFullscreenState(pFullscreen, ppTarget);
}

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 {
return m_dispatch->SetFullscreenState(Fullscreen, pTarget);
}


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:

IDXGISwapChain4* m_dispatch;

};

}

0 comments on commit a690210

Please sign in to comment.