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