diff --git a/dlls/d3d8/cubetexture.c b/dlls/d3d8/cubetexture.c index dffc08ea0f4..49006b51b32 100644 --- a/dlls/d3d8/cubetexture.c +++ b/dlls/d3d8/cubetexture.c @@ -57,7 +57,7 @@ static ULONG WINAPI IDirect3DCubeTexture8Impl_Release(LPDIRECT3DCUBETEXTURE8 ifa 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 4e8b96be8f2..de553c6ffdb 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_CreateRenderTarget(IUnknown *device, IUnknown *pSup 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 565f4afed53..68a1a5faa8b 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1622,8 +1622,20 @@ HRESULT WINAPI D3D8CB_CreateSurface(IUnknown *device, IUnknown *pSuperior, UINT *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 8ab312e6a30..61db48563b6 100644 --- a/dlls/d3d8/surface.c +++ b/dlls/d3d8/surface.c @@ -42,15 +42,13 @@ static HRESULT WINAPI IDirect3DSurface8Impl_QueryInterface(LPDIRECT3DSURFACE8 if 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 IDirect3DSurface8Impl_AddRef(LPDIRECT3DSURFACE8 iface) { 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 e7e274cbf8e..5508c2f6859 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 2ab851487b3..17af4ee2644 100644 --- a/dlls/d3d8/texture.c +++ b/dlls/d3d8/texture.c @@ -57,7 +57,7 @@ static ULONG WINAPI IDirect3DTexture8Impl_Release(LPDIRECT3DTEXTURE8 iface) { 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); }