Module: wine Branch: master Commit: 69f81188831526874e91f0c4037dc33850ad41ad URL: https://gitlab.winehq.org/wine/wine/-/commit/69f81188831526874e91f0c4037dc33...
Author: Rémi Bernon rbernon@codeweavers.com Date: Thu Mar 7 17:51:09 2024 +0100
winevulkan: Allow only one vulkan surface at a time for an HWND.
Fixes bb872831deb48382e4733979e00243e5122385d0 which lost this from the winex11 driver. This might be something we want to relax at some point to allow multiple APIs to draw to the same HWND, but it was done like that before and it is technically a regression.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56380
---
dlls/winevulkan/vulkan.c | 41 ++++++++++++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_private.h | 2 ++ 2 files changed, 43 insertions(+)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 9981bd0141e..0846f2dfc73 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -26,11 +26,50 @@
#include "vulkan_private.h" #include "wine/vulkan_driver.h" +#include "wine/rbtree.h" #include "ntgdi.h" #include "ntuser.h"
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
+static int window_surface_compare(const void *key, const struct rb_entry *entry) +{ + const struct wine_surface *surface = RB_ENTRY_VALUE(entry, struct wine_surface, window_entry); + HWND key_hwnd = (HWND)key; + + if (key_hwnd < surface->hwnd) return -1; + if (key_hwnd > surface->hwnd) return 1; + return 0; +} + +static pthread_mutex_t window_surfaces_lock = PTHREAD_MUTEX_INITIALIZER; +static struct rb_tree window_surfaces = {.compare = window_surface_compare}; + +static void window_surfaces_insert(struct wine_surface *surface) +{ + struct wine_surface *previous; + struct rb_entry *ptr; + + pthread_mutex_lock(&window_surfaces_lock); + + if (!(ptr = rb_get(&window_surfaces, surface->hwnd))) + rb_put(&window_surfaces, surface->hwnd, &surface->window_entry); + else + { + previous = RB_ENTRY_VALUE(ptr, struct wine_surface, window_entry); + rb_replace(&window_surfaces, &previous->window_entry, &surface->window_entry); + previous->hwnd = 0; /* make sure previous surface becomes invalid */ + } + + pthread_mutex_unlock(&window_surfaces_lock); +} + +static void window_surfaces_remove(struct wine_surface *surface) +{ + pthread_mutex_lock(&window_surfaces_lock); + if (surface->hwnd) rb_remove(&window_surfaces, &surface->window_entry); + pthread_mutex_unlock(&window_surfaces_lock); +}
static BOOL is_wow64(void) { @@ -1542,6 +1581,7 @@ VkResult wine_vkCreateWin32SurfaceKHR(VkInstance handle, const VkWin32SurfaceCre
object->host_surface = vk_funcs->p_wine_get_host_surface(object->driver_surface); if (dummy) NtUserDestroyWindow(dummy); + window_surfaces_insert(object);
*surface = wine_surface_to_handle(object); add_handle_mapping(instance, *surface, object->host_surface, &object->wrapper_entry); @@ -1559,6 +1599,7 @@ void wine_vkDestroySurfaceKHR(VkInstance handle, VkSurfaceKHR surface,
instance->funcs.p_vkDestroySurfaceKHR(instance->host_instance, object->driver_surface, NULL); remove_handle_mapping(instance, &object->wrapper_entry); + window_surfaces_remove(object);
free(object); } diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index f65b285e02a..b44285722a7 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -27,6 +27,7 @@
#include "vulkan_loader.h" #include "vulkan_thunks.h" +#include "wine/rbtree.h"
#include "wine/rbtree.h"
@@ -236,6 +237,7 @@ struct wine_surface VkSurfaceKHR driver_surface; HWND hwnd;
+ struct rb_entry window_entry; struct wrapper_entry wrapper_entry; };