[PATCH 06/11] wined3d: Don't free D3D vertex shaders until the wined3d vertex shader is destroyed.

Henri Verbeet hverbeet at codeweavers.com
Wed Sep 23 11:42:08 CDT 2009


---
 dlls/d3d10core/shader.c        |   23 +++++++++++++++++++----
 dlls/d3d8/vertexshader.c       |   28 +++++++++++++++++++++++++---
 dlls/d3d9/vertexshader.c       |   25 +++++++++++++++++++++----
 dlls/wined3d/device.c          |    5 +++--
 dlls/wined3d/vertexshader.c    |    4 +++-
 dlls/wined3d/wined3d_private.h |    3 ++-
 include/wine/wined3d.idl       |    3 ++-
 7 files changed, 75 insertions(+), 16 deletions(-)

diff --git a/dlls/d3d10core/shader.c b/dlls/d3d10core/shader.c
index 197b40a..e96de1f 100644
--- a/dlls/d3d10core/shader.c
+++ b/dlls/d3d10core/shader.c
@@ -161,6 +161,11 @@ static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_AddRef(ID3D10VertexShader *if
 
     TRACE("%p increasing refcount to %u\n", This, refcount);
 
+    if (refcount == 1)
+    {
+        IWineD3DVertexShader_AddRef(This->wined3d_shader);
+    }
+
     return refcount;
 }
 
@@ -174,8 +179,6 @@ static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_Release(ID3D10VertexShader *i
     if (!refcount)
     {
         IWineD3DVertexShader_Release(This->wined3d_shader);
-        shader_free_signature(&This->output_signature);
-        HeapFree(GetProcessHeap(), 0, This);
     }
 
     return refcount;
@@ -227,6 +230,18 @@ static const struct ID3D10VertexShaderVtbl d3d10_vertex_shader_vtbl =
     d3d10_vertex_shader_SetPrivateDataInterface,
 };
 
+static void STDMETHODCALLTYPE d3d10_vertex_shader_wined3d_object_destroyed(void *parent)
+{
+    struct d3d10_vertex_shader *shader = parent;
+    shader_free_signature(&shader->output_signature);
+    HeapFree(GetProcessHeap(), 0, shader);
+}
+
+static const struct wined3d_parent_ops d3d10_vertex_shader_wined3d_parent_ops =
+{
+    d3d10_vertex_shader_wined3d_object_destroyed,
+};
+
 HRESULT d3d10_vertex_shader_init(struct d3d10_vertex_shader *shader, struct d3d10_device *device,
         const void *byte_code, SIZE_T byte_code_length)
 {
@@ -245,8 +260,8 @@ HRESULT d3d10_vertex_shader_init(struct d3d10_vertex_shader *shader, struct d3d1
     }
 
     hr = IWineD3DDevice_CreateVertexShader(device->wined3d_device,
-            shader_info.shader_code, &shader->output_signature,
-            &shader->wined3d_shader, (IUnknown *)shader);
+            shader_info.shader_code, &shader->output_signature, &shader->wined3d_shader,
+            (IUnknown *)shader, &d3d10_vertex_shader_wined3d_parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
diff --git a/dlls/d3d8/vertexshader.c b/dlls/d3d8/vertexshader.c
index 2e58421..aacf15c 100644
--- a/dlls/d3d8/vertexshader.c
+++ b/dlls/d3d8/vertexshader.c
@@ -46,9 +46,23 @@ static ULONG WINAPI IDirect3DVertexShader8Impl_AddRef(IDirect3DVertexShader8 *if
 
     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
 
+    if (ref == 1 && This->wineD3DVertexShader)
+    {
+        wined3d_mutex_lock();
+        IWineD3DVertexShader_AddRef(This->wineD3DVertexShader);
+        wined3d_mutex_unlock();
+    }
+
     return ref;
 }
 
+static void STDMETHODCALLTYPE d3d8_vertexshader_wined3d_object_destroyed(void *parent)
+{
+    IDirect3DVertexShader8Impl *shader = parent;
+    IDirect3DVertexDeclaration8_Release(shader->vertex_declaration);
+    HeapFree(GetProcessHeap(), 0, shader);
+}
+
 static ULONG WINAPI IDirect3DVertexShader8Impl_Release(IDirect3DVertexShader8 *iface) {
     IDirect3DVertexShader8Impl *This = (IDirect3DVertexShader8Impl *)iface;
     ULONG ref = InterlockedDecrement(&This->ref);
@@ -56,14 +70,16 @@ static ULONG WINAPI IDirect3DVertexShader8Impl_Release(IDirect3DVertexShader8 *i
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
-        IDirect3DVertexDeclaration8_Release(This->vertex_declaration);
         if (This->wineD3DVertexShader)
         {
             wined3d_mutex_lock();
             IWineD3DVertexShader_Release(This->wineD3DVertexShader);
             wined3d_mutex_unlock();
         }
-        HeapFree(GetProcessHeap(), 0, This);
+        else
+        {
+            d3d8_vertexshader_wined3d_object_destroyed(This);
+        }
     }
     return ref;
 }
@@ -76,6 +92,11 @@ static const IDirect3DVertexShader8Vtbl Direct3DVertexShader8_Vtbl =
     IDirect3DVertexShader8Impl_Release,
 };
 
+static const struct wined3d_parent_ops d3d8_vertexshader_wined3d_parent_ops =
+{
+    d3d8_vertexshader_wined3d_object_destroyed,
+};
+
 static HRESULT vertexshader_create_vertexdeclaration(IDirect3DDevice8Impl *device,
         const DWORD *declaration, DWORD shader_handle, IDirect3DVertexDeclaration8 **decl_ptr)
 {
@@ -149,7 +170,8 @@ HRESULT vertexshader_init(IDirect3DVertexShader8Impl *shader, IDirect3DDevice8Im
 
         wined3d_mutex_lock();
         hr = IWineD3DDevice_CreateVertexShader(device->WineD3DDevice, byte_code,
-                NULL /* output signature */, &shader->wineD3DVertexShader, (IUnknown *)shader);
+                NULL /* output signature */, &shader->wineD3DVertexShader,
+                (IUnknown *)shader, &d3d8_vertexshader_wined3d_parent_ops);
         wined3d_mutex_unlock();
         if (FAILED(hr))
         {
diff --git a/dlls/d3d9/vertexshader.c b/dlls/d3d9/vertexshader.c
index 399dadb..8b775de 100644
--- a/dlls/d3d9/vertexshader.c
+++ b/dlls/d3d9/vertexshader.c
@@ -46,6 +46,14 @@ static ULONG WINAPI IDirect3DVertexShader9Impl_AddRef(LPDIRECT3DVERTEXSHADER9 if
 
     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
 
+    if (ref == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(This->parentDevice);
+        wined3d_mutex_lock();
+        IWineD3DVertexShader_AddRef(This->wineD3DVertexShader);
+        wined3d_mutex_unlock();
+    }
+
     return ref;
 }
 
@@ -56,12 +64,10 @@ static ULONG WINAPI IDirect3DVertexShader9Impl_Release(LPDIRECT3DVERTEXSHADER9 i
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
+        IDirect3DDevice9Ex_Release(This->parentDevice);
         wined3d_mutex_lock();
         IWineD3DVertexShader_Release(This->wineD3DVertexShader);
         wined3d_mutex_unlock();
-
-        IDirect3DDevice9Ex_Release(This->parentDevice);
-        HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
 }
@@ -111,6 +117,16 @@ static const IDirect3DVertexShader9Vtbl Direct3DVertexShader9_Vtbl =
     IDirect3DVertexShader9Impl_GetFunction
 };
 
+static void STDMETHODCALLTYPE d3d9_vertexshader_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_vertexshader_wined3d_parent_ops =
+{
+    d3d9_vertexshader_wined3d_object_destroyed,
+};
+
 HRESULT vertexshader_init(IDirect3DVertexShader9Impl *shader, IDirect3DDevice9Impl *device, const DWORD *byte_code)
 {
     HRESULT hr;
@@ -120,7 +136,8 @@ HRESULT vertexshader_init(IDirect3DVertexShader9Impl *shader, IDirect3DDevice9Im
 
     wined3d_mutex_lock();
     hr = IWineD3DDevice_CreateVertexShader(device->WineD3DDevice, byte_code,
-            NULL /* output signature */, &shader->wineD3DVertexShader, (IUnknown *)shader);
+            NULL /* output signature */, &shader->wineD3DVertexShader,
+            (IUnknown *)shader, &d3d9_vertexshader_wined3d_parent_ops);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 75e173f..b19f846 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1762,7 +1762,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3D
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface,
         const DWORD *pFunction, const struct wined3d_shader_signature *output_signature,
-        IWineD3DVertexShader **ppVertexShader, IUnknown *parent)
+        IWineD3DVertexShader **ppVertexShader, IUnknown *parent,
+        const struct wined3d_parent_ops *parent_ops)
 {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DVertexShaderImpl *object;
@@ -1775,7 +1776,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac
         return E_OUTOFMEMORY;
     }
 
-    hr = vertexshader_init(object, This, pFunction, output_signature, parent);
+    hr = vertexshader_init(object, This, pFunction, output_signature, parent, parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index ea700ba..0a5bf40 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -174,6 +174,7 @@ static ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface
     if (!refcount)
     {
         shader_cleanup((IWineD3DBaseShader *)iface);
+        This->parent_ops->wined3d_object_destroyed(This->parent);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -355,7 +356,7 @@ void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockIm
 
 HRESULT vertexshader_init(IWineD3DVertexShaderImpl *shader, IWineD3DDeviceImpl *device,
         const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
-        IUnknown *parent)
+        IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
 {
     HRESULT hr;
 
@@ -363,6 +364,7 @@ HRESULT vertexshader_init(IWineD3DVertexShaderImpl *shader, IWineD3DDeviceImpl *
 
     shader->lpVtbl = &IWineD3DVertexShader_Vtbl;
     shader->parent = parent;
+    shader->parent_ops = parent_ops;
     shader_init(&shader->baseShader, (IWineD3DDevice *)device);
     list_add_head(&device->shaders, &shader->baseShader.shader_list_entry);
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 784b024..1c93b22 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2764,6 +2764,7 @@ typedef struct IWineD3DVertexShaderImpl {
 
     /* IWineD3DVertexShaderImpl */
     IUnknown                    *parent;
+    const struct wined3d_parent_ops *parent_ops;
 
     /* The GL shader */
     void                        *backend_priv;
@@ -2780,7 +2781,7 @@ void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockIm
         struct vs_compile_args *args) DECLSPEC_HIDDEN;
 HRESULT vertexshader_init(IWineD3DVertexShaderImpl *shader, IWineD3DDeviceImpl *device,
         const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
-        IUnknown *parent) DECLSPEC_HIDDEN;
+        IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 /*****************************************************************************
  * IDirect3DPixelShader implementation structure
diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl
index faae2a6..e4d8144 100644
--- a/include/wine/wined3d.idl
+++ b/include/wine/wined3d.idl
@@ -3006,7 +3006,8 @@ interface IWineD3DDevice : IWineD3DBase
         [in] const DWORD *function,
         [in] const struct wined3d_shader_signature *output_signature,
         [out] IWineD3DVertexShader **shader,
-        [in] IUnknown *parent
+        [in] IUnknown *parent,
+        [in] const struct wined3d_parent_ops *parent_ops
     );
     HRESULT CreatePixelShader(
         [in] const DWORD *function,
-- 
1.6.0.6




More information about the wine-patches mailing list