Commit 73b5fb05 authored by Markus Amsler's avatar Markus Amsler Committed by Alexandre Julliard

d3d9: Fix implicit swap chain refcounting.

parent 5e0fc621
...@@ -261,6 +261,9 @@ typedef struct IDirect3DSwapChain9Impl ...@@ -261,6 +261,9 @@ typedef struct IDirect3DSwapChain9Impl
/* Parent reference */ /* Parent reference */
LPDIRECT3DDEVICE9 parentDevice; LPDIRECT3DDEVICE9 parentDevice;
/* Flags an implicit swap chain */
BOOL isImplicit;
} IDirect3DSwapChain9Impl; } IDirect3DSwapChain9Impl;
/* ------------------ */ /* ------------------ */
......
...@@ -236,8 +236,9 @@ HRESULT WINAPI D3D9CB_CreateAdditionalSwapChain(IUnknown *device, ...@@ -236,8 +236,9 @@ HRESULT WINAPI D3D9CB_CreateAdditionalSwapChain(IUnknown *device,
if (SUCCEEDED(res)) { if (SUCCEEDED(res)) {
*ppSwapChain = d3dSwapChain->wineD3DSwapChain; *ppSwapChain = d3dSwapChain->wineD3DSwapChain;
IUnknown_Release(d3dSwapChain->parentDevice); d3dSwapChain->isImplicit = TRUE;
d3dSwapChain->parentDevice = NULL; /* Implicit swap chains are created with an refcount of 0 */
IUnknown_Release((IUnknown *)d3dSwapChain);
} else { } else {
*ppSwapChain = NULL; *ppSwapChain = NULL;
} }
...@@ -261,12 +262,13 @@ HRESULT WINAPI D3D9CB_CreateAdditionalSwapChain(IUnknown *device, ...@@ -261,12 +262,13 @@ HRESULT WINAPI D3D9CB_CreateAdditionalSwapChain(IUnknown *device,
} }
ULONG WINAPI D3D9CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) { ULONG WINAPI D3D9CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
IUnknown* swapChainParent; IDirect3DSwapChain9Impl* swapChainParent;
TRACE("(%p) call back\n", pSwapChain); TRACE("(%p) call back\n", pSwapChain);
IWineD3DSwapChain_GetParent(pSwapChain, &swapChainParent); IWineD3DSwapChain_GetParent(pSwapChain,(IUnknown **) &swapChainParent);
IUnknown_Release(swapChainParent); swapChainParent->isImplicit = FALSE;
return IUnknown_Release(swapChainParent); /* 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 */ /* Internal function called back during the CreateDevice to create a render target */
......
...@@ -48,6 +48,8 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_AddRef(LPDIRECT3DSWAPCHAIN9 iface) { ...@@ -48,6 +48,8 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_AddRef(LPDIRECT3DSWAPCHAIN9 iface) {
TRACE("(%p) : AddRef from %d\n", This, ref - 1); TRACE("(%p) : AddRef from %d\n", This, ref - 1);
if(ref == 1 && This->parentDevice) IUnknown_AddRef(This->parentDevice);
return ref; return ref;
} }
...@@ -58,9 +60,11 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface) ...@@ -58,9 +60,11 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface)
TRACE("(%p) : ReleaseRef to %d\n", This, ref); TRACE("(%p) : ReleaseRef to %d\n", This, ref);
if (ref == 0) { if (ref == 0) {
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain, D3D9CB_DestroyRenderTarget);
if (This->parentDevice) IUnknown_Release(This->parentDevice); 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; return ref;
} }
......
...@@ -358,41 +358,41 @@ static void test_refcount(void) ...@@ -358,41 +358,41 @@ static void test_refcount(void)
* - the refcount is not forwarded to the container. * - the refcount is not forwarded to the container.
*/ */
hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapChain); hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapChain);
todo_wine CHECK_CALL( hr, "GetSwapChain", pDevice, ++refcount); CHECK_CALL( hr, "GetSwapChain", pDevice, ++refcount);
if (pSwapChain) if (pSwapChain)
{ {
todo_wine CHECK_REFCOUNT( pSwapChain, 1); CHECK_REFCOUNT( pSwapChain, 1);
hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget); hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
todo_wine CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount); CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
todo_wine CHECK_REFCOUNT( pSwapChain, 1); CHECK_REFCOUNT( pSwapChain, 1);
if(pRenderTarget) if(pRenderTarget)
{ {
CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain); CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
CHECK_REFCOUNT( pRenderTarget, 1); CHECK_REFCOUNT( pRenderTarget, 1);
CHECK_ADDREF_REFCOUNT(pRenderTarget, 2); CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
todo_wine CHECK_REFCOUNT(pDevice, refcount); CHECK_REFCOUNT(pDevice, refcount);
CHECK_RELEASE_REFCOUNT(pRenderTarget, 1); CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
todo_wine CHECK_REFCOUNT(pDevice, refcount); CHECK_REFCOUNT(pDevice, refcount);
hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget); 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_REFCOUNT( pRenderTarget, 2);
CHECK_RELEASE_REFCOUNT( pRenderTarget, 1); CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
CHECK_RELEASE_REFCOUNT( pRenderTarget, 0); 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. */ /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
CHECK_ADDREF_REFCOUNT(pRenderTarget, 1); CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
todo_wine CHECK_REFCOUNT(pDevice, ++refcount); CHECK_REFCOUNT(pDevice, ++refcount);
CHECK_RELEASE_REFCOUNT(pRenderTarget, 0); CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
todo_wine CHECK_REFCOUNT(pDevice, --refcount); CHECK_REFCOUNT(pDevice, --refcount);
} }
/* Render target and back buffer are identical. */ /* Render target and back buffer are identical. */
hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, 0, &pBackBuffer); hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, 0, &pBackBuffer);
todo_wine CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount); CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
if(pBackBuffer) if(pBackBuffer)
{ {
CHECK_RELEASE_REFCOUNT(pBackBuffer, 0); CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
...@@ -400,39 +400,39 @@ static void test_refcount(void) ...@@ -400,39 +400,39 @@ static void test_refcount(void)
pRenderTarget, pBackBuffer); pRenderTarget, pBackBuffer);
pBackBuffer = NULL; pBackBuffer = NULL;
} }
todo_wine CHECK_REFCOUNT( pDevice, --refcount); CHECK_REFCOUNT( pDevice, --refcount);
hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pStencilSurface); hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pStencilSurface);
todo_wine CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount); CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
todo_wine CHECK_REFCOUNT( pSwapChain, 1); CHECK_REFCOUNT( pSwapChain, 1);
if(pStencilSurface) if(pStencilSurface)
{ {
CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice9, pDevice); CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice9, pDevice);
CHECK_REFCOUNT( pStencilSurface, 1); CHECK_REFCOUNT( pStencilSurface, 1);
CHECK_ADDREF_REFCOUNT(pStencilSurface, 2); CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
todo_wine CHECK_REFCOUNT(pDevice, refcount); CHECK_REFCOUNT(pDevice, refcount);
CHECK_RELEASE_REFCOUNT(pStencilSurface, 1); CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
todo_wine CHECK_REFCOUNT(pDevice, refcount); CHECK_REFCOUNT(pDevice, refcount);
CHECK_RELEASE_REFCOUNT( pStencilSurface, 0); 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. */ /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
CHECK_ADDREF_REFCOUNT(pStencilSurface, 1); CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
todo_wine CHECK_REFCOUNT(pDevice, ++refcount); CHECK_REFCOUNT(pDevice, ++refcount);
CHECK_RELEASE_REFCOUNT(pStencilSurface, 0); CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
todo_wine CHECK_REFCOUNT(pDevice, --refcount); CHECK_REFCOUNT(pDevice, --refcount);
pStencilSurface = NULL; pStencilSurface = NULL;
} }
todo_wine CHECK_RELEASE_REFCOUNT( pSwapChain, 0); CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
CHECK_REFCOUNT( pDevice, --refcount); CHECK_REFCOUNT( pDevice, --refcount);
/* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */ /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
todo_wine CHECK_ADDREF_REFCOUNT(pSwapChain, 1); CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
todo_wine CHECK_REFCOUNT(pDevice, ++refcount); CHECK_REFCOUNT(pDevice, ++refcount);
todo_wine CHECK_RELEASE_REFCOUNT(pSwapChain, 0); CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
CHECK_REFCOUNT(pDevice, --refcount); CHECK_REFCOUNT(pDevice, --refcount);
pSwapChain = NULL; pSwapChain = NULL;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment