Skip to content

Commit 7492b0c

Browse files
committed
Merge janblade PR y4my4my4m#2 with reviewed window-sized and composition swapchain handling
2 parents 3e83edf + 0328a5b commit 7492b0c

10 files changed

Lines changed: 330 additions & 22 deletions

‎OptiScaler/OptiScaler.vcxproj‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
328328
<ClInclude Include="fsr4\FSR4ModelSelection.h" />
329329
<ClInclude Include="hooks\D3D12_Hooks.h" />
330330
<ClInclude Include="hooks\DxgiFactory_Hooks.h" />
331+
<ClInclude Include="hooks\DxgiSwapchainSizing.h" />
331332
<ClInclude Include="hooks\DxgiFactory_WrappedCalls.h" />
332333
<ClInclude Include="hooks\Dxgi_Hooks.h" />
333334
<ClInclude Include="hooks\FG_Hooks.h" />

‎OptiScaler/hooks/DxgiFactory_Hooks.cpp‎

Lines changed: 104 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "pch.h"
22
#include "DxgiFactory_Hooks.h"
3+
#include "DxgiSwapchainSizing.h"
34

45
#include "D3D11_Hooks.h"
56
#include "D3D12_Hooks.h"
@@ -116,6 +117,7 @@ void DxgiFactoryHooks::HookToFactory(IDXGIFactory* pFactory)
116117
IDXGIFactory2* factory2 = nullptr;
117118
if (pFactory->QueryInterface(IID_PPV_ARGS(&factory2)) == S_OK)
118119
{
120+
void** factory2VTable = *reinterpret_cast<void***>(factory2);
119121
factory2->Release();
120122

121123
if (o_CreateSwapChainForHwnd == nullptr)
@@ -133,6 +135,13 @@ void DxgiFactoryHooks::HookToFactory(IDXGIFactory* pFactory)
133135
if (o_CreateSwapChainForCoreWindow != nullptr)
134136
DetourAttach(&(PVOID&) o_CreateSwapChainForCoreWindow, DxgiFactoryHooks::CreateSwapChainForCoreWindow);
135137
}
138+
139+
if (o_CreateSwapChainForComposition == nullptr)
140+
{
141+
o_CreateSwapChainForComposition = (PFN_CreateSwapChainForComposition) factory2VTable[24];
142+
if (o_CreateSwapChainForComposition != nullptr)
143+
DetourAttach(&(PVOID&) o_CreateSwapChainForComposition, DxgiFactoryHooks::CreateSwapChainForComposition);
144+
}
136145
}
137146

138147
IDXGIFactory4* factory4 = nullptr;
@@ -172,6 +181,7 @@ void DxgiFactoryHooks::HookToFactory(IDXGIFactory* pFactory)
172181
o_EnumAdapters1 = nullptr;
173182
o_CreateSwapChainForHwnd = nullptr;
174183
o_CreateSwapChainForCoreWindow = nullptr;
184+
o_CreateSwapChainForComposition = nullptr;
175185
o_EnumAdapterByLuid = nullptr;
176186
o_EnumAdapterByGpuPreference = nullptr;
177187
}
@@ -261,9 +271,14 @@ HRESULT DxgiFactoryHooks::CreateSwapChain(IDXGIFactory* realFactory, IUnknown* p
261271
return res;
262272
}
263273

264-
if (pDesc->BufferDesc.Height < 100 || pDesc->BufferDesc.Width < 100)
274+
DXGI_SWAP_CHAIN_DESC localDesc = *pDesc;
275+
const bool sizeToWindow = ResolveWindowSizedSwapchain(localDesc);
276+
277+
if (localDesc.BufferDesc.Height < 100 || localDesc.BufferDesc.Width < 100)
265278
{
266-
LOG_WARN("Overlay call!");
279+
LOG_WARN("Overlay call! Width: {}, Height: {}, Format: {}, Count: {}, Hwnd: {:X}, Windowed: {}",
280+
pDesc->BufferDesc.Width, pDesc->BufferDesc.Height, (UINT) pDesc->BufferDesc.Format,
281+
pDesc->BufferCount, (SIZE_T) pDesc->OutputWindow, pDesc->Windowed);
267282

268283
ScopedSkipDxgiLoadChecks skipDxgiLoadChecks {};
269284
ScopedSkipParentWrapping skipParentWrapping {};
@@ -272,8 +287,9 @@ HRESULT DxgiFactoryHooks::CreateSwapChain(IDXGIFactory* realFactory, IUnknown* p
272287
return res;
273288
}
274289

275-
DXGI_SWAP_CHAIN_DESC localDesc {};
276-
memcpy(&localDesc, pDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
290+
if (sizeToWindow)
291+
LOG_INFO("CreateSwapChain: 0x0 size-to-window descriptor, Hwnd: {:X}, Count: {}, wrapping normally",
292+
(SIZE_T) pDesc->OutputWindow, pDesc->BufferCount);
277293

278294
LOG_DEBUG("Width: {}, Height: {}, Format: {}, Count: {}, Flags: {:X}, Hwnd: {:X}, Windowed: {}, SkipWrapping: {}",
279295
localDesc.BufferDesc.Width, localDesc.BufferDesc.Height, (UINT) localDesc.BufferDesc.Format,
@@ -525,6 +541,19 @@ HRESULT DxgiFactoryHooks::CreateSwapChain(IDXGIFactory* realFactory, IUnknown* p
525541

526542
if (result == S_OK)
527543
{
544+
if (sizeToWindow)
545+
{
546+
// Keep the dimensions actually created by DXGI authoritative for menu sizing.
547+
DXGI_SWAP_CHAIN_DESC resolvedDesc {};
548+
if ((*ppSwapChain)->GetDesc(&resolvedDesc) == S_OK)
549+
{
550+
LOG_INFO("CreateSwapChain: resolved size-to-window swapchain to {}x{}",
551+
resolvedDesc.BufferDesc.Width, resolvedDesc.BufferDesc.Height);
552+
localDesc.BufferDesc.Width = resolvedDesc.BufferDesc.Width;
553+
localDesc.BufferDesc.Height = resolvedDesc.BufferDesc.Height;
554+
}
555+
}
556+
528557
State::Instance().currentSwapchainDesc = localDesc;
529558
State::Instance().swapchainInteropApi = SwapchainInteropApi::None;
530559

@@ -630,7 +659,7 @@ HRESULT DxgiFactoryHooks::CreateSwapChainForHwnd(IDXGIFactory2* realFactory, IUn
630659

631660
if (pDesc->Height < 100 || pDesc->Width < 100)
632661
{
633-
LOG_WARN("Overlay call!");
662+
LOG_WARN("Overlay call! Width: {}, Height: {}", pDesc->Width, pDesc->Height);
634663
HRESULT result;
635664

636665
{
@@ -1010,7 +1039,7 @@ HRESULT DxgiFactoryHooks::CreateSwapChainForCoreWindow(IDXGIFactory2* realFactor
10101039

10111040
if (pDesc->Height < 100 || pDesc->Width < 100)
10121041
{
1013-
LOG_WARN("Overlay call!");
1042+
LOG_WARN("Overlay call! Width: {}, Height: {}", pDesc->Width, pDesc->Height);
10141043

10151044
ScopedSkipDxgiLoadChecks skipDxgiLoadChecks {};
10161045
return realFactory->CreateSwapChainForCoreWindow(pDevice, pWindow, pDesc, pRestrictToOutput, ppSwapChain);
@@ -1099,6 +1128,68 @@ HRESULT DxgiFactoryHooks::CreateSwapChainForCoreWindow(IDXGIFactory2* realFactor
10991128
return result;
11001129
}
11011130

1131+
1132+
HRESULT DxgiFactoryHooks::CreateSwapChainForComposition(IDXGIFactory2* realFactory, IUnknown* pDevice,
1133+
const DXGI_SWAP_CHAIN_DESC1* pDesc,
1134+
IDXGIOutput* pRestrictToOutput,
1135+
IDXGISwapChain1** ppSwapChain)
1136+
{
1137+
// Always call the trampoline, including pass-through/error cases. Calling the detoured virtual
1138+
// method here re-enters this hook. Keep the composition descriptor intact: notably, a desktop
1139+
// VSync override must not turn its FLIP_SEQUENTIAL swap effect into FLIP_DISCARD.
1140+
const bool passThrough = State::Instance().vulkanCreatingSC || _skipFGSwapChainCreation ||
1141+
pDevice == nullptr || pDesc == nullptr || ppSwapChain == nullptr ||
1142+
pDesc->Width < 100 || pDesc->Height < 100;
1143+
if (pDesc != nullptr && (pDesc->Width < 100 || pDesc->Height < 100))
1144+
LOG_WARN("Composition overlay/helper call! Width: {}, Height: {}", pDesc->Width, pDesc->Height);
1145+
1146+
HRESULT result;
1147+
{
1148+
ScopedSkipDxgiLoadChecks skipDxgiLoadChecks {};
1149+
ScopedSkipParentWrapping skipParentWrapping {};
1150+
result = o_CreateSwapChainForComposition(realFactory, pDevice, pDesc, pRestrictToOutput, ppSwapChain);
1151+
}
1152+
if (passThrough || FAILED(result) || *ppSwapChain == nullptr)
1153+
return result;
1154+
1155+
WrappedIDXGISwapChain4* existing = nullptr;
1156+
if ((*ppSwapChain)->QueryInterface(IID_PPV_ARGS(&existing)) == S_OK)
1157+
{
1158+
existing->Release();
1159+
return result;
1160+
}
1161+
1162+
DXGI_SWAP_CHAIN_DESC1 resolved {};
1163+
if (FAILED((*ppSwapChain)->GetDesc1(&resolved)))
1164+
return result; // Do not install a wrapper with unknown dimensions/flags.
1165+
1166+
// A composition chain has no native HWND. Use only an eligible window in this process, and
1167+
// defer overlay initialization to Present if no unambiguous window exists yet. Do not borrow
1168+
// another application's foreground window. HWND association remains a best-effort fallback.
1169+
const HWND window = FindCompositionWindow();
1170+
IDXGISwapChain1* const created = *ppSwapChain;
1171+
auto* wrapped = new WrappedIDXGISwapChain4(created, pDevice, window, resolved.Flags, false, true);
1172+
*ppSwapChain = wrapped;
1173+
1174+
// Preserve the returned COM/proxy chain: the wrapper owns its original reference. Unwrapping it
1175+
// here can leak an outer proxy and bypass another provider's presentation path.
1176+
State::Instance().currentRealSwapchain = created;
1177+
State::Instance().currentSwapchain = wrapped;
1178+
State::Instance().currentWrappedSwapchain = wrapped;
1179+
State::Instance().swapchainInteropApi = SwapchainInteropApi::None;
1180+
State::Instance().SCAllowTearing = (resolved.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) != 0;
1181+
State::Instance().SCLastFlags = resolved.Flags;
1182+
State::Instance().realExclusiveFullscreen = false;
1183+
State::Instance().screenWidth = (float) resolved.Width;
1184+
State::Instance().screenHeight = (float) resolved.Height;
1185+
DXGI_SWAP_CHAIN_DESC legacy {};
1186+
if (SUCCEEDED(created->GetDesc(&legacy)))
1187+
State::Instance().currentSwapchainDesc = legacy;
1188+
LOG_INFO("Wrapped composition swapchain {}x{}, window {:X}; plain presentation, no FG swapchain replacement",
1189+
resolved.Width, resolved.Height, (SIZE_T) window);
1190+
return result;
1191+
}
1192+
11021193
HRESULT DxgiFactoryHooks::DLSSGCreateSwapChain(IDXGIFactory* realFactory, IUnknown* pDevice,
11031194
DXGI_SWAP_CHAIN_DESC* pDesc, IDXGISwapChain** ppSwapChain)
11041195
{
@@ -1131,9 +1222,12 @@ HRESULT DxgiFactoryHooks::DLSSGCreateSwapChain(IDXGIFactory* realFactory, IUnkno
11311222
return res;
11321223
}
11331224

1134-
if (pDesc->BufferDesc.Height < 100 || pDesc->BufferDesc.Width < 100)
1225+
DXGI_SWAP_CHAIN_DESC localDesc = *pDesc;
1226+
ResolveWindowSizedSwapchain(localDesc);
1227+
1228+
if (localDesc.BufferDesc.Height < 100 || localDesc.BufferDesc.Width < 100)
11351229
{
1136-
LOG_WARN("Overlay call!");
1230+
LOG_WARN("Overlay call! Width: {}, Height: {}", pDesc->BufferDesc.Width, pDesc->BufferDesc.Height);
11371231

11381232
ScopedSkipDxgiLoadChecks skipDxgiLoadChecks {};
11391233
ScopedSkipParentWrapping skipParentWrapping {};
@@ -1142,9 +1236,6 @@ HRESULT DxgiFactoryHooks::DLSSGCreateSwapChain(IDXGIFactory* realFactory, IUnkno
11421236
return res;
11431237
}
11441238

1145-
DXGI_SWAP_CHAIN_DESC localDesc {};
1146-
memcpy(&localDesc, pDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
1147-
11481239
LOG_DEBUG("Width: {}, Height: {}, Format: {}, Count: {}, Flags: {:X}, Hwnd: {:X}, Windowed: {}, SkipWrapping: {}",
11491240
localDesc.BufferDesc.Width, localDesc.BufferDesc.Height, (UINT) localDesc.BufferDesc.Format,
11501241
localDesc.BufferCount, localDesc.Flags, (SIZE_T) localDesc.OutputWindow, localDesc.Windowed,
@@ -1427,7 +1518,7 @@ HRESULT DxgiFactoryHooks::DLSSGCreateSwapChainForHwnd(IDXGIFactory2* realFactory
14271518

14281519
if (pDesc->Height < 100 || pDesc->Width < 100)
14291520
{
1430-
LOG_WARN("Overlay call!");
1521+
LOG_WARN("Overlay call! Width: {}, Height: {}", pDesc->Width, pDesc->Height);
14311522
HRESULT result;
14321523

14331524
{
@@ -1722,7 +1813,7 @@ HRESULT DxgiFactoryHooks::DLSSGCreateSwapChainForCoreWindow(IDXGIFactory2* realF
17221813

17231814
if (pDesc->Height < 100 || pDesc->Width < 100)
17241815
{
1725-
LOG_WARN("Overlay call!");
1816+
LOG_WARN("Overlay call! Width: {}, Height: {}", pDesc->Width, pDesc->Height);
17261817

17271818
ScopedSkipDxgiLoadChecks skipDxgiLoadChecks {};
17281819
return realFactory->CreateSwapChainForCoreWindow(pDevice, pWindow, pDesc, pRestrictToOutput, ppSwapChain);

‎OptiScaler/hooks/DxgiFactory_Hooks.h‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class DxgiFactoryHooks
2121
using PFN_CreateSwapChainForHwnd = rewrite_signature<decltype(&IDXGIFactory2::CreateSwapChainForHwnd)>::type;
2222
using PFN_CreateSwapChainForCoreWindow =
2323
rewrite_signature<decltype(&IDXGIFactory2::CreateSwapChainForCoreWindow)>::type;
24+
using PFN_CreateSwapChainForComposition =
25+
rewrite_signature<decltype(&IDXGIFactory2::CreateSwapChainForComposition)>::type;
2426

2527
inline static PFN_EnumAdapterByGpuPreference o_EnumAdapterByGpuPreference = nullptr;
2628
inline static PFN_EnumAdapterByLuid o_EnumAdapterByLuid = nullptr;
@@ -29,6 +31,7 @@ class DxgiFactoryHooks
2931
inline static PFN_CreateSwapChain o_CreateSwapChain = nullptr;
3032
inline static PFN_CreateSwapChainForHwnd o_CreateSwapChainForHwnd = nullptr;
3133
inline static PFN_CreateSwapChainForCoreWindow o_CreateSwapChainForCoreWindow = nullptr;
34+
inline static PFN_CreateSwapChainForComposition o_CreateSwapChainForComposition = nullptr;
3235

3336
inline static PFN_CreateSwapChain o_DLSSGCreateSwapChain = nullptr;
3437
inline static PFN_CreateSwapChainForHwnd o_DLSSGCreateSwapChainForHwnd = nullptr;
@@ -48,6 +51,9 @@ class DxgiFactoryHooks
4851

4952
static HRESULT DLSSGCreateSwapChain(IDXGIFactory* realFactory, IUnknown* pDevice, DXGI_SWAP_CHAIN_DESC* pDesc,
5053
IDXGISwapChain** ppSwapChain);
54+
static HRESULT CreateSwapChainForComposition(IDXGIFactory2* realFactory, IUnknown* pDevice,
55+
const DXGI_SWAP_CHAIN_DESC1* pDesc, IDXGIOutput* pRestrictToOutput,
56+
IDXGISwapChain1** ppSwapChain);
5157

5258
static HRESULT DLSSGCreateSwapChainForHwnd(IDXGIFactory2* realFactory, IUnknown* pDevice, HWND hWnd,
5359
const DXGI_SWAP_CHAIN_DESC1* pDesc,
@@ -67,6 +73,7 @@ class DxgiFactoryHooks
6773
VALIDATE_MEMBER_HOOK(CreateSwapChain, PFN_CreateSwapChain)
6874
VALIDATE_MEMBER_HOOK(CreateSwapChainForHwnd, PFN_CreateSwapChainForHwnd)
6975
VALIDATE_MEMBER_HOOK(CreateSwapChainForCoreWindow, PFN_CreateSwapChainForCoreWindow)
76+
VALIDATE_MEMBER_HOOK(CreateSwapChainForComposition, PFN_CreateSwapChainForComposition)
7077
VALIDATE_MEMBER_HOOK(EnumAdapters, PFN_EnumAdapters)
7178
VALIDATE_MEMBER_HOOK(EnumAdapters1, PFN_EnumAdapters1)
7279
VALIDATE_MEMBER_HOOK(EnumAdapterByLuid, PFN_EnumAdapterByLuid)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#pragma once
2+
3+
#include <windows.h>
4+
#include <dxgi.h>
5+
6+
// Resolve DXGI's 0x0 "use the window's client size" descriptor before the small-swapchain
7+
// heuristic and before FG/interop can substitute a different HWND. Only modify our local copy.
8+
// Window visibility is not a size test: games often create the swapchain before showing the window.
9+
inline bool ResolveWindowSizedSwapchain(DXGI_SWAP_CHAIN_DESC& desc)
10+
{
11+
if (desc.BufferDesc.Width != 0 || desc.BufferDesc.Height != 0 || desc.OutputWindow == nullptr)
12+
return false;
13+
14+
RECT rect {};
15+
if (!GetClientRect(desc.OutputWindow, &rect))
16+
return false;
17+
const LONG width = rect.right - rect.left;
18+
const LONG height = rect.bottom - rect.top;
19+
if (width < 100 || height < 100)
20+
return false;
21+
22+
desc.BufferDesc.Width = (UINT) width;
23+
desc.BufferDesc.Height = (UINT) height;
24+
return true;
25+
}
26+
27+
inline bool IsCompositionWindow(HWND window)
28+
{
29+
DWORD pid = 0;
30+
RECT rect {};
31+
return window != nullptr && window != GetConsoleWindow() && GetWindow(window, GW_OWNER) == nullptr &&
32+
GetWindowThreadProcessId(window, &pid) != 0 && pid == GetCurrentProcessId() &&
33+
GetClientRect(window, &rect) && rect.right - rect.left >= 100 && rect.bottom - rect.top >= 100;
34+
}
35+
36+
inline HWND FindCompositionWindow()
37+
{
38+
const HWND foreground = GetForegroundWindow();
39+
if (IsCompositionWindow(foreground))
40+
return foreground;
41+
struct Search { HWND window = nullptr; unsigned int count = 0; } search;
42+
EnumWindows([](HWND window, LPARAM context) -> BOOL {
43+
auto& found = *reinterpret_cast<Search*>(context);
44+
if (IsCompositionWindow(window)) { found.window = window; ++found.count; }
45+
return TRUE;
46+
}, reinterpret_cast<LPARAM>(&search));
47+
return search.count == 1 ? search.window : nullptr;
48+
}

‎OptiScaler/wrapped/wrapped_swapchain.cpp‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "pch.h"
22
#include "wrapped_swapchain.h"
3+
#include <hooks/DxgiSwapchainSizing.h>
34

45
#include <Util.h>
56
#include <Config.h>
@@ -419,8 +420,8 @@ static HRESULT LocalPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT
419420
}
420421

421422
WrappedIDXGISwapChain4::WrappedIDXGISwapChain4(IDXGISwapChain* real, IUnknown* pDevice, HWND hWnd, UINT flags,
422-
bool isUWP)
423-
: _real(real), _device(pDevice), _handle(hWnd), _refcount(1), _uwp(isUWP)
423+
bool isUWP, bool isComposition)
424+
: _real(real), _device(pDevice), _handle(hWnd), _refcount(1), _uwp(isUWP), _composition(isComposition)
424425
{
425426
_id = ++scCount;
426427
_lastFlags = flags;
@@ -647,6 +648,11 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::Present(UINT SyncInterval, UIN
647648
OwnedLockGuard lock(_localMutex, 4);
648649
#endif
649650

651+
if (_composition && !IsCompositionWindow(_handle))
652+
_handle = FindCompositionWindow();
653+
if (_composition && _handle == nullptr)
654+
return _real->Present(SyncInterval, Flags);
655+
650656
HRESULT result;
651657

652658
if ((Flags & DXGI_PRESENT_TEST) == 0)
@@ -769,7 +775,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers(UINT BufferCount
769775

770776
State::Instance().scChanged = true;
771777

772-
if (Config::Instance()->OverrideVsync.value_or_default() && !State::Instance().SCExclusiveFullscreen &&
778+
if (!_composition && Config::Instance()->OverrideVsync.value_or_default() && !State::Instance().SCExclusiveFullscreen &&
773779
State::Instance().currentFG == nullptr)
774780
{
775781
LOG_DEBUG("Overriding flags");
@@ -1003,6 +1009,11 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::Present1(UINT SyncInterval, UI
10031009
OwnedLockGuard lock(_localMutex, 5);
10041010
#endif
10051011

1012+
if (_composition && !IsCompositionWindow(_handle))
1013+
_handle = FindCompositionWindow();
1014+
if (_composition && _handle == nullptr)
1015+
return _real1->Present1(SyncInterval, Flags, pPresentParameters);
1016+
10061017
HRESULT result;
10071018

10081019
if ((Flags & DXGI_PRESENT_TEST) == 0)
@@ -1194,7 +1205,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::ResizeBuffers1(UINT BufferCoun
11941205

11951206
State::Instance().scChanged = true;
11961207

1197-
if (Config::Instance()->OverrideVsync.value_or_default() && !State::Instance().SCExclusiveFullscreen &&
1208+
if (!_composition && Config::Instance()->OverrideVsync.value_or_default() && !State::Instance().SCExclusiveFullscreen &&
11981209
State::Instance().currentFG == nullptr)
11991210
{
12001211
LOG_DEBUG("Overriding flags");

‎OptiScaler/wrapped/wrapped_swapchain.h‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
class DECLSPEC_UUID("3af622a3-82d0-49cd-994f-cce05122c222") WrappedIDXGISwapChain4 final : public IDXGISwapChain4
1313
{
1414
public:
15-
WrappedIDXGISwapChain4(IDXGISwapChain* real, IUnknown* pDevice, HWND hWnd, UINT flags, bool isUWP);
15+
WrappedIDXGISwapChain4(IDXGISwapChain* real, IUnknown* pDevice, HWND hWnd, UINT flags, bool isUWP,
16+
bool isComposition = false);
1617
virtual ~WrappedIDXGISwapChain4();
1718

1819
// implement IUnknown
@@ -86,6 +87,7 @@ class DECLSPEC_UUID("3af622a3-82d0-49cd-994f-cce05122c222") WrappedIDXGISwapChai
8687

8788
int _id = 0;
8889
bool _uwp = false;
90+
bool _composition = false;
8991
LONG _refcount;
9092
UINT _lastFlags = 0;
9193

0 commit comments

Comments
 (0)