[PATCH v2 1/4] winex11: Add initial vkCreateWin32SurfaceKHR implementation.

Roderick Colenbrander thunderbird2k at gmail.com
Tue Mar 13 01:32:03 CDT 2018


Implement surface creation for top-level windows. Child window rendering
is not yet supported.

Signed-off-by: Roderick Colenbrander <thunderbird2k at gmail.com>
---
 dlls/winex11.drv/vulkan.c | 90 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 88 insertions(+), 2 deletions(-)

diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c
index 11d9f61b91..4b20b46e1b 100644
--- a/dlls/winex11.drv/vulkan.c
+++ b/dlls/winex11.drv/vulkan.c
@@ -28,6 +28,7 @@
 #include "wine/debug.h"
 #include "wine/heap.h"
 #include "wine/library.h"
+#include "x11drv.h"
 
 /* We only want host compatible structures and don't need alignment. */
 #define WINE_VK_ALIGN(x)
@@ -43,8 +44,28 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
 #endif
 
+typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
+#define VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR 1000004000
+
+struct wine_vk_surface
+{
+    Window window;
+    VkSurfaceKHR surface; /* native surface */
+};
+
+typedef struct VkXlibSurfaceCreateInfoKHR
+{
+    VkStructureType sType;
+    const void *pNext;
+    VkXlibSurfaceCreateFlagsKHR flags;
+    Display *dpy;
+    Window window;
+} VkXlibSurfaceCreateInfoKHR;
+
 static VkResult (*pvkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *);
+static VkResult (*pvkCreateXlibSurfaceKHR)(VkInstance, const VkXlibSurfaceCreateInfoKHR *, const VkAllocationCallbacks *, VkSurfaceKHR *);
 static void (*pvkDestroyInstance)(VkInstance, const VkAllocationCallbacks *);
+static void (*pvkDestroySurfaceKHR)(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks *);
 static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *);
 static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *);
 
@@ -67,7 +88,9 @@ static BOOL wine_vk_init(void)
 
 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(vulkan_handle, #f, NULL, 0)) == NULL) return FALSE;
 LOAD_FUNCPTR(vkCreateInstance)
+LOAD_FUNCPTR(vkCreateXlibSurfaceKHR)
 LOAD_FUNCPTR(vkDestroyInstance)
+LOAD_FUNCPTR(vkDestroySurfaceKHR)
 LOAD_FUNCPTR(vkGetDeviceProcAddr)
 LOAD_FUNCPTR(vkGetInstanceProcAddr)
 #undef LOAD_FUNCPTR
@@ -123,6 +146,20 @@ 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)
+{
+    if (!surface)
+        return;
+
+    /* vkDestroySurfaceKHR must handle VK_NULL_HANDLE (0) for surface. */
+    pvkDestroySurfaceKHR(instance, surface->surface, NULL /* allocator */);
+
+    if (surface->window)
+        XDestroyWindow(gdi_display, surface->window);
+
+    heap_free(surface);
+}
+
 static VkResult X11DRV_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain,
         uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *index)
 {
@@ -172,8 +209,57 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
         const VkWin32SurfaceCreateInfoKHR *create_info,
         const VkAllocationCallbacks *allocator, VkSurfaceKHR *surface)
 {
-    FIXME("stub: %p %p %p %p\n", instance, create_info, allocator, surface);
-    return VK_ERROR_OUT_OF_HOST_MEMORY;
+    VkResult res;
+    VkXlibSurfaceCreateInfoKHR create_info_host;
+    struct wine_vk_surface *x11_surface;
+
+    TRACE("%p %p %p %p\n", instance, create_info, allocator, surface);
+
+    if (allocator)
+        FIXME("Support for allocation callbacks not implemented yet\n");
+
+    /* TODO: support child window rendering. */
+    if (GetAncestor(create_info->hwnd, GA_PARENT) != GetDesktopWindow())
+    {
+        FIXME("Application requires child window rendering, which is not implemented yet!\n");
+        return VK_ERROR_INCOMPATIBLE_DRIVER;
+    }
+
+    x11_surface = heap_alloc_zero(sizeof(*x11_surface));
+    if (!x11_surface)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    x11_surface->window = create_client_window(create_info->hwnd, &default_visual);
+    if (!x11_surface->window)
+    {
+        ERR("Failed to allocate client window for hwnd=%p\n", create_info->hwnd);
+
+        /* VK_KHR_win32_surface only allows out of host and device memory as errors. */
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto err;
+    }
+
+    create_info_host.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
+    create_info_host.pNext = NULL;
+    create_info_host.flags = 0; /* reserved */
+    create_info_host.dpy = gdi_display;
+    create_info_host.window = x11_surface->window;
+
+    res = pvkCreateXlibSurfaceKHR(instance, &create_info_host, NULL /* allocator */, &x11_surface->surface);
+    if (res != VK_SUCCESS)
+    {
+        ERR("Failed to create Xlib surface, res=%d\n", res);
+        goto err;
+    }
+
+    *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);
+    return res;
 }
 
 static void X11DRV_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *allocator)
-- 
2.14.3




More information about the wine-devel mailing list