wined3d: Fix the relation between surfaces and their container.

This commit is contained in:
H. Verbeet 2006-03-06 18:28:03 +00:00 committed by Alexandre Julliard
parent fd2739b023
commit f7356a34c3
8 changed files with 99 additions and 19 deletions

View File

@ -41,24 +41,46 @@ HRESULT WINAPI IDirect3DSurface8Impl_QueryInterface(LPDIRECT3DSURFACE8 iface, RE
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) : ReleaseRef to %ld\n", This, ref);
TRACE("(%p)\n", This);
if (ref == 0) {
IWineD3DSurface_Release(This->wineD3DSurface);
HeapFree(GetProcessHeap(), 0, This);
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);
}
return ref;
}
return ref;
}
/* IDirect3DSurface8 IDirect3DResource8 Interface follow: */

View File

@ -42,24 +42,48 @@ HRESULT WINAPI IDirect3DSurface9Impl_QueryInterface(LPDIRECT3DSURFACE9 iface, RE
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) : ReleaseRef to %ld\n", This, ref);
TRACE("(%p)\n", This);
if (ref == 0) {
IWineD3DSurface_Release(This->wineD3DSurface);
HeapFree(GetProcessHeap(), 0, This);
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);
}
return ref;
}
return ref;
}
/* IDirect3DSurface9 IDirect3DResource9 Interface follow: */

View File

@ -84,6 +84,9 @@ ULONG WINAPI IWineD3DCubeTextureImpl_Release(IWineD3DCubeTexture *iface) {
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);

View File

@ -1433,7 +1433,7 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* ifac
&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

View File

@ -173,6 +173,29 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **
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 IWineD3DSurface_Vtbl =
IWineD3DSurfaceImpl_PreLoad,
IWineD3DSurfaceImpl_GetType,
/* IWineD3DSurface */
IWineD3DSurfaceImpl_GetContainerParent,
IWineD3DSurfaceImpl_GetContainer,
IWineD3DSurfaceImpl_GetDesc,
IWineD3DSurfaceImpl_LockRect,

View File

@ -93,12 +93,14 @@ ULONG WINAPI IWineD3DSwapChainImpl_Release(IWineD3DSwapChain *iface) {
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){

View File

@ -66,6 +66,9 @@ ULONG WINAPI IWineD3DTextureImpl_Release(IWineD3DTexture *iface) {
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);

View File

@ -1045,6 +1045,7 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource)
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,IWineD3DResource)
#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)