H. Verbeet : wined3d: Fix the relation between volumes and their container.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Mar 6 15:27:52 CST 2006


Module: wine
Branch: refs/heads/master
Commit: 07004966a8585f55074d5fff903c51bf2a033070
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=07004966a8585f55074d5fff903c51bf2a033070

Author: H. Verbeet <hverbeet at gmail.com>
Date:   Mon Mar  6 18:28:20 2006 +0000

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 cffc50b..20421a8 100644
--- a/dlls/d3d8/volume.c
+++ b/dlls/d3d8/volume.c
@@ -40,24 +40,47 @@ HRESULT WINAPI IDirect3DVolume8Impl_Quer
 
 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) : ReleaseRef to %ld\n", This, ref);
+    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);
+
+        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 4e53b2a..1223932 100644
--- a/dlls/d3d9/volume.c
+++ b/dlls/d3d9/volume.c
@@ -41,24 +41,46 @@ HRESULT WINAPI IDirect3DVolume9Impl_Quer
 
 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) : ReleaseRef to %ld\n", This, ref);
+    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);
+
+        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 3fa1717..151ade3 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -103,6 +103,29 @@ D3DRESOURCETYPE WINAPI IWineD3DVolumeImp
 /* *******************************************
    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_
     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 14e1154..9464357 100644
--- a/dlls/wined3d/volumetexture.c
+++ b/dlls/wined3d/volumetexture.c
@@ -60,8 +60,19 @@ ULONG WINAPI IWineD3DVolumeTextureImpl_R
     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 4184fee..c37ac00 100644
--- a/include/wine/wined3d_interface.h
+++ b/include/wine/wined3d_interface.h
@@ -1125,6 +1125,7 @@ DECLARE_INTERFACE_(IWineD3DVolume,IWineD
     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,IWineD
 #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)




More information about the wine-cvs mailing list