From 07004966a8585f55074d5fff903c51bf2a033070 Mon Sep 17 00:00:00 2001 From: "H. Verbeet" Date: Mon, 6 Mar 2006 18:28:20 +0000 Subject: [PATCH] wined3d: Fix the relation between volumes and their container. --- dlls/d3d8/volume.c | 41 +++++++++++++++++++++++++++++++--------- dlls/d3d9/volume.c | 40 ++++++++++++++++++++++++++++++--------- dlls/wined3d/volume.c | 24 +++++++++++++++++++++++ dlls/wined3d/volumetexture.c | 13 ++++++++++++- include/wine/wined3d_interface.h | 2 ++ 5 files changed, 101 insertions(+), 19 deletions(-) diff --git a/dlls/d3d8/volume.c b/dlls/d3d8/volume.c index cffc50b66a9..20421a87acf 100644 --- a/dlls/d3d8/volume.c +++ b/dlls/d3d8/volume.c @@ -40,24 +40,47 @@ HRESULT WINAPI IDirect3DVolume8Impl_QueryInterface(LPDIRECT3DVOLUME8 iface, REFI ULONG WINAPI IDirect3DVolume8Impl_AddRef(LPDIRECT3DVOLUME8 iface) { IDirect3DVolume8Impl *This = (IDirect3DVolume8Impl *)iface; - ULONG ref = InterlockedIncrement(&This->ref); + IUnknown *containerParent = NULL; - TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + TRACE("(%p)\n", This); - return ref; + IWineD3DVolume_GetContainerParent(This->wineD3DVolume, &containerParent); + if (containerParent) { + /* Forward to the containerParent */ + TRACE("(%p) : Forwarding to %p\n", This, containerParent); + return IUnknown_AddRef(containerParent); + } else { + /* No container, handle our own refcounting */ + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + return ref; + } } ULONG WINAPI IDirect3DVolume8Impl_Release(LPDIRECT3DVOLUME8 iface) { IDirect3DVolume8Impl *This = (IDirect3DVolume8Impl *)iface; - ULONG ref = InterlockedDecrement(&This->ref); + IUnknown *containerParent = NULL; + + TRACE("(%p)\n", This); + + IWineD3DVolume_GetContainerParent(This->wineD3DVolume, &containerParent); + if (containerParent) { + /* Forward to the containerParent */ + TRACE("(%p) : Forwarding to %p\n", This, containerParent); + return IUnknown_Release(containerParent); + } + else { + /* No container, handle our own refcounting */ + ULONG ref = InterlockedDecrement(&This->ref); + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { + IWineD3DVolume_Release(This->wineD3DVolume); + HeapFree(GetProcessHeap(), 0, This); + } - if (ref == 0) { - IWineD3DVolume_Release(This->wineD3DVolume); - HeapFree(GetProcessHeap(), 0, This); + return ref; } - return ref; } /* IDirect3DVolume8 Interface follow: */ diff --git a/dlls/d3d9/volume.c b/dlls/d3d9/volume.c index 4e53b2ad91d..1223932974d 100644 --- a/dlls/d3d9/volume.c +++ b/dlls/d3d9/volume.c @@ -41,24 +41,46 @@ HRESULT WINAPI IDirect3DVolume9Impl_QueryInterface(LPDIRECT3DVOLUME9 iface, REFI ULONG WINAPI IDirect3DVolume9Impl_AddRef(LPDIRECT3DVOLUME9 iface) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - ULONG ref = InterlockedIncrement(&This->ref); + IUnknown *containerParent = NULL; - TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + TRACE("(%p)\n", This); - return ref; + IWineD3DVolume_GetContainerParent(This->wineD3DVolume, &containerParent); + if (containerParent) { + /* Forward to the containerParent */ + TRACE("(%p) : Forwarding to %p\n", This, containerParent); + return IUnknown_AddRef(containerParent); + } else { + /* No container, handle our own refcounting */ + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + return ref; + } } ULONG WINAPI IDirect3DVolume9Impl_Release(LPDIRECT3DVOLUME9 iface) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - ULONG ref = InterlockedDecrement(&This->ref); + IUnknown *containerParent = NULL; + + TRACE("(%p)\n", This); + + IWineD3DVolume_GetContainerParent(This->wineD3DVolume, &containerParent); + if (containerParent) { + /* Forward to the containerParent */ + TRACE("(%p) : Forwarding to %p\n", This, containerParent); + return IUnknown_Release(containerParent); + } else { + /* No container, handle our own refcounting */ + ULONG ref = InterlockedDecrement(&This->ref); + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { + IWineD3DVolume_Release(This->wineD3DVolume); + HeapFree(GetProcessHeap(), 0, This); + } - if (ref == 0) { - IWineD3DVolume_Release(This->wineD3DVolume); - HeapFree(GetProcessHeap(), 0, This); + return ref; } - return ref; } /* IDirect3DVolume9 Interface follow: */ diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c index 3fa17178cdf..151ade3a89d 100644 --- a/dlls/wined3d/volume.c +++ b/dlls/wined3d/volume.c @@ -103,6 +103,29 @@ D3DRESOURCETYPE WINAPI IWineD3DVolumeImpl_GetType(IWineD3DVolume *iface) { /* ******************************************* IWineD3DVolume parts follow ******************************************* */ +HRESULT WINAPI IWineD3DVolumeImpl_GetContainerParent(IWineD3DVolume *iface, IUnknown **ppContainerParent) { + IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface; + + TRACE("(%p) : ppContainerParent %p\n", This, ppContainerParent); + + if (!ppContainerParent) { + ERR("(%p) : Called without a valid ppContainerParent\n", This); + } + + if (This->container) { + IWineD3DBase_GetParent(This->container, ppContainerParent); + if (!ppContainerParent) { + /* WineD3D objects should always have a parent */ + ERR("(%p) : GetParent returned NULL\n", This); + } + IUnknown_Release(*ppContainerParent); /* GetParent adds a reference; we want just the pointer */ + } else { + *ppContainerParent = NULL; + } + + return D3D_OK; +} + HRESULT WINAPI IWineD3DVolumeImpl_GetContainer(IWineD3DVolume *iface, REFIID riid, void** ppContainer) { IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface; @@ -304,6 +327,7 @@ const IWineD3DVolumeVtbl IWineD3DVolume_Vtbl = IWineD3DVolumeImpl_PreLoad, IWineD3DVolumeImpl_GetType, /* IWineD3DVolume */ + IWineD3DVolumeImpl_GetContainerParent, IWineD3DVolumeImpl_GetContainer, IWineD3DVolumeImpl_GetDesc, IWineD3DVolumeImpl_LockBox, diff --git a/dlls/wined3d/volumetexture.c b/dlls/wined3d/volumetexture.c index 14e1154ab5c..9464357d101 100644 --- a/dlls/wined3d/volumetexture.c +++ b/dlls/wined3d/volumetexture.c @@ -60,8 +60,19 @@ ULONG WINAPI IWineD3DVolumeTextureImpl_Release(IWineD3DVolumeTexture *iface) { if (ref == 0) { for (i = 0; i < This->baseTexture.levels; i++) { if (This->volumes[i] != NULL) { + /* Since the volumes were created by callback, the texture is + * keeping the reference to the parent, so the texture should + * release it. */ + IUnknown *volumeParent = NULL; + TRACE("(%p) : Releasing volume %p\n", This, This->volumes[i]); - IWineD3DVolume_Release(This->volumes[i]); + + /* Cleanup the container */ + IWineD3DVolume_SetContainer(This->volumes[i], 0); + /* Now, release the parent, which will take care of cleaning up the volume for us */ + IWineD3DVolume_GetParent(This->volumes[i], &volumeParent); + IUnknown_Release(volumeParent); /* Once for the reference GetParent added */ + IUnknown_Release(volumeParent); /* Once for the reference we're keeping */ } } IWineD3DBaseTextureImpl_CleanUp((IWineD3DBaseTexture *) iface); diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h index 4184fee5ae3..c37ac007a9b 100644 --- a/include/wine/wined3d_interface.h +++ b/include/wine/wined3d_interface.h @@ -1125,6 +1125,7 @@ DECLARE_INTERFACE_(IWineD3DVolume,IWineD3DResource) STDMETHOD_(void,PreLoad)(THIS) PURE; STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE; /*** IWineD3DVolume methods ***/ + STDMETHOD(GetContainerParent)(THIS_ IUnknown **ppContainerParent) PURE; STDMETHOD(GetContainer)(THIS_ REFIID riid, void ** ppContainer) PURE; STDMETHOD(GetDesc)(THIS_ WINED3DVOLUME_DESC * pDesc) PURE; STDMETHOD(LockBox)(THIS_ D3DLOCKED_BOX* pLockedVolume, CONST D3DBOX* pBox, DWORD Flags) PURE; @@ -1153,6 +1154,7 @@ DECLARE_INTERFACE_(IWineD3DVolume,IWineD3DResource) #define IWineD3DVolume_PreLoad(p) (p)->lpVtbl->PreLoad(p) #define IWineD3DVolume_GetType(p) (p)->lpVtbl->GetType(p) /*** IWineD3DVolume methods ***/ +#define IWineD3DVolume_GetContainerParent(p,a) (p)->lpVtbl->GetContainerParent(p,a) #define IWineD3DVolume_GetContainer(p,a,b) (p)->lpVtbl->GetContainer(p,a,b) #define IWineD3DVolume_GetDesc(p,a) (p)->lpVtbl->GetDesc(p,a) #define IWineD3DVolume_LockBox(p,a,b,c) (p)->lpVtbl->LockBox(p,a,b,c) -- 2.11.4.GIT