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

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


Similar to the patch for surfaces.
---
 dlls/d3d8/d3d8_private.h       |    1 -
 dlls/d3d8/device.c             |    3 +++
 dlls/d3d8/volume.c             |   28 +++++++++++++++++-----------
 dlls/d3d8/volumetexture.c      |    2 +-
 dlls/d3d9/d3d9_private.h       |    1 -
 dlls/d3d9/device.c             |    3 +++
 dlls/d3d9/volume.c             |   28 +++++++++++++++++-----------
 dlls/d3d9/volumetexture.c      |    2 +-
 dlls/wined3d/device.c          |    8 ++++----
 dlls/wined3d/volume.c          |    7 +++++--
 dlls/wined3d/volumetexture.c   |   13 +++++++------
 dlls/wined3d/wined3d_private.h |    6 ++++--
 include/wine/wined3d.idl       |    5 ++---
 13 files changed, 64 insertions(+), 43 deletions(-)

diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h
index 8674342..5cbc2d0 100644
--- a/dlls/d3d8/d3d8_private.h
+++ b/dlls/d3d8/d3d8_private.h
@@ -649,6 +649,5 @@ size_t parse_token(const DWORD* pToken);
 
 /* Callbacks */
 extern ULONG WINAPI D3D8CB_DestroySwapChain (IWineD3DSwapChain *pSwapChain);
-extern ULONG WINAPI D3D8CB_DestroyVolume(IWineD3DVolume *pVolume);
 
 #endif /* __WINE_D3DX8_PRIVATE_H */
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 7cb8563..aaf5bb2 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -2762,6 +2762,9 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent
     }
 
     *volume = object->wineD3DVolume;
+    IWineD3DVolume_AddRef(*volume);
+    IDirect3DVolume8_Release((IDirect3DVolume8 *)object);
+
     object->container = superior;
     object->forwardReference = superior;
 
diff --git a/dlls/d3d8/volume.c b/dlls/d3d8/volume.c
index 7f525d4..2d29d10 100644
--- a/dlls/d3d8/volume.c
+++ b/dlls/d3d8/volume.c
@@ -52,6 +52,14 @@ static ULONG WINAPI IDirect3DVolume8Impl_AddRef(LPDIRECT3DVOLUME8 iface) {
         /* No container, handle our own refcounting */
         ULONG ref = InterlockedIncrement(&This->ref);
         TRACE("(%p) : AddRef from %d\n", This, ref - 1);
+
+        if (ref == 1)
+        {
+            wined3d_mutex_lock();
+            IWineD3DVolume_AddRef(This->wineD3DVolume);
+            wined3d_mutex_unlock();
+        }
+
         return ref;
     }
 }
@@ -75,8 +83,6 @@ static ULONG WINAPI IDirect3DVolume8Impl_Release(LPDIRECT3DVOLUME8 iface) {
             wined3d_mutex_lock();
             IWineD3DVolume_Release(This->wineD3DVolume);
             wined3d_mutex_unlock();
-
-            HeapFree(GetProcessHeap(), 0, This);
         }
 
         return ref;
@@ -219,16 +225,16 @@ static const IDirect3DVolume8Vtbl Direct3DVolume8_Vtbl =
     IDirect3DVolume8Impl_UnlockBox
 };
 
-ULONG WINAPI D3D8CB_DestroyVolume(IWineD3DVolume *pVolume) {
-    IDirect3DVolume8Impl* volumeParent;
-
-    IWineD3DVolume_GetParent(pVolume, (IUnknown **) &volumeParent);
-    /* GetParent's AddRef was forwarded to an object in destruction.
-     * Releasing it here again would cause an endless recursion. */
-    volumeParent->forwardReference = NULL;
-    return IDirect3DVolume8_Release((IDirect3DVolume8*) volumeParent);
+static void STDMETHODCALLTYPE volume_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
 }
 
+static const struct wined3d_parent_ops d3d8_volume_wined3d_parent_ops =
+{
+    volume_wined3d_object_destroyed,
+};
+
 HRESULT volume_init(IDirect3DVolume8Impl *volume, IDirect3DDevice8Impl *device, UINT width, UINT height,
         UINT depth, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool)
 {
@@ -238,7 +244,7 @@ HRESULT volume_init(IDirect3DVolume8Impl *volume, IDirect3DDevice8Impl *device,
     volume->ref = 1;
 
     hr = IWineD3DDevice_CreateVolume(device->WineD3DDevice, width, height, depth, usage,
-            format, pool, &volume->wineD3DVolume, (IUnknown *)volume);
+            format, pool, &volume->wineD3DVolume, (IUnknown *)volume, &d3d8_volume_wined3d_parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to create wined3d volume, hr %#x.\n", hr);
diff --git a/dlls/d3d8/volumetexture.c b/dlls/d3d8/volumetexture.c
index 1875081..2b88d54 100644
--- a/dlls/d3d8/volumetexture.c
+++ b/dlls/d3d8/volumetexture.c
@@ -58,7 +58,7 @@ static ULONG WINAPI IDirect3DVolumeTexture8Impl_Release(LPDIRECT3DVOLUMETEXTURE8
 
     if (ref == 0) {
         wined3d_mutex_lock();
-        IWineD3DVolumeTexture_Destroy(This->wineD3DVolumeTexture, D3D8CB_DestroyVolume);
+        IWineD3DVolumeTexture_Destroy(This->wineD3DVolumeTexture);
         wined3d_mutex_unlock();
 
         IUnknown_Release(This->parentDevice);
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index c50f4d7..a50bbbe 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -538,6 +538,5 @@ typedef struct IDirect3DQuery9Impl {
 
 /* Callbacks */
 extern ULONG WINAPI D3D9CB_DestroySwapChain (IWineD3DSwapChain *pSwapChain);
-extern ULONG WINAPI D3D9CB_DestroyVolume(IWineD3DVolume *pVolume);
 
 #endif /* __WINE_D3D9_PRIVATE_H */
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index 156490a..cdd46a1 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -2158,6 +2158,9 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent
     }
 
     *volume = object->wineD3DVolume;
+    IWineD3DVolume_AddRef(*volume);
+    IDirect3DVolume9_Release((IDirect3DVolume9 *)object);
+
     object->container = superior;
     object->forwardReference = superior;
 
diff --git a/dlls/d3d9/volume.c b/dlls/d3d9/volume.c
index 389da9e..9dbb313 100644
--- a/dlls/d3d9/volume.c
+++ b/dlls/d3d9/volume.c
@@ -53,6 +53,14 @@ static ULONG WINAPI IDirect3DVolume9Impl_AddRef(LPDIRECT3DVOLUME9 iface) {
         /* No container, handle our own refcounting */
         ULONG ref = InterlockedIncrement(&This->ref);
         TRACE("(%p) : AddRef from %d\n", This, ref - 1);
+
+        if (ref == 1)
+        {
+            wined3d_mutex_lock();
+            IWineD3DVolume_AddRef(This->wineD3DVolume);
+            wined3d_mutex_unlock();
+        }
+
         return ref;
     }
 }
@@ -75,8 +83,6 @@ static ULONG WINAPI IDirect3DVolume9Impl_Release(LPDIRECT3DVOLUME9 iface) {
             wined3d_mutex_lock();
             IWineD3DVolume_Release(This->wineD3DVolume);
             wined3d_mutex_unlock();
-
-            HeapFree(GetProcessHeap(), 0, This);
         }
 
         return ref;
@@ -240,16 +246,16 @@ static const IDirect3DVolume9Vtbl Direct3DVolume9_Vtbl =
     IDirect3DVolume9Impl_UnlockBox
 };
 
-ULONG WINAPI D3D9CB_DestroyVolume(IWineD3DVolume *pVolume) {
-    IDirect3DVolume9Impl* volumeParent;
-
-    IWineD3DVolume_GetParent(pVolume, (IUnknown **) &volumeParent);
-    /* GetParent's AddRef was forwarded to an object in destruction.
-     * Releasing it here again would cause an endless recursion. */
-    volumeParent->forwardReference = NULL;
-    return IDirect3DVolume9_Release((IDirect3DVolume9*) volumeParent);
+static void STDMETHODCALLTYPE volume_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
 }
 
+static const struct wined3d_parent_ops d3d9_volume_wined3d_parent_ops =
+{
+    volume_wined3d_object_destroyed,
+};
+
 HRESULT volume_init(IDirect3DVolume9Impl *volume, IDirect3DDevice9Impl *device, UINT width, UINT height,
         UINT depth, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool)
 {
@@ -259,7 +265,7 @@ HRESULT volume_init(IDirect3DVolume9Impl *volume, IDirect3DDevice9Impl *device,
     volume->ref = 1;
 
     hr = IWineD3DDevice_CreateVolume(device->WineD3DDevice, width, height, depth, usage & WINED3DUSAGE_MASK,
-            format, pool, &volume->wineD3DVolume, (IUnknown *)volume);
+            format, pool, &volume->wineD3DVolume, (IUnknown *)volume, &d3d9_volume_wined3d_parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to create wined3d volume, hr %#x.\n", hr);
diff --git a/dlls/d3d9/volumetexture.c b/dlls/d3d9/volumetexture.c
index 31b90bc..8980663 100644
--- a/dlls/d3d9/volumetexture.c
+++ b/dlls/d3d9/volumetexture.c
@@ -59,7 +59,7 @@ static ULONG WINAPI IDirect3DVolumeTexture9Impl_Release(LPDIRECT3DVOLUMETEXTURE9
 
     if (ref == 0) {
         wined3d_mutex_lock();
-        IWineD3DVolumeTexture_Destroy(This->wineD3DVolumeTexture, D3D9CB_DestroyVolume);
+        IWineD3DVolumeTexture_Destroy(This->wineD3DVolumeTexture);
         wined3d_mutex_unlock();
 
         IDirect3DDevice9Ex_Release(This->parentDevice);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index f73f32e..1ae2f8b 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1036,9 +1036,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
     return WINED3D_OK;
 }
 
-static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
-        UINT Width, UINT Height, UINT Depth, DWORD Usage, WINED3DFORMAT Format,
-        WINED3DPOOL Pool, IWineD3DVolume **ppVolume, IUnknown *parent)
+static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface, UINT Width, UINT Height,
+        UINT Depth, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DVolume **ppVolume,
+        IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
 {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DVolumeImpl *object;
@@ -1055,7 +1055,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
         return WINED3DERR_OUTOFVIDEOMEMORY;
     }
 
-    hr = volume_init(object, This, Width, Height, Depth, Usage, Format, Pool, parent);
+    hr = volume_init(object, This, Width, Height, Depth, Usage, Format, Pool, parent, parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to initialize volume, returning %#x.\n", hr);
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index d705f75..dec0087 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -123,6 +123,7 @@ static ULONG WINAPI IWineD3DVolumeImpl_Release(IWineD3DVolume *iface) {
     ref = InterlockedDecrement(&This->resource.ref);
     if (ref == 0) {
         resource_cleanup((IWineD3DResource *)iface);
+        This->parent_ops->wined3d_object_destroyed(This->resource.parent);
         HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
@@ -374,8 +375,9 @@ static const IWineD3DVolumeVtbl IWineD3DVolume_Vtbl =
     IWineD3DVolumeImpl_SetContainer
 };
 
-HRESULT volume_init(IWineD3DVolumeImpl *volume, IWineD3DDeviceImpl *device, UINT width, UINT height,
-        UINT depth, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent)
+HRESULT volume_init(IWineD3DVolumeImpl *volume, IWineD3DDeviceImpl *device, UINT width,
+        UINT height, UINT depth, 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);
@@ -397,6 +399,7 @@ HRESULT volume_init(IWineD3DVolumeImpl *volume, IWineD3DDeviceImpl *device, UINT
         return hr;
     }
 
+    volume->parent_ops = parent_ops;
     volume->currentDesc.Width = width;
     volume->currentDesc.Height = height;
     volume->currentDesc.Depth = depth;
diff --git a/dlls/wined3d/volumetexture.c b/dlls/wined3d/volumetexture.c
index 134ff74..fcc8c15 100644
--- a/dlls/wined3d/volumetexture.c
+++ b/dlls/wined3d/volumetexture.c
@@ -76,7 +76,7 @@ static void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINE
     This->baseTexture.dirty = FALSE;
 }
 
-static void volumetexture_cleanup(IWineD3DVolumeTextureImpl *This, D3DCB_DESTROYVOLUMEFN volume_destroy_cb)
+static void volumetexture_cleanup(IWineD3DVolumeTextureImpl *This)
 {
     unsigned int i;
 
@@ -90,7 +90,7 @@ static void volumetexture_cleanup(IWineD3DVolumeTextureImpl *This, D3DCB_DESTROY
         {
             /* Cleanup the container. */
             IWineD3DVolume_SetContainer(volume, NULL);
-            volume_destroy_cb(volume);
+            IWineD3DVolume_Release(volume);
         }
     }
     basetexture_cleanup((IWineD3DBaseTexture *)This);
@@ -170,7 +170,7 @@ HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT
         {
             ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr);
             texture->volumes[i] = NULL;
-            volumetexture_cleanup(texture, D3DCB_DefaultDestroyVolume);
+            volumetexture_cleanup(texture);
             return hr;
         }
 
@@ -224,7 +224,7 @@ static ULONG WINAPI IWineD3DVolumeTextureImpl_Release(IWineD3DVolumeTexture *ifa
     TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
     ref = InterlockedDecrement(&This->resource.ref);
     if (ref == 0) {
-        IWineD3DVolumeTexture_Destroy(iface, D3DCB_DefaultDestroyVolume);
+        IWineD3DVolumeTexture_Destroy(iface);
     }
     return ref;
 }
@@ -344,10 +344,11 @@ static BOOL WINAPI IWineD3DVolumeTextureImpl_IsCondNP2(IWineD3DVolumeTexture *if
 /* *******************************************
    IWineD3DVolumeTexture IWineD3DVolumeTexture parts follow
    ******************************************* */
-static void WINAPI IWineD3DVolumeTextureImpl_Destroy(IWineD3DVolumeTexture *iface, D3DCB_DESTROYVOLUMEFN D3DCB_DestroyVolume) {
+static void WINAPI IWineD3DVolumeTextureImpl_Destroy(IWineD3DVolumeTexture *iface)
+{
     IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface;
 
-    volumetexture_cleanup(This, D3DCB_DestroyVolume);
+    volumetexture_cleanup(This);
 
     HeapFree(GetProcessHeap(), 0, This);
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index b5a6775..a8867ae 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1866,6 +1866,7 @@ typedef struct IWineD3DVolumeImpl
     IWineD3DResourceClass      resource;
 
     /* WineD3DVolume Information */
+    const struct wined3d_parent_ops *parent_ops;
     WINED3DVOLUMET_DESC      currentDesc;
     IWineD3DBase            *container;
     BOOL                    lockable;
@@ -1876,8 +1877,9 @@ typedef struct IWineD3DVolumeImpl
 } IWineD3DVolumeImpl;
 
 void volume_add_dirty_box(IWineD3DVolume *iface, const WINED3DBOX *dirty_box) DECLSPEC_HIDDEN;
-HRESULT volume_init(IWineD3DVolumeImpl *volume, IWineD3DDeviceImpl *device, UINT width, UINT height,
-        UINT depth, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent) DECLSPEC_HIDDEN;
+HRESULT volume_init(IWineD3DVolumeImpl *volume, IWineD3DDeviceImpl *device, UINT width,
+        UINT height, UINT depth, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool,
+        IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 /*****************************************************************************
  * IWineD3DVolumeTexture implementation structure (extends IWineD3DBaseTextureImpl)
diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl
index 46d2335..aed4159 100644
--- a/include/wine/wined3d.idl
+++ b/include/wine/wined3d.idl
@@ -2215,7 +2215,6 @@ interface IWineD3DDeviceParent : IUnknown
         [out] IWineD3DSwapChain **swapchain
     );
 }
-typedef ULONG (*D3DCB_DESTROYVOLUMEFN)(IWineD3DVolume *pVolume);
 typedef ULONG (*D3DCB_DESTROYSWAPCHAINFN)(IWineD3DSwapChain *pSwapChain);
 typedef HRESULT (*D3DCB_ENUMRESOURCES)(IWineD3DResource *resource, void *pData);
 
@@ -2689,7 +2688,6 @@ interface IWineD3DCubeTexture : IWineD3DBaseTexture
 interface IWineD3DVolumeTexture : IWineD3DBaseTexture
 {
     void Destroy(
-        [in] D3DCB_DESTROYVOLUMEFN destroy_volume_callback
     );
     HRESULT GetLevelDesc(
         [in] UINT level,
@@ -2968,7 +2966,8 @@ interface IWineD3DDevice : IWineD3DBase
         [in] WINED3DFORMAT format,
         [in] WINED3DPOOL pool,
         [out] IWineD3DVolume **volume,
-        [in] IUnknown *parent
+        [in] IUnknown *parent,
+        [in] const struct wined3d_parent_ops *parent_ops
     );
     HRESULT CreateCubeTexture(
         [in] UINT edge_length,
-- 
1.6.0.6




More information about the wine-patches mailing list