ddraw: Move complex surface destruction into its own function
Luke Benstead
kazade at gmail.com
Mon Jun 28 13:03:04 CDT 2010
Needed to properly fix ddraw surface refcounting as it must be called from
the surface thunks.
Luke.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20100628/4a6dbee1/attachment.htm>
-------------- next part --------------
From 837357fccc8b6c10ea4a76aa0d1b3801d99a9811 Mon Sep 17 00:00:00 2001
From: Luke Benstead <kazade at gmail.com>
Date: Mon, 28 Jun 2010 18:40:12 +0100
Subject: ddraw: Move complex surface destruction into its own function (required to implement per-surface version refcounts)
---
dlls/ddraw/surface.c | 226 +++++++++++++++++++++++++------------------------
1 files changed, 115 insertions(+), 111 deletions(-)
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index ef7b381..4bd7310 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -48,6 +48,120 @@
WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
+void DestroyComplexSurface(IDirectDrawSurfaceImpl *This)
+{
+ IDirectDrawSurfaceImpl *surf;
+ IDirectDrawImpl *ddraw;
+ IUnknown *ifaceToRelease = This->ifaceToRelease;
+ UINT i;
+
+ /* Complex attached surfaces are destroyed implicitly when the root is released */
+ EnterCriticalSection(&ddraw_cs);
+ if(!This->is_complex_root)
+ {
+ WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
+ LeaveCriticalSection(&ddraw_cs);
+ return;
+ }
+ ddraw = This->ddraw;
+
+ /* If it's a texture, destroy the WineD3DTexture.
+ * WineD3D will destroy the IParent interfaces
+ * of the sublevels, which destroys the WineD3DSurfaces.
+ * Set the surfaces to NULL to avoid destroying them again later
+ */
+ if(This->wineD3DTexture)
+ {
+ IWineD3DBaseTexture_Release(This->wineD3DTexture);
+ }
+ /* If it's the RenderTarget, destroy the d3ddevice */
+ else if(This->wineD3DSwapChain)
+ {
+ if((ddraw->d3d_initialized) && (This == ddraw->d3d_target)) {
+ TRACE("(%p) Destroying the render target, uninitializing D3D\n", This);
+
+ /* Unset any index buffer, just to be sure */
+ IWineD3DDevice_SetIndexBuffer(ddraw->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
+ IWineD3DDevice_SetDepthStencilSurface(ddraw->wineD3DDevice, NULL);
+ IWineD3DDevice_SetVertexDeclaration(ddraw->wineD3DDevice, NULL);
+ for(i = 0; i < ddraw->numConvertedDecls; i++)
+ {
+ IWineD3DVertexDeclaration_Release(ddraw->decls[i].decl);
+ }
+ HeapFree(GetProcessHeap(), 0, ddraw->decls);
+ ddraw->numConvertedDecls = 0;
+
+ if (FAILED(IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain)))
+ {
+ /* Not good */
+ ERR("(%p) Failed to uninit 3D\n", This);
+ }
+ else
+ {
+ /* Free the d3d window if one was created */
+ if(ddraw->d3d_window != 0 && ddraw->d3d_window != ddraw->dest_window)
+ {
+ TRACE(" (%p) Destroying the hidden render window %p\n", This, ddraw->d3d_window);
+ DestroyWindow(ddraw->d3d_window);
+ ddraw->d3d_window = 0;
+ }
+ /* Unset the pointers */
+ }
+
+ This->wineD3DSwapChain = NULL; /* Uninit3D releases the swapchain */
+ ddraw->d3d_initialized = FALSE;
+ ddraw->d3d_target = NULL;
+ } else {
+ IWineD3DDevice_UninitGDI(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain);
+ This->wineD3DSwapChain = NULL;
+ }
+
+ /* Reset to the default surface implementation type. This is needed if apps use
+ * non render target surfaces and expect blits to work after destroying the render
+ * target.
+ *
+ * TODO: Recreate existing offscreen surfaces
+ */
+ ddraw->ImplType = DefaultSurfaceType;
+
+ /* Write a trace because D3D unloading was the reason for many
+ * crashes during development.
+ */
+ TRACE("(%p) D3D unloaded\n", This);
+ }
+
+ /* The refcount test shows that the palette is detached when the surface is destroyed */
+ IDirectDrawSurface7_SetPalette((IDirectDrawSurface7 *)This, NULL);
+
+ /* Loop through all complex attached surfaces,
+ * and destroy them.
+ *
+ * Yet again, only the root can have more than one complexly attached surface, all the others
+ * have a total of one;
+ */
+ for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
+ {
+ if(!This->complex_array[i]) break;
+
+ surf = This->complex_array[i];
+ This->complex_array[i] = NULL;
+ while(surf)
+ {
+ IDirectDrawSurfaceImpl *destroy = surf;
+ surf = surf->complex_array[0]; /* Iterate through the "tree" */
+ IDirectDrawSurfaceImpl_Destroy(destroy); /* Destroy it */
+ }
+ }
+
+ /* Destroy the root surface.
+ */
+ IDirectDrawSurfaceImpl_Destroy(This);
+
+ /* Reduce the ddraw refcount */
+ if(ifaceToRelease) IUnknown_Release(ifaceToRelease);
+ LeaveCriticalSection(&ddraw_cs);
+}
+
/*****************************************************************************
* IUnknown parts follow
*****************************************************************************/
@@ -285,117 +399,7 @@ IDirectDrawSurfaceImpl_Release(IDirectDrawSurface7 *iface)
if (ref == 0)
{
-
- IDirectDrawSurfaceImpl *surf;
- IDirectDrawImpl *ddraw;
- IUnknown *ifaceToRelease = This->ifaceToRelease;
- UINT i;
-
- /* Complex attached surfaces are destroyed implicitly when the root is released */
- EnterCriticalSection(&ddraw_cs);
- if(!This->is_complex_root)
- {
- WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
- LeaveCriticalSection(&ddraw_cs);
- return ref;
- }
- ddraw = This->ddraw;
-
- /* If it's a texture, destroy the WineD3DTexture.
- * WineD3D will destroy the IParent interfaces
- * of the sublevels, which destroys the WineD3DSurfaces.
- * Set the surfaces to NULL to avoid destroying them again later
- */
- if(This->wineD3DTexture)
- {
- IWineD3DBaseTexture_Release(This->wineD3DTexture);
- }
- /* If it's the RenderTarget, destroy the d3ddevice */
- else if(This->wineD3DSwapChain)
- {
- if((ddraw->d3d_initialized) && (This == ddraw->d3d_target)) {
- TRACE("(%p) Destroying the render target, uninitializing D3D\n", This);
-
- /* Unset any index buffer, just to be sure */
- IWineD3DDevice_SetIndexBuffer(ddraw->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
- IWineD3DDevice_SetDepthStencilSurface(ddraw->wineD3DDevice, NULL);
- IWineD3DDevice_SetVertexDeclaration(ddraw->wineD3DDevice, NULL);
- for(i = 0; i < ddraw->numConvertedDecls; i++)
- {
- IWineD3DVertexDeclaration_Release(ddraw->decls[i].decl);
- }
- HeapFree(GetProcessHeap(), 0, ddraw->decls);
- ddraw->numConvertedDecls = 0;
-
- if (FAILED(IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain)))
- {
- /* Not good */
- ERR("(%p) Failed to uninit 3D\n", This);
- }
- else
- {
- /* Free the d3d window if one was created */
- if(ddraw->d3d_window != 0 && ddraw->d3d_window != ddraw->dest_window)
- {
- TRACE(" (%p) Destroying the hidden render window %p\n", This, ddraw->d3d_window);
- DestroyWindow(ddraw->d3d_window);
- ddraw->d3d_window = 0;
- }
- /* Unset the pointers */
- }
-
- This->wineD3DSwapChain = NULL; /* Uninit3D releases the swapchain */
- ddraw->d3d_initialized = FALSE;
- ddraw->d3d_target = NULL;
- } else {
- IWineD3DDevice_UninitGDI(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain);
- This->wineD3DSwapChain = NULL;
- }
-
- /* Reset to the default surface implementation type. This is needed if apps use
- * non render target surfaces and expect blits to work after destroying the render
- * target.
- *
- * TODO: Recreate existing offscreen surfaces
- */
- ddraw->ImplType = DefaultSurfaceType;
-
- /* Write a trace because D3D unloading was the reason for many
- * crashes during development.
- */
- TRACE("(%p) D3D unloaded\n", This);
- }
-
- /* The refcount test shows that the palette is detached when the surface is destroyed */
- IDirectDrawSurface7_SetPalette((IDirectDrawSurface7 *)This, NULL);
-
- /* Loop through all complex attached surfaces,
- * and destroy them.
- *
- * Yet again, only the root can have more than one complexly attached surface, all the others
- * have a total of one;
- */
- for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
- {
- if(!This->complex_array[i]) break;
-
- surf = This->complex_array[i];
- This->complex_array[i] = NULL;
- while(surf)
- {
- IDirectDrawSurfaceImpl *destroy = surf;
- surf = surf->complex_array[0]; /* Iterate through the "tree" */
- IDirectDrawSurfaceImpl_Destroy(destroy); /* Destroy it */
- }
- }
-
- /* Destroy the root surface.
- */
- IDirectDrawSurfaceImpl_Destroy(This);
-
- /* Reduce the ddraw refcount */
- if(ifaceToRelease) IUnknown_Release(ifaceToRelease);
- LeaveCriticalSection(&ddraw_cs);
+ DestroyComplexSurface(This);
}
return ref;
--
1.7.0.4
More information about the wine-patches
mailing list