mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-09-30 22:14:55 -07:00
103 lines
3.0 KiB
C++
103 lines
3.0 KiB
C++
// dx11 factory vtable hooks. patches CreateSwapChain / CreateSwapChainForHwnd
|
|
// so we can install_swapchain_hooks against every newly-created swapchain.
|
|
|
|
#include "d3d11_backend.h"
|
|
|
|
#ifdef SPICE_D3D11
|
|
|
|
#include <mutex>
|
|
|
|
#include <windows.h>
|
|
#include <d3d11.h>
|
|
#include <dxgi.h>
|
|
#include <dxgi1_2.h>
|
|
|
|
#include "d3d11_internal.h"
|
|
|
|
namespace {
|
|
|
|
using CreateSwapChain_t = HRESULT(STDMETHODCALLTYPE *)(
|
|
IDXGIFactory *, IUnknown *, DXGI_SWAP_CHAIN_DESC *, IDXGISwapChain **);
|
|
using CreateSwapChainForHwnd_t = HRESULT(STDMETHODCALLTYPE *)(
|
|
IDXGIFactory2 *, IUnknown *, HWND,
|
|
const DXGI_SWAP_CHAIN_DESC1 *,
|
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *,
|
|
IDXGIOutput *, IDXGISwapChain1 **);
|
|
|
|
CreateSwapChain_t CreateSwapChain_orig = nullptr;
|
|
CreateSwapChainForHwnd_t CreateSwapChainForHwnd_orig = nullptr;
|
|
|
|
bool g_factory_hooked = false;
|
|
bool g_factory2_hooked = false;
|
|
std::mutex g_hook_mutex;
|
|
|
|
HRESULT STDMETHODCALLTYPE CreateSwapChain_hook(
|
|
IDXGIFactory *factory, IUnknown *pDevice,
|
|
DXGI_SWAP_CHAIN_DESC *pDesc, IDXGISwapChain **ppSwapChain)
|
|
{
|
|
HRESULT res = CreateSwapChain_orig(factory, pDevice, pDesc, ppSwapChain);
|
|
if (SUCCEEDED(res) && ppSwapChain && *ppSwapChain) {
|
|
if (pDesc) {
|
|
d3d11_hooks::note_main_hwnd(pDesc->OutputWindow);
|
|
}
|
|
d3d11_hooks::install_swapchain_hooks(*ppSwapChain);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd_hook(
|
|
IDXGIFactory2 *factory, IUnknown *pDevice, HWND hWnd,
|
|
const DXGI_SWAP_CHAIN_DESC1 *pDesc,
|
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc,
|
|
IDXGIOutput *pRestrictToOutput, IDXGISwapChain1 **ppSwapChain)
|
|
{
|
|
HRESULT res = CreateSwapChainForHwnd_orig(
|
|
factory, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain);
|
|
if (SUCCEEDED(res) && ppSwapChain && *ppSwapChain) {
|
|
d3d11_hooks::note_main_hwnd(hWnd);
|
|
d3d11_hooks::install_swapchain_hooks(*ppSwapChain);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
// QI-and-hook helper: dedupes the IDXGIFactory / IDXGIFactory2 install paths.
|
|
template<typename Iface>
|
|
void install_on(IUnknown *factory, bool &flag,
|
|
size_t vtbl_index, void *hook, void **orig, const char *name)
|
|
{
|
|
if (flag) {
|
|
return;
|
|
}
|
|
Iface *f = nullptr;
|
|
if (FAILED(factory->QueryInterface(IID_PPV_ARGS(&f))) || !f) {
|
|
return;
|
|
}
|
|
if (d3d11_hooks::hook_vtbl(f, vtbl_index, hook, orig, name)) {
|
|
flag = true;
|
|
}
|
|
f->Release();
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace d3d11_hooks {
|
|
|
|
void install_factory_hooks(IUnknown *factory) {
|
|
if (!factory) {
|
|
return;
|
|
}
|
|
std::lock_guard<std::mutex> lock(g_hook_mutex);
|
|
|
|
install_on<IDXGIFactory>(factory, g_factory_hooked, 10,
|
|
(void *) CreateSwapChain_hook, (void **) &CreateSwapChain_orig,
|
|
"IDXGIFactory::CreateSwapChain");
|
|
|
|
install_on<IDXGIFactory2>(factory, g_factory2_hooked, 15,
|
|
(void *) CreateSwapChainForHwnd_hook, (void **) &CreateSwapChainForHwnd_orig,
|
|
"IDXGIFactory2::CreateSwapChainForHwnd");
|
|
}
|
|
|
|
}
|
|
|
|
#endif // SPICE_D3D11
|