D3D: Fix the relation between surfaces and their container.

H. Verbeet hverbeet at gmail.com
Mon Mar 6 12:28:03 CST 2006


Based on a suggestion by Stefan Dösinger. Fix the relation between
surfaces and their container, as described here:
http://www.winehq.org/pipermail/wine-devel/2006-February/044857.html

Changelog:
  - Fix the relation between surfaces and their container.
-------------- next part --------------
diff --git a/dlls/d3d8/surface.c b/dlls/d3d8/surface.c
index 5443411..587e20f 100644
--- a/dlls/d3d8/surface.c
+++ b/dlls/d3d8/surface.c
@@ -41,24 +41,46 @@ HRESULT WINAPI IDirect3DSurface8Impl_Que
 
 ULONG WINAPI IDirect3DSurface8Impl_AddRef(LPDIRECT3DSURFACE8 iface) {
     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
-    ULONG ref = InterlockedIncrement(&This->ref);
+    IUnknown *containerParent = NULL;
 
-    TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
+    TRACE("(%p)\n", This);
 
-    return ref;
+    IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &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 IDirect3DSurface8Impl_Release(LPDIRECT3DSURFACE8 iface) {
     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
-    ULONG ref = InterlockedDecrement(&This->ref);
+    IUnknown *containerParent = NULL;
+
+    TRACE("(%p)\n", This);
 
-    TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
+    IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &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) {
+            IWineD3DSurface_Release(This->wineD3DSurface);
+            HeapFree(GetProcessHeap(), 0, This);
+        }
 
-    if (ref == 0) {
-        IWineD3DSurface_Release(This->wineD3DSurface);
-        HeapFree(GetProcessHeap(), 0, This);
+        return ref;
     }
-    return ref;
 }
 
 /* IDirect3DSurface8 IDirect3DResource8 Interface follow: */
diff --git a/dlls/d3d9/surface.c b/dlls/d3d9/surface.c
index 62c99c7..479bcae 100644
--- a/dlls/d3d9/surface.c
+++ b/dlls/d3d9/surface.c
@@ -42,24 +42,48 @@ HRESULT WINAPI IDirect3DSurface9Impl_Que
 
 ULONG WINAPI IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) {
     IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface;
-    ULONG ref = InterlockedIncrement(&This->ref);
+    IUnknown *containerParent = NULL;
 
-    TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
+    TRACE("(%p)\n", This);
+
+    IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &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;
+    }
 
-    return ref;
 }
 
 ULONG WINAPI IDirect3DSurface9Impl_Release(LPDIRECT3DSURFACE9 iface) {
     IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface;
-    ULONG ref = InterlockedDecrement(&This->ref);
+    IUnknown *containerParent = NULL;
+
+    TRACE("(%p)\n", This);
 
-    TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
+    IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &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) {
+            IWineD3DSurface_Release(This->wineD3DSurface);
+            HeapFree(GetProcessHeap(), 0, This);
+        }
 
-    if (ref == 0) {
-        IWineD3DSurface_Release(This->wineD3DSurface);
-        HeapFree(GetProcessHeap(), 0, This);
+        return ref;
     }
-    return ref;
 }
 
 /* IDirect3DSurface9 IDirect3DResource9 Interface follow: */
diff --git a/dlls/wined3d/cubetexture.c b/dlls/wined3d/cubetexture.c
index 966d8c2..9313b52 100644
--- a/dlls/wined3d/cubetexture.c
+++ b/dlls/wined3d/cubetexture.c
@@ -84,6 +84,9 @@ ULONG WINAPI IWineD3DCubeTextureImpl_Rel
                     IUnknown* surfaceParent;
                     /* Clean out the texture name we gave to the suface so that the surface doesn't try and release it */
                     IWineD3DSurface_SetGlTextureDesc(This->surfaces[j][i], 0, 0);
+                    /* Cleanup the container */
+                    IWineD3DSurface_SetContainer(This->surfaces[j][i], 0);
+                    /* Now, release the parent, which will take care of cleaning up the surface for us */
                     TRACE("(%p) : Releasing surface%d %d  %p\n", This, j, i, This->surfaces[j][i]);
                     IWineD3DSurface_GetParent(This->surfaces[j][i], &surfaceParent);
                     IUnknown_Release(surfaceParent);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 00c17e0..6b8a17f 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1433,7 +1433,7 @@ HRESULT WINAPI IWineD3DDeviceImpl_Create
                                     &This->depthStencilBuffer,
                                     NULL /* pShared (always null)*/  );
             if (This->depthStencilBuffer != NULL)
-                IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IWineD3DBase *)iface);
+                IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
         }
 
         /** TODO: A check on width, height and multisample types
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index f8e6abf..c03587e 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -173,6 +173,29 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetPa
    IWineD3DSurface IWineD3DSurface parts follow
    ****************************************************** */
 
+HRESULT WINAPI IWineD3DSurfaceImpl_GetContainerParent(IWineD3DSurface* iface, IUnknown **ppContainerParent) {
+    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)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 IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
     IWineD3DBase *container = 0;
@@ -1439,6 +1462,7 @@ const IWineD3DSurfaceVtbl IWineD3DSurfac
     IWineD3DSurfaceImpl_PreLoad,
     IWineD3DSurfaceImpl_GetType,
     /* IWineD3DSurface */
+    IWineD3DSurfaceImpl_GetContainerParent,
     IWineD3DSurfaceImpl_GetContainer,
     IWineD3DSurfaceImpl_GetDesc,
     IWineD3DSurfaceImpl_LockRect,
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 72effcd..02a8d2e 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -93,12 +93,14 @@ ULONG WINAPI IWineD3DSwapChainImpl_Relea
         IWineD3DDevice_SwapChainReleased((IWineD3DDevice *)This->wineD3DDevice, iface);
 
         /* release the ref to the front and back buffer parents */
+        IWineD3DSurface_SetContainer(This->frontBuffer, 0);
         IWineD3DSurface_GetParent(This->frontBuffer, &bufferParent);
         IUnknown_Release(bufferParent); /* once for the get parent */
         if(IUnknown_Release(bufferParent) > 0){
             FIXME("(%p) Something's still holding the front buffer\n",This);
         }
 
+        IWineD3DSurface_SetContainer(This->backBuffer, 0);
         IWineD3DSurface_GetParent(This->backBuffer, &bufferParent);
         IUnknown_Release(bufferParent); /* once for the get parent */
         if(IUnknown_Release(bufferParent) > 0){
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index e9d4600..125f81b 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -66,6 +66,9 @@ ULONG WINAPI IWineD3DTextureImpl_Release
                 IUnknown* surfaceParent;
                 /* Clean out the texture name we gave to the suface so that the surface doesn't try and release it */
                 IWineD3DSurface_SetGlTextureDesc(This->surfaces[i], 0, 0);
+                /* Cleanup the container */
+                IWineD3DSurface_SetContainer(This->surfaces[i], 0);
+                /* Now, release the parent, which will take care of cleaning up the surface for us */
                 IWineD3DSurface_GetParent(This->surfaces[i], &surfaceParent);
                 IUnknown_Release(surfaceParent);
                 IUnknown_Release(surfaceParent);
diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h
index 6947183..4184fee 100644
--- a/include/wine/wined3d_interface.h
+++ b/include/wine/wined3d_interface.h
@@ -1045,6 +1045,7 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWine
     STDMETHOD_(void,PreLoad)(THIS) PURE;
     STDMETHOD_(D3DRESOURCETYPE,GetType)(THIS) PURE;
     /*** IWineD3DSurface methods ***/
+    STDMETHOD(GetContainerParent)(THIS_ IUnknown **ppContainerParent) PURE;
     STDMETHOD(GetContainer)(THIS_ REFIID  riid, void ** ppContainer) PURE;
     STDMETHOD(GetDesc)(THIS_ WINED3DSURFACE_DESC * pDesc) PURE;
     STDMETHOD(LockRect)(THIS_ D3DLOCKED_RECT * pLockedRect, CONST RECT * pRect,DWORD  Flags) PURE;
@@ -1082,6 +1083,7 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWine
 #define IWineD3DSurface_PreLoad(p)                   (p)->lpVtbl->PreLoad(p)
 #define IWineD3DSurface_GetType(p)                   (p)->lpVtbl->GetType(p)
 /*** IWineD3DSurface methods ***/
+#define IWineD3DSurface_GetContainerParent(p,a)      (p)->lpVtbl->GetContainerParent(p,a)
 #define IWineD3DSurface_GetContainer(p,a,b)          (p)->lpVtbl->GetContainer(p,a,b)
 #define IWineD3DSurface_GetDesc(p,a)                 (p)->lpVtbl->GetDesc(p,a)
 #define IWineD3DSurface_LockRect(p,a,b,c)            (p)->lpVtbl->LockRect(p,a,b,c)





More information about the wine-patches mailing list