diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index 1fba1b3cf0..97991041d5 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -261,6 +261,9 @@ typedef struct IDirect3DSwapChain9Impl /* Parent reference */ LPDIRECT3DDEVICE9 parentDevice; + + /* Flags an implicit swap chain */ + BOOL isImplicit; } IDirect3DSwapChain9Impl; /* ------------------ */ diff --git a/dlls/d3d9/directx.c b/dlls/d3d9/directx.c index 548d790b57..899463af6b 100644 --- a/dlls/d3d9/directx.c +++ b/dlls/d3d9/directx.c @@ -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 */ diff --git a/dlls/d3d9/swapchain.c b/dlls/d3d9/swapchain.c index 07b93d67ee..093ad4381b 100644 --- a/dlls/d3d9/swapchain.c +++ b/dlls/d3d9/swapchain.c @@ -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; } diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index dac04b7e1a..96fdfc264e 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -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; }