From 04ae4596ffeef88e6fc409bce207e19654a8ba81 Mon Sep 17 00:00:00 2001 From: Markus Amsler Date: Tue, 5 Dec 2006 00:28:58 +0100 Subject: [PATCH] d3d: Callback infrastructure for implicit surface destruction in IWineD3DTexture. --- dlls/wined3d/directx.c | 10 ++++++++ dlls/wined3d/texture.c | 43 ++++++++++++++++---------------- dlls/wined3d/wined3d_private.h | 3 +++ include/wine/wined3d_interface.h | 7 ++++++ 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index dd50ecf8a60..5f8bb7455e9 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2490,6 +2490,16 @@ static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent return WINED3D_OK; } +ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) { + IUnknown* surfaceParent; + TRACE("(%p) call back\n", pSurface); + + /* Now, release the parent, which will take care of cleaning up the surface for us */ + IWineD3DSurface_GetParent(pSurface, &surfaceParent); + IUnknown_Release(surfaceParent); + return IUnknown_Release(surfaceParent); +} + /********************************************************** * IWineD3D VTbl follows **********************************************************/ diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index a1ce7214a68..e9a78cc5d08 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -58,31 +58,12 @@ static ULONG WINAPI IWineD3DTextureImpl_Release(IWineD3DTexture *iface) { TRACE("(%p) : Releasing from %d\n", This, This->resource.ref); ref = InterlockedDecrement(&This->resource.ref); if (ref == 0) { - int i; - - TRACE("(%p) : Cleaning up\n",This); - for (i = 0; i < This->baseTexture.levels; i++) { - if (This->surfaces[i] != NULL) { - /* Because the surfaces were created using a callback we need to release there parent otehrwise we leave the parent hanging */ - IUnknown* surfaceParent; - /* Clean out the texture name we gave to the surface 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); - } - } - TRACE("(%p) : cleaning up base texture\n", This); - IWineD3DBaseTextureImpl_CleanUp((IWineD3DBaseTexture *)iface); - /* free the object */ - HeapFree(GetProcessHeap(), 0, This); + IWineD3DTexture_Destroy(iface, D3DCB_DefaultDestroySurface); } return ref; } + /* **************************************************** IWineD3DTexture IWineD3DResource parts follow **************************************************** */ @@ -246,6 +227,25 @@ static void WINAPI IWineD3DTextureImpl_ApplyStateChanges(IWineD3DTexture *iface, /* ******************************************* IWineD3DTexture IWineD3DTexture parts follow ******************************************* */ +static void WINAPI IWineD3DTextureImpl_Destroy(IWineD3DTexture *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroySurface) { + IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; + int i; + + TRACE("(%p) : Cleaning up\n",This); + for (i = 0; i < This->baseTexture.levels; i++) { + if (This->surfaces[i] != NULL) { + /* Clean out the texture name we gave to the surface so that the surface doesn't try and release it */ + IWineD3DSurface_SetGlTextureDesc(This->surfaces[i], 0, 0); + IWineD3DSurface_SetContainer(This->surfaces[i], 0); + D3DCB_DestroySurface(This->surfaces[i]); + } + } + TRACE("(%p) : cleaning up base texture\n", This); + IWineD3DBaseTextureImpl_CleanUp((IWineD3DBaseTexture *)iface); + /* free the object */ + HeapFree(GetProcessHeap(), 0, This); +} + static HRESULT WINAPI IWineD3DTextureImpl_GetLevelDesc(IWineD3DTexture *iface, UINT Level, WINED3DSURFACE_DESC* pDesc) { IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; @@ -343,6 +343,7 @@ const IWineD3DTextureVtbl IWineD3DTexture_Vtbl = IWineD3DTextureImpl_GetTextureDimensions, IWineD3DTextureImpl_ApplyStateChanges, /* IWineD3DTexture */ + IWineD3DTextureImpl_Destroy, IWineD3DTextureImpl_GetLevelDesc, IWineD3DTextureImpl_GetSurfaceLevel, IWineD3DTextureImpl_LockRect, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 077676714d4..208ec0b463e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -416,6 +416,9 @@ BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display); #define WINE_D3D8_CAPABLE(gl_info) WINE_D3D7_CAPABLE(gl_info) && (gl_info->supported[ARB_MULTISAMPLE] && gl_info->supported[ARB_TEXTURE_BORDER_CLAMP]) #define WINE_D3D9_CAPABLE(gl_info) WINE_D3D8_CAPABLE(gl_info) && (gl_info->supported[ARB_FRAGMENT_PROGRAM] && gl_info->supported[ARB_VERTEX_SHADER]) +/* Default callbacks for implicit object destruction */ +extern ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface); + /***************************************************************************** * Internal representation of a light */ diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h index 6a779f3a659..1e0e08ed496 100644 --- a/include/wine/wined3d_interface.h +++ b/include/wine/wined3d_interface.h @@ -240,6 +240,11 @@ typedef HRESULT WINAPI (*D3DCB_ENUMDISPLAYMODESCALLBACK) (IUnknown *pDevice, FLOAT Refresh, LPVOID context); +/***************************************************************************** + * Callback functions for custom implicit surface / volume destruction. + */ +typedef ULONG WINAPI (*D3DCB_DESTROYSURFACEFN) (struct IWineD3DSurface *pSurface); + /***************************************************************************** * IWineD3DBase interface */ @@ -855,6 +860,7 @@ DECLARE_INTERFACE_(IWineD3DTexture,IWineD3DBaseTexture) STDMETHOD_(UINT, GetTextureDimensions)(THIS) PURE; STDMETHOD_(void, ApplyStateChanges)(THIS_ const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1], const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) PURE; /*** IWineD3DTexture methods ***/ + STDMETHOD_(void, Destroy)(THIS_ D3DCB_DESTROYSURFACEFN pFn) PURE; STDMETHOD(GetLevelDesc)(THIS_ UINT Level, WINED3DSURFACE_DESC* pDesc) PURE; STDMETHOD(GetSurfaceLevel)(THIS_ UINT Level, struct IWineD3DSurface** ppSurfaceLevel) PURE; STDMETHOD(LockRect)(THIS_ UINT Level, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) PURE; @@ -893,6 +899,7 @@ DECLARE_INTERFACE_(IWineD3DTexture,IWineD3DBaseTexture) #define IWineD3DTexture_GetTextureDimensions(p) (p)->lpVtbl->GetTextureDimensions(p) #define IWineD3DTexture_ApplyStateChanges(p,a,b) (p)->lpVtbl->ApplyStateChanges(p,a,b) /*** IWineD3DTexture methods ***/ +#define IWineD3DTexture_Destroy(p,a) (p)->lpVtbl->Destroy(p,a) #define IWineD3DTexture_GetLevelDesc(p,a,b) (p)->lpVtbl->GetLevelDesc(p,a,b) #define IWineD3DTexture_GetSurfaceLevel(p,a,b) (p)->lpVtbl->GetSurfaceLevel(p,a,b) #define IWineD3DTexture_LockRect(p,a,b,c,d) (p)->lpVtbl->LockRect(p,a,b,c,d)