winex11.drv: Detach vulkan surfaces during thread detach.

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2021-10-15 21:50:52 +03:00 committed by Alexandre Julliard
parent 5f916f7f35
commit 6dcaff421f
4 changed files with 51 additions and 10 deletions

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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 );