diff --git a/CMakeLists.txt b/CMakeLists.txt index 11345d35e5..7dd3c71ba8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,10 @@ option(FILAMENT_ENABLE_LTO "Enable link-time optimizations if supported by the c option(FILAMENT_SKIP_SAMPLES "Don't build samples" OFF) +option(FILAMENT_SUPPORTS_XCB "Include XCB support in Linux builds" ON) + +option(FILAMENT_SUPPORTS_XLIB "Include XLIB support in Linux builds" ON) + set(FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB "2" CACHE STRING "Per render pass arena size. Must be roughly 1 MB larger than FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB, default 2." ) @@ -84,6 +88,15 @@ if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT WEBGL) endif() if (LINUX) + + if (FILAMENT_SUPPORTS_XCB) + add_definitions(-DFILAMENT_SUPPORTS_XCB) + endif() + + if (FILAMENT_SUPPORTS_XLIB) + add_definitions(-DFILAMENT_SUPPORTS_XLIB) + endif() + execute_process(COMMAND uname -p OUTPUT_VARIABLE PROCESSOR_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE diff --git a/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java b/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java index 3f16a81172..96821515fc 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java +++ b/android/filament-android/src/main/java/com/google/android/filament/SwapChain.java @@ -85,6 +85,12 @@ public class SwapChain { */ public static final long CONFIG_READABLE = 0x2; + /** + * Indicates that the native X11 window is an XCB window rather than an XLIB window. + * This is ignored on non-Linux platforms and in builds that support only one X11 API. + */ + public static final long CONFIG_ENABLE_XCB = 0x4; + SwapChain(long nativeSwapChain, Object surface) { mNativeObject = nativeSwapChain; mSurface = surface; diff --git a/filament/backend/include/backend/DriverEnums.h b/filament/backend/include/backend/DriverEnums.h index cb17bdf010..b951756650 100644 --- a/filament/backend/include/backend/DriverEnums.h +++ b/filament/backend/include/backend/DriverEnums.h @@ -41,6 +41,7 @@ namespace backend { static constexpr uint64_t SWAP_CHAIN_CONFIG_TRANSPARENT = 0x1; static constexpr uint64_t SWAP_CHAIN_CONFIG_READABLE = 0x2; +static constexpr uint64_t SWAP_CHAIN_CONFIG_ENABLE_XCB = 0x4; static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES. static constexpr size_t MAX_SAMPLER_COUNT = 16; // Matches the Adreno Vulkan driver. diff --git a/filament/backend/src/vulkan/PlatformVkAndroid.cpp b/filament/backend/src/vulkan/PlatformVkAndroid.cpp index 273e32dc31..409199232a 100644 --- a/filament/backend/src/vulkan/PlatformVkAndroid.cpp +++ b/filament/backend/src/vulkan/PlatformVkAndroid.cpp @@ -47,7 +47,7 @@ Driver* PlatformVkAndroid::createDriver(void* const sharedContext) noexcept { sizeof(requiredInstanceExtensions) / sizeof(requiredInstanceExtensions[0])); } -void* PlatformVkAndroid::createVkSurfaceKHR(void* nativeWindow, void* vkinstance) noexcept { +void* PlatformVkAndroid::createVkSurfaceKHR(void* nativeWindow, void* vkinstance, uint64_t flags) noexcept { const VkInstance instance = (VkInstance) vkinstance; ANativeWindow* aNativeWindow = (ANativeWindow*) nativeWindow; VkAndroidSurfaceCreateInfoKHR createInfo { diff --git a/filament/backend/src/vulkan/PlatformVkAndroid.h b/filament/backend/src/vulkan/PlatformVkAndroid.h index c8fa312740..a7ee6de47c 100644 --- a/filament/backend/src/vulkan/PlatformVkAndroid.h +++ b/filament/backend/src/vulkan/PlatformVkAndroid.h @@ -29,7 +29,7 @@ public: backend::Driver* createDriver(void* const sharedContext) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept override; + void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } }; diff --git a/filament/backend/src/vulkan/PlatformVkCocoa.h b/filament/backend/src/vulkan/PlatformVkCocoa.h index 3309e2121e..ea5956e050 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoa.h +++ b/filament/backend/src/vulkan/PlatformVkCocoa.h @@ -27,7 +27,7 @@ namespace filament { class PlatformVkCocoa final : public backend::VulkanPlatform { public: backend::Driver* createDriver(void* sharedContext) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept override; + void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } }; diff --git a/filament/backend/src/vulkan/PlatformVkCocoa.mm b/filament/backend/src/vulkan/PlatformVkCocoa.mm index 91a3ff9118..b488df2117 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoa.mm +++ b/filament/backend/src/vulkan/PlatformVkCocoa.mm @@ -51,7 +51,7 @@ Driver* PlatformVkCocoa::createDriver(void* sharedContext) noexcept { sizeof(requiredInstanceExtensions) / sizeof(requiredInstanceExtensions[0])); } -void* PlatformVkCocoa::createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept { +void* PlatformVkCocoa::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { // Obtain the CAMetalLayer-backed view. NSView* nsview = (__bridge NSView*) nativeWindow; ASSERT_POSTCONDITION(nsview, "Unable to obtain Metal-backed NSView."); diff --git a/filament/backend/src/vulkan/PlatformVkCocoaTouch.h b/filament/backend/src/vulkan/PlatformVkCocoaTouch.h index d2242b6276..b4be989420 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoaTouch.h +++ b/filament/backend/src/vulkan/PlatformVkCocoaTouch.h @@ -27,7 +27,7 @@ namespace filament { class PlatformVkCocoaTouch final : public backend::VulkanPlatform { public: backend::Driver* createDriver(void* const sharedContext) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept override; + void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } }; diff --git a/filament/backend/src/vulkan/PlatformVkCocoaTouch.mm b/filament/backend/src/vulkan/PlatformVkCocoaTouch.mm index f73ac70ece..d32c2a6872 100644 --- a/filament/backend/src/vulkan/PlatformVkCocoaTouch.mm +++ b/filament/backend/src/vulkan/PlatformVkCocoaTouch.mm @@ -46,7 +46,7 @@ Driver* PlatformVkCocoaTouch::createDriver(void* const sharedContext) noexcept { sizeof(requestedExtensions) / sizeof(requestedExtensions[0])); } -void* PlatformVkCocoaTouch::createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept { +void* PlatformVkCocoaTouch::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { #if METAL_AVAILABLE CAMetalLayer* metalLayer = (CAMetalLayer*) nativeWindow; diff --git a/filament/backend/src/vulkan/PlatformVkLinux.cpp b/filament/backend/src/vulkan/PlatformVkLinux.cpp index 94e89b3e5a..f1d61f7ea8 100644 --- a/filament/backend/src/vulkan/PlatformVkLinux.cpp +++ b/filament/backend/src/vulkan/PlatformVkLinux.cpp @@ -36,14 +36,18 @@ 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 +#endif + +#ifdef FILAMENT_SUPPORTS_XLIB typedef Display* (*X11_OPEN_DISPLAY)(const char*); #endif struct X11Functions { #ifdef FILAMENT_SUPPORTS_XCB XCB_CONNECT xcbConnect; -#else +#endif + +#ifdef FILAMENT_SUPPORTS_XLIB X11_OPEN_DISPLAY openDisplay; #endif void* library = nullptr; @@ -55,7 +59,8 @@ Driver* PlatformVkLinux::createDriver(void* const sharedContext) noexcept { "VK_KHR_surface", #ifdef FILAMENT_SUPPORTS_XCB "VK_KHR_xcb_surface", -#else +#endif +#ifdef FILAMENT_SUPPORTS_XLIB "VK_KHR_xlib_surface", #endif "VK_KHR_get_physical_device_properties2", @@ -67,42 +72,57 @@ Driver* PlatformVkLinux::createDriver(void* const sharedContext) noexcept { sizeof(requiredInstanceExtensions) / sizeof(requiredInstanceExtensions[0])); } -void* PlatformVkLinux::createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept { -#ifdef FILAMENT_SUPPORTS_XCB +void* PlatformVkLinux::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { 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."); + +#ifdef FILAMENT_SUPPORTS_XCB 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."); + ASSERT_POSTCONDITION(vkCreateXcbSurfaceKHR, "Unable to load vkCreateXcbSurfaceKHR function."); +#endif + +#ifdef FILAMENT_SUPPORTS_XLIB g_x11.openDisplay = (X11_OPEN_DISPLAY) dlsym(g_x11.library, "XOpenDisplay"); mDisplay = g_x11.openDisplay(NULL); ASSERT_PRECONDITION(mDisplay, "Unable to open X11 display."); + ASSERT_POSTCONDITION(vkCreateXlibSurfaceKHR, "Unable to load vkCreateXlibSurfaceKHR function."); +#endif + } - ASSERT_POSTCONDITION(vkCreateXlibSurfaceKHR, "Unable to load vkCreateXlibSurfaceKHR function."); + VkSurfaceKHR surface = nullptr; + +#ifdef FILAMENT_SUPPORTS_XCB +#ifdef FILAMENT_SUPPORTS_XLIB +const bool windowIsXCB = flags & SWAP_CHAIN_CONFIG_ENABLE_XCB; +#else +const bool windowIsXCB = true; +#endif + + if (windowIsXCB) { + 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, + }; + vkCreateXcbSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); + return surface; + } +#endif + +#ifdef FILAMENT_SUPPORTS_XLIB VkXlibSurfaceCreateInfoKHR createInfo = { .sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, .dpy = mDisplay, .window = (Window) nativeWindow, }; - VkResult result = vkCreateXlibSurfaceKHR((VkInstance) instance, &createInfo, VKALLOC, &surface); + 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 c112ecd628..8dde97bc73 100644 --- a/filament/backend/src/vulkan/PlatformVkLinux.h +++ b/filament/backend/src/vulkan/PlatformVkLinux.h @@ -24,7 +24,9 @@ #ifdef FILAMENT_SUPPORTS_XCB #include -#else +#endif + +#ifdef FILAMENT_SUPPORTS_XLIB #include #endif @@ -35,14 +37,15 @@ public: backend::Driver* createDriver(void* const sharedContext) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept override; + void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } private: #ifdef FILAMENT_SUPPORTS_XCB xcb_connection_t* mConnection; -#else +#endif +#ifdef FILAMENT_SUPPORTS_XLIB Display* mDisplay; #endif }; diff --git a/filament/backend/src/vulkan/PlatformVkWindows.cpp b/filament/backend/src/vulkan/PlatformVkWindows.cpp index e5a168304f..a38b05075d 100644 --- a/filament/backend/src/vulkan/PlatformVkWindows.cpp +++ b/filament/backend/src/vulkan/PlatformVkWindows.cpp @@ -40,7 +40,7 @@ Driver* PlatformVkWindows::createDriver(void* const sharedContext) noexcept { sizeof(requiredInstanceExtensions) / sizeof(requiredInstanceExtensions[0])); } -void* PlatformVkWindows::createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept { +void* PlatformVkWindows::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept { VkSurfaceKHR surface = nullptr; HWND window = (HWND) nativeWindow; diff --git a/filament/backend/src/vulkan/PlatformVkWindows.h b/filament/backend/src/vulkan/PlatformVkWindows.h index dfc7f84493..335bda8327 100644 --- a/filament/backend/src/vulkan/PlatformVkWindows.h +++ b/filament/backend/src/vulkan/PlatformVkWindows.h @@ -29,7 +29,7 @@ public: backend::Driver* createDriver(void* const sharedContext) noexcept override; - void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept override; + void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override; int getOSVersion() const noexcept override { return 0; } diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index 8c032195cf..419246b81c 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -559,7 +559,8 @@ void VulkanDriver::createSyncR(Handle sh, int) { void VulkanDriver::createSwapChainR(Handle sch, void* nativeWindow, uint64_t flags) { const VkInstance instance = mContext.instance; - auto vksurface = (VkSurfaceKHR) mContextManager.createVkSurfaceKHR(nativeWindow, instance); + auto vksurface = (VkSurfaceKHR) mContextManager.createVkSurfaceKHR(nativeWindow, instance, + flags); auto* swapChain = construct_handle(mHandleMap, sch, mContext, vksurface); // TODO: move the following line into makeCurrent. diff --git a/filament/backend/src/vulkan/VulkanPlatform.h b/filament/backend/src/vulkan/VulkanPlatform.h index daa32da03f..0d560dcffa 100644 --- a/filament/backend/src/vulkan/VulkanPlatform.h +++ b/filament/backend/src/vulkan/VulkanPlatform.h @@ -43,7 +43,7 @@ namespace backend { class VulkanPlatform : public DefaultPlatform { public: // Given a Vulkan instance and native window handle, creates the platform-specific surface. - virtual void* createVkSurfaceKHR(void* nativeWindow, void* instance) noexcept = 0; + virtual void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept = 0; ~VulkanPlatform() override; }; diff --git a/filament/include/filament/SwapChain.h b/filament/include/filament/SwapChain.h index 61470c0c5d..6ebd331134 100644 --- a/filament/include/filament/SwapChain.h +++ b/filament/include/filament/SwapChain.h @@ -153,6 +153,12 @@ public: */ static const uint64_t CONFIG_READABLE = backend::SWAP_CHAIN_CONFIG_READABLE; + /** + * Indicates that the native X11 window is an XCB window rather than an XLIB window. + * This is ignored on non-Linux platforms and in builds that support only one X11 API. + */ + static const uint64_t CONFIG_ENABLE_XCB = backend::SWAP_CHAIN_CONFIG_ENABLE_XCB; + void* getNativeWindow() const noexcept; }; diff --git a/libs/bluevk/include/vulkan/vk_platform.h b/libs/bluevk/include/vulkan/vk_platform.h index 4bfd1f0c1a..e8dc718721 100644 --- a/libs/bluevk/include/vulkan/vk_platform.h +++ b/libs/bluevk/include/vulkan/vk_platform.h @@ -28,7 +28,8 @@ #elif defined(__linux__) #if defined(FILAMENT_SUPPORTS_XCB) #define VK_USE_PLATFORM_XCB_KHR 1 -#else +#endif +#if defined(FILAMENT_SUPPORTS_XLIB) #define VK_USE_PLATFORM_XLIB_KHR 1 #endif #elif defined(__APPLE__)