From 5ceb9fc5d5ddd34cdb6d9fdbc5729c213daa8414 Mon Sep 17 00:00:00 2001 From: Philip Rideout Date: Fri, 16 Oct 2020 16:11:05 -0700 Subject: [PATCH] Add optional XCB support to PlatformVkLinux. This allows clients to build the Vulkan backend with either XLIB or XCB support. I did a quick smoke test of the XCB option, but for now we are continuing to default to XLIB. Note that the native window type used to create the swap chain differs between these two API's. --- .../backend/src/vulkan/PlatformVkLinux.cpp | 47 ++++++++++++++----- filament/backend/src/vulkan/PlatformVkLinux.h | 8 ++++ libs/bluevk/include/vulkan/vk_platform.h | 4 ++ 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/filament/backend/src/vulkan/PlatformVkLinux.cpp b/filament/backend/src/vulkan/PlatformVkLinux.cpp index c1d8010b68..94e89b3e5a 100644 --- a/filament/backend/src/vulkan/PlatformVkLinux.cpp +++ b/filament/backend/src/vulkan/PlatformVkLinux.cpp @@ -34,15 +34,18 @@ constexpr VkAllocationCallbacks* VKALLOC = nullptr; static constexpr const char* LIBRARY_X11 = "libX11.so.6"; +#ifdef FILAMENT_SUPPORTS_XCB +typedef xcb_connection_t* (*XCB_CONNECT)(const char *displayname, int *screenp); +#else typedef Display* (*X11_OPEN_DISPLAY)(const char*); -typedef Display* (*X11_CLOSE_DISPLAY)(Display*); -typedef Status (*X11_GET_GEOMETRY)(Display*, Drawable, Window*, int*, int*, unsigned int*, - unsigned int*, unsigned int*, unsigned int*); +#endif struct X11Functions { +#ifdef FILAMENT_SUPPORTS_XCB + XCB_CONNECT xcbConnect; +#else X11_OPEN_DISPLAY openDisplay; - X11_CLOSE_DISPLAY closeDisplay; - X11_GET_GEOMETRY getGeometry; +#endif void* library = nullptr; } g_x11; @@ -50,7 +53,11 @@ Driver* PlatformVkLinux::createDriver(void* const sharedContext) noexcept { ASSERT_PRECONDITION(sharedContext == nullptr, "Vulkan does not support shared contexts."); const char* requiredInstanceExtensions[] = { "VK_KHR_surface", +#ifdef FILAMENT_SUPPORTS_XCB + "VK_KHR_xcb_surface", +#else "VK_KHR_xlib_surface", +#endif "VK_KHR_get_physical_device_properties2", #if VK_ENABLE_VALIDATION "VK_EXT_debug_utils", @@ -61,22 +68,40 @@ Driver* PlatformVkLinux::createDriver(void* const sharedContext) noexcept { } void* PlatformVkLinux::createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept { +#ifdef FILAMENT_SUPPORTS_XCB + if (g_x11.library == nullptr) { + g_x11.library = dlopen(LIBRARY_X11, RTLD_LOCAL | RTLD_NOW); + ASSERT_PRECONDITION(g_x11.library, "Unable to open X11 library."); + g_x11.xcbConnect = (XCB_CONNECT) dlsym(g_x11.library, "xcb_connect"); + int screen; + mConnection = g_x11.xcbConnect(nullptr, &screen); + } + ASSERT_POSTCONDITION(vkCreateXcbSurfaceKHR, "Unable to load vkCreateXcbSurfaceKHR function."); + VkSurfaceKHR surface = nullptr; + const uint64_t ptrval = reinterpret_cast(nativeWindow); + VkXcbSurfaceCreateInfoKHR createInfo = { + .sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, + .connection = mConnection, + .window = (xcb_window_t) ptrval, + }; + VkResult result = vkCreateXcbSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); +#else if (g_x11.library == nullptr) { g_x11.library = dlopen(LIBRARY_X11, RTLD_LOCAL | RTLD_NOW); ASSERT_PRECONDITION(g_x11.library, "Unable to open X11 library."); g_x11.openDisplay = (X11_OPEN_DISPLAY) dlsym(g_x11.library, "XOpenDisplay"); - g_x11.closeDisplay = (X11_CLOSE_DISPLAY) dlsym(g_x11.library, "XCloseDisplay"); - g_x11.getGeometry = (X11_GET_GEOMETRY) dlsym(g_x11.library, "XGetGeometry"); mDisplay = g_x11.openDisplay(NULL); ASSERT_PRECONDITION(mDisplay, "Unable to open X11 display."); } ASSERT_POSTCONDITION(vkCreateXlibSurfaceKHR, "Unable to load vkCreateXlibSurfaceKHR function."); VkSurfaceKHR surface = nullptr; - VkXlibSurfaceCreateInfoKHR createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; - createInfo.dpy = mDisplay; - createInfo.window = (Window) nativeWindow; + VkXlibSurfaceCreateInfoKHR createInfo = { + .sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, + .dpy = mDisplay, + .window = (Window) nativeWindow, + }; VkResult result = vkCreateXlibSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); +#endif ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateXlibSurfaceKHR error."); return surface; } diff --git a/filament/backend/src/vulkan/PlatformVkLinux.h b/filament/backend/src/vulkan/PlatformVkLinux.h index fbbc07d757..c112ecd628 100644 --- a/filament/backend/src/vulkan/PlatformVkLinux.h +++ b/filament/backend/src/vulkan/PlatformVkLinux.h @@ -22,7 +22,11 @@ #include #include "VulkanPlatform.h" +#ifdef FILAMENT_SUPPORTS_XCB +#include +#else #include +#endif namespace filament { @@ -36,7 +40,11 @@ public: int getOSVersion() const noexcept override { return 0; } private: +#ifdef FILAMENT_SUPPORTS_XCB + xcb_connection_t* mConnection; +#else Display* mDisplay; +#endif }; } // namespace filament diff --git a/libs/bluevk/include/vulkan/vk_platform.h b/libs/bluevk/include/vulkan/vk_platform.h index 830b8e780e..4bfd1f0c1a 100644 --- a/libs/bluevk/include/vulkan/vk_platform.h +++ b/libs/bluevk/include/vulkan/vk_platform.h @@ -26,7 +26,11 @@ #elif defined(IOS) #define VK_USE_PLATFORM_IOS_MVK 1 #elif defined(__linux__) +#if defined(FILAMENT_SUPPORTS_XCB) +#define VK_USE_PLATFORM_XCB_KHR 1 +#else #define VK_USE_PLATFORM_XLIB_KHR 1 +#endif #elif defined(__APPLE__) #define VK_USE_PLATFORM_MACOS_MVK 1 #elif defined(WIN32)