[PATCH 0/1] MR9856: win32u: Update client surface state before swapping or presenting.
With winex11, when multiple client surfaces are being active at the same time, we are detaching / attaching the client surfaces to keep the last one onscreen. This is done within the client_surface_present call, and it was called from within opengl_drawable_flush, before GL swap. Since bcb1f3d29562edabfd089bedb539cf2295a5e6a8 we don't call the flush callback as often and we only call client_surface_present *after* the VK present / GL swap, which breaks the display as the surface is not offscreen and yet not attached to its parent. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59190 -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9856
From: Rémi Bernon <rbernon@codeweavers.com> With winex11, when multiple client surfaces are being active at the same time, we are detaching / attaching the client surfaces to keep the last one onscreen. This is done within the client_surface_present call, and it was called from within opengl_drawable_flush, before GL swap. Since bcb1f3d29562edabfd089bedb539cf2295a5e6a8 we don't call the flush callback as often and we only call client_surface_present *after* the VK present / GL swap, which breaks the display as the surface is not offscreen and yet not attached to its parent. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59190 --- dlls/win32u/opengl.c | 1 + dlls/win32u/vulkan.c | 7 +++++++ dlls/win32u/window.c | 7 +++++++ include/wine/gdi_driver.h | 3 ++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 23ea61a207d..2b185e1aefd 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -168,6 +168,7 @@ static void opengl_drawable_flush( struct opengl_drawable *drawable, int interva static BOOL opengl_drawable_swap( struct opengl_drawable *drawable ) { if (!is_client_surface_window( drawable->client, 0 )) return FALSE; + client_surface_update( drawable->client ); return drawable->funcs->swap( drawable ); } diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 9030017eb82..3c9bc02a997 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -1945,6 +1945,13 @@ static VkResult win32u_vkQueuePresentKHR( VkQueue client_queue, const VkPresentI client_swapchains = present_info->pSwapchains; present_info->pSwapchains = swapchains; + for (uint32_t i = 0; i < present_info->swapchainCount; i++) + { + struct swapchain *swapchain = swapchain_from_handle( client_swapchains[i] ); + struct surface *surface = swapchain->surface; + client_surface_update( surface->client ); + } + res = device->p_vkQueuePresentKHR( queue->host.queue, present_info ); for (uint32_t i = 0; i < present_info->swapchainCount; i++) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 1464d45697e..4bceb90fcd2 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -376,6 +376,13 @@ void client_surface_present( struct client_surface *surface ) pthread_mutex_unlock( &surfaces_lock ); } +void client_surface_update( struct client_surface *surface ) +{ + pthread_mutex_lock( &surfaces_lock ); + if (surface->hwnd) surface->funcs->update( surface ); + pthread_mutex_unlock( &surfaces_lock ); +} + BOOL is_client_surface_window( struct client_surface *surface, HWND hwnd ) { BOOL ret; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 81932436963..d7b5018719c 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -252,7 +252,7 @@ struct client_surface_funcs void (*destroy)( struct client_surface *surface ); /* detach the surface from its window, called from window owner thread */ void (*detach)( struct client_surface *surface ); - /* update the surface to match its window state, called from window owner thread */ + /* update the surface to match its window state */ void (*update)( struct client_surface *surface ); /* present the client surface if necessary, hdc != NULL when offscreen, called from render thread */ void (*present)( struct client_surface *surface, HDC hdc ); @@ -272,6 +272,7 @@ W32KAPI void *client_surface_create( UINT size, const struct client_surface_func W32KAPI void client_surface_add_ref( struct client_surface *surface ); W32KAPI void client_surface_release( struct client_surface *surface ); W32KAPI void client_surface_present( struct client_surface *surface ); +W32KAPI void client_surface_update( struct client_surface *surface ); W32KAPI void detach_client_surfaces( HWND hwnd ); static inline const char *debugstr_client_surface( struct client_surface *surface ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9856
participants (2)
-
Rémi Bernon -
Rémi Bernon (@rbernon)