[PATCH 05/12] wined3d: Don't free D3D vertex declarations until the wined3d vertex declaration is destroyed.

Henri Verbeet hverbeet at codeweavers.com
Wed Sep 23 03:05:52 CDT 2009


---
 dlls/d3d10core/inputlayout.c     |   18 ++++++++++++++++--
 dlls/d3d8/vertexdeclaration.c    |   28 +++++++++++++++++++++++-----
 dlls/d3d9/vertexdeclaration.c    |   28 +++++++++++++++++++++-------
 dlls/ddraw/ddraw.c               |    3 ++-
 dlls/wined3d/device.c            |    9 +++++----
 dlls/wined3d/vertexdeclaration.c |    5 ++++-
 dlls/wined3d/wined3d_private.h   |    6 ++++--
 include/wine/wined3d.idl         |    2 ++
 8 files changed, 77 insertions(+), 22 deletions(-)

diff --git a/dlls/d3d10core/inputlayout.c b/dlls/d3d10core/inputlayout.c
index 6300a9d..bdbff3a 100644
--- a/dlls/d3d10core/inputlayout.c
+++ b/dlls/d3d10core/inputlayout.c
@@ -129,6 +129,11 @@ static ULONG STDMETHODCALLTYPE d3d10_input_layout_AddRef(ID3D10InputLayout *ifac
 
     TRACE("%p increasing refcount to %u\n", This, refcount);
 
+    if (refcount == 1)
+    {
+        IWineD3DVertexDeclaration_AddRef(This->wined3d_decl);
+    }
+
     return refcount;
 }
 
@@ -142,7 +147,6 @@ static ULONG STDMETHODCALLTYPE d3d10_input_layout_Release(ID3D10InputLayout *ifa
     if (!refcount)
     {
         IWineD3DVertexDeclaration_Release(This->wined3d_decl);
-        HeapFree(GetProcessHeap(), 0, This);
     }
 
     return refcount;
@@ -194,6 +198,16 @@ static const struct ID3D10InputLayoutVtbl d3d10_input_layout_vtbl =
     d3d10_input_layout_SetPrivateDataInterface,
 };
 
+static void STDMETHODCALLTYPE d3d10_input_layout_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d10_input_layout_wined3d_parent_ops =
+{
+    d3d10_input_layout_wined3d_object_destroyed,
+};
+
 HRESULT d3d10_input_layout_init(struct d3d10_input_layout *layout, struct d3d10_device *device,
         const D3D10_INPUT_ELEMENT_DESC *element_descs, UINT element_count,
         const void *shader_byte_code, SIZE_T shader_byte_code_length)
@@ -214,7 +228,7 @@ HRESULT d3d10_input_layout_init(struct d3d10_input_layout *layout, struct d3d10_
     }
 
     hr = IWineD3DDevice_CreateVertexDeclaration(device->wined3d_device, &layout->wined3d_decl,
-            (IUnknown *)layout, wined3d_elements, wined3d_element_count);
+            (IUnknown *)layout, &d3d10_input_layout_wined3d_parent_ops, wined3d_elements, wined3d_element_count);
     HeapFree(GetProcessHeap(), 0, wined3d_elements);
     if (FAILED(hr))
     {
diff --git a/dlls/d3d8/vertexdeclaration.c b/dlls/d3d8/vertexdeclaration.c
index cf0a3f4..fad58fb 100644
--- a/dlls/d3d8/vertexdeclaration.c
+++ b/dlls/d3d8/vertexdeclaration.c
@@ -50,6 +50,13 @@ static ULONG WINAPI IDirect3DVertexDeclaration8Impl_AddRef(IDirect3DVertexDeclar
     ULONG ref_count = InterlockedIncrement(&This->ref_count);
     TRACE("(%p) : AddRef increasing to %d\n", This, ref_count);
 
+    if (ref_count == 1)
+    {
+        wined3d_mutex_lock();
+        IWineD3DVertexDeclaration_AddRef(This->wined3d_vertex_declaration);
+        wined3d_mutex_unlock();
+    }
+
     return ref_count;
 }
 
@@ -64,9 +71,6 @@ static ULONG WINAPI IDirect3DVertexDeclaration8Impl_Release(IDirect3DVertexDecla
         wined3d_mutex_lock();
         IWineD3DVertexDeclaration_Release(This->wined3d_vertex_declaration);
         wined3d_mutex_unlock();
-
-        HeapFree(GetProcessHeap(), 0, This->elements);
-        HeapFree(GetProcessHeap(), 0, This);
     }
 
     return ref_count;
@@ -359,6 +363,18 @@ static const IDirect3DVertexDeclaration8Vtbl Direct3DVertexDeclaration8_Vtbl =
     IDirect3DVertexDeclaration8Impl_Release
 };
 
+static void STDMETHODCALLTYPE d3d8_vertexdeclaration_wined3d_object_destroyed(void *parent)
+{
+    IDirect3DVertexDeclaration8Impl *declaration = parent;
+    HeapFree(GetProcessHeap(), 0, declaration->elements);
+    HeapFree(GetProcessHeap(), 0, declaration);
+}
+
+static const struct wined3d_parent_ops d3d8_vertexdeclaration_wined3d_parent_ops =
+{
+    d3d8_vertexdeclaration_wined3d_object_destroyed,
+};
+
 HRESULT vertexdeclaration_init(IDirect3DVertexDeclaration8Impl *declaration,
         IDirect3DDevice8Impl *device, const DWORD *elements)
 {
@@ -382,7 +398,8 @@ HRESULT vertexdeclaration_init(IDirect3DVertexDeclaration8Impl *declaration,
 
     wined3d_mutex_lock();
     hr = IWineD3DDevice_CreateVertexDeclaration(device->WineD3DDevice, &declaration->wined3d_vertex_declaration,
-            (IUnknown *)declaration, wined3d_elements, wined3d_element_count);
+            (IUnknown *)declaration, &d3d8_vertexdeclaration_wined3d_parent_ops,
+            wined3d_elements, wined3d_element_count);
     wined3d_mutex_unlock();
     HeapFree(GetProcessHeap(), 0, wined3d_elements);
     if (FAILED(hr))
@@ -407,7 +424,8 @@ HRESULT vertexdeclaration_init_fvf(IDirect3DVertexDeclaration8Impl *declaration,
     declaration->shader_handle = fvf;
 
     hr = IWineD3DDevice_CreateVertexDeclarationFromFVF(device->WineD3DDevice,
-            &declaration->wined3d_vertex_declaration, (IUnknown *)declaration, fvf);
+            &declaration->wined3d_vertex_declaration, (IUnknown *)declaration,
+            &d3d8_vertexdeclaration_wined3d_parent_ops, fvf);
     if (FAILED(hr))
     {
         WARN("Failed to create wined3d vertex declaration, hr %#x.\n", hr);
diff --git a/dlls/d3d9/vertexdeclaration.c b/dlls/d3d9/vertexdeclaration.c
index fc00f41..44371bb 100644
--- a/dlls/d3d9/vertexdeclaration.c
+++ b/dlls/d3d9/vertexdeclaration.c
@@ -217,6 +217,12 @@ static ULONG WINAPI IDirect3DVertexDeclaration9Impl_AddRef(LPDIRECT3DVERTEXDECLA
 
     if(ref == 1) {
         IDirect3DDevice9Ex_AddRef(This->parentDevice);
+        if (!This->convFVF)
+        {
+            wined3d_mutex_lock();
+            IWineD3DVertexDeclaration_AddRef(This->wineD3DVertexDeclaration);
+            wined3d_mutex_unlock();
+        }
     }
 
     return ref;
@@ -233,9 +239,6 @@ void IDirect3DVertexDeclaration9Impl_Destroy(LPDIRECT3DVERTEXDECLARATION9 iface)
     wined3d_mutex_lock();
     IWineD3DVertexDeclaration_Release(This->wineD3DVertexDeclaration);
     wined3d_mutex_unlock();
-
-    HeapFree(GetProcessHeap(), 0, This->elements);
-    HeapFree(GetProcessHeap(), 0, This);
 }
 
 static ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECLARATION9 iface) {
@@ -245,12 +248,10 @@ static ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECL
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
-        IDirect3DDevice9Ex *parentDevice = This->parentDevice;
-
+        IDirect3DDevice9Ex_Release(This->parentDevice);
         if(!This->convFVF) {
             IDirect3DVertexDeclaration9Impl_Destroy(iface);
         }
-        IDirect3DDevice9Ex_Release(parentDevice);
     }
     return ref;
 }
@@ -304,6 +305,18 @@ static const IDirect3DVertexDeclaration9Vtbl Direct3DVertexDeclaration9_Vtbl =
     IDirect3DVertexDeclaration9Impl_GetDeclaration
 };
 
+static void STDMETHODCALLTYPE d3d9_vertexdeclaration_wined3d_object_destroyed(void *parent)
+{
+    IDirect3DVertexDeclaration9Impl *declaration = parent;
+    HeapFree(GetProcessHeap(), 0, declaration->elements);
+    HeapFree(GetProcessHeap(), 0, declaration);
+}
+
+static const struct wined3d_parent_ops d3d9_vertexdeclaration_wined3d_parent_ops =
+{
+    d3d9_vertexdeclaration_wined3d_object_destroyed,
+};
+
 static HRESULT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9* d3d9_elements,
         WINED3DVERTEXELEMENT **wined3d_elements, UINT *element_count)
 {
@@ -380,7 +393,8 @@ HRESULT vertexdeclaration_init(IDirect3DVertexDeclaration9Impl *declaration,
 
     wined3d_mutex_lock();
     hr = IWineD3DDevice_CreateVertexDeclaration(device->WineD3DDevice, &declaration->wineD3DVertexDeclaration,
-            (IUnknown *)declaration, wined3d_elements, wined3d_element_count);
+            (IUnknown *)declaration, &d3d9_vertexdeclaration_wined3d_parent_ops,
+            wined3d_elements, wined3d_element_count);
     wined3d_mutex_unlock();
     HeapFree(GetProcessHeap(), 0, wined3d_elements);
     if (FAILED(hr))
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 6e27337..4573fd6 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -3250,7 +3250,8 @@ IDirectDrawImpl_FindDecl(IDirectDrawImpl *This,
     }
     TRACE("not found. Creating and inserting at position %d.\n", low);
 
-    hr = IWineD3DDevice_CreateVertexDeclarationFromFVF(This->wineD3DDevice, &pDecl, (IUnknown *)This, fvf);
+    hr = IWineD3DDevice_CreateVertexDeclarationFromFVF(This->wineD3DDevice, &pDecl,
+            (IUnknown *)This, &ddraw_null_wined3d_parent_ops, fvf);
     if (hr != S_OK) return NULL;
 
     if(This->declArraySize == This->numConvertedDecls) {
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 91c12fb..17f51a8 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1573,7 +1573,7 @@ static HRESULT  WINAPI  IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, U
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice *iface,
-        IWineD3DVertexDeclaration **declaration, IUnknown *parent,
+        IWineD3DVertexDeclaration **declaration, IUnknown *parent, const struct wined3d_parent_ops *parent_ops,
         const WINED3DVERTEXELEMENT *elements, UINT element_count)
 {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
@@ -1590,7 +1590,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice
         return E_OUTOFMEMORY;
     }
 
-    hr = vertexdeclaration_init(object, This, elements, element_count, parent);
+    hr = vertexdeclaration_init(object, This, elements, element_count, parent, parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
@@ -1742,7 +1742,8 @@ static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice *iface,
-        IWineD3DVertexDeclaration **declaration, IUnknown *parent, DWORD fvf)
+        IWineD3DVertexDeclaration **declaration, IUnknown *parent,
+        const struct wined3d_parent_ops *parent_ops, DWORD fvf)
 {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
     WINED3DVERTEXELEMENT *elements;
@@ -1754,7 +1755,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3D
     size = ConvertFvfToDeclaration(This, fvf, &elements);
     if (size == ~0U) return E_OUTOFMEMORY;
 
-    hr = IWineD3DDevice_CreateVertexDeclaration(iface, declaration, parent, elements, size);
+    hr = IWineD3DDevice_CreateVertexDeclaration(iface, declaration, parent, parent_ops, elements, size);
     HeapFree(GetProcessHeap(), 0, elements);
     return hr;
 }
diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c
index e19aba5..280d9a7 100644
--- a/dlls/wined3d/vertexdeclaration.c
+++ b/dlls/wined3d/vertexdeclaration.c
@@ -74,6 +74,7 @@ static ULONG WINAPI IWineD3DVertexDeclarationImpl_Release(IWineD3DVertexDeclarat
         }
 
         HeapFree(GetProcessHeap(), 0, This->elements);
+        This->parent_ops->wined3d_object_destroyed(This->parent);
         HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
@@ -202,7 +203,8 @@ static const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl =
 };
 
 HRESULT vertexdeclaration_init(IWineD3DVertexDeclarationImpl *declaration, IWineD3DDeviceImpl *device,
-        const WINED3DVERTEXELEMENT *elements, UINT element_count, IUnknown *parent)
+        const WINED3DVERTEXELEMENT *elements, UINT element_count,
+        IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     WORD preloaded = 0; /* MAX_STREAMS, 16 */
@@ -219,6 +221,7 @@ HRESULT vertexdeclaration_init(IWineD3DVertexDeclarationImpl *declaration, IWine
     declaration->lpVtbl = &IWineD3DVertexDeclaration_Vtbl;
     declaration->ref = 1;
     declaration->parent = parent;
+    declaration->parent_ops = parent_ops;
     declaration->wineD3DDevice = device;
     declaration->elements = HeapAlloc(GetProcessHeap(), 0, sizeof(*declaration->elements) * element_count);
     if (!declaration->elements)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index f06ab72..51b0dbb 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2187,6 +2187,7 @@ typedef struct IWineD3DVertexDeclarationImpl {
     LONG                    ref;
 
     IUnknown                *parent;
+    const struct wined3d_parent_ops *parent_ops;
     IWineD3DDeviceImpl      *wineD3DDevice;
 
     struct wined3d_vertex_declaration_element *elements;
@@ -2198,8 +2199,9 @@ typedef struct IWineD3DVertexDeclarationImpl {
     BOOL                    half_float_conv_needed;
 } IWineD3DVertexDeclarationImpl;
 
-HRESULT vertexdeclaration_init(IWineD3DVertexDeclarationImpl *This, IWineD3DDeviceImpl *device,
-        const WINED3DVERTEXELEMENT *elements, UINT element_count, IUnknown *parent) DECLSPEC_HIDDEN;
+HRESULT vertexdeclaration_init(IWineD3DVertexDeclarationImpl *declaration, IWineD3DDeviceImpl *device,
+        const WINED3DVERTEXELEMENT *elements, UINT element_count,
+        IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 /*****************************************************************************
  * IWineD3DStateBlock implementation structure
diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl
index bcf7ded..faae2a6 100644
--- a/include/wine/wined3d.idl
+++ b/include/wine/wined3d.idl
@@ -2992,12 +2992,14 @@ interface IWineD3DDevice : IWineD3DBase
     HRESULT CreateVertexDeclaration(
         [out] IWineD3DVertexDeclaration **declaration,
         [in] IUnknown *parent,
+        [in] const struct wined3d_parent_ops *parent_ops,
         [in] const WINED3DVERTEXELEMENT *elements,
         [in] UINT element_count
     );
     HRESULT CreateVertexDeclarationFromFVF(
         [out] IWineD3DVertexDeclaration **declaration,
         [in] IUnknown *parent,
+        [in] const struct wined3d_parent_ops *parent_ops,
         [in] DWORD fvf
     );
     HRESULT CreateVertexShader(
-- 
1.6.0.6




More information about the wine-patches mailing list