[PATCH 3/6] d3d9: Do not decrease swapchain surface refcount when it is already 0.

Józef Kucia jkucia at codeweavers.com
Mon Feb 13 06:07:34 CST 2017


Based on a patch by Henri Verbeet.

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---

For https://bugs.winehq.org/show_bug.cgi?id=18477

---
 dlls/d3d9/surface.c      |  6 ++++++
 dlls/d3d9/tests/device.c | 22 ++++++++++++++++------
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/dlls/d3d9/surface.c b/dlls/d3d9/surface.c
index 07eaf7b..976a7fa 100644
--- a/dlls/d3d9/surface.c
+++ b/dlls/d3d9/surface.c
@@ -91,6 +91,12 @@ static ULONG WINAPI d3d9_surface_Release(IDirect3DSurface9 *iface)
         return IDirect3DBaseTexture9_Release(&surface->texture->IDirect3DBaseTexture9_iface);
     }
 
+    if (!surface->resource.refcount)
+    {
+        WARN("Surface does not have any references.\n");
+        return 0;
+    }
+
     refcount = InterlockedDecrement(&surface->resource.refcount);
     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index feb1efc..27f3a1d 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -1464,16 +1464,20 @@ static void test_refcount(void)
             CHECK_REFCOUNT(device, ++refcount);
             CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
             CHECK_REFCOUNT(device, --refcount);
+            CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
+            CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
         }
 
         /* Render target and back buffer are identical. */
         hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
         CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
-        if(pBackBuffer)
+        if (pBackBuffer)
         {
             CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
             ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
-            pRenderTarget, pBackBuffer);
+                    pRenderTarget, pBackBuffer);
+            CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
+            CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
             pBackBuffer = NULL;
         }
         CHECK_REFCOUNT(device, --refcount);
@@ -1481,7 +1485,7 @@ static void test_refcount(void)
         hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
         CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
         CHECK_REFCOUNT( pSwapChain, 1);
-        if(pStencilSurface)
+        if (pStencilSurface)
         {
             CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
             CHECK_REFCOUNT( pStencilSurface, 1);
@@ -1491,7 +1495,7 @@ static void test_refcount(void)
             CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
             CHECK_REFCOUNT(device, refcount);
 
-            CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
+            CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
             CHECK_REFCOUNT(device, --refcount);
 
             /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
@@ -1499,6 +1503,8 @@ static void test_refcount(void)
             CHECK_REFCOUNT(device, ++refcount);
             CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
             CHECK_REFCOUNT(device, --refcount);
+            CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
+            CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
             pStencilSurface = NULL;
         }
 
@@ -1653,6 +1659,8 @@ static void test_refcount(void)
             CHECK_REFCOUNT(device, ++refcount);
             CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
             CHECK_REFCOUNT(device, --refcount);
+            CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
+            CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
             pBackBuffer = NULL;
         }
         CHECK_REFCOUNT( pSwapChain, 1);
@@ -1669,12 +1677,14 @@ static void test_refcount(void)
      * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
     CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
-    if(pRenderTarget2)
+    if (pRenderTarget2)
     {
         CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
         ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
-           pRenderTarget, pRenderTarget2);
+                pRenderTarget, pRenderTarget2);
         CHECK_REFCOUNT(device, --refcount);
+        CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
+        CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
         pRenderTarget2 = NULL;
     }
     pRenderTarget = NULL;
-- 
2.10.2




More information about the wine-patches mailing list