From: Matteo Bruni mbruni@codeweavers.com
--- Originally written to avoid triggering a Mesa slowpath introduced by Mesa commit e7f3a8d6959c74f63c877dd8776fe519d54f946f. It seems to me like this would be a good idea for more reasons than just that though. --- dlls/wined3d/adapter_gl.c | 2 +- dlls/wined3d/context_gl.c | 26 ++++++++---- dlls/wined3d/device.c | 42 ++++++++++++++++--- dlls/wined3d/swapchain.c | 76 +++++----------------------------- dlls/wined3d/wined3d_private.h | 13 ++---- 5 files changed, 70 insertions(+), 89 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 60a168b5cef..0c03fcf1739 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4567,7 +4567,7 @@ static HRESULT adapter_gl_init_3d(struct wined3d_device *device)
wined3d_cs_init_object(device->cs, wined3d_device_gl_create_primary_opengl_context_cs, wined3d_device_gl(device)); wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); - if (!wined3d_swapchain_gl(device->swapchains[0])->context_count) + if (!device->blitter) return E_FAIL;
return WINED3D_OK; diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index b1f217b4e50..187d7c2ce59 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -1258,9 +1258,11 @@ success:
static BOOL wined3d_context_gl_set_gl_context(struct wined3d_context_gl *context_gl) { - struct wined3d_swapchain_gl *swapchain_gl = wined3d_swapchain_gl(context_gl->c.swapchain); + struct wined3d_device_gl *device_gl = wined3d_device_gl(context_gl->c.device); BOOL backup = FALSE;
+ TRACE("context_gl %p.\n", context_gl); + if (!wined3d_context_gl_set_pixel_format(context_gl)) { WARN("Failed to set pixel format %d on device context %p.\n", @@ -1275,23 +1277,20 @@ static BOOL wined3d_context_gl_set_gl_context(struct wined3d_context_gl *context context_gl->valid = 0; WARN("Trying fallback to the backup window.\n");
- /* FIXME: If the context is destroyed it's no longer associated with - * a swapchain, so we can't use the swapchain to get a backup dc. To - * make this work windowless contexts would need to be handled by the - * device. */ - if (context_gl->c.destroyed || !swapchain_gl) + if (context_gl->c.destroyed) { FIXME("Unable to get backup dc for destroyed context %p.\n", context_gl); wined3d_context_gl_set_current(NULL); return FALSE; }
- if (!(context_gl->dc = wined3d_swapchain_gl_get_backup_dc(swapchain_gl))) + if (!(context_gl->dc = wined3d_device_gl_get_backup_dc(device_gl))) { wined3d_context_gl_set_current(NULL); return FALSE; }
+ TRACE("Using backup DC %p.\n", context_gl->dc); context_gl->dc_is_private = TRUE; context_gl->dc_has_format = FALSE;
@@ -1369,6 +1368,8 @@ static void wined3d_context_gl_cleanup(struct wined3d_context_gl *context_gl) HDC restore_dc; unsigned int i;
+ TRACE("context_gl %p.\n", context_gl); + restore_ctx = wglGetCurrentContext(); restore_dc = wglGetCurrentDC();
@@ -2016,7 +2017,7 @@ static BOOL wined3d_context_gl_create_wgl_ctx(struct wined3d_context_gl *context context_gl->pixel_format, context_gl->dc);
wined3d_release_dc(context_gl->window, context_gl->dc); - if (!(context_gl->dc = wined3d_swapchain_gl_get_backup_dc(swapchain_gl))) + if (!(context_gl->dc = wined3d_device_gl_get_backup_dc(wined3d_device_gl(device)))) { ERR("Failed to retrieve the backup device context.\n"); return FALSE; @@ -2093,7 +2094,7 @@ HRESULT wined3d_context_gl_init(struct wined3d_context_gl *context_gl, struct wi
if (!context_gl->dc) { - if (!(context_gl->dc = wined3d_swapchain_gl_get_backup_dc(swapchain_gl))) + if (!(context_gl->dc = wined3d_device_gl_get_backup_dc(wined3d_device_gl(device)))) { ERR("Failed to retrieve a device context.\n"); return E_FAIL; @@ -2338,6 +2339,7 @@ void wined3d_context_gl_destroy(struct wined3d_context_gl *context_gl) context_gl->c.destroy_delayed = 1; /* FIXME: Get rid of a pointer to swapchain from wined3d_context. */ context_gl->c.swapchain = NULL; + context_gl->c.device = NULL; return; }
@@ -4467,6 +4469,12 @@ static void wined3d_context_gl_activate(struct wined3d_context_gl *context_gl, struct wined3d_texture *texture, unsigned int sub_resource_idx) { wined3d_context_gl_enter(context_gl); + if (texture && texture->swapchain && texture->swapchain != context_gl->c.swapchain) + { + TRACE("Switching context_gl %p from swapchain %p to swapchain %p.\n", + context_gl, context_gl->c.swapchain, texture->swapchain); + context_gl->c.swapchain = texture->swapchain; + } wined3d_context_gl_update_window(context_gl); wined3d_context_gl_setup_target(context_gl, texture, sub_resource_idx); if (!context_gl->valid) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 34b3a4bd6fe..6d9c56c9ace 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1187,7 +1187,6 @@ bool wined3d_device_gl_create_bo(struct wined3d_device_gl *device_gl, struct win void wined3d_device_gl_delete_opengl_contexts_cs(void *object) { struct wined3d_device_gl *device_gl = object; - struct wined3d_swapchain_gl *swapchain_gl; struct wined3d_context_gl *context_gl; struct wined3d_context *context; struct wined3d_device *device; @@ -1219,11 +1218,14 @@ void wined3d_device_gl_delete_opengl_contexts_cs(void *object) context_release(context);
while (device->context_count) + wined3d_context_gl_destroy(wined3d_context_gl(device->contexts[0])); + + if (device_gl->backup_dc) { - if ((swapchain_gl = wined3d_swapchain_gl(device->contexts[0]->swapchain))) - wined3d_swapchain_gl_destroy_contexts(swapchain_gl); - else - wined3d_context_gl_destroy(wined3d_context_gl(device->contexts[0])); + TRACE("Destroying backup wined3d window %p, dc %p.\n", device_gl->backup_wnd, device_gl->backup_dc); + + wined3d_release_dc(device_gl->backup_wnd, device_gl->backup_dc); + DestroyWindow(device_gl->backup_wnd); } }
@@ -1252,6 +1254,7 @@ void wined3d_device_gl_create_primary_opengl_context_cs(void *object) { WARN("Failed to initialise allocator.\n"); context_release(context); + wined3d_context_gl_destroy(wined3d_context_gl(device->contexts[0])); return; }
@@ -1261,6 +1264,7 @@ void wined3d_device_gl_create_primary_opengl_context_cs(void *object) ERR("Failed to allocate shader private data, hr %#x.\n", hr); wined3d_allocator_cleanup(&device_gl->allocator); context_release(context); + wined3d_context_gl_destroy(wined3d_context_gl(device->contexts[0])); return; }
@@ -1270,6 +1274,7 @@ void wined3d_device_gl_create_primary_opengl_context_cs(void *object) device->shader_backend->shader_free_private(device, NULL); wined3d_allocator_cleanup(&device_gl->allocator); context_release(context); + wined3d_context_gl_destroy(wined3d_context_gl(device->contexts[0])); return; }
@@ -5913,6 +5918,33 @@ void CDECL wined3d_device_get_gamma_ramp(const struct wined3d_device *device, wined3d_swapchain_get_gamma_ramp(swapchain, ramp); }
+HDC wined3d_device_gl_get_backup_dc(struct wined3d_device_gl *device_gl) +{ + TRACE("device_gl %p.\n", device_gl); + + if (!device_gl->backup_dc) + { + TRACE("Creating the backup window for device %p.\n", device_gl); + + if (!(device_gl->backup_wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window", + WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL))) + { + ERR("Failed to create a window.\n"); + return NULL; + } + + if (!(device_gl->backup_dc = GetDC(device_gl->backup_wnd))) + { + ERR("Failed to get a DC.\n"); + DestroyWindow(device_gl->backup_wnd); + device_gl->backup_wnd = NULL; + return NULL; + } + } + + return device_gl->backup_dc; +} + void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) { TRACE("device %p, resource %p.\n", device, resource); diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 346fd1e6497..53f075785cb 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -23,6 +23,7 @@ #include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain) { @@ -87,7 +88,6 @@ void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain)
static void wined3d_swapchain_gl_destroy_object(void *object) { - wined3d_swapchain_gl_destroy_contexts(object); }
void wined3d_swapchain_gl_cleanup(struct wined3d_swapchain_gl *swapchain_gl) @@ -98,14 +98,6 @@ void wined3d_swapchain_gl_cleanup(struct wined3d_swapchain_gl *swapchain_gl)
wined3d_cs_destroy_object(cs, wined3d_swapchain_gl_destroy_object, swapchain_gl); wined3d_cs_finish(cs, WINED3D_CS_QUEUE_DEFAULT); - - if (swapchain_gl->backup_dc) - { - TRACE("Destroying backup wined3d window %p, dc %p.\n", swapchain_gl->backup_wnd, swapchain_gl->backup_dc); - - wined3d_release_dc(swapchain_gl->backup_wnd, swapchain_gl->backup_dc); - DestroyWindow(swapchain_gl->backup_wnd); - } }
static void wined3d_swapchain_vk_destroy_vulkan_swapchain(struct wined3d_swapchain_vk *swapchain_vk) @@ -591,7 +583,6 @@ static bool swapchain_present_is_partial_copy(struct wined3d_swapchain *swapchai static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, unsigned int swap_interval, DWORD flags) { - struct wined3d_swapchain_gl *swapchain_gl = wined3d_swapchain_gl(swapchain); struct wined3d_texture *back_buffer = swapchain->back_buffers[0]; const struct wined3d_pixel_format *pixel_format; const struct wined3d_gl_info *gl_info; @@ -610,7 +601,8 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, TRACE("Presenting DC %p.\n", context_gl->dc);
pixel_format = &wined3d_adapter_gl(swapchain->device->adapter)->pixel_formats[context_gl->pixel_format]; - if (context_gl->dc == swapchain_gl->backup_dc || (pixel_format->swap_method != WGL_SWAP_COPY_ARB + if (context_gl->dc == wined3d_device_gl(swapchain->device)->backup_dc + || (pixel_format->swap_method != WGL_SWAP_COPY_ARB && swapchain_present_is_partial_copy(swapchain, dst_rect))) { swapchain_blit_gdi(swapchain, context, src_rect, dst_rect); @@ -626,8 +618,11 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) swapchain_blit(swapchain, context, src_rect, dst_rect);
- if (swapchain_gl->context_count > 1) + if (swapchain->device->context_count > 1) + { + WARN_(d3d_perf)("Multiple contexts, calling glFinish() to enforce ordering.\n"); gl_info->gl_ops.gl.p_glFinish(); + }
/* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */ gl_info->gl_ops.wgl.p_wglSwapBuffers(context_gl->dc); @@ -1799,74 +1794,25 @@ static struct wined3d_context_gl *wined3d_swapchain_gl_create_context(struct win
context_release(&context_gl->c);
- if (!wined3d_array_reserve((void **)&swapchain_gl->contexts, &swapchain_gl->contexts_size, - swapchain_gl->context_count + 1, sizeof(*swapchain_gl->contexts))) - { - ERR("Failed to allocate new context array memory.\n"); - wined3d_context_gl_destroy(context_gl); - return NULL; - } - swapchain_gl->contexts[swapchain_gl->context_count++] = context_gl; - return context_gl; }
-void wined3d_swapchain_gl_destroy_contexts(struct wined3d_swapchain_gl *swapchain_gl) -{ - unsigned int i; - - TRACE("swapchain_gl %p.\n", swapchain_gl); - - for (i = 0; i < swapchain_gl->context_count; ++i) - { - wined3d_context_gl_destroy(swapchain_gl->contexts[i]); - } - heap_free(swapchain_gl->contexts); - swapchain_gl->contexts_size = 0; - swapchain_gl->context_count = 0; - swapchain_gl->contexts = NULL; -} - struct wined3d_context_gl *wined3d_swapchain_gl_get_context(struct wined3d_swapchain_gl *swapchain_gl) { + struct wined3d_device *device = swapchain_gl->s.device; DWORD tid = GetCurrentThreadId(); unsigned int i;
- for (i = 0; i < swapchain_gl->context_count; ++i) + for (i = 0; i < device->context_count; ++i) { - if (swapchain_gl->contexts[i]->tid == tid) - return swapchain_gl->contexts[i]; + if (wined3d_context_gl(device->contexts[i])->tid == tid) + return wined3d_context_gl(device->contexts[i]); }
/* Create a new context for the thread. */ return wined3d_swapchain_gl_create_context(swapchain_gl); }
-HDC wined3d_swapchain_gl_get_backup_dc(struct wined3d_swapchain_gl *swapchain_gl) -{ - if (!swapchain_gl->backup_dc) - { - TRACE("Creating the backup window for swapchain %p.\n", swapchain_gl); - - if (!(swapchain_gl->backup_wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window", - WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL))) - { - ERR("Failed to create a window.\n"); - return NULL; - } - - if (!(swapchain_gl->backup_dc = GetDC(swapchain_gl->backup_wnd))) - { - ERR("Failed to get a DC.\n"); - DestroyWindow(swapchain_gl->backup_wnd); - swapchain_gl->backup_wnd = NULL; - return NULL; - } - } - - return swapchain_gl->backup_dc; -} - void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) { UINT i; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index b7d3b579ed2..fee803eef8e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4294,6 +4294,9 @@ struct wined3d_device_gl } *retired_blocks; SIZE_T retired_blocks_size; SIZE_T retired_block_count; + + HWND backup_wnd; + HDC backup_dc; };
static inline struct wined3d_device_gl *wined3d_device_gl(struct wined3d_device *device) @@ -4331,6 +4334,7 @@ bool wined3d_device_gl_create_bo(struct wined3d_device_gl *device_gl, GLenum usage, bool coherent, GLbitfield flags, struct wined3d_bo_gl *bo) DECLSPEC_HIDDEN; void wined3d_device_gl_create_primary_opengl_context_cs(void *object) DECLSPEC_HIDDEN; void wined3d_device_gl_delete_opengl_contexts_cs(void *object) DECLSPEC_HIDDEN; +HDC wined3d_device_gl_get_backup_dc(struct wined3d_device_gl *device_gl) DECLSPEC_HIDDEN; GLbitfield wined3d_device_gl_get_memory_type_flags(unsigned int memory_type_idx) DECLSPEC_HIDDEN;
static inline float wined3d_alpha_ref(const struct wined3d_state *state) @@ -5704,13 +5708,6 @@ HRESULT wined3d_swapchain_no3d_init(struct wined3d_swapchain *swapchain_no3d, struct wined3d_swapchain_gl { struct wined3d_swapchain s; - - struct wined3d_context_gl **contexts; - SIZE_T contexts_size; - SIZE_T context_count; - - HDC backup_dc; - HWND backup_wnd; };
static inline struct wined3d_swapchain_gl *wined3d_swapchain_gl(struct wined3d_swapchain *swapchain) @@ -5719,8 +5716,6 @@ static inline struct wined3d_swapchain_gl *wined3d_swapchain_gl(struct wined3d_s }
void wined3d_swapchain_gl_cleanup(struct wined3d_swapchain_gl *swapchain_gl) DECLSPEC_HIDDEN; -void wined3d_swapchain_gl_destroy_contexts(struct wined3d_swapchain_gl *swapchain_gl) DECLSPEC_HIDDEN; -HDC wined3d_swapchain_gl_get_backup_dc(struct wined3d_swapchain_gl *swapchain_gl) DECLSPEC_HIDDEN; struct wined3d_context_gl *wined3d_swapchain_gl_get_context(struct wined3d_swapchain_gl *swapchain_gl) DECLSPEC_HIDDEN; HRESULT wined3d_swapchain_gl_init(struct wined3d_swapchain_gl *swapchain_gl, struct wined3d_device *device, struct wined3d_swapchain_desc *desc,