diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index 867434210d..5cbc2d05db 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 7cb85630a5..aaf5bb2ae1 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 7f525d485a..2d29d10f1f 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 1875081a3b..2b88d54398 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 c50f4d7a74..a50bbbea19 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 156490ad77..cdd46a1f75 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 389da9ee53..9dbb313695 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 31b90bce62..8980663c49 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 f73f32e058..1ae2f8bdfe 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 d705f75f80..dec0087fab 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 134ff74398..fcc8c15a13 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 b5a6775ce3..a8867ae84e 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 46d23359f6..aed4159517 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,