Commit f74e8a29 authored by Andrew Eikum's avatar Andrew Eikum Committed by Alexandre Julliard

winex11.drv: Refcount the vulkan surface window.

parent 8b3294a4
...@@ -41,11 +41,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan); ...@@ -41,11 +41,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
#ifdef SONAME_LIBVULKAN #ifdef SONAME_LIBVULKAN
static CRITICAL_SECTION context_section;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &context_section,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": context_section") }
};
static CRITICAL_SECTION context_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static XContext vulkan_hwnd_context;
typedef VkFlags VkXlibSurfaceCreateFlagsKHR; typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
#define VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR 1000004000 #define VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR 1000004000
struct wine_vk_surface struct wine_vk_surface
{ {
LONG ref;
Window window; Window window;
VkSurfaceKHR surface; /* native surface */ VkSurfaceKHR surface; /* native surface */
}; };
...@@ -115,6 +127,8 @@ static BOOL WINAPI wine_vk_init(INIT_ONCE *once, void *param, void **context) ...@@ -115,6 +127,8 @@ static BOOL WINAPI wine_vk_init(INIT_ONCE *once, void *param, void **context)
LOAD_FUNCPTR(vkQueuePresentKHR) LOAD_FUNCPTR(vkQueuePresentKHR)
#undef LOAD_FUNCPTR #undef LOAD_FUNCPTR
vulkan_hwnd_context = XUniqueContext();
return TRUE; return TRUE;
fail: fail:
...@@ -171,13 +185,16 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo ...@@ -171,13 +185,16 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
return VK_SUCCESS; return VK_SUCCESS;
} }
static void wine_vk_surface_destroy(VkInstance instance, struct wine_vk_surface *surface) static struct wine_vk_surface *wine_vk_surface_grab(struct wine_vk_surface *surface)
{ {
if (!surface) InterlockedIncrement(&surface->ref);
return; return surface;
}
/* vkDestroySurfaceKHR must handle VK_NULL_HANDLE (0) for surface. */ static void wine_vk_surface_release(struct wine_vk_surface *surface)
pvkDestroySurfaceKHR(instance, surface->surface, NULL /* allocator */); {
if (InterlockedDecrement(&surface->ref))
return;
if (surface->window) if (surface->window)
XDestroyWindow(gdi_display, surface->window); XDestroyWindow(gdi_display, surface->window);
...@@ -185,6 +202,18 @@ static void wine_vk_surface_destroy(VkInstance instance, struct wine_vk_surface ...@@ -185,6 +202,18 @@ static void wine_vk_surface_destroy(VkInstance instance, struct wine_vk_surface
heap_free(surface); heap_free(surface);
} }
void wine_vk_surface_destroy(HWND hwnd)
{
struct wine_vk_surface *surface;
EnterCriticalSection(&context_section);
if (!XFindContext(gdi_display, (XID)hwnd, vulkan_hwnd_context, (char **)&surface))
{
wine_vk_surface_release(surface);
}
XDeleteContext(gdi_display, (XID)hwnd, vulkan_hwnd_context);
LeaveCriticalSection(&context_section);
}
static VkResult X11DRV_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, static VkResult X11DRV_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain,
uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *index) uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *index)
{ {
...@@ -245,7 +274,7 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance, ...@@ -245,7 +274,7 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
{ {
VkResult res; VkResult res;
VkXlibSurfaceCreateInfoKHR create_info_host; VkXlibSurfaceCreateInfoKHR create_info_host;
struct wine_vk_surface *x11_surface; struct wine_vk_surface *x11_surface, *prev;
TRACE("%p %p %p %p\n", instance, create_info, allocator, surface); TRACE("%p %p %p %p\n", instance, create_info, allocator, surface);
...@@ -263,6 +292,8 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance, ...@@ -263,6 +292,8 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
if (!x11_surface) if (!x11_surface)
return VK_ERROR_OUT_OF_HOST_MEMORY; return VK_ERROR_OUT_OF_HOST_MEMORY;
x11_surface->ref = 1;
x11_surface->window = create_client_window(create_info->hwnd, &default_visual); x11_surface->window = create_client_window(create_info->hwnd, &default_visual);
if (!x11_surface->window) if (!x11_surface->window)
{ {
...@@ -286,13 +317,21 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance, ...@@ -286,13 +317,21 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
goto err; goto err;
} }
EnterCriticalSection(&context_section);
if (!XFindContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char **)&prev))
{
wine_vk_surface_release(prev);
}
XSaveContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char *)wine_vk_surface_grab(x11_surface));
LeaveCriticalSection(&context_section);
*surface = (uintptr_t)x11_surface; *surface = (uintptr_t)x11_surface;
TRACE("Created surface=0x%s\n", wine_dbgstr_longlong(*surface)); TRACE("Created surface=0x%s\n", wine_dbgstr_longlong(*surface));
return VK_SUCCESS; return VK_SUCCESS;
err: err:
wine_vk_surface_destroy(instance, x11_surface); wine_vk_surface_release(x11_surface);
return res; return res;
} }
...@@ -316,7 +355,13 @@ static void X11DRV_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface ...@@ -316,7 +355,13 @@ static void X11DRV_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface
if (allocator) if (allocator)
FIXME("Support for allocation callbacks not implemented yet\n"); FIXME("Support for allocation callbacks not implemented yet\n");
wine_vk_surface_destroy(instance, x11_surface); /* vkDestroySurfaceKHR must handle VK_NULL_HANDLE (0) for surface. */
if (x11_surface)
{
pvkDestroySurfaceKHR(instance, x11_surface->surface, NULL /* allocator */);
wine_vk_surface_release(x11_surface);
}
} }
static void X11DRV_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, static void X11DRV_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
......
...@@ -1719,6 +1719,7 @@ void CDECL X11DRV_DestroyWindow( HWND hwnd ) ...@@ -1719,6 +1719,7 @@ void CDECL X11DRV_DestroyWindow( HWND hwnd )
release_win_data( data ); release_win_data( data );
HeapFree( GetProcessHeap(), 0, data ); HeapFree( GetProcessHeap(), 0, data );
destroy_gl_drawable( hwnd ); destroy_gl_drawable( hwnd );
wine_vk_surface_destroy( hwnd );
} }
......
...@@ -586,6 +586,7 @@ extern XIC X11DRV_get_ic( HWND hwnd ) DECLSPEC_HIDDEN; ...@@ -586,6 +586,7 @@ extern XIC X11DRV_get_ic( HWND hwnd ) DECLSPEC_HIDDEN;
extern void sync_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN; extern void sync_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN;
extern void set_gl_drawable_parent( HWND hwnd, HWND parent ) 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 destroy_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN;
extern void wine_vk_surface_destroy( HWND hwnd ) DECLSPEC_HIDDEN;
extern void wait_for_withdrawn_state( HWND hwnd, BOOL set ) DECLSPEC_HIDDEN; extern void wait_for_withdrawn_state( HWND hwnd, BOOL set ) DECLSPEC_HIDDEN;
extern Window init_clip_window(void) DECLSPEC_HIDDEN; extern Window init_clip_window(void) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment