Stefan Dösinger : d3d9: Fix the circular converted vertex declaration reference.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Apr 12 09:59:53 CDT 2007


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

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Sun Apr  8 00:11:09 2007 +0200

d3d9: Fix the circular converted vertex declaration reference.

---

 dlls/d3d9/device.c            |    7 +++----
 dlls/d3d9/tests/visual.c      |    7 -------
 dlls/d3d9/vertexdeclaration.c |   22 ++++++++++++++++------
 3 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index e9c4078..8fc7511 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -62,8 +62,7 @@ static ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9 iface) {
 
     if (ref == 0) {
       This->inDestruction = TRUE;
-      if (This->convertedDecl != NULL)
-          IUnknown_Release(This->convertedDecl);
+      IDirect3DDevice9_SetVertexDeclaration(iface, NULL);
       IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D9CB_DestroyDepthStencilSurface, D3D9CB_DestroySwapChain);
       IWineD3DDevice_Release(This->WineD3DDevice);
       HeapFree(GetProcessHeap(), 0, This);
@@ -784,14 +783,14 @@ HRESULT  WINAPI  IDirect3DDevice9Impl_SetFVF(LPDIRECT3DDEVICE9 iface, DWORD FVF)
 
          hr = IDirect3DDevice9Impl_CreateVertexDeclaration(iface, elements, &pDecl);
          if (hr != S_OK) goto exit;
-             
+
          hr = IDirect3DDevice9Impl_SetVertexDeclaration(iface, pDecl);
          if (hr != S_OK) goto exit;
          This->convertedDecl = pDecl;
-         pDecl = NULL;
 
          exit:
          HeapFree(GetProcessHeap(), 0, elements);
+         /* If allocated and set correctly, this will reduce the refcount to 0, but not destroy the declaration */
          if (pDecl) IUnknown_Release(pDecl);
          if (hr != S_OK) return hr;
     }
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index 33c4231..bde2a5b 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -259,11 +259,6 @@ static void lighting_test(IDirect3DDevice9 *device)
 
     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
-
-    /* Hack for a bug in d3d9: SetFVF creates a converted vertex declaration, with a circular refcount.
-     * This prevents the screen resolution from being restored correctly on device release. Unset the vdecl
-     */
-    IDirect3DDevice9_SetVertexDeclaration(device, NULL);
 }
 
 static void clear_test(IDirect3DDevice9 *device)
@@ -547,8 +542,6 @@ static void fog_test(IDirect3DDevice9 *device)
     /* Turn off the fog master switch to avoid confusing other tests */
     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
     ok(hr == D3D_OK, "Turning off fog calculations returned %s\n", DXGetErrorString9(hr));
-
-    IDirect3DDevice9_SetVertexDeclaration(device, NULL);
 }
 
 /* This test verifies the behaviour of cube maps wrt. texture wrapping.
diff --git a/dlls/d3d9/vertexdeclaration.c b/dlls/d3d9/vertexdeclaration.c
index 84d4359..892f8ac 100644
--- a/dlls/d3d9/vertexdeclaration.c
+++ b/dlls/d3d9/vertexdeclaration.c
@@ -216,10 +216,15 @@ static ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECL
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
-        IWineD3DVertexDeclaration_Release(This->wineD3DVertexDeclaration);
-        IUnknown_Release(This->parentDevice);
-        HeapFree(GetProcessHeap(), 0, This->elements);
-        HeapFree(GetProcessHeap(), 0, This);
+        IDirect3DDevice9 *parentDevice = This->parentDevice;
+        BOOL converted = ((IDirect3DDevice9Impl *) parentDevice)->convertedDecl == iface;
+
+        if(!converted) {
+            IWineD3DVertexDeclaration_Release(This->wineD3DVertexDeclaration);
+            HeapFree(GetProcessHeap(), 0, This->elements);
+            HeapFree(GetProcessHeap(), 0, This);
+        }
+        IUnknown_Release(parentDevice);
     }
     return ref;
 }
@@ -367,12 +372,17 @@ HRESULT  WINAPI  IDirect3DDevice9Impl_SetVertexDeclaration(LPDIRECT3DDEVICE9 ifa
     TRACE("(%p) : Relay\n", iface);
 
     if (This->convertedDecl && This->convertedDecl != pDecl) {
-        IUnknown_Release(This->convertedDecl);
+        IDirect3DVertexDeclaration9Impl *iDecl = (IDirect3DVertexDeclaration9Impl *) This->convertedDecl;
+
+        /* Will need locking once we claim to be thread safe */
+        if(iDecl->ref == 0) {
+            IUnknown_AddRef(This->convertedDecl);
+            IUnknown_Release(This->convertedDecl);
+        }
         This->convertedDecl = NULL;
     }
 
     hr = IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, pDeclImpl == NULL ? NULL : pDeclImpl->wineD3DVertexDeclaration);
-
     return hr;
 }
 




More information about the wine-cvs mailing list