提交 1ca9f887 编写于 作者: J jp9000

win-capture: Add IDXGISwapChain1::Present1 hook support

Allows capturing games/programs that may be using Present1 instead of
the regular Present call for rendering.
上级 96f746ce
#include <windows.h>
#include <d3d10.h>
#include <dxgi.h>
#include <VersionHelpers.h>
#include <dxgi1_2.h>
#include "get-graphics-offsets.h"
typedef HRESULT (WINAPI *d3d10create_t)(IDXGIAdapter*, D3D10_DRIVER_TYPE,
HMODULE, UINT, UINT, DXGI_SWAP_CHAIN_DESC*,
IDXGISwapChain**, IUnknown**);
typedef HRESULT (WINAPI *create_fac_t)(IID *id, void**);
struct dxgi_info {
HMODULE module;
......@@ -13,10 +15,16 @@ struct dxgi_info {
IDXGISwapChain *swap;
};
static const IID dxgiFactory2 =
{0x50c83a1c, 0xe072, 0x4c48, {0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0}};
static inline bool dxgi_init(dxgi_info &info)
{
HMODULE d3d10_module;
d3d10create_t create;
create_fac_t create_factory;
IDXGIFactory1 *factory;
IDXGIAdapter1 *adapter;
IUnknown *device;
HRESULT hr;
......@@ -32,6 +40,9 @@ static inline bool dxgi_init(dxgi_info &info)
return false;
}
create_factory = (create_fac_t)GetProcAddress(info.module,
"CreateDXGIFactory1");
d3d10_module = LoadLibraryA("d3d10.dll");
if (!d3d10_module) {
return false;
......@@ -43,6 +54,21 @@ static inline bool dxgi_init(dxgi_info &info)
return false;
}
IID factory_iid = IsWindows8OrGreater()
? dxgiFactory2
: __uuidof(IDXGIFactory1);
hr = create_factory(&factory_iid, (void**)&factory);
if (FAILED(hr)) {
return false;
}
hr = factory->EnumAdapters1(0, &adapter);
factory->Release();
if (FAILED(hr)) {
return false;
}
DXGI_SWAP_CHAIN_DESC desc = {};
desc.BufferCount = 2;
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
......@@ -53,8 +79,9 @@ static inline bool dxgi_init(dxgi_info &info)
desc.SampleDesc.Count = 1;
desc.Windowed = true;
hr = create(nullptr, D3D10_DRIVER_TYPE_NULL, nullptr, 0,
hr = create(adapter, D3D10_DRIVER_TYPE_HARDWARE, nullptr, 0,
D3D10_SDK_VERSION, &desc, &info.swap, &device);
adapter->Release();
if (FAILED(hr)) {
return false;
}
......@@ -75,10 +102,20 @@ void get_dxgi_offsets(struct dxgi_offsets *offsets)
{
dxgi_info info = {};
bool success = dxgi_init(info);
HRESULT hr;
if (success) {
offsets->present = vtable_offset(info.module, info.swap, 8);
offsets->resize = vtable_offset(info.module, info.swap, 13);
IDXGISwapChain1 *swap1;
hr = info.swap->QueryInterface(__uuidof(IDXGISwapChain1),
(void**)&swap1);
if (SUCCEEDED(hr)) {
offsets->present1 =
vtable_offset(info.module, swap1, 22);
swap1->Release();
}
}
dxgi_free(info);
......
......@@ -34,6 +34,7 @@ int main(int argc, char *argv[])
printf("is_d3d9ex_clsoff=0x%"PRIx32"\n", d3d9.is_d3d9ex_clsoff);
printf("[dxgi]\n");
printf("present=0x%"PRIx32"\n", dxgi.present);
printf("present1=0x%"PRIx32"\n", dxgi.present1);
printf("resize=0x%"PRIx32"\n", dxgi.resize);
(void)argc;
......
......@@ -42,6 +42,8 @@ struct d3d9_offsets {
struct dxgi_offsets {
uint32_t present;
uint32_t resize;
uint32_t present1;
};
struct ddraw_offsets {
......
#include <d3d10_1.h>
#include <d3d11.h>
#include <dxgi.h>
#include <dxgi1_2.h>
#include <d3dcompiler.h>
#include "d3d1x_shaders.hpp"
......@@ -14,9 +14,12 @@
typedef HRESULT (STDMETHODCALLTYPE *resize_buffers_t)(IDXGISwapChain*, UINT,
UINT, UINT, DXGI_FORMAT, UINT);
typedef HRESULT (STDMETHODCALLTYPE *present_t)(IDXGISwapChain*, UINT, UINT);
typedef HRESULT (STDMETHODCALLTYPE *present1_t)(IDXGISwapChain1*, UINT, UINT,
const DXGI_PRESENT_PARAMETERS *);
static struct func_hook resize_buffers;
static struct func_hook present;
static struct func_hook present1;
struct dxgi_swap_data {
IDXGISwapChain *swap;
......@@ -165,6 +168,53 @@ static HRESULT STDMETHODCALLTYPE hook_present(IDXGISwapChain *swap,
return hr;
}
static HRESULT STDMETHODCALLTYPE hook_present1(IDXGISwapChain1 *swap,
UINT sync_interval, UINT flags,
const DXGI_PRESENT_PARAMETERS *params)
{
IUnknown *backbuffer = nullptr;
bool capture_overlay = global_hook_info->capture_overlay;
bool test_draw = (flags & DXGI_PRESENT_TEST) != 0;
bool capture;
HRESULT hr;
if (!data.swap && !capture_active()) {
setup_dxgi(swap);
}
capture = !test_draw && swap == data.swap && !!data.capture;
if (capture && !capture_overlay) {
backbuffer = get_dxgi_backbuffer(swap);
if (!!backbuffer) {
DXGI_SWAP_CHAIN_DESC1 desc;
swap->GetDesc1(&desc);
data.capture(swap, backbuffer, capture_overlay);
backbuffer->Release();
}
}
unhook(&present1);
present1_t call = (present1_t)present1.call_addr;
hr = call(swap, sync_interval, flags, params);
rehook(&present1);
if (capture && capture_overlay) {
if (resize_buffers_called) {
resize_buffers_called = false;
} else {
backbuffer = get_dxgi_backbuffer(swap);
if (!!backbuffer) {
data.capture(swap, backbuffer, capture_overlay);
backbuffer->Release();
}
}
}
return hr;
}
static pD3DCompile get_compiler(void)
{
pD3DCompile compile = nullptr;
......@@ -202,6 +252,7 @@ bool hook_dxgi(void)
HRESULT hr;
void *present_addr;
void *resize_addr;
void *present1_addr = nullptr;
if (!dxgi_module) {
return false;
......@@ -251,14 +302,22 @@ bool hook_dxgi(void)
global_hook_info->offsets.dxgi.present);
resize_addr = get_offset_addr(dxgi_module,
global_hook_info->offsets.dxgi.resize);
if (global_hook_info->offsets.dxgi.present1)
present1_addr = get_offset_addr(dxgi_module,
global_hook_info->offsets.dxgi.present1);
hook_init(&present, present_addr, (void*)hook_present,
"IDXGISwapChain::Present");
hook_init(&resize_buffers, resize_addr, (void*)hook_resize_buffers,
"IDXGISwapChain::ResizeBuffers");
if (present1_addr)
hook_init(&present1, present1_addr, (void*)hook_present1,
"IDXGISwapChain1::Present1");
rehook(&resize_buffers);
rehook(&present);
if (present1_addr)
rehook(&present1);
hlog("Hooked DXGI");
return true;
......
......@@ -36,6 +36,8 @@ static inline bool load_offsets_from_string(struct graphics_offsets *offsets,
offsets->dxgi.present =
(uint32_t)config_get_uint(config, "dxgi", "present");
offsets->dxgi.present1 =
(uint32_t)config_get_uint(config, "dxgi", "present1");
offsets->dxgi.resize =
(uint32_t)config_get_uint(config, "dxgi", "resize");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册