From a286646f518847aa32e84cb04cd9fbb7a3378f46 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 16 Sep 2009 08:37:24 +0200 Subject: [PATCH] wined3d: Don't free D3D volume textures until the wined3d volume texture is destroyed. --- dlls/d3d8/volumetexture.c | 30 +++++++++++++++++++++++------- dlls/d3d9/volumetexture.c | 30 +++++++++++++++++++++++------- dlls/wined3d/device.c | 6 +++--- dlls/wined3d/volumetexture.c | 24 ++++++++++-------------- dlls/wined3d/wined3d_private.h | 5 +++-- include/wine/wined3d.idl | 5 ++--- 6 files changed, 64 insertions(+), 36 deletions(-) diff --git a/dlls/d3d8/volumetexture.c b/dlls/d3d8/volumetexture.c index 1087a5348fc..46c1ec5af83 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) { - wined3d_mutex_lock(); - IWineD3DVolumeTexture_Destroy(This->wineD3DVolumeTexture); - wined3d_mutex_unlock(); - IUnknown_Release(This->parentDevice); - HeapFree(GetProcessHeap(), 0, This); + wined3d_mutex_lock(); + IWineD3DVolumeTexture_Release(This->wineD3DVolumeTexture); + wined3d_mutex_unlock(); } 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 cc4a6986228..3adab632813 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) { - wined3d_mutex_lock(); - IWineD3DVolumeTexture_Destroy(This->wineD3DVolumeTexture); - wined3d_mutex_unlock(); - IDirect3DDevice9Ex_Release(This->parentDevice); - HeapFree(GetProcessHeap(), 0, This); + wined3d_mutex_lock(); + IWineD3DVolumeTexture_Release(This->wineD3DVolumeTexture); + wined3d_mutex_unlock(); } 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 81af9a10db1..c5b8d971ec8 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 ed894037343..252de28acb0 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 77d1d6ca5f1..23fc13c3ee6 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 aed4159517d..d22b2b6d561 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,