Module: wine Branch: master Commit: 13e464d0fbd70309f47a6d8cca5a7e4b3ae84161 URL: http://source.winehq.org/git/wine.git/?a=commit;h=13e464d0fbd70309f47a6d8cca...
Author: Józef Kucia jkucia@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@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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;