[Bf-blender-cvs] [e58e023e1a3] master: GHOST/Wayland: support dynamic loading libraries for Wayland

Campbell Barton noreply at git.blender.org
Wed Jul 6 07:30:56 CEST 2022


Commit: e58e023e1a3e10f4ff2557aedcd730b5dba23579
Author: Campbell Barton
Date:   Tue Jul 5 14:49:36 2022 +1000
Branches: master
https://developer.blender.org/rBe58e023e1a3e10f4ff2557aedcd730b5dba23579

GHOST/Wayland: support dynamic loading libraries for Wayland

Add intern/wayland_dynload which is used when WITH_GHOST_WAYLAND_DYNLOAD
is enabled (off by default). When enabled, systems without Wayland
installed will fall back to X11.

This allows Blender to dynamically load:
- libwayland-client
- libwayland-cursor
- libwayland-egl
- libdecor-0 (when WITH_GHOST_WAYLAND_LIBDECOR is enabled).

===================================================================

M	CMakeLists.txt
M	build_files/cmake/platform/platform_unix.cmake
M	intern/CMakeLists.txt
M	intern/ghost/CMakeLists.txt
M	intern/ghost/intern/GHOST_ISystem.cpp
M	intern/ghost/intern/GHOST_SystemWayland.cpp
M	intern/ghost/intern/GHOST_SystemWayland.h
M	intern/ghost/intern/GHOST_WindowWayland.cpp
A	intern/wayland_dynload/CMakeLists.txt
A	intern/wayland_dynload/extern/wayland_dynload_API.h
A	intern/wayland_dynload/extern/wayland_dynload_client.h
A	intern/wayland_dynload/extern/wayland_dynload_cursor.h
A	intern/wayland_dynload/extern/wayland_dynload_egl.h
A	intern/wayland_dynload/extern/wayland_dynload_libdecor.h
A	intern/wayland_dynload/intern/wayland_dynload_client.c
A	intern/wayland_dynload/intern/wayland_dynload_cursor.c
A	intern/wayland_dynload/intern/wayland_dynload_egl.c
A	intern/wayland_dynload/intern/wayland_dynload_libdecor.c
A	intern/wayland_dynload/intern/wayland_dynload_utils.c
A	intern/wayland_dynload/intern/wayland_dynload_utils.h

===================================================================

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b2b8c56001b..1416b5b4189 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -229,6 +229,9 @@ if(UNIX AND NOT (APPLE OR HAIKU))
 
     option(WITH_GHOST_WAYLAND_DBUS "Optionally build with DBUS support (used for Cursor themes). May hang on startup systems where DBUS is not used." OFF)
     mark_as_advanced(WITH_GHOST_WAYLAND_DBUS)
+
+    option(WITH_GHOST_WAYLAND_DYNLOAD  "Enable runtime dynamic WAYLAND libraries loading" OFF)
+    mark_as_advanced(WITH_GHOST_WAYLAND_DYNLOAD)
   endif()
 endif()
 
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake
index dff860d9876..4b654420531 100644
--- a/build_files/cmake/platform/platform_unix.cmake
+++ b/build_files/cmake/platform/platform_unix.cmake
@@ -641,12 +641,17 @@ if(WITH_GHOST_WAYLAND)
   endif()
 
   list(APPEND PLATFORM_LINKLIBS
-    ${wayland-client_LINK_LIBRARIES}
-    ${wayland-egl_LINK_LIBRARIES}
     ${xkbcommon_LINK_LIBRARIES}
-    ${wayland-cursor_LINK_LIBRARIES}
   )
 
+  if(NOT WITH_GHOST_WAYLAND_DYNLOAD)
+    list(APPEND PLATFORM_LINKLIBS
+      ${wayland-client_LINK_LIBRARIES}
+      ${wayland-egl_LINK_LIBRARIES}
+      ${wayland-cursor_LINK_LIBRARIES}
+    )
+  endif()
+
   if(WITH_GHOST_WAYLAND_DBUS)
     list(APPEND PLATFORM_LINKLIBS
       ${dbus_LINK_LIBRARIES}
@@ -655,9 +660,11 @@ if(WITH_GHOST_WAYLAND)
   endif()
 
   if(WITH_GHOST_WAYLAND_LIBDECOR)
-    list(APPEND PLATFORM_LINKLIBS
-      ${libdecor_LIBRARIES}
-    )
+    if(NOT WITH_GHOST_WAYLAND_DYNLOAD)
+      list(APPEND PLATFORM_LINKLIBS
+        ${libdecor_LIBRARIES}
+      )
+    endif()
     add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR)
   endif()
 endif()
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index 2ff2fb39806..6387fd016ba 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -67,3 +67,10 @@ endif()
 if(UNIX AND NOT APPLE)
   add_subdirectory(libc_compat)
 endif()
+
+if(UNIX AND NOT APPLE)
+  # Important this comes after "ghost" as it uses includes defined by GHOST's CMake.
+  if(WITH_GHOST_WAYLAND AND WITH_GHOST_WAYLAND_DYNLOAD)
+    add_subdirectory(wayland_dynload)
+  endif()
+endif()
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 6a11d00cbc4..0203c5ecf5d 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -270,6 +270,16 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
       ${wayland-cursor_INCLUDE_DIRS}
     )
 
+    if(WITH_GHOST_WAYLAND_DYNLOAD)
+      list(APPEND INC_SYS
+        ../../intern/wayland_dynload/extern
+      )
+      list(APPEND LIB
+        bf_intern_wayland_dynload
+      )
+      add_definitions(-DWITH_GHOST_WAYLAND_DYNLOAD)
+    endif()
+
     if(WITH_GHOST_WAYLAND_DBUS)
       list(APPEND INC_SYS
         ${dbus_INCLUDE_DIRS}
diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp
index 745d5faeed4..4f6a9531077 100644
--- a/intern/ghost/intern/GHOST_ISystem.cpp
+++ b/intern/ghost/intern/GHOST_ISystem.cpp
@@ -37,12 +37,23 @@ GHOST_TSuccess GHOST_ISystem::createSystem()
 {
   GHOST_TSuccess success;
   if (!m_system) {
+
+#if defined(WITH_HEADLESS)
+    /* Pass. */
+#elif defined(WITH_GHOST_WAYLAND)
+#  if defined(WITH_GHOST_WAYLAND_DYNLOAD)
+    const bool has_wayland_libraries = ghost_wl_dynload_libraries();
+#  else
+    const bool has_wayland_libraries = true;
+#  endif
+#endif
+
 #if defined(WITH_HEADLESS)
     m_system = new GHOST_SystemNULL();
 #elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND)
     /* Special case, try Wayland, fall back to X11. */
     try {
-      m_system = new GHOST_SystemWayland();
+      m_system = has_wayland_libraries ? new GHOST_SystemWayland() : nullptr;
     }
     catch (const std::runtime_error &) {
       /* fallback to X11. */
@@ -55,7 +66,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem()
 #elif defined(WITH_GHOST_X11)
     m_system = new GHOST_SystemX11();
 #elif defined(WITH_GHOST_WAYLAND)
-    m_system = new GHOST_SystemWayland();
+    m_system = has_wayland_libraries ? new GHOST_SystemWayland() : nullptr;
 #elif defined(WITH_GHOST_SDL)
     m_system = new GHOST_SystemSDL();
 #elif defined(WIN32)
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 8cd3476c4d6..98526eb0bc6 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -16,7 +16,15 @@
 
 #include "GHOST_ContextEGL.h"
 
+#ifdef WITH_GHOST_WAYLAND_DYNLOAD
+#  include <wayland_dynload_API.h> /* For `ghost_wl_dynload_libraries`. */
+#endif
+
 #include <EGL/egl.h>
+
+#ifdef WITH_GHOST_WAYLAND_DYNLOAD
+#  include <wayland_dynload_egl.h>
+#endif
 #include <wayland-egl.h>
 
 #include <algorithm>
@@ -26,6 +34,9 @@
 #include <unordered_map>
 #include <unordered_set>
 
+#ifdef WITH_GHOST_WAYLAND_DYNLOAD
+#  include <wayland_dynload_cursor.h>
+#endif
 #include <wayland-cursor.h>
 
 #include "GHOST_WaylandCursorSettings.h"
@@ -3614,4 +3625,35 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
   return GHOST_kSuccess;
 }
 
+#ifdef WITH_GHOST_WAYLAND_DYNLOAD
+bool ghost_wl_dynload_libraries()
+{
+  /* Only report when `libwayland-client` is not found when building without X11,
+   * which will be used as a fallback. */
+#  ifdef WITH_GHOST_X11
+  bool verbose = false;
+#  else
+  bool verbose = true;
+#  endif
+
+  if (wayland_dynload_client_init(verbose) && /* `libwayland-client`. */
+      wayland_dynload_cursor_init(verbose) && /* `libwayland-cursor`. */
+      wayland_dynload_egl_init(verbose) &&    /* `libwayland-egl`. */
+#  ifdef WITH_GHOST_WAYLAND_LIBDECOR
+      wayland_dynload_libdecor_init(verbose) && /* `libdecor-0`. */
+#  endif
+      true) {
+    return true;
+  }
+#  ifdef WITH_GHOST_WAYLAND_LIBDECOR
+  wayland_dynload_libdecor_exit();
+#  endif
+  wayland_dynload_client_exit();
+  wayland_dynload_cursor_exit();
+  wayland_dynload_egl_exit();
+
+  return false;
+}
+#endif /* WITH_GHOST_WAYLAND_DYNLOAD */
+
 /** \} */
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index e336b02ec9e..e40448ff20b 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -11,9 +11,15 @@
 #include "GHOST_System.h"
 #include "GHOST_WindowWayland.h"
 
+#ifdef WITH_GHOST_WAYLAND_DYNLOAD
+#  include <wayland_dynload_client.h>
+#endif
 #include <wayland-client.h>
 
 #ifdef WITH_GHOST_WAYLAND_LIBDECOR
+#  ifdef WITH_GHOST_WAYLAND_DYNLOAD
+#    include <wayland_dynload_libdecor.h>
+#  endif
 #  include <libdecor.h>
 #else
 /* Generated by `wayland-scanner`. */
@@ -35,6 +41,14 @@ bool ghost_wl_surface_own(const struct wl_surface *surface);
 void ghost_wl_surface_tag(struct wl_surface *surface);
 GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *surface);
 
+#ifdef WITH_GHOST_WAYLAND_DYNLOAD
+/**
+ * Return true when all required WAYLAND libraries are present,
+ * Performs dynamic loading when `WITH_GHOST_WAYLAND_DYNLOAD` is in use.
+ */
+bool ghost_wl_dynload_libraries();
+#endif
+
 struct output_t {
   struct wl_output *wl_output = nullptr;
   struct zxdg_output_v1 *xdg_output = nullptr;
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index d26dfe0e7e6..77eddbb13a5 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -15,11 +15,18 @@
 #include "GHOST_ContextNone.h"
 
 #include <wayland-client-protocol.h>
+
+#ifdef WITH_GHOST_WAYLAND_DYNLOAD
+#  include <wayland_dynload_egl.h>
+#endif
 #include <wayland-egl.h>
 
 #include <algorithm> /* For `std::find`. */
 
 #ifdef WITH_GHOST_WAYLAND_LIBDECOR
+#  ifdef WITH_GHOST_WAYLAND_DYNLOAD
+#    include <wayland_dynload_libdecor.h>
+#  endif
 #  include <libdecor.h>
 #endif
 
@@ -347,7 +354,7 @@ static void surface_handle_leave(void *data,
   }
 }
 
-struct wl_surface_listener wl_surface_listener = {
+static struct wl_surface_listener wl_surface_listener = {
     surface_handle_enter,
     surface_handle_leave,
 };
diff --git a/intern/wayland_dynload/CMakeLists.txt b/intern/wayland_dynload/CMakeLists.txt
new file mode 100644
index 00000000000..2b1a6370126
--- /dev/null
+++ b/intern/wayland_dynload/CMakeLists.txt
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+set(INC
+  extern
+
+  # For internal includes.
+  intern
+)
+
+set(INC_SYS
+  ${wayland-client_INCLUDE_DIRS}
+  ${wayland-egl_INCLUDE_DIRS}
+  ${wayland-cursor_INCLUDE_DIRS}
+)
+
+set(SRC
+  intern/wayland_dynload_client.c
+  intern/wayland_dynload_cursor.c
+  intern/wayland_dynload_egl.c
+  intern/wayland_dynload_utils.c
+
+  extern/wayland_dynload_API.h
+  extern/wayland_dynload_client.h
+  extern/wayland_dynload_cursor.h
+  extern/wayland_dynload_egl.h
+  intern/wayland_dynload_utils.h
+)
+
+if(WITH_GHOST_WAYLAND_LIBDECOR)
+  list(APPEND INC_SYS
+    ${libdecor_INCLUDE_DIRS}
+  )
+  list(APPEND SRC
+    intern/wayland_dynload_libdecor.c
+
+    extern/wayland_dynload_libdecor.h
+  )
+endif()
+
+set(LIB
+)
+
+
+blender_add_lib(bf_intern_wayland_dynload "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/intern/wayland_dynload/extern/wayland_dynload_API.h b/intern/wayland_dynload/extern/wayland_dynload_API.h
new file mode 100644
index 00000000000..07ff00b5a76
--- /dev/null
+++ b/intern/wayland_dynload/extern/wayland_dynload_API.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup intern_wayland_dynload
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+bool wayland_dynload_client_init(bool verbose);
+void wayland_dynload_client_exit(void);
+
+bool wayland_dynload_cursor_init(bool verbose);
+void wayland_dynload_cursor_exit(void);
+
+bool wayland_dynload_egl_init(bool verbose);
+void wayland_dynload_egl_exit(void);
+
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+bool wayland_dynload_libdecor_init(bool verbose);
+void wayland_dynload_libdecor_exit(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/intern/wayland_dynload/extern/wayland_dynload_client.h b/intern/wayland_dynload/extern/wayland_dynload_client.h
new file mode

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list