[PATCH 10/10] wined3d: Don't free D3D volume textures until the wined3d volume texture is destroyed.

Henri Verbeet hverbeet at codeweavers.com
Wed Sep 16 01:37:24 CDT 2009


---
 dlls/d3d8/volumetexture.c      |   28 ++++++++++++++++++++++------
 dlls/d3d9/volumetexture.c      |   28 ++++++++++++++++++++++------
 dlls/wined3d/device.c          |    6 +++---
 dlls/wined3d/volumetexture.c   |   24 ++++++++++--------------
 dlls/wined3d/wined3d_private.h |    5 +++--
 include/wine/wined3d.idl       |    5 ++---
 6 files changed, 62 insertions(+), 34 deletions(-)

diff --git a/dlls/d3d8/volumetexture.c b/dlls/d3d8/volumetexture.c
index 1087a53..46c1ec5 100644
--- a/dlls/d3d8/volumetexture.c
+++ b/dlls/d3d8/volumetexture.c
@@ -47,6 +47,14 @@ static ULONG WINAPI IDirect3DVolumeTexture8Impl_AddRef(LPDIRECT3DVOLUMETEXTURE8
 
     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
 
+    if (ref == 1)
+    {
+        IDirect3DDevice8_AddRef(This->parentDevice);
+        wined3d_mutex_lock();
+        IWineD3DVolumeTexture_AddRef(This->wineD3DVolumeTexture);
+        wined3d_mutex_unlock();
+    }
+
     return ref;
 }
 
@@ -57,12 +65,10 @@ static ULONG WINAPI IDirect3DVolumeTexture8Impl_Release(LPDIRECT3DVOLUMETEXTURE8
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
+        IUnknown_Release(This->parentDevice);
         wined3d_mutex_lock();
-        IWineD3DVolumeTexture_Destroy(This->wineD3DVolumeTexture);
+        IWineD3DVolumeTexture_Release(This->wineD3DVolumeTexture);
         wined3d_mutex_unlock();
-
-        IUnknown_Release(This->parentDevice);
-        HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
 }
@@ -312,6 +318,16 @@ static const IDirect3DVolumeTexture8Vtbl Direct3DVolumeTexture8_Vtbl =
     IDirect3DVolumeTexture8Impl_AddDirtyBox
 };
 
+static void STDMETHODCALLTYPE volumetexture_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d8_volumetexture_wined3d_parent_ops =
+{
+    volumetexture_wined3d_object_destroyed,
+};
+
 HRESULT volumetexture_init(IDirect3DVolumeTexture8Impl *texture, IDirect3DDevice8Impl *device,
         UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
@@ -322,8 +338,8 @@ HRESULT volumetexture_init(IDirect3DVolumeTexture8Impl *texture, IDirect3DDevice
 
     wined3d_mutex_lock();
     hr = IWineD3DDevice_CreateVolumeTexture(device->WineD3DDevice, width, height, depth, levels,
-            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format),
-            pool, &texture->wineD3DVolumeTexture, (IUnknown *)texture);
+            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool,
+            &texture->wineD3DVolumeTexture, (IUnknown *)texture, &d3d8_volumetexture_wined3d_parent_ops);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/d3d9/volumetexture.c b/dlls/d3d9/volumetexture.c
index cc4a698..3adab63 100644
--- a/dlls/d3d9/volumetexture.c
+++ b/dlls/d3d9/volumetexture.c
@@ -48,6 +48,14 @@ static ULONG WINAPI IDirect3DVolumeTexture9Impl_AddRef(LPDIRECT3DVOLUMETEXTURE9
 
     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
 
+    if (ref == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(This->parentDevice);
+        wined3d_mutex_lock();
+        IWineD3DVolumeTexture_AddRef(This->wineD3DVolumeTexture);
+        wined3d_mutex_unlock();
+    }
+
     return ref;
 }
 
@@ -58,12 +66,10 @@ static ULONG WINAPI IDirect3DVolumeTexture9Impl_Release(LPDIRECT3DVOLUMETEXTURE9
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
+        IDirect3DDevice9Ex_Release(This->parentDevice);
         wined3d_mutex_lock();
-        IWineD3DVolumeTexture_Destroy(This->wineD3DVolumeTexture);
+        IWineD3DVolumeTexture_Release(This->wineD3DVolumeTexture);
         wined3d_mutex_unlock();
-
-        IDirect3DDevice9Ex_Release(This->parentDevice);
-        HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
 }
@@ -403,6 +409,16 @@ static const IDirect3DVolumeTexture9Vtbl Direct3DVolumeTexture9_Vtbl =
     IDirect3DVolumeTexture9Impl_AddDirtyBox
 };
 
+static void STDMETHODCALLTYPE volumetexture_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_volumetexture_wined3d_parent_ops =
+{
+    volumetexture_wined3d_object_destroyed,
+};
+
 HRESULT volumetexture_init(IDirect3DVolumeTexture9Impl *texture, IDirect3DDevice9Impl *device,
         UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
@@ -413,8 +429,8 @@ HRESULT volumetexture_init(IDirect3DVolumeTexture9Impl *texture, IDirect3DDevice
 
     wined3d_mutex_lock();
     hr = IWineD3DDevice_CreateVolumeTexture(device->WineD3DDevice, width, height, depth, levels,
-            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format),
-            pool, &texture->wineD3DVolumeTexture, (IUnknown *)texture);
+            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool,
+            &texture->wineD3DVolumeTexture, (IUnknown *)texture, &d3d9_volumetexture_wined3d_parent_ops);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 81af9a1..c5b8d97 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1000,8 +1000,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface,
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
-        UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, WINED3DFORMAT Format,
-        WINED3DPOOL Pool, IWineD3DVolumeTexture **ppVolumeTexture, IUnknown *parent)
+        UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
+        IWineD3DVolumeTexture **ppVolumeTexture, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
 {
     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DVolumeTextureImpl *object;
@@ -1018,7 +1018,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
         return WINED3DERR_OUTOFVIDEOMEMORY;
     }
 
-    hr = volumetexture_init(object, Width, Height, Depth, Levels, This, Usage, Format, Pool, parent);
+    hr = volumetexture_init(object, Width, Height, Depth, Levels, This, Usage, Format, Pool, parent, parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to initialize volumetexture, returning %#x\n", hr);
diff --git a/dlls/wined3d/volumetexture.c b/dlls/wined3d/volumetexture.c
index ed89403..252de28 100644
--- a/dlls/wined3d/volumetexture.c
+++ b/dlls/wined3d/volumetexture.c
@@ -133,8 +133,11 @@ static ULONG WINAPI IWineD3DVolumeTextureImpl_Release(IWineD3DVolumeTexture *ifa
     ULONG ref;
     TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
     ref = InterlockedDecrement(&This->resource.ref);
-    if (ref == 0) {
-        IWineD3DVolumeTexture_Destroy(iface);
+    if (!ref)
+    {
+        volumetexture_cleanup(This);
+        This->parent_ops->wined3d_object_destroyed(This->resource.parent);
+        HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
 }
@@ -254,15 +257,6 @@ static BOOL WINAPI IWineD3DVolumeTextureImpl_IsCondNP2(IWineD3DVolumeTexture *if
 /* *******************************************
    IWineD3DVolumeTexture IWineD3DVolumeTexture parts follow
    ******************************************* */
-static void WINAPI IWineD3DVolumeTextureImpl_Destroy(IWineD3DVolumeTexture *iface)
-{
-    IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface;
-
-    volumetexture_cleanup(This);
-
-    HeapFree(GetProcessHeap(), 0, This);
-}
-
 static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetLevelDesc(IWineD3DVolumeTexture *iface, UINT Level,WINED3DVOLUME_DESC *pDesc) {
     IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface;
     if (Level < This->baseTexture.levels) {
@@ -356,7 +350,6 @@ static const IWineD3DVolumeTextureVtbl IWineD3DVolumeTexture_Vtbl =
     IWineD3DVolumeTextureImpl_GetTextureDimensions,
     IWineD3DVolumeTextureImpl_IsCondNP2,
     /* volume texture */
-    IWineD3DVolumeTextureImpl_Destroy,
     IWineD3DVolumeTextureImpl_GetLevelDesc,
     IWineD3DVolumeTextureImpl_GetVolumeLevel,
     IWineD3DVolumeTextureImpl_LockBox,
@@ -364,8 +357,9 @@ static const IWineD3DVolumeTextureVtbl IWineD3DVolumeTexture_Vtbl =
     IWineD3DVolumeTextureImpl_AddDirtyBox
 };
 
-HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT height, UINT depth, UINT levels,
-        IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent)
+HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT height,
+        UINT depth, UINT levels, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format,
+        WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, gl_info);
@@ -420,6 +414,8 @@ HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT
         return hr;
     }
 
+    texture->parent_ops = parent_ops;
+
     /* Is NP2 support for volumes needed? */
     texture->baseTexture.pow2Matrix[0] = 1.0f;
     texture->baseTexture.pow2Matrix[5] = 1.0f;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 77d1d6c..23fc13c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1888,12 +1888,13 @@ typedef struct IWineD3DVolumeTextureImpl
     IWineD3DBaseTextureClass  baseTexture;
 
     /* IWineD3DVolumeTexture */
+    const struct wined3d_parent_ops *parent_ops;
     IWineD3DVolume           *volumes[MAX_MIP_LEVELS];
 } IWineD3DVolumeTextureImpl;
 
 HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT height,
-        UINT depth, UINT levels, IWineD3DDeviceImpl *device, DWORD usage,
-        WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent) DECLSPEC_HIDDEN;
+        UINT depth, UINT levels, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format,
+        WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 typedef struct _WINED3DSURFACET_DESC
 {
diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl
index aed4159..d22b2b6 100644
--- a/include/wine/wined3d.idl
+++ b/include/wine/wined3d.idl
@@ -2687,8 +2687,6 @@ interface IWineD3DCubeTexture : IWineD3DBaseTexture
 ]
 interface IWineD3DVolumeTexture : IWineD3DBaseTexture
 {
-    void Destroy(
-    );
     HRESULT GetLevelDesc(
         [in] UINT level,
         [out] WINED3DVOLUME_DESC *desc
@@ -2956,7 +2954,8 @@ interface IWineD3DDevice : IWineD3DBase
         [in] WINED3DFORMAT format,
         [in] WINED3DPOOL pool,
         [out] IWineD3DVolumeTexture **texture,
-        [in] IUnknown *parent
+        [in] IUnknown *parent,
+        [in] const struct wined3d_parent_ops *parent_ops
     );
     HRESULT CreateVolume(
         [in] UINT width,
-- 
1.6.0.6




More information about the wine-patches mailing list