Paul Gofman : winex11.drv: Detach vulkan surfaces during thread detach.

Alexandre Julliard julliard at winehq.org
Mon Oct 18 16:16:29 CDT 2021


Module: wine
Branch: master
Commit: 6dcaff421f87a93efe18b2efe0ec64d94ed1d483
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=6dcaff421f87a93efe18b2efe0ec64d94ed1d483

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Fri Oct 15 21:50:52 2021 +0300

winex11.drv: Detach vulkan surfaces during thread detach.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winex11.drv/vulkan.c      | 56 +++++++++++++++++++++++++++++++++++-------
 dlls/winex11.drv/window.c      |  2 +-
 dlls/winex11.drv/x11drv.h      |  2 ++
 dlls/winex11.drv/x11drv_main.c |  1 +
 4 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c
index 1bbdba2ce1d..4f6624b3db8 100644
--- a/dlls/winex11.drv/vulkan.c
+++ b/dlls/winex11.drv/vulkan.c
@@ -57,12 +57,16 @@ static XContext vulkan_hwnd_context;
 
 #define VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR 1000004000
 
+static struct list surface_list = LIST_INIT( surface_list );
+
 struct wine_vk_surface
 {
     LONG ref;
+    struct list entry;
     Window window;
     VkSurfaceKHR surface; /* native surface */
     HWND hwnd;
+    DWORD hwnd_thread_id;
 };
 
 typedef struct VkXlibSurfaceCreateInfoKHR
@@ -207,6 +211,10 @@ static void wine_vk_surface_release(struct wine_vk_surface *surface)
     if (InterlockedDecrement(&surface->ref))
         return;
 
+    EnterCriticalSection(&context_section);
+    list_remove(&surface->entry);
+    LeaveCriticalSection(&context_section);
+
     if (surface->window)
         XDestroyWindow(gdi_display, surface->window);
 
@@ -219,12 +227,33 @@ void wine_vk_surface_destroy(HWND hwnd)
     EnterCriticalSection(&context_section);
     if (!XFindContext(gdi_display, (XID)hwnd, vulkan_hwnd_context, (char **)&surface))
     {
+        surface->hwnd_thread_id = 0;
+        surface->hwnd = NULL;
         wine_vk_surface_release(surface);
     }
     XDeleteContext(gdi_display, (XID)hwnd, vulkan_hwnd_context);
     LeaveCriticalSection(&context_section);
 }
 
+void vulkan_thread_detach(void)
+{
+    struct wine_vk_surface *surface, *next;
+    DWORD thread_id = GetCurrentThreadId();
+
+    EnterCriticalSection(&context_section);
+    LIST_FOR_EACH_ENTRY_SAFE(surface, next, &surface_list, struct wine_vk_surface, entry)
+    {
+        if (surface->hwnd_thread_id != thread_id)
+            continue;
+
+        TRACE("Detaching surface %p, hwnd %p.\n", surface, surface->hwnd);
+        XReparentWindow(gdi_display, surface->window, get_dummy_parent(), 0, 0);
+        XSync(gdi_display, False);
+        wine_vk_surface_destroy(surface->hwnd);
+    }
+    LeaveCriticalSection(&context_section);
+}
+
 static VkResult X11DRV_vkCreateInstance(const VkInstanceCreateInfo *create_info,
         const VkAllocationCallbacks *allocator, VkInstance *instance)
 {
@@ -278,7 +307,7 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
 {
     VkResult res;
     VkXlibSurfaceCreateInfoKHR create_info_host;
-    struct wine_vk_surface *x11_surface, *prev;
+    struct wine_vk_surface *x11_surface;
 
     TRACE("%p %p %p %p\n", instance, create_info, allocator, surface);
 
@@ -298,8 +327,15 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
 
     x11_surface->ref = 1;
     x11_surface->hwnd = create_info->hwnd;
-    x11_surface->window = x11_surface->hwnd ? create_client_window(create_info->hwnd, &default_visual)
-                                            : create_dummy_client_window();
+    if (x11_surface->hwnd)
+    {
+        x11_surface->window = create_client_window(create_info->hwnd, &default_visual);
+        x11_surface->hwnd_thread_id = GetWindowThreadProcessId(x11_surface->hwnd, NULL);
+    }
+    else
+    {
+        x11_surface->window = create_dummy_client_window();
+    }
 
     if (!x11_surface->window)
     {
@@ -323,16 +359,14 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
         goto err;
     }
 
+    EnterCriticalSection(&context_section);
     if (x11_surface->hwnd)
     {
-        EnterCriticalSection(&context_section);
-        if (!XFindContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char **)&prev))
-        {
-            wine_vk_surface_release(prev);
-        }
+        wine_vk_surface_destroy( x11_surface->hwnd );
         XSaveContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char *)wine_vk_surface_grab(x11_surface));
-        LeaveCriticalSection(&context_section);
     }
+    list_add_tail(&surface_list, &x11_surface->entry);
+    LeaveCriticalSection(&context_section);
 
     *surface = (uintptr_t)x11_surface;
 
@@ -713,4 +747,8 @@ void wine_vk_surface_destroy(HWND hwnd)
 {
 }
 
+void vulkan_thread_detach(void)
+{
+}
+
 #endif /* SONAME_LIBVULKAN */
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 0057a341525..7ec2639e309 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1446,7 +1446,7 @@ static void move_window_bits( HWND hwnd, Window window, const RECT *old_rect, co
  *
  * Create a dummy parent window for child windows that don't have a true X11 parent.
  */
-static Window get_dummy_parent(void)
+Window get_dummy_parent(void)
 {
     static Window dummy_parent;
 
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 5ed2fcf73fb..e82ee921830 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -587,11 +587,13 @@ extern struct x11drv_win_data *get_win_data( HWND hwnd ) DECLSPEC_HIDDEN;
 extern void release_win_data( struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
 extern Window X11DRV_get_whole_window( HWND hwnd ) DECLSPEC_HIDDEN;
 extern XIC X11DRV_get_ic( HWND hwnd ) DECLSPEC_HIDDEN;
+extern Window get_dummy_parent(void) DECLSPEC_HIDDEN;
 
 extern void sync_gl_drawable( HWND hwnd, BOOL known_child ) DECLSPEC_HIDDEN;
 extern void set_gl_drawable_parent( HWND hwnd, HWND parent ) DECLSPEC_HIDDEN;
 extern void destroy_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN;
 extern void wine_vk_surface_destroy( HWND hwnd ) DECLSPEC_HIDDEN;
+extern void vulkan_thread_detach(void) DECLSPEC_HIDDEN;
 
 extern void wait_for_withdrawn_state( HWND hwnd, BOOL set ) DECLSPEC_HIDDEN;
 extern Window init_clip_window(void) DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index e8b273d055e..bd21afc8174 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -645,6 +645,7 @@ void CDECL X11DRV_ThreadDetach(void)
 
     if (data)
     {
+        vulkan_thread_detach();
         if (data->xim) XCloseIM( data->xim );
         if (data->font_set) XFreeFontSet( data->display, data->font_set );
         XCloseDisplay( data->display );




More information about the wine-cvs mailing list