[11/10] WineD3D: Activate a different context if the active render target is destroyed

Stefan Dösinger stefan at codeweavers.com
Sat Feb 17 11:06:30 CST 2007


This is a fix for a regression with my context selection patch some days ago. 
It applies on top of my 10 patches from yesterday.
-------------- next part --------------
From e77321bad0c6c894017ed15cf86de7fcf04b5253 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Sat, 17 Feb 2007 18:00:47 +0100
Subject: [PATCH] WineD3D: Activate a different context if the active render target is destroyed

If the currently active render target is destroyed, the lastActiveRenderTarget pointer becomes invalid. The idea is to make sure that during
release and creation a correct render target is found and activated to avoid the need for NULL pointer checks in the more performance critical
ActivateContext code. The creation code takes care for that already, this patch fixes the release code. If the active target is destroyed, the
implicit swapchain's target is activated

Destroying the active render target is valid when the device is about to be destroyed(Uninit3D). If the implicit swapchain's target is
destroyed, or no swapchain found(can happen during ddraw uninit) then lastActiveRenderTarget is set to 0xdeadbabe or 0xdeadcafe.
---
 dlls/wined3d/surface.c |   36 ++++++++++++++++++++++++++++++++----
 1 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 333712d..b090366 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -247,6 +247,38 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
     if (ref == 0) {
         IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice;
         TRACE("(%p) : cleaning up\n", This);
+
+        if(iface == device->lastActiveRenderTarget) {
+            IWineD3DSwapChainImpl *swapchain = device->swapchains ? (IWineD3DSwapChainImpl *) device->swapchains[0] : NULL;
+
+            TRACE("Last active render target destroyed\n");
+            /* Find a replacement surface for the currently active back buffer. The context manager does not do NULL
+             * checks, so switch to a valid target as long as the currently set surface is still valid. Use the
+             * surface of the implicit swpchain. If that is the same as the destroyed surface the device is destroyed
+             * and the lastActiveRenderTarget member shouldn't matter
+             */
+            if(swapchain) {
+                if(swapchain->backBuffer && swapchain->backBuffer[0] != iface) {
+                    TRACE("Activating primary back buffer\n");
+                    ActivateContext(device, swapchain->backBuffer[0], CTXUSAGE_RESOURCELOAD);
+                } else if(!swapchain->backBuffer && swapchain->frontBuffer != iface) {
+                    /* Single buffering environment */
+                    TRACE("Activating primary front buffer\n");
+                    ActivateContext(device, swapchain->frontBuffer, CTXUSAGE_RESOURCELOAD);
+                } else {
+                    TRACE("Device is beeing destroyed, setting lastActiveRenderTarget = 0xdeadbabe\n");
+                    /* Implicit render target destroyed, that means the device is beeing destroyed
+                     * whatever we set here, it shouldn't matter
+                     */
+                    device->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadbabe;
+                }
+            } else {
+                /* May happen during ddraw uninitialization */
+                TRACE("Render target set, but swapchain does not exist!\n");
+                device->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadcafe;
+            }
+        }
+
         if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
             ENTER_GL();
             TRACE("Deleting texture %d\n", This->glDescription.textureName);
@@ -269,10 +301,6 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
         if(iface == device->ddraw_primary)
             device->ddraw_primary = NULL;
 
-        if(iface == device->lastActiveRenderTarget) {
-            device->lastActiveRenderTarget = NULL;
-        }
-
         TRACE("(%p) Released\n", This);
         HeapFree(GetProcessHeap(), 0, This);
 
-- 
1.4.4.3



More information about the wine-patches mailing list