Commit 04dcffe3 authored by Markus Amsler's avatar Markus Amsler Committed by Alexandre Julliard

d3d9: Handle surface refcount forwarding in d3d9.

parent 0bceec1b
...@@ -60,7 +60,7 @@ static ULONG WINAPI IDirect3DCubeTexture9Impl_Release(LPDIRECT3DCUBETEXTURE9 ifa ...@@ -60,7 +60,7 @@ static ULONG WINAPI IDirect3DCubeTexture9Impl_Release(LPDIRECT3DCUBETEXTURE9 ifa
if (ref == 0) { if (ref == 0) {
TRACE("Releasing child %p\n", This->wineD3DCubeTexture); TRACE("Releasing child %p\n", This->wineD3DCubeTexture);
IWineD3DCubeTexture_Release(This->wineD3DCubeTexture); IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture, D3D9CB_DestroySurface);
IUnknown_Release(This->parentDevice); IUnknown_Release(This->parentDevice);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
} }
......
...@@ -301,6 +301,9 @@ typedef struct IDirect3DSurface9Impl ...@@ -301,6 +301,9 @@ typedef struct IDirect3DSurface9Impl
/* Parent reference */ /* Parent reference */
LPDIRECT3DDEVICE9 parentDevice; LPDIRECT3DDEVICE9 parentDevice;
/* If set forward refcounting to this object */
IUnknown *forwardReference;
} IDirect3DSurface9Impl; } IDirect3DSurface9Impl;
/* ---------------------- */ /* ---------------------- */
...@@ -543,4 +546,6 @@ extern HRESULT WINAPI D3D9CB_CreateRenderTarget(IUnknown *device, IUnknown *pSup ...@@ -543,4 +546,6 @@ extern HRESULT WINAPI D3D9CB_CreateRenderTarget(IUnknown *device, IUnknown *pSup
extern ULONG WINAPI D3D9CB_DestroyDepthStencilSurface (IWineD3DSurface *pSurface); extern ULONG WINAPI D3D9CB_DestroyDepthStencilSurface (IWineD3DSurface *pSurface);
extern ULONG WINAPI D3D9CB_DestroySurface(IWineD3DSurface *pSurface);
#endif /* __WINE_D3D9_PRIVATE_H */ #endif /* __WINE_D3D9_PRIVATE_H */
...@@ -1011,8 +1011,20 @@ HRESULT WINAPI D3D9CB_CreateSurface(IUnknown *device, IUnknown *pSuperior, UINT ...@@ -1011,8 +1011,20 @@ HRESULT WINAPI D3D9CB_CreateSurface(IUnknown *device, IUnknown *pSuperior, UINT
*ppSurface = d3dSurface->wineD3DSurface; *ppSurface = d3dSurface->wineD3DSurface;
IUnknown_Release(d3dSurface->parentDevice); IUnknown_Release(d3dSurface->parentDevice);
d3dSurface->parentDevice = NULL; d3dSurface->parentDevice = NULL;
d3dSurface->forwardReference = pSuperior;
} else { } else {
FIXME("(%p) IDirect3DDevice9_CreateSurface failed\n", device); FIXME("(%p) IDirect3DDevice9_CreateSurface failed\n", device);
} }
return res; return res;
} }
ULONG WINAPI D3D9CB_DestroySurface(IWineD3DSurface *pSurface) {
IDirect3DSurface9Impl* 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 IDirect3DSurface9_Release((IDirect3DSurface9*) surfaceParent);
}
...@@ -43,15 +43,13 @@ static HRESULT WINAPI IDirect3DSurface9Impl_QueryInterface(LPDIRECT3DSURFACE9 if ...@@ -43,15 +43,13 @@ static HRESULT WINAPI IDirect3DSurface9Impl_QueryInterface(LPDIRECT3DSURFACE9 if
static ULONG WINAPI IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) { static ULONG WINAPI IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) {
IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface;
IUnknown *containerParent = NULL;
TRACE("(%p)\n", This); TRACE("(%p)\n", This);
IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &containerParent); if (This->forwardReference) {
if (containerParent) { /* Forward refcounting */
/* Forward to the containerParent */ TRACE("(%p) : Forwarding to %p\n", This, This->forwardReference);
TRACE("(%p) : Forwarding to %p\n", This, containerParent); return IUnknown_AddRef(This->forwardReference);
return IUnknown_AddRef(containerParent);
} else { } else {
/* No container, handle our own refcounting */ /* No container, handle our own refcounting */
ULONG ref = InterlockedIncrement(&This->ref); ULONG ref = InterlockedIncrement(&This->ref);
...@@ -64,15 +62,13 @@ static ULONG WINAPI IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) { ...@@ -64,15 +62,13 @@ static ULONG WINAPI IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) {
static ULONG WINAPI IDirect3DSurface9Impl_Release(LPDIRECT3DSURFACE9 iface) { static ULONG WINAPI IDirect3DSurface9Impl_Release(LPDIRECT3DSURFACE9 iface) {
IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface;
IUnknown *containerParent = NULL;
TRACE("(%p)\n", This); TRACE("(%p)\n", This);
IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &containerParent); if (This->forwardReference) {
if (containerParent) {
/* Forward to the containerParent */ /* Forward to the containerParent */
TRACE("(%p) : Forwarding to %p\n", This, containerParent); TRACE("(%p) : Forwarding to %p\n", This, This->forwardReference);
return IUnknown_Release(containerParent); return IUnknown_Release(This->forwardReference);
} else { } else {
/* No container, handle our own refcounting */ /* No container, handle our own refcounting */
ULONG ref = InterlockedDecrement(&This->ref); ULONG ref = InterlockedDecrement(&This->ref);
......
...@@ -540,7 +540,7 @@ static void test_refcount(void) ...@@ -540,7 +540,7 @@ static void test_refcount(void)
/* check implicit back buffer */ /* check implicit back buffer */
hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer); hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
todo_wine CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount); todo_wine CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
todo_wine CHECK_REFCOUNT( pSwapChain, 1); CHECK_REFCOUNT( pSwapChain, 1);
if(pBackBuffer) if(pBackBuffer)
{ {
CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain); CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
......
...@@ -59,7 +59,7 @@ static ULONG WINAPI IDirect3DTexture9Impl_Release(LPDIRECT3DTEXTURE9 iface) { ...@@ -59,7 +59,7 @@ static ULONG WINAPI IDirect3DTexture9Impl_Release(LPDIRECT3DTEXTURE9 iface) {
TRACE("(%p) : ReleaseRef to %d\n", This, ref); TRACE("(%p) : ReleaseRef to %d\n", This, ref);
if (ref == 0) { if (ref == 0) {
IWineD3DTexture_Release(This->wineD3DTexture); IWineD3DTexture_Destroy(This->wineD3DTexture, D3D9CB_DestroySurface);
IUnknown_Release(This->parentDevice); IUnknown_Release(This->parentDevice);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment