summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--retrace/d3dretrace_dxgi.hpp3
-rw-r--r--retrace/d3dretrace_dxgi_priv.cpp333
-rwxr-xr-xretrace/dxgiretrace.py3
3 files changed, 178 insertions, 161 deletions
diff --git a/retrace/d3dretrace_dxgi.hpp b/retrace/d3dretrace_dxgi.hpp
index 6d369d77..eafc3054 100644
--- a/retrace/d3dretrace_dxgi.hpp
+++ b/retrace/d3dretrace_dxgi.hpp
@@ -61,7 +61,8 @@ createWindowForSwapChain(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
}
-HRESULT QueryInterface(IUnknown *pThis, REFIID riid, void **ppvObj);
+BOOL
+overrideQueryInterface(IUnknown *pThis, REFIID riid, void **ppvObj, HRESULT *pResult);
diff --git a/retrace/d3dretrace_dxgi_priv.cpp b/retrace/d3dretrace_dxgi_priv.cpp
index ad1627c7..d8b30b6c 100644
--- a/retrace/d3dretrace_dxgi_priv.cpp
+++ b/retrace/d3dretrace_dxgi_priv.cpp
@@ -36,140 +36,150 @@
* and IDXGISwapChain interfaces, just for sake of d3dretrace. Retracing on
* top of the undocumented interfaces works, but it may interfere with running
* DWM and causes corruption of the desktop upon exit.
+ *
+ * Note that we don't maintain our own reference counts in these
+ * implementations, as there should only be one reference count for all
+ * interfaces. See http://msdn.microsoft.com/en-us/library/ms686590.aspx
*/
namespace d3dretrace {
+static HRESULT __stdcall
+GetInterface(IUnknown *pUnknown, void **ppvObj) {
+ if (!ppvObj) {
+ return E_POINTER;
+ }
+ *ppvObj = (LPVOID)pUnknown;
+ pUnknown->AddRef();
+ return S_OK;
+}
+
+
class CDXGISwapChainDWM : public IDXGISwapChainDWM
{
-public:
+protected:
IDXGISwapChain *m_pSwapChain;
-public:
- CDXGISwapChainDWM(IDXGISwapChain *pSwapChain);
- ~CDXGISwapChainDWM();
-
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj);
- ULONG STDMETHODCALLTYPE AddRef(void);
- ULONG STDMETHODCALLTYPE Release(void);
- HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID Name, UINT DataSize, const void *pData);
- HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(REFGUID Name, const IUnknown *pUnknown);
- HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID Name, UINT *pDataSize, void *pData);
- HRESULT STDMETHODCALLTYPE GetParent(REFIID riid, void **ppParent);
- HRESULT STDMETHODCALLTYPE GetDevice(REFIID riid, void **ppDevice);
-
- HRESULT STDMETHODCALLTYPE Present(UINT SyncInterval, UINT Flags);
- HRESULT STDMETHODCALLTYPE GetBuffer(UINT Buffer, REFIID riid, void **ppSurface);
- HRESULT STDMETHODCALLTYPE GetDesc(DXGI_SWAP_CHAIN_DESC *pDesc);
- HRESULT STDMETHODCALLTYPE ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags);
- HRESULT STDMETHODCALLTYPE ResizeTarget(const DXGI_MODE_DESC *pNewTargetParameters);
- HRESULT STDMETHODCALLTYPE GetContainingOutput(IDXGIOutput **ppOutput);
- HRESULT STDMETHODCALLTYPE GetFrameStatistics(DXGI_FRAME_STATISTICS *pStats);
- HRESULT STDMETHODCALLTYPE GetLastPresentCount(UINT *pLastPresentCount);
-};
-
-CDXGISwapChainDWM::CDXGISwapChainDWM(IDXGISwapChain *pSwapChain) :
- m_pSwapChain(pSwapChain)
-{
-}
+ ~CDXGISwapChainDWM() {
+ m_pSwapChain->SetFullscreenState(FALSE, NULL);
+ }
-CDXGISwapChainDWM::~CDXGISwapChainDWM()
-{
- m_pSwapChain->SetFullscreenState(FALSE, NULL);
- m_pSwapChain->Release();
-}
+public:
+ CDXGISwapChainDWM(IDXGISwapChain *pSwapChain) :
+ m_pSwapChain(pSwapChain)
+ {}
+ /*
+ * IUnknown
+ */
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::QueryInterface(REFIID riid, void **ppvObj)
-{
- return m_pSwapChain->QueryInterface(riid, ppvObj);
-}
+ HRESULT STDMETHODCALLTYPE
+ QueryInterface(REFIID riid, void **ppvObj)
+ {
+ if (riid == IID_IDXGISwapChainDWM) {
+ return GetInterface(this, ppvObj);
+ }
+ return m_pSwapChain->QueryInterface(riid, ppvObj);
+ }
-ULONG STDMETHODCALLTYPE CDXGISwapChainDWM::AddRef(void)
-{
- // FIXME
- return 1;
-}
+ ULONG STDMETHODCALLTYPE
+ AddRef(void) {
+ return m_pSwapChain->AddRef();
+ }
-ULONG STDMETHODCALLTYPE CDXGISwapChainDWM::Release(void)
-{
- // FIXME
- return 1;
-}
+ ULONG STDMETHODCALLTYPE
+ Release(void) {
+ ULONG cRef = m_pSwapChain->Release();
+ if (cRef == 0) {
+ delete this;
+ }
+ return cRef;
+ }
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::SetPrivateData(REFGUID Name, UINT DataSize, const void *pData)
-{
- return m_pSwapChain->SetPrivateData(Name, DataSize, pData);
-}
+ /*
+ * IDXGIObject
+ */
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::SetPrivateDataInterface(REFGUID Name, const IUnknown *pUnknown)
-{
- return m_pSwapChain->SetPrivateDataInterface(Name, pUnknown);
-}
+ HRESULT STDMETHODCALLTYPE
+ SetPrivateData(REFGUID Name, UINT DataSize, const void *pData) {
+ return m_pSwapChain->SetPrivateData(Name, DataSize, pData);
+ }
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetPrivateData(REFGUID Name, UINT *pDataSize, void *pData)
-{
- return m_pSwapChain->GetPrivateData(Name, pDataSize, pData);
-}
+ HRESULT STDMETHODCALLTYPE
+ SetPrivateDataInterface(REFGUID Name, const IUnknown *pUnknown) {
+ return m_pSwapChain->SetPrivateDataInterface(Name, pUnknown);
+ }
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetParent(REFIID riid, void **ppParent)
-{
- return m_pSwapChain->GetParent(riid, ppParent);
-}
+ HRESULT STDMETHODCALLTYPE
+ GetPrivateData(REFGUID Name, UINT *pDataSize, void *pData) {
+ return m_pSwapChain->GetPrivateData(Name, pDataSize, pData);
+ }
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetDevice(REFIID riid, void **ppDevice)
-{
- return m_pSwapChain->GetDevice(riid, ppDevice);
-}
+ HRESULT STDMETHODCALLTYPE
+ GetParent(REFIID riid, void **ppParent) {
+ return m_pSwapChain->GetParent(riid, ppParent);
+ }
+ /*
+ * IDXGIDeviceSubObject
+ */
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::Present(UINT SyncInterval, UINT Flags)
-{
- return m_pSwapChain->Present(SyncInterval, Flags);
-}
+ HRESULT STDMETHODCALLTYPE
+ GetDevice(REFIID riid, void **ppDevice) {
+ return m_pSwapChain->GetDevice(riid, ppDevice);
+ }
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetBuffer(UINT Buffer, REFIID riid, void **ppSurface)
-{
- /* XXX: IDXGISwapChain buffers with indexes greater than zero can only be
- * read from, per
- * http://msdn.microsoft.com/en-gb/library/windows/desktop/bb174570.aspx,
- * but it appears that IDXGISwapChainDWM don't have that limitation.
+ /*
+ * IDXGISwapChainDWM
*/
- return m_pSwapChain->GetBuffer(Buffer, riid, ppSurface);
-}
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetDesc(DXGI_SWAP_CHAIN_DESC *pDesc)
-{
- return m_pSwapChain->GetDesc(pDesc);
-}
+ HRESULT STDMETHODCALLTYPE
+ Present(UINT SyncInterval, UINT Flags) {
+ return m_pSwapChain->Present(SyncInterval, Flags);
+ }
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags)
-{
- return m_pSwapChain->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags);
-}
+ HRESULT STDMETHODCALLTYPE
+ GetBuffer(UINT Buffer, REFIID riid, void **ppSurface) {
+ /* XXX: IDXGISwapChain buffers with indexes greater than zero can only
+ * be read from, per
+ * http://msdn.microsoft.com/en-gb/library/windows/desktop/bb174570.aspx,
+ * but it appears that IDXGISwapChainDWM doesn't have that limitation.
+ */
+ return m_pSwapChain->GetBuffer(Buffer, riid, ppSurface);
+ }
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::ResizeTarget(const DXGI_MODE_DESC *pNewTargetParameters)
-{
- return m_pSwapChain->ResizeTarget(pNewTargetParameters);
-}
+ HRESULT STDMETHODCALLTYPE
+ GetDesc(DXGI_SWAP_CHAIN_DESC *pDesc) {
+ return m_pSwapChain->GetDesc(pDesc);
+ }
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetContainingOutput(IDXGIOutput **ppOutput)
-{
- return m_pSwapChain->GetContainingOutput(ppOutput);
-}
+ HRESULT STDMETHODCALLTYPE
+ ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) {
+ return m_pSwapChain->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags);
+ }
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetFrameStatistics(DXGI_FRAME_STATISTICS *pStats)
-{
- return m_pSwapChain->GetFrameStatistics(pStats);
-}
+ HRESULT STDMETHODCALLTYPE
+ ResizeTarget(const DXGI_MODE_DESC *pNewTargetParameters) {
+ return m_pSwapChain->ResizeTarget(pNewTargetParameters);
+ }
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetLastPresentCount(UINT *pLastPresentCount)
-{
- return m_pSwapChain->GetLastPresentCount(pLastPresentCount);
-}
+ HRESULT STDMETHODCALLTYPE
+ GetContainingOutput(IDXGIOutput **ppOutput) {
+ return m_pSwapChain->GetContainingOutput(ppOutput);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ GetFrameStatistics(DXGI_FRAME_STATISTICS *pStats) {
+ return m_pSwapChain->GetFrameStatistics(pStats);
+ }
+ HRESULT STDMETHODCALLTYPE
+ GetLastPresentCount(UINT *pLastPresentCount) {
+ return m_pSwapChain->GetLastPresentCount(pLastPresentCount);
+ }
+};
class CDXGIFactoryDWM : public IDXGIFactoryDWM
@@ -177,80 +187,87 @@ class CDXGIFactoryDWM : public IDXGIFactoryDWM
private:
IDXGIFactory *m_pFactory;
- ~CDXGIFactoryDWM();
+ ~CDXGIFactoryDWM() {
+ }
public:
- CDXGIFactoryDWM(IDXGIFactory *pFactory);
-
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj);
- ULONG STDMETHODCALLTYPE AddRef(void);
- ULONG STDMETHODCALLTYPE Release(void);
- HRESULT STDMETHODCALLTYPE CreateSwapChain(IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGIOutput *pOutput, IDXGISwapChainDWM **ppSwapChain);
-};
-
-CDXGIFactoryDWM::CDXGIFactoryDWM(IDXGIFactory *pFactory) :
- m_pFactory(pFactory)
-{}
+ CDXGIFactoryDWM(IDXGIFactory *pFactory) :
+ m_pFactory(pFactory)
+ {}
-CDXGIFactoryDWM::~CDXGIFactoryDWM()
-{
- m_pFactory->Release();
-}
+ /*
+ * IUnknown
+ */
+ HRESULT STDMETHODCALLTYPE
+ QueryInterface(REFIID riid, void **ppvObj)
+ {
+ if (riid == IID_IDXGIFactoryDWM) {
+ return GetInterface(static_cast<IDXGIFactoryDWM *>(this), ppvObj);
+ }
+ return m_pFactory->QueryInterface(riid, ppvObj);
+ }
-HRESULT STDMETHODCALLTYPE CDXGIFactoryDWM::QueryInterface(REFIID riid, void **ppvObj)
-{
- return m_pFactory->QueryInterface(riid, ppvObj);
-}
+ ULONG STDMETHODCALLTYPE
+ AddRef(void) {
+ return m_pFactory->AddRef();
+ }
-ULONG STDMETHODCALLTYPE CDXGIFactoryDWM::AddRef(void)
-{
- // FIXME
- return 1;
-}
+ ULONG STDMETHODCALLTYPE
+ Release(void) {
+ ULONG cRef = m_pFactory->Release();
+ if (cRef == 0) {
+ delete this;
+ }
+ return cRef;
+ }
-ULONG STDMETHODCALLTYPE CDXGIFactoryDWM::Release(void)
-{
- // FIXME
- return 1;
-}
+ /*
+ * IDXGIFactoryDWM
+ */
-HRESULT STDMETHODCALLTYPE CDXGIFactoryDWM::CreateSwapChain(IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGIOutput *pOutput, IDXGISwapChainDWM **ppSwapChain)
-{
- IDXGISwapChain *pSwapChain = NULL;
- if (retrace::forceWindowed) {
- assert(pDesc->Windowed);
- }
- assert(!pDesc->OutputWindow);
- pDesc->OutputWindow = d3dretrace::createWindow(pDesc->BufferDesc.Width, pDesc->BufferDesc.Height);
- HRESULT hr = m_pFactory->CreateSwapChain(pDevice, pDesc, &pSwapChain);
- if (SUCCEEDED(hr)) {
- if (!retrace::forceWindowed) {
- pSwapChain->SetFullscreenState(TRUE, pOutput);
+ HRESULT STDMETHODCALLTYPE
+ CreateSwapChain(IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGIOutput *pOutput, IDXGISwapChainDWM **ppSwapChain)
+ {
+ IDXGISwapChain *pSwapChain = NULL;
+ if (retrace::forceWindowed) {
+ assert(pDesc->Windowed);
+ }
+ assert(!pDesc->OutputWindow);
+ pDesc->OutputWindow = d3dretrace::createWindow(pDesc->BufferDesc.Width, pDesc->BufferDesc.Height);
+ HRESULT hr = m_pFactory->CreateSwapChain(pDevice, pDesc, &pSwapChain);
+ if (SUCCEEDED(hr)) {
+ if (!retrace::forceWindowed) {
+ pSwapChain->SetFullscreenState(TRUE, pOutput);
+ }
+ *ppSwapChain = new CDXGISwapChainDWM(pSwapChain);
}
- *ppSwapChain = new CDXGISwapChainDWM(pSwapChain);
+ return hr;
}
- return hr;
-}
+};
-HRESULT QueryInterface(IUnknown *pUnknown, REFIID riid, void **ppvObj)
+BOOL
+overrideQueryInterface(IUnknown *pUnknown, REFIID riid, void **ppvObj, HRESULT *pResult)
{
+ HRESULT hr;
+
if (!ppvObj) {
- return E_POINTER;
+ *pResult = E_POINTER;
+ return TRUE;
}
- HRESULT hr;
if (riid == IID_IDXGIFactoryDWM) {
- IDXGIFactory *pFactory = NULL;
- hr = pUnknown->QueryInterface(IID_IDXGIFactory, (VOID **)&pFactory);
- if (SUCCEEDED(hr)) {
- *ppvObj = new d3dretrace::CDXGIFactoryDWM(pFactory);
- return S_OK;
- }
+ IDXGIFactory *pFactory = NULL;
+ hr = pUnknown->QueryInterface(IID_IDXGIFactory, (VOID **)&pFactory);
+ if (SUCCEEDED(hr)) {
+ *ppvObj = new d3dretrace::CDXGIFactoryDWM(pFactory);
+ *pResult = S_OK;
+ return TRUE;
+ }
}
- return E_NOINTERFACE;
+ return FALSE;
}
diff --git a/retrace/dxgiretrace.py b/retrace/dxgiretrace.py
index 07302181..3f17a097 100755
--- a/retrace/dxgiretrace.py
+++ b/retrace/dxgiretrace.py
@@ -187,8 +187,7 @@ class D3DRetracer(Retracer):
# intercept private interfaces
if method.name == 'QueryInterface':
- print r' _result = d3dretrace::QueryInterface(_this, riid, ppvObj);'
- print r' if (FAILED(_result)) {'
+ print r' if (!d3dretrace::overrideQueryInterface(_this, riid, ppvObj, &_result)) {'
Retracer.invokeInterfaceMethod(self, interface, method)
print r' }'
return