[PATCH 5/7] wined3d: Avoid destroying active contexts.

Józef Kucia jkucia at codeweavers.com
Wed Oct 5 04:17:07 CDT 2016


This commit fixes a problem which can be observed in d3d10core and d3d11
tests while a device is destroyed in test_swapchain_flip().

When a swapchain is destroyed all contexts associated with this
swapchain are destroyed. A context is destroyed even if it is active.
This might lead to using a destroyed context. In order to fix this the
destruction of context is delayed until leaving the last level.

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---

Ideally, a pointer to a swapchain would be completely removed from
struct wined3d_context. There are still two places which use
"context->swapchain" unsafely: surface_get_drawable_size() and
surface_load_ds_location(). If one of this function gets called with a
context marked for delayed destruction we'll get a NULL pointer
dereference (previously it would access freed memory).

---
 dlls/wined3d/context.c         | 17 +++++++++++++++++
 dlls/wined3d/device.c          |  6 +-----
 dlls/wined3d/wined3d_private.h |  3 ++-
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 89cc9ce..394a2dc 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1354,6 +1354,12 @@ void context_release(struct wined3d_context *context)
             context->restore_ctx = NULL;
             context->restore_dc = NULL;
         }
+
+        if (context->destroy_delayed)
+        {
+            TRACE("Destroying context %p.\n", context);
+            context_destroy(context->device, context);
+        }
     }
 }
 
@@ -2012,6 +2018,17 @@ void context_destroy(struct wined3d_device *device, struct wined3d_context *cont
 
     TRACE("Destroying ctx %p\n", context);
 
+    /* We delay destroying a context when it is active. The context_release()
+     * function invokes context_destroy() again while leaving the last level. */
+    if (context->level)
+    {
+        TRACE("Delaying destruction of context %p.\n", context);
+        context->destroy_delayed = 1;
+        /* FIXME: Get rid of a pointer to swapchain from wined3d_context. */
+        context->swapchain = NULL;
+        return;
+    }
+
     if (context->tid == GetCurrentThreadId() || !context->current)
     {
         context_destroy_gl_resources(context);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 90d0008..1c8cb90 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1185,13 +1185,9 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
     destroy_dummy_textures(device, gl_info);
     destroy_default_samplers(device);
 
-    /* Release the context again as soon as possible. In particular,
-     * releasing the render target views below may release the last reference
-     * to the swapchain associated with this context, which in turn will
-     * destroy the context. */
     context_release(context);
 
-    /* Release the buffers (with sanity checks)*/
+    /* Release the buffers (with sanity checks) */
     if (device->onscreen_depth_stencil)
     {
         surface = device->onscreen_depth_stencil;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 08e9120..3887f91 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1497,7 +1497,8 @@ struct wined3d_context
     DWORD hdc_is_private : 1;
     DWORD hdc_has_format : 1;           /* only meaningful if hdc_is_private */
     DWORD update_shader_resource_bindings : 1;
-    DWORD padding : 14;
+    DWORD destroy_delayed : 1;
+    DWORD padding : 13;
     DWORD last_swizzle_map; /* MAX_ATTRIBS, 16 */
     DWORD shader_update_mask;
     DWORD constant_update_mask;
-- 
2.7.3




More information about the wine-patches mailing list