Module: wine
Branch: master
Commit: 13e464d0fbd70309f47a6d8cca5a7e4b3ae84161
URL: http://source.winehq.org/git/wine.git/?a=commit;h=13e464d0fbd70309f47a6d8cc…
Author: Józef Kucia <jkucia(a)codeweavers.com>
Date: Wed Oct 5 11:17:07 2016 +0200
wined3d: Avoid destroying active contexts.
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(a)codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
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;