Markus Amsler : d3d8: Handle surface refcount forwarding in d3d8.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Dec 6 05:49:10 CST 2006


Module: wine
Branch: master
Commit: 0d725490d643b8c654afbbeeedbfe754e6dcda3a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=0d725490d643b8c654afbbeeedbfe754e6dcda3a

Author: Markus Amsler <markus.amsler at oribi.org>
Date:   Tue Dec  5 00:29:37 2006 +0100

d3d8: Handle surface refcount forwarding in d3d8.

---

 dlls/d3d8/cubetexture.c  |    2 +-
 dlls/d3d8/d3d8_private.h |    5 +++++
 dlls/d3d8/device.c       |   12 ++++++++++++
 dlls/d3d8/surface.c      |   20 ++++++++------------
 dlls/d3d8/tests/device.c |    2 +-
 dlls/d3d8/texture.c      |    2 +-
 6 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/dlls/d3d8/cubetexture.c b/dlls/d3d8/cubetexture.c
index dffc08e..49006b5 100644
--- a/dlls/d3d8/cubetexture.c
+++ b/dlls/d3d8/cubetexture.c
@@ -57,7 +57,7 @@ static ULONG WINAPI IDirect3DCubeTexture
 
     if (ref == 0) {
         TRACE("Releasing child %p\n", This->wineD3DCubeTexture);
-        IWineD3DCubeTexture_Release(This->wineD3DCubeTexture);
+        IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture, D3D8CB_DestroySurface);
         IUnknown_Release(This->parentDevice);
         HeapFree(GetProcessHeap(), 0, This);
     }
diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h
index 4e8b96b..de553c6 100644
--- a/dlls/d3d8/d3d8_private.h
+++ b/dlls/d3d8/d3d8_private.h
@@ -246,6 +246,9 @@ struct IDirect3DSurface8Impl
 
     /* Parent reference */
     LPDIRECT3DDEVICE8                  parentDevice;
+
+    /* If set forward refcounting to this object */
+    IUnknown                    *forwardReference;
 };
 
 /* ------------------ */
@@ -593,4 +596,6 @@ extern HRESULT WINAPI D3D8CB_CreateRende
 
 extern ULONG WINAPI D3D8CB_DestroyDepthStencilSurface (IWineD3DSurface *pSurface);
 
+extern ULONG WINAPI D3D8CB_DestroySurface(IWineD3DSurface *pSurface);
+
 #endif /* __WINE_D3DX8_PRIVATE_H */
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 565f4af..68a1a5f 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -1622,8 +1622,20 @@ HRESULT WINAPI D3D8CB_CreateSurface(IUnk
         *ppSurface = d3dSurface->wineD3DSurface;
         IUnknown_Release(d3dSurface->parentDevice);
         d3dSurface->parentDevice = NULL;
+        d3dSurface->forwardReference = pSuperior;
     } else {
         FIXME("(%p) IDirect3DDevice8_CreateSurface failed\n", device);
     }
     return res;
 }
+
+ULONG WINAPI D3D8CB_DestroySurface(IWineD3DSurface *pSurface) {
+    IDirect3DSurface8Impl* surfaceParent;
+    TRACE("(%p) call back\n", pSurface);
+
+    IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
+    /* GetParent's AddRef was forwarded to an object in destruction.
+     * Releasing it here again would cause an endless recursion. */
+    surfaceParent->forwardReference = NULL;
+    return IDirect3DSurface8_Release((IDirect3DSurface8*) surfaceParent);
+}
diff --git a/dlls/d3d8/surface.c b/dlls/d3d8/surface.c
index 8ab312e..61db485 100644
--- a/dlls/d3d8/surface.c
+++ b/dlls/d3d8/surface.c
@@ -42,15 +42,13 @@ static HRESULT WINAPI IDirect3DSurface8I
 
 static ULONG WINAPI IDirect3DSurface8Impl_AddRef(LPDIRECT3DSURFACE8 iface) {
     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
-    IUnknown *containerParent = NULL;
 
     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);
+    if (This->forwardReference) {
+        /* Forward refcounting */
+        TRACE("(%p) : Forwarding to %p\n", This, This->forwardReference);
+        return IUnknown_AddRef(This->forwardReference);
     } else {
         /* No container, handle our own refcounting */
         ULONG ref = InterlockedIncrement(&This->ref);
@@ -61,15 +59,13 @@ static ULONG WINAPI IDirect3DSurface8Imp
 
 static ULONG WINAPI IDirect3DSurface8Impl_Release(LPDIRECT3DSURFACE8 iface) {
     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
-    IUnknown *containerParent = NULL;
 
     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_Release(containerParent);
+    if (This->forwardReference) {
+        /* Forward refcounting */
+        TRACE("(%p) : Forwarding to %p\n", This, This->forwardReference);
+        return IUnknown_Release(This->forwardReference);
     } else {
         /* No container, handle our own refcounting */
         ULONG ref = InterlockedDecrement(&This->ref);
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index e7e274c..5508c2f 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -490,7 +490,7 @@ static void test_refcount(void)
         /* check implicit back buffer */
         hr = IDirect3DSwapChain8_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
         todo_wine CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
-        todo_wine CHECK_REFCOUNT( pSwapChain, 1);
+        CHECK_REFCOUNT( pSwapChain, 1);
         if(pBackBuffer)
         {
             todo_wine CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DDevice8, pDevice);
diff --git a/dlls/d3d8/texture.c b/dlls/d3d8/texture.c
index 2ab8514..17af4ee 100644
--- a/dlls/d3d8/texture.c
+++ b/dlls/d3d8/texture.c
@@ -57,7 +57,7 @@ static ULONG WINAPI IDirect3DTexture8Imp
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
-        IWineD3DTexture_Release(This->wineD3DTexture);
+        IWineD3DTexture_Destroy(This->wineD3DTexture, D3D8CB_DestroySurface);
         IUnknown_Release(This->parentDevice);
         HeapFree(GetProcessHeap(), 0, This);
     }




More information about the wine-cvs mailing list