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