[10/13] D3D9: Fix the circular converted vertex declaration reference

Stefan Dösinger stefan at codeweavers.com
Tue Feb 20 15:59:39 CST 2007


If anyone knows a nicer way to release the converted declaration from 
SetVertexDeclaration feel free to comment.

Not applying this patch won't affect patches 11-13
-------------- next part --------------
From f6fde2f2da9e5ca27361eeb7ca9226b72bfc27a6 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Tue, 20 Feb 2007 19:19:24 +0100
Subject: [PATCH] D3D9: Fix the circular converted vertex declaration reference

The converted vertex declaration has ref 1 when returned the first time, so it has to be created with ref 0 and may not
hold a reference to the device. When the converted vertex decl is unset while it has ref 0 it should be
destroyed. Also removes the hack from the visual test.
---
 dlls/d3d9/d3d9_private.h      |    2 +-
 dlls/d3d9/device.c            |   12 ++++++++----
 dlls/d3d9/tests/visual.c      |    5 -----
 dlls/d3d9/vertexdeclaration.c |   14 +++++++++++---
 4 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index 972945d..3eee2c5 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -152,7 +152,6 @@ typedef struct IDirect3D9Impl
 
     /* The WineD3D device */
     IWineD3D               *WineD3D;
-
 } IDirect3D9Impl;
 
 /* ---------------- */
@@ -483,6 +482,7 @@ typedef struct IDirect3DVertexDeclaration9Impl {
 
   D3DVERTEXELEMENT9 *elements;
   size_t element_count;
+  BOOL convertedDecl;
 
   /* IDirect3DVertexDeclaration9 fields */
   IWineD3DVertexDeclaration *wineD3DVertexDeclaration;
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index 4dd16e0..bea4265 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);
@@ -779,17 +778,22 @@ HRESULT  WINAPI  IDirect3DDevice9Impl_SetFVF(LPDIRECT3DDEVICE9 iface, DWORD FVF)
          HRESULT hr;
          D3DVERTEXELEMENT9* elements = NULL;
          IDirect3DVertexDeclaration9* pDecl = NULL;
+         IDirect3DVertexDeclaration9Impl *iDecl = NULL;
 
          hr = vdecl_convert_fvf(FVF, &elements);
          if (hr != S_OK) goto exit;
 
          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;
+         iDecl = (IDirect3DVertexDeclaration9Impl *) pDecl;
+         iDecl->convertedDecl = TRUE;
+
+         /* This won't destroy it now, but reduce the refcount and release the device */
+         IDirect3DVertexDeclaration9_Release(pDecl);
 
          exit:
          HeapFree(GetProcessHeap(), 0, elements);
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index 40b8134..aab811c 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 resulution from beeing restored correctly on device release. Unset the vdecl
-     */
-    IDirect3DDevice9_SetVertexDeclaration(device, NULL);
 }
 
 START_TEST(visual)
diff --git a/dlls/d3d9/vertexdeclaration.c b/dlls/d3d9/vertexdeclaration.c
index 1497a50..b19ebf6 100644
--- a/dlls/d3d9/vertexdeclaration.c
+++ b/dlls/d3d9/vertexdeclaration.c
@@ -216,9 +216,13 @@ static ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECL
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
-        IWineD3DVertexDeclaration_Release(This->wineD3DVertexDeclaration);
+        if(!This->convertedDecl) {
+            IWineD3DVertexDeclaration_Release(This->wineD3DVertexDeclaration);
+        }
         IUnknown_Release(This->parentDevice);
-        HeapFree(GetProcessHeap(), 0, This);
+        if(!This->convertedDecl) {
+            HeapFree(GetProcessHeap(), 0, This);
+        }
     }
     return ref;
 }
@@ -365,12 +369,16 @@ HRESULT  WINAPI  IDirect3DDevice9Impl_SetVertexDeclaration(LPDIRECT3DDEVICE9 ifa
     TRACE("(%p) : Relay\n", iface);
 
     if (This->convertedDecl && This->convertedDecl != pDecl) {
+        IDirect3DVertexDeclaration9Impl *iDecl = (IDirect3DVertexDeclaration9Impl *) This->convertedDecl;
+        iDecl->convertedDecl = FALSE;
+
+        /* 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;
 }
 
-- 
1.4.4.3



More information about the wine-patches mailing list