Andrew Eikum : winex11.drv: Refcount the vulkan surface window.

Alexandre Julliard julliard at winehq.org
Thu Jun 14 16:53:23 CDT 2018


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

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Wed Jun 13 15:08:20 2018 -0500

winex11.drv: Refcount the vulkan surface window.

Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winex11.drv/vulkan.c | 61 ++++++++++++++++++++++++++++++++++++++++-------
 dlls/winex11.drv/window.c |  1 +
 dlls/winex11.drv/x11drv.h |  1 +
 3 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c
index 7e25232..7eca31b 100644
--- a/dlls/winex11.drv/vulkan.c
+++ b/dlls/winex11.drv/vulkan.c
@@ -41,11 +41,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
 
 #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;
 #define VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR 1000004000
 
 struct wine_vk_surface
 {
+    LONG ref;
     Window window;
     VkSurfaceKHR surface; /* native surface */
 };
@@ -115,6 +127,8 @@ static BOOL WINAPI wine_vk_init(INIT_ONCE *once, void *param, void **context)
     LOAD_FUNCPTR(vkQueuePresentKHR)
 #undef LOAD_FUNCPTR
 
+    vulkan_hwnd_context = XUniqueContext();
+
     return TRUE;
 
 fail:
@@ -171,13 +185,16 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
     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)
-        return;
+    InterlockedIncrement(&surface->ref);
+    return surface;
+}
 
-    /* vkDestroySurfaceKHR must handle VK_NULL_HANDLE (0) for surface. */
-    pvkDestroySurfaceKHR(instance, surface->surface, NULL /* allocator */);
+static void wine_vk_surface_release(struct wine_vk_surface *surface)
+{
+    if (InterlockedDecrement(&surface->ref))
+        return;
 
     if (surface->window)
         XDestroyWindow(gdi_display, surface->window);
@@ -185,6 +202,18 @@ static void wine_vk_surface_destroy(VkInstance instance, struct wine_vk_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,
         uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *index)
 {
@@ -245,7 +274,7 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
 {
     VkResult res;
     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);
 
@@ -263,6 +292,8 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
     if (!x11_surface)
         return VK_ERROR_OUT_OF_HOST_MEMORY;
 
+    x11_surface->ref = 1;
+
     x11_surface->window = create_client_window(create_info->hwnd, &default_visual);
     if (!x11_surface->window)
     {
@@ -286,13 +317,21 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
         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;
 
     TRACE("Created surface=0x%s\n", wine_dbgstr_longlong(*surface));
     return VK_SUCCESS;
 
 err:
-    wine_vk_surface_destroy(instance, x11_surface);
+    wine_vk_surface_release(x11_surface);
     return res;
 }
 
@@ -316,7 +355,13 @@ static void X11DRV_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface
     if (allocator)
         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,
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 5fecd9a..a848dc6 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1719,6 +1719,7 @@ void CDECL X11DRV_DestroyWindow( HWND hwnd )
     release_win_data( data );
     HeapFree( GetProcessHeap(), 0, data );
     destroy_gl_drawable( hwnd );
+    wine_vk_surface_destroy( hwnd );
 }
 
 
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 85a05a9..939c2e7 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -586,6 +586,7 @@ extern XIC X11DRV_get_ic( 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 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 Window init_clip_window(void) DECLSPEC_HIDDEN;




More information about the wine-cvs mailing list