Markus Amsler : d3d9: Fix implicit swap chain refcounting.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Dec 18 05:34:40 CST 2006


Module: wine
Branch: master
Commit: 73b5fb059f8a62bb2862515cdfe7624963cce974
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=73b5fb059f8a62bb2862515cdfe7624963cce974

Author: Markus Amsler <markus.amsler at oribi.org>
Date:   Mon Dec 18 00:17:31 2006 +0100

d3d9: Fix implicit swap chain refcounting.

---

 dlls/d3d9/d3d9_private.h |    3 +++
 dlls/d3d9/directx.c      |   14 ++++++++------
 dlls/d3d9/swapchain.c    |    8 ++++++--
 dlls/d3d9/tests/device.c |   46 +++++++++++++++++++++++-----------------------
 4 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index 1fba1b3..9799104 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 548d790..899463a 100644
--- a/dlls/d3d9/directx.c
+++ b/dlls/d3d9/directx.c
@@ -236,8 +236,9 @@ HRESULT WINAPI D3D9CB_CreateAdditionalSw
 
     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_CreateAdditionalSw
 }
 
 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 07b93d6..093ad43 100644
--- a/dlls/d3d9/swapchain.c
+++ b/dlls/d3d9/swapchain.c
@@ -48,6 +48,8 @@ static ULONG WINAPI IDirect3DSwapChain9I
 
     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 IDirect3DSwapChain9I
     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 dac04b7..96fdfc2 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;
     }




More information about the wine-cvs mailing list