d3d9: Fix implicit swap chain refcounting.
This commit is contained in:
parent
5e0fc62135
commit
73b5fb059f
|
@ -261,6 +261,9 @@ typedef struct IDirect3DSwapChain9Impl
|
|||
|
||||
/* Parent reference */
|
||||
LPDIRECT3DDEVICE9 parentDevice;
|
||||
|
||||
/* Flags an implicit swap chain */
|
||||
BOOL isImplicit;
|
||||
} IDirect3DSwapChain9Impl;
|
||||
|
||||
/* ------------------ */
|
||||
|
|
|
@ -236,8 +236,9 @@ HRESULT WINAPI D3D9CB_CreateAdditionalSwapChain(IUnknown *device,
|
|||
|
||||
if (SUCCEEDED(res)) {
|
||||
*ppSwapChain = d3dSwapChain->wineD3DSwapChain;
|
||||
IUnknown_Release(d3dSwapChain->parentDevice);
|
||||
d3dSwapChain->parentDevice = NULL;
|
||||
d3dSwapChain->isImplicit = TRUE;
|
||||
/* Implicit swap chains are created with an refcount of 0 */
|
||||
IUnknown_Release((IUnknown *)d3dSwapChain);
|
||||
} else {
|
||||
*ppSwapChain = NULL;
|
||||
}
|
||||
|
@ -261,12 +262,13 @@ HRESULT WINAPI D3D9CB_CreateAdditionalSwapChain(IUnknown *device,
|
|||
}
|
||||
|
||||
ULONG WINAPI D3D9CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
|
||||
IUnknown* swapChainParent;
|
||||
IDirect3DSwapChain9Impl* swapChainParent;
|
||||
TRACE("(%p) call back\n", pSwapChain);
|
||||
|
||||
IWineD3DSwapChain_GetParent(pSwapChain, &swapChainParent);
|
||||
IUnknown_Release(swapChainParent);
|
||||
return IUnknown_Release(swapChainParent);
|
||||
IWineD3DSwapChain_GetParent(pSwapChain,(IUnknown **) &swapChainParent);
|
||||
swapChainParent->isImplicit = FALSE;
|
||||
/* Swap chain had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
|
||||
return IDirect3DSwapChain9_Release((IDirect3DSwapChain9*) swapChainParent);
|
||||
}
|
||||
|
||||
/* Internal function called back during the CreateDevice to create a render target */
|
||||
|
|
|
@ -48,6 +48,8 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_AddRef(LPDIRECT3DSWAPCHAIN9 iface) {
|
|||
|
||||
TRACE("(%p) : AddRef from %d\n", This, ref - 1);
|
||||
|
||||
if(ref == 1 && This->parentDevice) IUnknown_AddRef(This->parentDevice);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
@ -58,9 +60,11 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface)
|
|||
TRACE("(%p) : ReleaseRef to %d\n", This, ref);
|
||||
|
||||
if (ref == 0) {
|
||||
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain, D3D9CB_DestroyRenderTarget);
|
||||
if (This->parentDevice) IUnknown_Release(This->parentDevice);
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
if (!This->isImplicit) {
|
||||
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain, D3D9CB_DestroyRenderTarget);
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
|
|
@ -358,41 +358,41 @@ static void test_refcount(void)
|
|||
* - the refcount is not forwarded to the container.
|
||||
*/
|
||||
hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapChain);
|
||||
todo_wine CHECK_CALL( hr, "GetSwapChain", pDevice, ++refcount);
|
||||
CHECK_CALL( hr, "GetSwapChain", pDevice, ++refcount);
|
||||
if (pSwapChain)
|
||||
{
|
||||
todo_wine CHECK_REFCOUNT( pSwapChain, 1);
|
||||
CHECK_REFCOUNT( pSwapChain, 1);
|
||||
|
||||
hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
|
||||
todo_wine CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
|
||||
todo_wine CHECK_REFCOUNT( pSwapChain, 1);
|
||||
CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
|
||||
CHECK_REFCOUNT( pSwapChain, 1);
|
||||
if(pRenderTarget)
|
||||
{
|
||||
CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
|
||||
CHECK_REFCOUNT( pRenderTarget, 1);
|
||||
|
||||
CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
|
||||
todo_wine CHECK_REFCOUNT(pDevice, refcount);
|
||||
CHECK_REFCOUNT(pDevice, refcount);
|
||||
CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
|
||||
todo_wine CHECK_REFCOUNT(pDevice, refcount);
|
||||
CHECK_REFCOUNT(pDevice, refcount);
|
||||
|
||||
hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
|
||||
todo_wine CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
|
||||
CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
|
||||
CHECK_REFCOUNT( pRenderTarget, 2);
|
||||
CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
|
||||
CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
|
||||
todo_wine CHECK_REFCOUNT( pDevice, --refcount);
|
||||
CHECK_REFCOUNT( pDevice, --refcount);
|
||||
|
||||
/* The render target is released with the device, so AddRef with refcount=0 is fine here. */
|
||||
CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
|
||||
todo_wine CHECK_REFCOUNT(pDevice, ++refcount);
|
||||
CHECK_REFCOUNT(pDevice, ++refcount);
|
||||
CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
|
||||
todo_wine CHECK_REFCOUNT(pDevice, --refcount);
|
||||
CHECK_REFCOUNT(pDevice, --refcount);
|
||||
}
|
||||
|
||||
/* Render target and back buffer are identical. */
|
||||
hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, 0, &pBackBuffer);
|
||||
todo_wine CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
|
||||
CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
|
||||
if(pBackBuffer)
|
||||
{
|
||||
CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
|
||||
|
@ -400,39 +400,39 @@ static void test_refcount(void)
|
|||
pRenderTarget, pBackBuffer);
|
||||
pBackBuffer = NULL;
|
||||
}
|
||||
todo_wine CHECK_REFCOUNT( pDevice, --refcount);
|
||||
CHECK_REFCOUNT( pDevice, --refcount);
|
||||
|
||||
hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pStencilSurface);
|
||||
todo_wine CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
|
||||
todo_wine CHECK_REFCOUNT( pSwapChain, 1);
|
||||
CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
|
||||
CHECK_REFCOUNT( pSwapChain, 1);
|
||||
if(pStencilSurface)
|
||||
{
|
||||
CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice9, pDevice);
|
||||
CHECK_REFCOUNT( pStencilSurface, 1);
|
||||
|
||||
CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
|
||||
todo_wine CHECK_REFCOUNT(pDevice, refcount);
|
||||
CHECK_REFCOUNT(pDevice, refcount);
|
||||
CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
|
||||
todo_wine CHECK_REFCOUNT(pDevice, refcount);
|
||||
CHECK_REFCOUNT(pDevice, refcount);
|
||||
|
||||
CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
|
||||
todo_wine CHECK_REFCOUNT( pDevice, --refcount);
|
||||
CHECK_REFCOUNT( pDevice, --refcount);
|
||||
|
||||
/* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
|
||||
CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
|
||||
todo_wine CHECK_REFCOUNT(pDevice, ++refcount);
|
||||
CHECK_REFCOUNT(pDevice, ++refcount);
|
||||
CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
|
||||
todo_wine CHECK_REFCOUNT(pDevice, --refcount);
|
||||
CHECK_REFCOUNT(pDevice, --refcount);
|
||||
pStencilSurface = NULL;
|
||||
}
|
||||
|
||||
todo_wine CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
|
||||
CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
|
||||
CHECK_REFCOUNT( pDevice, --refcount);
|
||||
|
||||
/* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
|
||||
todo_wine CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
|
||||
todo_wine CHECK_REFCOUNT(pDevice, ++refcount);
|
||||
todo_wine CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
|
||||
CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
|
||||
CHECK_REFCOUNT(pDevice, ++refcount);
|
||||
CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
|
||||
CHECK_REFCOUNT(pDevice, --refcount);
|
||||
pSwapChain = NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue