mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-17 21:17:09 +00:00
92040f4636
* DXGI is entangled with the API unfortunately, such that for D3D11 DXGI_SWAP_EFFECT_FLIP_DISCARD can only access buffer 0 (like DXGI_SWAP_EFFECT_DISCARD) but for D3D12 it can access any buffer. This is naturally undocumented.
1498 lines
40 KiB
C++
1498 lines
40 KiB
C++
/******************************************************************************
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2019-2020 Baldur Karlsson
|
|
* Copyright (c) 2014 Crytek
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
******************************************************************************/
|
|
|
|
#include "dxgi_wrapped.h"
|
|
#include "core/core.h"
|
|
#include "serialise/serialiser.h"
|
|
#include "dxgi_common.h"
|
|
|
|
ID3D11Resource *UnwrapDXResource(void *dxObject);
|
|
IDXGIResource *UnwrapDXGIResource(void *dxgiObject);
|
|
|
|
WRAPPED_POOL_INST(WrappedIDXGIDevice4);
|
|
|
|
rdcarray<D3DDeviceCallback> WrappedIDXGISwapChain4::m_D3DCallbacks;
|
|
|
|
ID3DDevice *GetD3DDevice(IUnknown *pDevice)
|
|
{
|
|
ID3DDevice *wrapDevice = NULL;
|
|
|
|
if(WrappedIDXGIDevice4::IsAlloc(pDevice))
|
|
wrapDevice = ((WrappedIDXGIDevice4 *)(IDXGIDevice3 *)pDevice)->GetD3DDevice();
|
|
|
|
if(wrapDevice == NULL)
|
|
wrapDevice = WrappedIDXGISwapChain4::GetD3DDevice(pDevice);
|
|
|
|
return wrapDevice;
|
|
}
|
|
|
|
bool RefCountDXGIObject::HandleWrap(REFIID riid, void **ppvObject)
|
|
{
|
|
if(ppvObject == NULL || *ppvObject == NULL)
|
|
{
|
|
RDCWARN("HandleWrap called with NULL ppvObject");
|
|
return false;
|
|
}
|
|
|
|
// unknown GUID that we only want to print once to avoid log spam
|
|
// {79D2046C-22EF-451B-9E74-2245D9C760EA}
|
|
static const GUID Unknown_uuid = {
|
|
0x79d2046c, 0x22ef, 0x451b, {0x9e, 0x74, 0x22, 0x45, 0xd9, 0xc7, 0x60, 0xea}};
|
|
|
|
// ditto
|
|
// {9B7E4C04-342C-4106-A19F-4F2704F689F0}
|
|
static const GUID ID3D10Texture2D_uuid = {
|
|
0x9b7e4c04, 0x342c, 0x4106, {0xa1, 0x9f, 0x4f, 0x27, 0x04, 0xf6, 0x89, 0xf0}};
|
|
|
|
// unknown/undocumented internal interface
|
|
// {7abb6563-02bc-47c4-8ef9-acc4795edbcf}
|
|
static const GUID IDXGIAdapterInternal2_uuid = {
|
|
0x7abb6563, 0x02bc, 0x47c4, {0x8e, 0xf9, 0xac, 0xc4, 0x79, 0x5e, 0xdb, 0xcf}};
|
|
|
|
if(riid == __uuidof(IDXGIDevice))
|
|
{
|
|
// should have been handled elsewhere, so we can properly create this device
|
|
RDCERR("Unexpected uuid in RefCountDXGIObject::HandleWrap");
|
|
return false;
|
|
}
|
|
else if(riid == __uuidof(IDXGIAdapter))
|
|
{
|
|
IDXGIAdapter *real = (IDXGIAdapter *)(*ppvObject);
|
|
*ppvObject = (IDXGIAdapter *)(new WrappedIDXGIAdapter4(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIAdapter1))
|
|
{
|
|
IDXGIAdapter1 *real = (IDXGIAdapter1 *)(*ppvObject);
|
|
*ppvObject = (IDXGIAdapter1 *)(new WrappedIDXGIAdapter4(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIAdapter2))
|
|
{
|
|
IDXGIAdapter2 *real = (IDXGIAdapter2 *)(*ppvObject);
|
|
*ppvObject = (IDXGIAdapter2 *)(new WrappedIDXGIAdapter4(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIAdapter3))
|
|
{
|
|
IDXGIAdapter3 *real = (IDXGIAdapter3 *)(*ppvObject);
|
|
*ppvObject = (IDXGIAdapter3 *)(new WrappedIDXGIAdapter4(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIAdapter4))
|
|
{
|
|
IDXGIAdapter4 *real = (IDXGIAdapter4 *)(*ppvObject);
|
|
*ppvObject = (IDXGIAdapter4 *)(new WrappedIDXGIAdapter4(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory))
|
|
{
|
|
// yes I know PRECISELY how fucked up this is. Speak to microsoft - after KB2670838 the internal
|
|
// D3D11 device creation function will pass in __uuidof(IDXGIFactory) then attempt to call
|
|
// EnumDevices1 (which is in the IDXGIFactory1 vtable). Doing this *should* be safe as using a
|
|
// IDXGIFactory1 like a IDXGIFactory should all just work by definition, but there's no way to
|
|
// know now if someone trying to create a IDXGIFactory really means it or not.
|
|
IDXGIFactory *real = (IDXGIFactory *)(*ppvObject);
|
|
*ppvObject = (IDXGIFactory *)(new WrappedIDXGIFactory(real));
|
|
return true;
|
|
}
|
|
|
|
else if(riid == __uuidof(IDXGIDevice1))
|
|
{
|
|
// should have been handled elsewhere, so we can properly create this device
|
|
RDCERR("Unexpected uuid in RefCountDXGIObject::HandleWrap");
|
|
return false;
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory1))
|
|
{
|
|
IDXGIFactory1 *real = (IDXGIFactory1 *)(*ppvObject);
|
|
*ppvObject = (IDXGIFactory1 *)(new WrappedIDXGIFactory(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory2))
|
|
{
|
|
IDXGIFactory2 *real = (IDXGIFactory2 *)(*ppvObject);
|
|
*ppvObject = (IDXGIFactory2 *)(new WrappedIDXGIFactory(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory3))
|
|
{
|
|
IDXGIFactory3 *real = (IDXGIFactory3 *)(*ppvObject);
|
|
*ppvObject = (IDXGIFactory3 *)(new WrappedIDXGIFactory(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory4))
|
|
{
|
|
IDXGIFactory4 *real = (IDXGIFactory4 *)(*ppvObject);
|
|
*ppvObject = (IDXGIFactory4 *)(new WrappedIDXGIFactory(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory5))
|
|
{
|
|
IDXGIFactory5 *real = (IDXGIFactory5 *)(*ppvObject);
|
|
*ppvObject = (IDXGIFactory5 *)(new WrappedIDXGIFactory(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory6))
|
|
{
|
|
IDXGIFactory6 *real = (IDXGIFactory6 *)(*ppvObject);
|
|
*ppvObject = (IDXGIFactory6 *)(new WrappedIDXGIFactory(real));
|
|
return true;
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory7))
|
|
{
|
|
IDXGIFactory7 *real = (IDXGIFactory7 *)(*ppvObject);
|
|
*ppvObject = (IDXGIFactory7 *)(new WrappedIDXGIFactory(real));
|
|
return true;
|
|
}
|
|
else if(riid == ID3D10Texture2D_uuid)
|
|
{
|
|
static bool printed = false;
|
|
if(!printed)
|
|
{
|
|
printed = true;
|
|
RDCWARN("Querying IDXGIObject for unsupported D3D10 interface: %s", ToStr(riid).c_str());
|
|
}
|
|
return false;
|
|
}
|
|
else if(riid == IDXGIAdapterInternal2_uuid)
|
|
{
|
|
static bool printed = false;
|
|
if(!printed)
|
|
{
|
|
printed = true;
|
|
RDCWARN(
|
|
"Querying IDXGIObject for unsupported/undocumented IDXGIAdapterInternal2 interface: %s",
|
|
ToStr(riid).c_str());
|
|
}
|
|
return false;
|
|
}
|
|
else if(riid == Unknown_uuid)
|
|
{
|
|
static bool printed = false;
|
|
if(!printed)
|
|
{
|
|
printed = true;
|
|
RDCWARN("Querying IDXGIObject for unknown GUID: %s", ToStr(riid).c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WarnUnknownGUID("IDXGIObject", riid);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE RefCountDXGIObject::GetParent(
|
|
/* [in] */ REFIID riid,
|
|
/* [retval][out] */ void **ppParent)
|
|
{
|
|
HRESULT ret = m_pReal->GetParent(riid, ppParent);
|
|
|
|
if(SUCCEEDED(ret))
|
|
HandleWrap(riid, ppParent);
|
|
|
|
return ret;
|
|
}
|
|
|
|
HRESULT RefCountDXGIObject::WrapQueryInterface(IUnknown *real, REFIID riid, void **ppvObject)
|
|
{
|
|
HRESULT ret = real->QueryInterface(riid, ppvObject);
|
|
|
|
if(SUCCEEDED(ret))
|
|
HandleWrap(riid, ppvObject);
|
|
|
|
return ret;
|
|
}
|
|
|
|
WrappedIDXGISwapChain4::WrappedIDXGISwapChain4(IDXGISwapChain *real, HWND w, ID3DDevice *device)
|
|
: RefCountDXGIObject(real), m_pReal(real), m_pDevice(device), m_Wnd(w)
|
|
{
|
|
DXGI_SWAP_CHAIN_DESC desc;
|
|
real->GetDesc(&desc);
|
|
|
|
m_pDevice->AddRef();
|
|
|
|
m_pReal1 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGISwapChain1), (void **)&m_pReal1);
|
|
m_pReal2 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGISwapChain2), (void **)&m_pReal2);
|
|
m_pReal3 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGISwapChain3), (void **)&m_pReal3);
|
|
m_pReal4 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGISwapChain4), (void **)&m_pReal4);
|
|
|
|
WrapBuffersAfterResize();
|
|
|
|
HWND wnd = GetHWND();
|
|
|
|
if(wnd)
|
|
{
|
|
Keyboard::AddInputWindow(WindowingSystem::Win32, wnd);
|
|
|
|
RenderDoc::Inst().AddFrameCapturer(m_pDevice->GetFrameCapturerDevice(), wnd,
|
|
m_pDevice->GetFrameCapturer());
|
|
}
|
|
|
|
// we do a 'fake' present right at the start, so that we can capture frame 1, by
|
|
// going from this fake present to the first present.
|
|
m_pDevice->FirstFrame(this);
|
|
}
|
|
|
|
WrappedIDXGISwapChain4::~WrappedIDXGISwapChain4()
|
|
{
|
|
HWND wnd = GetHWND();
|
|
|
|
if(wnd)
|
|
{
|
|
Keyboard::RemoveInputWindow(WindowingSystem::Win32, wnd);
|
|
|
|
RenderDoc::Inst().RemoveFrameCapturer(m_pDevice->GetFrameCapturerDevice(), wnd);
|
|
}
|
|
|
|
m_pDevice->ReleaseSwapchainResources(this, 0, NULL, NULL);
|
|
|
|
SAFE_RELEASE(m_pDevice);
|
|
|
|
SAFE_RELEASE(m_pReal1);
|
|
SAFE_RELEASE(m_pReal2);
|
|
SAFE_RELEASE(m_pReal3);
|
|
SAFE_RELEASE(m_pReal4);
|
|
SAFE_RELEASE(m_pReal);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::QueryInterface(REFIID riid, void **ppvObject)
|
|
{
|
|
if(riid == __uuidof(IDXGISwapChain))
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGISwapChain *)this;
|
|
return S_OK;
|
|
}
|
|
else if(riid == __uuidof(IDXGISwapChain1))
|
|
{
|
|
if(m_pReal1)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGISwapChain1 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGISwapChain2))
|
|
{
|
|
if(m_pReal2)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGISwapChain2 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGISwapChain3))
|
|
{
|
|
if(m_pReal3)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGISwapChain3 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGISwapChain4))
|
|
{
|
|
if(m_pReal4)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGISwapChain4 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WarnUnknownGUID("IDXGISwapChain", riid);
|
|
}
|
|
|
|
return RefCountDXGIObject::QueryInterface(riid, ppvObject);
|
|
}
|
|
|
|
void WrappedIDXGISwapChain4::ReleaseBuffersForResize(UINT QueueCount, IUnknown *const *ppPresentQueue,
|
|
IUnknown **unwrappedQueues)
|
|
{
|
|
m_pDevice->ReleaseSwapchainResources(this, QueueCount, ppPresentQueue, unwrappedQueues);
|
|
}
|
|
|
|
void WrappedIDXGISwapChain4::WrapBuffersAfterResize()
|
|
{
|
|
DXGI_SWAP_CHAIN_DESC desc;
|
|
m_pReal->GetDesc(&desc);
|
|
|
|
int bufCount = desc.BufferCount;
|
|
|
|
// discard swap effects only allow querying buffer 0, but only on D3D11 - on D3D12 they can (and
|
|
// must) still query the full set of buffers.
|
|
if(m_pDevice->GetFrameCapturer()->GetFrameCaptureDriver() == RDCDriver::D3D11 &&
|
|
(desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD || desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD))
|
|
{
|
|
bufCount = 1;
|
|
}
|
|
|
|
RDCASSERT(bufCount < MAX_NUM_BACKBUFFERS);
|
|
|
|
for(int i = 0; i < MAX_NUM_BACKBUFFERS; i++)
|
|
{
|
|
m_pBackBuffers[i] = NULL;
|
|
|
|
if(i < bufCount)
|
|
{
|
|
GetBuffer(i, m_pDevice->GetBackbufferUUID(), (void **)&m_pBackBuffers[i]);
|
|
m_pDevice->NewSwapchainBuffer(m_pBackBuffers[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
HRESULT WrappedIDXGISwapChain4::ResizeBuffers(
|
|
/* [in] */ UINT BufferCount,
|
|
/* [in] */ UINT Width,
|
|
/* [in] */ UINT Height,
|
|
/* [in] */ DXGI_FORMAT NewFormat,
|
|
/* [in] */ UINT SwapChainFlags)
|
|
{
|
|
ReleaseBuffersForResize(0, NULL, NULL);
|
|
|
|
HRESULT ret = m_pReal->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags);
|
|
|
|
WrapBuffersAfterResize();
|
|
|
|
m_LastPresentedBuffer = -1;
|
|
|
|
return ret;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::GetContainingOutput(IDXGIOutput **ppOutput)
|
|
{
|
|
HRESULT ret = m_pReal->GetContainingOutput(ppOutput);
|
|
|
|
if(SUCCEEDED(ret) && ppOutput && *ppOutput)
|
|
*ppOutput = (IDXGIOutput *)(new WrappedIDXGIOutput6(this, *ppOutput));
|
|
|
|
return ret;
|
|
}
|
|
|
|
HRESULT WrappedIDXGISwapChain4::ResizeBuffers1(_In_ UINT BufferCount, _In_ UINT Width,
|
|
_In_ UINT Height, _In_ DXGI_FORMAT Format,
|
|
_In_ UINT SwapChainFlags,
|
|
_In_reads_(BufferCount) const UINT *pCreationNodeMask,
|
|
_In_reads_(BufferCount)
|
|
IUnknown *const *ppPresentQueue)
|
|
{
|
|
IUnknown **unwrappedQueues = NULL;
|
|
|
|
if(ppPresentQueue)
|
|
unwrappedQueues = new IUnknown *[BufferCount];
|
|
|
|
ReleaseBuffersForResize(BufferCount, ppPresentQueue, unwrappedQueues);
|
|
|
|
HRESULT ret = m_pReal3->ResizeBuffers1(BufferCount, Width, Height, Format, SwapChainFlags,
|
|
pCreationNodeMask, unwrappedQueues);
|
|
|
|
SAFE_DELETE_ARRAY(unwrappedQueues);
|
|
|
|
WrapBuffersAfterResize();
|
|
|
|
m_LastPresentedBuffer = -1;
|
|
|
|
return ret;
|
|
}
|
|
|
|
HRESULT WrappedIDXGISwapChain4::SetFullscreenState(
|
|
/* [in] */ BOOL Fullscreen,
|
|
/* [in] */ IDXGIOutput *pTarget)
|
|
{
|
|
WrappedIDXGIOutput6 *wrappedOutput = (WrappedIDXGIOutput6 *)pTarget;
|
|
IDXGIOutput *unwrappedOutput = wrappedOutput ? wrappedOutput->GetReal() : NULL;
|
|
|
|
if(RenderDoc::Inst().GetCaptureOptions().allowFullscreen)
|
|
return m_pReal->SetFullscreenState(Fullscreen, unwrappedOutput);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT WrappedIDXGISwapChain4::GetFullscreenState(
|
|
/* [out] */ BOOL *pFullscreen,
|
|
/* [out] */ IDXGIOutput **ppTarget)
|
|
{
|
|
HRESULT ret = m_pReal->GetFullscreenState(pFullscreen, ppTarget);
|
|
|
|
if(SUCCEEDED(ret) && ppTarget && *ppTarget)
|
|
*ppTarget = (IDXGIOutput *)(new WrappedIDXGIOutput6(this, *ppTarget));
|
|
|
|
return ret;
|
|
}
|
|
|
|
HRESULT WrappedIDXGISwapChain4::GetBuffer(
|
|
/* [in] */ UINT Buffer,
|
|
/* [in] */ REFIID riid,
|
|
/* [out][in] */ void **ppSurface)
|
|
{
|
|
if(ppSurface == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
// ID3D10Texture2D UUID {9B7E4C04-342C-4106-A19F-4F2704F689F0}
|
|
static const GUID ID3D10Texture2D_uuid = {
|
|
0x9b7e4c04, 0x342c, 0x4106, {0xa1, 0x9f, 0x4f, 0x27, 0x04, 0xf6, 0x89, 0xf0}};
|
|
|
|
// ID3D10Resource UUID {9B7E4C01-342C-4106-A19F-4F2704F689F0}
|
|
static const GUID ID3D10Resource_uuid = {
|
|
0x9b7e4c01, 0x342c, 0x4106, {0xa1, 0x9f, 0x4f, 0x27, 0x04, 0xf6, 0x89, 0xf0}};
|
|
|
|
IID uuid = riid;
|
|
|
|
if(uuid == ID3D10Texture2D_uuid || uuid == ID3D10Resource_uuid)
|
|
{
|
|
RDCERR("Querying swapchain buffers via D3D10 interface UUIDs is not supported");
|
|
return E_NOINTERFACE;
|
|
}
|
|
else if(uuid == __uuidof(IDXGISurface))
|
|
{
|
|
RDCWARN("Querying swapchain buffer for IDXGISurface. This query is ambiguous.");
|
|
|
|
// query as native format so that wrapping works as expected
|
|
uuid = m_pDevice->GetBackbufferUUID();
|
|
}
|
|
else if(uuid != __uuidof(ID3D11Texture2D) && uuid != __uuidof(ID3D11Texture2D1) &&
|
|
uuid != __uuidof(ID3D11Resource) && uuid != __uuidof(ID3D12Resource) &&
|
|
uuid != __uuidof(ID3D12Resource1))
|
|
{
|
|
RDCERR("Unsupported or unrecognised UUID passed to IDXGISwapChain::GetBuffer - %s",
|
|
ToStr(uuid).c_str());
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
RDCASSERT(uuid == __uuidof(ID3D11Texture2D) || uuid == __uuidof(ID3D11Texture2D1) ||
|
|
uuid == __uuidof(ID3D11Resource) || uuid == __uuidof(ID3D12Resource) ||
|
|
uuid == __uuidof(ID3D12Resource1));
|
|
|
|
HRESULT ret = m_pReal->GetBuffer(Buffer, uuid, ppSurface);
|
|
|
|
{
|
|
IUnknown *realSurface = (IUnknown *)*ppSurface;
|
|
IUnknown *tex = realSurface;
|
|
|
|
if(FAILED(ret))
|
|
{
|
|
RDCERR("Failed to get swapchain backbuffer %d: HRESULT: %s", Buffer, ToStr(ret).c_str());
|
|
SAFE_RELEASE(realSurface);
|
|
tex = NULL;
|
|
}
|
|
else
|
|
{
|
|
DXGI_SWAP_CHAIN_DESC desc;
|
|
GetDesc(&desc);
|
|
tex = m_pDevice->WrapSwapchainBuffer(this, desc.BufferDesc.Format, Buffer, realSurface);
|
|
}
|
|
|
|
// if the original UUID was IDXGISurface, fixup for the expected interface being returned
|
|
if(tex && riid == __uuidof(IDXGISurface))
|
|
{
|
|
IDXGISurface *surf = NULL;
|
|
HRESULT hr = tex->QueryInterface(__uuidof(IDXGISurface), (void **)&surf);
|
|
RDCASSERTEQUAL(hr, S_OK);
|
|
|
|
tex->Release();
|
|
tex = surf;
|
|
}
|
|
|
|
*ppSurface = tex;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
HRESULT WrappedIDXGISwapChain4::GetDevice(
|
|
/* [in] */ REFIID riid,
|
|
/* [retval][out] */ void **ppDevice)
|
|
{
|
|
HRESULT ret = m_pReal->GetDevice(riid, ppDevice);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
// try one of the trivial wraps, we don't mind making a new one of those
|
|
if(m_pDevice->IsDeviceUUID(riid))
|
|
{
|
|
// probably they're asking for the device device.
|
|
*ppDevice = m_pDevice->GetDeviceInterface(riid);
|
|
m_pDevice->AddRef();
|
|
}
|
|
else if(riid == __uuidof(IDXGISwapChain))
|
|
{
|
|
// don't think anyone would try this, but what the hell.
|
|
*ppDevice = this;
|
|
AddRef();
|
|
}
|
|
else if(!HandleWrap(riid, ppDevice))
|
|
{
|
|
// can probably get away with returning the real result here,
|
|
// but it worries me a bit.
|
|
RDCUNIMPLEMENTED("Not returning trivial type");
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
HRESULT WrappedIDXGISwapChain4::Present(
|
|
/* [in] */ UINT SyncInterval,
|
|
/* [in] */ UINT Flags)
|
|
{
|
|
if(!RenderDoc::Inst().GetCaptureOptions().allowVSync)
|
|
{
|
|
SyncInterval = 0;
|
|
}
|
|
|
|
if((Flags & DXGI_PRESENT_TEST) == 0)
|
|
{
|
|
TickLastPresentedBuffer();
|
|
m_pDevice->Present(this, SyncInterval, Flags);
|
|
}
|
|
|
|
return m_pReal->Present(SyncInterval, Flags);
|
|
}
|
|
|
|
HRESULT WrappedIDXGISwapChain4::Present1(UINT SyncInterval, UINT Flags,
|
|
const DXGI_PRESENT_PARAMETERS *pPresentParameters)
|
|
{
|
|
if(!RenderDoc::Inst().GetCaptureOptions().allowVSync)
|
|
{
|
|
SyncInterval = 0;
|
|
}
|
|
|
|
if((Flags & DXGI_PRESENT_TEST) == 0)
|
|
{
|
|
TickLastPresentedBuffer();
|
|
m_pDevice->Present(this, SyncInterval, Flags);
|
|
}
|
|
|
|
return m_pReal1->Present1(SyncInterval, Flags, pPresentParameters);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::GetRestrictToOutput(IDXGIOutput **ppRestrictToOutput)
|
|
{
|
|
HRESULT ret = m_pReal1->GetRestrictToOutput(ppRestrictToOutput);
|
|
|
|
if(SUCCEEDED(ret) && ppRestrictToOutput && *ppRestrictToOutput)
|
|
*ppRestrictToOutput = (IDXGIOutput *)(new WrappedIDXGIOutput6(this, *ppRestrictToOutput));
|
|
|
|
return ret;
|
|
}
|
|
|
|
WrappedIDXGIOutput6::WrappedIDXGIOutput6(RefCountDXGIObject *owner, IDXGIOutput *real)
|
|
: RefCountDXGIObject(real), m_Owner(owner), m_pReal(real)
|
|
{
|
|
SAFE_ADDREF(m_Owner);
|
|
|
|
m_pReal1 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIOutput1), (void **)&m_pReal1);
|
|
m_pReal2 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIOutput2), (void **)&m_pReal2);
|
|
m_pReal3 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIOutput3), (void **)&m_pReal3);
|
|
m_pReal4 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIOutput4), (void **)&m_pReal4);
|
|
m_pReal5 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIOutput5), (void **)&m_pReal5);
|
|
m_pReal6 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIOutput6), (void **)&m_pReal6);
|
|
}
|
|
|
|
WrappedIDXGIOutput6::~WrappedIDXGIOutput6()
|
|
{
|
|
SAFE_RELEASE(m_pReal1);
|
|
SAFE_RELEASE(m_pReal2);
|
|
SAFE_RELEASE(m_pReal3);
|
|
SAFE_RELEASE(m_pReal4);
|
|
SAFE_RELEASE(m_pReal5);
|
|
SAFE_RELEASE(m_pReal6);
|
|
SAFE_RELEASE(m_pReal);
|
|
SAFE_RELEASE(m_Owner);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::FindClosestMatchingMode(
|
|
const DXGI_MODE_DESC *pModeToMatch, DXGI_MODE_DESC *pClosestMatch, IUnknown *pConcernedDevice)
|
|
{
|
|
ID3DDevice *wrapDevice = GetD3DDevice(pConcernedDevice);
|
|
|
|
if(wrapDevice)
|
|
return m_pReal->FindClosestMatchingMode(pModeToMatch, pClosestMatch,
|
|
wrapDevice->GetRealIUnknown());
|
|
|
|
if(pConcernedDevice)
|
|
RDCERR("Unrecognised device in FindClosestMatchingMode()");
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::TakeOwnership(IUnknown *pDevice, BOOL Exclusive)
|
|
{
|
|
ID3DDevice *wrapDevice = GetD3DDevice(pDevice);
|
|
|
|
if(wrapDevice)
|
|
return m_pReal->TakeOwnership(wrapDevice->GetRealIUnknown(), Exclusive);
|
|
|
|
// since this is supposed to be an internal function, allow passing through the pointer directly
|
|
// just in case
|
|
return m_pReal->TakeOwnership(pDevice, Exclusive);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::FindClosestMatchingMode1(
|
|
const DXGI_MODE_DESC1 *pModeToMatch, DXGI_MODE_DESC1 *pClosestMatch, IUnknown *pConcernedDevice)
|
|
{
|
|
ID3DDevice *wrapDevice = GetD3DDevice(pConcernedDevice);
|
|
|
|
if(wrapDevice)
|
|
return m_pReal1->FindClosestMatchingMode1(pModeToMatch, pClosestMatch,
|
|
wrapDevice->GetRealIUnknown());
|
|
|
|
if(pConcernedDevice)
|
|
RDCERR("Unrecognised device in FindClosestMatchingMode1()");
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::GetDisplaySurfaceData1(IDXGIResource *pDestination)
|
|
{
|
|
return m_pReal1->GetDisplaySurfaceData1(UnwrapDXGIResource(pDestination));
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
WrappedIDXGIOutput6::DuplicateOutput(IUnknown *pDevice, IDXGIOutputDuplication **ppOutputDuplication)
|
|
{
|
|
if(!ppOutputDuplication)
|
|
return E_INVALIDARG;
|
|
|
|
ID3DDevice *wrapDevice = GetD3DDevice(pDevice);
|
|
|
|
if(wrapDevice)
|
|
{
|
|
IDXGIOutputDuplication *dup = NULL;
|
|
HRESULT ret = m_pReal1->DuplicateOutput(wrapDevice->GetRealIUnknown(), &dup);
|
|
|
|
if(SUCCEEDED(ret) && dup)
|
|
dup = new WrappedIDXGIOutputDuplication(wrapDevice, dup);
|
|
|
|
*ppOutputDuplication = dup;
|
|
|
|
return ret;
|
|
}
|
|
|
|
if(pDevice)
|
|
RDCERR("Unrecognised device in DuplicateOutput()");
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::CheckOverlaySupport(DXGI_FORMAT EnumFormat,
|
|
IUnknown *pConcernedDevice,
|
|
UINT *pFlags)
|
|
{
|
|
ID3DDevice *wrapDevice = GetD3DDevice(pConcernedDevice);
|
|
|
|
if(wrapDevice)
|
|
return m_pReal3->CheckOverlaySupport(EnumFormat, wrapDevice->GetRealIUnknown(), pFlags);
|
|
|
|
if(pConcernedDevice)
|
|
RDCERR("Unrecognised device in CheckOverlaySupport()");
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::DuplicateOutput1(
|
|
IUnknown *pDevice, UINT Flags, UINT SupportedFormatsCount, const DXGI_FORMAT *pSupportedFormats,
|
|
IDXGIOutputDuplication **ppOutputDuplication)
|
|
{
|
|
if(!ppOutputDuplication)
|
|
return E_INVALIDARG;
|
|
|
|
ID3DDevice *wrapDevice = GetD3DDevice(pDevice);
|
|
|
|
if(wrapDevice)
|
|
{
|
|
IDXGIOutputDuplication *dup = NULL;
|
|
HRESULT ret = m_pReal5->DuplicateOutput1(wrapDevice->GetRealIUnknown(), Flags,
|
|
SupportedFormatsCount, pSupportedFormats, &dup);
|
|
|
|
if(SUCCEEDED(ret) && dup)
|
|
dup = new WrappedIDXGIOutputDuplication(wrapDevice, dup);
|
|
|
|
*ppOutputDuplication = dup;
|
|
|
|
return ret;
|
|
}
|
|
|
|
if(pDevice)
|
|
RDCERR("Unrecognised device in DuplicateOutput()");
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::QueryInterface(REFIID riid, void **ppvObject)
|
|
{
|
|
if(riid == __uuidof(IDXGIOutput))
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIOutput *)this;
|
|
return S_OK;
|
|
}
|
|
else if(riid == __uuidof(IDXGIOutput1))
|
|
{
|
|
if(m_pReal1)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIOutput1 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIOutput2))
|
|
{
|
|
if(m_pReal2)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIOutput2 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIOutput3))
|
|
{
|
|
if(m_pReal3)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIOutput3 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIOutput4))
|
|
{
|
|
if(m_pReal4)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIOutput4 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIOutput5))
|
|
{
|
|
if(m_pReal5)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIOutput5 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIOutput6))
|
|
{
|
|
if(m_pReal6)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIOutput6 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WarnUnknownGUID("IDXGIOutput", riid);
|
|
}
|
|
|
|
return RefCountDXGIObject::QueryInterface(riid, ppvObject);
|
|
}
|
|
|
|
WrappedIDXGIAdapter4::WrappedIDXGIAdapter4(IDXGIAdapter *real)
|
|
: RefCountDXGIObject(real), m_pReal(real)
|
|
{
|
|
m_pReal1 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIAdapter1), (void **)&m_pReal1);
|
|
m_pReal2 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIAdapter2), (void **)&m_pReal2);
|
|
m_pReal3 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIAdapter3), (void **)&m_pReal3);
|
|
m_pReal4 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIAdapter4), (void **)&m_pReal4);
|
|
}
|
|
|
|
WrappedIDXGIAdapter4::~WrappedIDXGIAdapter4()
|
|
{
|
|
SAFE_RELEASE(m_pReal1);
|
|
SAFE_RELEASE(m_pReal2);
|
|
SAFE_RELEASE(m_pReal3);
|
|
SAFE_RELEASE(m_pReal4);
|
|
SAFE_RELEASE(m_pReal);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIAdapter4::QueryInterface(REFIID riid, void **ppvObject)
|
|
{
|
|
if(riid == __uuidof(IDXGIAdapter))
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIAdapter *)this;
|
|
return S_OK;
|
|
}
|
|
else if(riid == __uuidof(IDXGIAdapter1))
|
|
{
|
|
if(m_pReal1)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIAdapter1 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIAdapter2))
|
|
{
|
|
if(m_pReal2)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIAdapter2 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIAdapter3))
|
|
{
|
|
if(m_pReal3)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIAdapter3 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIAdapter4))
|
|
{
|
|
if(m_pReal3)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIAdapter4 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WarnUnknownGUID("IDXGIAdapter", riid);
|
|
}
|
|
|
|
return RefCountDXGIObject::QueryInterface(riid, ppvObject);
|
|
}
|
|
|
|
WrappedIDXGIDevice4::WrappedIDXGIDevice4(IDXGIDevice *real, ID3DDevice *d3d)
|
|
: RefCountDXGIObject(real), m_pReal(real), m_pD3DDevice(d3d)
|
|
{
|
|
m_pD3DDevice->AddRef();
|
|
|
|
m_pReal1 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIDevice1), (void **)&m_pReal1);
|
|
m_pReal2 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIDevice2), (void **)&m_pReal2);
|
|
m_pReal3 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIDevice3), (void **)&m_pReal3);
|
|
m_pReal4 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIDevice4), (void **)&m_pReal4);
|
|
}
|
|
|
|
WrappedIDXGIDevice4::~WrappedIDXGIDevice4()
|
|
{
|
|
SAFE_RELEASE(m_pReal1);
|
|
SAFE_RELEASE(m_pReal2);
|
|
SAFE_RELEASE(m_pReal3);
|
|
SAFE_RELEASE(m_pReal4);
|
|
SAFE_RELEASE(m_pReal);
|
|
SAFE_RELEASE(m_pD3DDevice);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIDevice4::QueryInterface(REFIID riid, void **ppvObject)
|
|
{
|
|
if(m_pD3DDevice->IsDeviceUUID(riid))
|
|
{
|
|
m_pD3DDevice->AddRef();
|
|
*ppvObject = m_pD3DDevice->GetDeviceInterface(riid);
|
|
return S_OK;
|
|
}
|
|
else if(riid == __uuidof(ID3D11Multithread))
|
|
{
|
|
// forward to the device as the lock is shared amongst all things
|
|
return m_pD3DDevice->QueryInterface(riid, ppvObject);
|
|
}
|
|
else if(riid == __uuidof(IDXGIDevice))
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIDevice *)this;
|
|
return S_OK;
|
|
}
|
|
else if(riid == __uuidof(IDXGIDevice1))
|
|
{
|
|
if(m_pReal1)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIDevice1 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIDevice2))
|
|
{
|
|
if(m_pReal2)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIDevice2 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIDevice3))
|
|
{
|
|
if(m_pReal3)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIDevice3 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIDevice4))
|
|
{
|
|
if(m_pReal4)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIDevice4 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WarnUnknownGUID("IDXGIDevice", riid);
|
|
}
|
|
|
|
return RefCountDXGIObject::QueryInterface(riid, ppvObject);
|
|
}
|
|
|
|
rdcarray<IDXGIResource *> UnwrapResourceSet(UINT NumResources, IDXGIResource *const *ppResources)
|
|
{
|
|
rdcarray<IDXGIResource *> resources;
|
|
resources.resize(NumResources);
|
|
for(UINT i = 0; i < NumResources; i++)
|
|
{
|
|
WrappedDXGIInterface<WrappedIDXGIOutput6> *wrapped =
|
|
(WrappedDXGIInterface<WrappedIDXGIOutput6> *)ppResources[i];
|
|
resources[i] = UnwrapDXGIResource(wrapped->GetWrapped());
|
|
if(resources[i] == NULL)
|
|
{
|
|
RDCERR("Unrecognised resource %p!", ppResources[i]);
|
|
resources[i] = ppResources[i];
|
|
}
|
|
}
|
|
return resources;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIDevice4::OfferResources(UINT NumResources,
|
|
IDXGIResource *const *ppResources,
|
|
DXGI_OFFER_RESOURCE_PRIORITY Priority)
|
|
{
|
|
rdcarray<IDXGIResource *> resources = UnwrapResourceSet(NumResources, ppResources);
|
|
return m_pReal2->OfferResources(NumResources, resources.data(), Priority);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIDevice4::ReclaimResources(UINT NumResources,
|
|
IDXGIResource *const *ppResources,
|
|
BOOL *pDiscarded)
|
|
{
|
|
rdcarray<IDXGIResource *> resources = UnwrapResourceSet(NumResources, ppResources);
|
|
return m_pReal2->ReclaimResources(NumResources, resources.data(), pDiscarded);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIDevice4::OfferResources1(UINT NumResources,
|
|
IDXGIResource *const *ppResources,
|
|
DXGI_OFFER_RESOURCE_PRIORITY Priority,
|
|
UINT Flags)
|
|
{
|
|
rdcarray<IDXGIResource *> resources = UnwrapResourceSet(NumResources, ppResources);
|
|
return m_pReal4->OfferResources1(NumResources, resources.data(), Priority, Flags);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIDevice4::ReclaimResources1(UINT NumResources,
|
|
IDXGIResource *const *ppResources,
|
|
|
|
DXGI_RECLAIM_RESOURCE_RESULTS *pResults)
|
|
{
|
|
rdcarray<IDXGIResource *> resources = UnwrapResourceSet(NumResources, ppResources);
|
|
return m_pReal4->ReclaimResources1(NumResources, resources.data(), pResults);
|
|
}
|
|
|
|
WrappedIDXGIFactory::WrappedIDXGIFactory(IDXGIFactory *real)
|
|
: RefCountDXGIObject(real), m_pReal(real)
|
|
{
|
|
m_pReal1 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIFactory1), (void **)&m_pReal1);
|
|
m_pReal2 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIFactory2), (void **)&m_pReal2);
|
|
m_pReal3 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIFactory3), (void **)&m_pReal3);
|
|
m_pReal4 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIFactory4), (void **)&m_pReal4);
|
|
m_pReal5 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIFactory5), (void **)&m_pReal5);
|
|
m_pReal6 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIFactory6), (void **)&m_pReal6);
|
|
m_pReal7 = NULL;
|
|
real->QueryInterface(__uuidof(IDXGIFactory7), (void **)&m_pReal7);
|
|
}
|
|
|
|
WrappedIDXGIFactory::~WrappedIDXGIFactory()
|
|
{
|
|
SAFE_RELEASE(m_pReal1);
|
|
SAFE_RELEASE(m_pReal2);
|
|
SAFE_RELEASE(m_pReal3);
|
|
SAFE_RELEASE(m_pReal4);
|
|
SAFE_RELEASE(m_pReal5);
|
|
SAFE_RELEASE(m_pReal6);
|
|
SAFE_RELEASE(m_pReal7);
|
|
SAFE_RELEASE(m_pReal);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIFactory::QueryInterface(REFIID riid, void **ppvObject)
|
|
{
|
|
// {713f394e-92ca-47e7-ab81-1159c2791e54}
|
|
static const GUID IDXGIFactoryDWM_uuid = {
|
|
0x713f394e, 0x92ca, 0x47e7, {0xab, 0x81, 0x11, 0x59, 0xc2, 0x79, 0x1e, 0x54}};
|
|
|
|
// {1ddd77aa-9a4a-4cc8-9e55-98c196bafc8f}
|
|
static const GUID IDXGIFactoryDWM8_uuid = {
|
|
0x1ddd77aa, 0x9a4a, 0x4cc8, {0x9e, 0x55, 0x98, 0xc1, 0x96, 0xba, 0xfc, 0x8f}};
|
|
|
|
if(riid == __uuidof(IDXGIFactory))
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIFactory *)this;
|
|
return S_OK;
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory1))
|
|
{
|
|
if(m_pReal1)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIFactory1 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory2))
|
|
{
|
|
if(m_pReal2)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIFactory2 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory3))
|
|
{
|
|
if(m_pReal3)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIFactory3 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory4))
|
|
{
|
|
if(m_pReal4)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIFactory4 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory5))
|
|
{
|
|
if(m_pReal5)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIFactory5 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory6))
|
|
{
|
|
if(m_pReal6)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIFactory6 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == __uuidof(IDXGIFactory7))
|
|
{
|
|
if(m_pReal7)
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIFactory7 *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
else if(riid == IDXGIFactoryDWM_uuid)
|
|
{
|
|
RDCWARN("Blocking QueryInterface for IDXGIFactoryDWM");
|
|
return E_NOINTERFACE;
|
|
}
|
|
else if(riid == IDXGIFactoryDWM8_uuid)
|
|
{
|
|
RDCWARN("Blocking QueryInterface for IDXGIFactoryDWM8");
|
|
return E_NOINTERFACE;
|
|
}
|
|
else
|
|
{
|
|
WarnUnknownGUID("IDXGIFactory", riid);
|
|
}
|
|
|
|
return RefCountDXGIObject::QueryInterface(riid, ppvObject);
|
|
}
|
|
|
|
HRESULT WrappedIDXGIFactory::CreateSwapChain(IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc,
|
|
IDXGISwapChain **ppSwapChain)
|
|
{
|
|
ID3DDevice *wrapDevice = GetD3DDevice(pDevice);
|
|
|
|
if(wrapDevice)
|
|
{
|
|
DXGI_SWAP_CHAIN_DESC local = {};
|
|
DXGI_SWAP_CHAIN_DESC *desc = NULL;
|
|
|
|
if(pDesc)
|
|
{
|
|
local = *pDesc;
|
|
desc = &local;
|
|
}
|
|
|
|
local.BufferUsage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
|
|
if(!RenderDoc::Inst().GetCaptureOptions().allowFullscreen)
|
|
local.Windowed = TRUE;
|
|
|
|
HRESULT ret = m_pReal->CreateSwapChain(wrapDevice->GetRealIUnknown(), desc, ppSwapChain);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
*ppSwapChain =
|
|
new WrappedIDXGISwapChain4(*ppSwapChain, desc ? desc->OutputWindow : NULL, wrapDevice);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
RDCERR("Creating swap chain with non-hooked device!");
|
|
|
|
return m_pReal->CreateSwapChain(pDevice, pDesc, ppSwapChain);
|
|
}
|
|
|
|
HRESULT WrappedIDXGIFactory::CreateSwapChainForHwnd(
|
|
IUnknown *pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1 *pDesc,
|
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc, IDXGIOutput *pRestrictToOutput,
|
|
IDXGISwapChain1 **ppSwapChain)
|
|
{
|
|
ID3DDevice *wrapDevice = GetD3DDevice(pDevice);
|
|
|
|
WrappedIDXGIOutput6 *wrappedOutput = (WrappedIDXGIOutput6 *)pRestrictToOutput;
|
|
IDXGIOutput *unwrappedOutput = wrappedOutput ? wrappedOutput->GetReal() : NULL;
|
|
|
|
if(wrapDevice)
|
|
{
|
|
DXGI_SWAP_CHAIN_DESC1 local;
|
|
DXGI_SWAP_CHAIN_DESC1 *desc = NULL;
|
|
|
|
if(pDesc)
|
|
{
|
|
local = *pDesc;
|
|
desc = &local;
|
|
}
|
|
|
|
local.BufferUsage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
|
|
if(!RenderDoc::Inst().GetCaptureOptions().allowFullscreen && pFullscreenDesc)
|
|
{
|
|
pFullscreenDesc = NULL;
|
|
}
|
|
|
|
HRESULT ret = m_pReal2->CreateSwapChainForHwnd(wrapDevice->GetRealIUnknown(), hWnd, desc,
|
|
pFullscreenDesc, unwrappedOutput, ppSwapChain);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
*ppSwapChain = new WrappedIDXGISwapChain4(*ppSwapChain, hWnd, wrapDevice);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Creating swap chain with non-hooked device!");
|
|
}
|
|
|
|
return m_pReal2->CreateSwapChainForHwnd(pDevice, hWnd, pDesc, pFullscreenDesc, unwrappedOutput,
|
|
ppSwapChain);
|
|
}
|
|
|
|
HRESULT WrappedIDXGIFactory::CreateSwapChainForCoreWindow(IUnknown *pDevice, IUnknown *pWindow,
|
|
const DXGI_SWAP_CHAIN_DESC1 *pDesc,
|
|
IDXGIOutput *pRestrictToOutput,
|
|
IDXGISwapChain1 **ppSwapChain)
|
|
{
|
|
ID3DDevice *wrapDevice = GetD3DDevice(pDevice);
|
|
|
|
WrappedIDXGIOutput6 *wrappedOutput = (WrappedIDXGIOutput6 *)pRestrictToOutput;
|
|
IDXGIOutput *unwrappedOutput = wrappedOutput ? wrappedOutput->GetReal() : NULL;
|
|
|
|
if(!RenderDoc::Inst().GetCaptureOptions().allowFullscreen)
|
|
{
|
|
RDCWARN("Impossible to disallow fullscreen on call to CreateSwapChainForCoreWindow");
|
|
}
|
|
|
|
if(wrapDevice)
|
|
{
|
|
DXGI_SWAP_CHAIN_DESC1 local = {};
|
|
DXGI_SWAP_CHAIN_DESC1 *desc = NULL;
|
|
|
|
if(pDesc)
|
|
{
|
|
local = *pDesc;
|
|
desc = &local;
|
|
}
|
|
|
|
local.BufferUsage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
|
|
HRESULT ret = m_pReal2->CreateSwapChainForCoreWindow(wrapDevice->GetRealIUnknown(), pWindow,
|
|
desc, unwrappedOutput, ppSwapChain);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
HWND wnd = NULL;
|
|
(*ppSwapChain)->GetHwnd(&wnd);
|
|
if(wnd == NULL)
|
|
wnd = (HWND)pWindow;
|
|
*ppSwapChain = new WrappedIDXGISwapChain4(*ppSwapChain, wnd, wrapDevice);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Creating swap chain with non-hooked device!");
|
|
}
|
|
|
|
return m_pReal2->CreateSwapChainForCoreWindow(pDevice, pWindow, pDesc, unwrappedOutput,
|
|
ppSwapChain);
|
|
}
|
|
|
|
HRESULT WrappedIDXGIFactory::CreateSwapChainForComposition(IUnknown *pDevice,
|
|
const DXGI_SWAP_CHAIN_DESC1 *pDesc,
|
|
IDXGIOutput *pRestrictToOutput,
|
|
IDXGISwapChain1 **ppSwapChain)
|
|
{
|
|
ID3DDevice *wrapDevice = GetD3DDevice(pDevice);
|
|
|
|
WrappedIDXGIOutput6 *wrappedOutput = (WrappedIDXGIOutput6 *)pRestrictToOutput;
|
|
IDXGIOutput *unwrappedOutput = wrappedOutput ? wrappedOutput->GetReal() : NULL;
|
|
|
|
if(!RenderDoc::Inst().GetCaptureOptions().allowFullscreen)
|
|
{
|
|
RDCWARN("Impossible to disallow fullscreen on call to CreateSwapChainForComposition");
|
|
}
|
|
|
|
if(wrapDevice)
|
|
{
|
|
DXGI_SWAP_CHAIN_DESC1 local = {};
|
|
DXGI_SWAP_CHAIN_DESC1 *desc = NULL;
|
|
|
|
if(pDesc)
|
|
{
|
|
local = *pDesc;
|
|
desc = &local;
|
|
}
|
|
|
|
local.BufferUsage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
|
|
HRESULT ret = m_pReal2->CreateSwapChainForComposition(wrapDevice->GetRealIUnknown(), desc,
|
|
unwrappedOutput, ppSwapChain);
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
HWND wnd = NULL;
|
|
(*ppSwapChain)->GetHwnd(&wnd);
|
|
if(wnd == NULL)
|
|
wnd = (HWND)0x1;
|
|
*ppSwapChain = new WrappedIDXGISwapChain4(*ppSwapChain, wnd, wrapDevice);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
RDCERR("Creating swap chain with non-hooked device!");
|
|
}
|
|
|
|
return m_pReal2->CreateSwapChainForComposition(pDevice, pDesc, unwrappedOutput, ppSwapChain);
|
|
}
|
|
|
|
WrappedIDXGIOutputDuplication::WrappedIDXGIOutputDuplication(ID3DDevice *device,
|
|
IDXGIOutputDuplication *real)
|
|
: RefCountDXGIObject(real), m_Device(device), m_pReal(real)
|
|
{
|
|
}
|
|
|
|
WrappedIDXGIOutputDuplication::~WrappedIDXGIOutputDuplication()
|
|
{
|
|
SAFE_RELEASE(m_pReal);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIOutputDuplication::AcquireNextFrame(
|
|
UINT TimeoutInMilliseconds, DXGI_OUTDUPL_FRAME_INFO *pFrameInfo, IDXGIResource **ppDesktopResource)
|
|
{
|
|
if(!ppDesktopResource)
|
|
return E_INVALIDARG;
|
|
|
|
IDXGIResource *desktop = NULL;
|
|
HRESULT ret = m_pReal->AcquireNextFrame(TimeoutInMilliseconds, pFrameInfo, &desktop);
|
|
|
|
if(SUCCEEDED(ret) && desktop)
|
|
desktop = m_Device->WrapExternalDXGIResource(desktop);
|
|
|
|
*ppDesktopResource = desktop;
|
|
|
|
return ret;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE WrappedIDXGIOutputDuplication::QueryInterface(REFIID riid, void **ppvObject)
|
|
{
|
|
if(riid == __uuidof(IDXGIOutputDuplication))
|
|
{
|
|
AddRef();
|
|
*ppvObject = (IDXGIOutputDuplication *)this;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
WarnUnknownGUID("IDXGIOutputDuplication", riid);
|
|
}
|
|
|
|
return RefCountDXGIObject::QueryInterface(riid, ppvObject);
|
|
}
|