Ver Fonte

Merge pull request #97771 from dsnopek/openxr-linux-egl

OpenXR: Add support for Wayland on Linux
Thaddeus Crews há 10 meses atrás
pai
commit
07e759b74a

+ 1 - 1
.github/workflows/linux_builds.yml

@@ -106,7 +106,7 @@ jobs:
       # TODO: Figure out somehow how to embed this one.
       - name: wayland-scanner dependency
         run: |
-          sudo apt-get install libwayland-bin
+          sudo apt-get install libwayland-bin libegl-dev
 
       - name: Free disk space on runner
         run: |

+ 13 - 0
doc/classes/DisplayServer.xml

@@ -2152,12 +2152,14 @@
 		<constant name="DISPLAY_HANDLE" value="0" enum="HandleType">
 			Display handle:
 			- Linux (X11): [code]X11::Display*[/code] for the display.
+			- Linux (Wayland): [code]wl_display[/code] for the display.
 			- Android: [code]EGLDisplay[/code] for the display.
 		</constant>
 		<constant name="WINDOW_HANDLE" value="1" enum="HandleType">
 			Window handle:
 			- Windows: [code]HWND[/code] for the window.
 			- Linux (X11): [code]X11::Window*[/code] for the window.
+			- Linux (Wayland): [code]wl_surface[/code] for the window.
 			- macOS: [code]NSWindow*[/code] for the window.
 			- iOS: [code]UIViewController*[/code] for the view controller.
 			- Android: [code]jObject[/code] for the activity.
@@ -2172,9 +2174,20 @@
 			OpenGL context (only with the GL Compatibility renderer):
 			- Windows: [code]HGLRC[/code] for the window (native GL), or [code]EGLContext[/code] for the window (ANGLE).
 			- Linux (X11): [code]GLXContext*[/code] for the window.
+			- Linux (Wayland): [code]EGLContext[/code] for the window.
 			- macOS: [code]NSOpenGLContext*[/code] for the window (native GL), or [code]EGLContext[/code] for the window (ANGLE).
 			- Android: [code]EGLContext[/code] for the window.
 		</constant>
+		<constant name="EGL_DISPLAY" value="4" enum="HandleType">
+			- Windows: [code]EGLDisplay[/code] for the window (ANGLE).
+			- macOS: [code]EGLDisplay[/code] for the window (ANGLE).
+			- Linux (Wayland): [code]EGLDisplay[/code] for the window.
+		</constant>
+		<constant name="EGL_CONFIG" value="5" enum="HandleType">
+			- Windows: [code]EGLConfig[/code] for the window (ANGLE).
+			- macOS: [code]EGLConfig[/code] for the window (ANGLE).
+			- Linux (Wayland): [code]EGLConfig[/code] for the window.
+		</constant>
 		<constant name="TTS_UTTERANCE_STARTED" value="0" enum="TTSUtteranceEvent">
 			Utterance has begun to be spoken.
 		</constant>

+ 24 - 0
drivers/egl/egl_manager.cpp

@@ -414,6 +414,30 @@ EGLContext EGLManager::get_context(DisplayServer::WindowID p_window_id) {
 	return display.egl_context;
 }
 
+EGLDisplay EGLManager::get_display(DisplayServer::WindowID p_window_id) {
+	GLWindow &glwindow = windows[p_window_id];
+
+	if (!glwindow.initialized) {
+		return EGL_NO_CONTEXT;
+	}
+
+	GLDisplay &display = displays[glwindow.gldisplay_id];
+
+	return display.egl_display;
+}
+
+EGLConfig EGLManager::get_config(DisplayServer::WindowID p_window_id) {
+	GLWindow &glwindow = windows[p_window_id];
+
+	if (!glwindow.initialized) {
+		return nullptr;
+	}
+
+	GLDisplay &display = displays[glwindow.gldisplay_id];
+
+	return display.egl_config;
+}
+
 Error EGLManager::initialize(void *p_native_display) {
 #if defined(GLAD_ENABLED) && !defined(EGL_STATIC)
 	// Loading EGL with a new display gets us just the bare minimum API. We'll then

+ 2 - 0
drivers/egl/egl_manager.h

@@ -113,6 +113,8 @@ public:
 	bool is_using_vsync() const;
 
 	EGLContext get_context(DisplayServer::WindowID p_window_id);
+	EGLDisplay get_display(DisplayServer::WindowID p_window_id);
+	EGLConfig get_config(DisplayServer::WindowID p_window_id);
 
 	Error initialize(void *p_native_display = nullptr);
 

+ 1 - 1
modules/openxr/SCsub

@@ -26,7 +26,7 @@ elif env["platform"] == "linuxbsd":
         env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_XLIB"])
 
     if env["wayland"]:
-        env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_WAYLAND"])
+        env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_EGL"])
 
     # FIXME: Review what needs to be set for Android and macOS.
     env_openxr.AppendUnique(CPPDEFINES=["HAVE_SECURE_GETENV"])

+ 31 - 6
modules/openxr/extensions/platform/openxr_opengl_extension.cpp

@@ -64,6 +64,9 @@ HashMap<String, bool *> OpenXROpenGLExtension::get_requested_extensions() {
 #else
 	request_extensions[XR_KHR_OPENGL_ENABLE_EXTENSION_NAME] = nullptr;
 #endif
+#if defined(LINUXBSD_ENABLED) && defined(EGL_ENABLED)
+	request_extensions[XR_MNDX_EGL_ENABLE_EXTENSION_NAME] = &egl_extension_enabled;
+#endif
 
 	return request_extensions;
 }
@@ -128,9 +131,14 @@ bool OpenXROpenGLExtension::check_graphics_api_support(XrVersion p_desired_versi
 XrGraphicsBindingOpenGLWin32KHR OpenXROpenGLExtension::graphics_binding_gl;
 #elif defined(ANDROID_ENABLED)
 XrGraphicsBindingOpenGLESAndroidKHR OpenXROpenGLExtension::graphics_binding_gl;
-#elif defined(X11_ENABLED)
+#elif defined(LINUXBSD_ENABLED)
+#ifdef X11_ENABLED
 XrGraphicsBindingOpenGLXlibKHR OpenXROpenGLExtension::graphics_binding_gl;
 #endif
+#ifdef EGL_ENABLED
+XrGraphicsBindingEGLMNDX OpenXROpenGLExtension::graphics_binding_egl;
+#endif
+#endif
 
 void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_next_pointer) {
 	XrVersion desired_version = XR_MAKE_VERSION(3, 3, 0);
@@ -142,10 +150,6 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex
 
 	DisplayServer *display_server = DisplayServer::get_singleton();
 
-#ifdef WAYLAND_ENABLED
-	ERR_FAIL_COND_V_MSG(display_server->get_name() == "Wayland", p_next_pointer, "OpenXR is not yet supported on OpenGL Wayland.");
-#endif
-
 #ifdef WIN32
 	graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR,
 	graphics_binding_gl.next = p_next_pointer;
@@ -159,7 +163,23 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex
 	graphics_binding_gl.display = (void *)display_server->window_get_native_handle(DisplayServer::DISPLAY_HANDLE);
 	graphics_binding_gl.config = (EGLConfig)0; // https://github.com/KhronosGroup/OpenXR-SDK-Source/blob/master/src/tests/hello_xr/graphicsplugin_opengles.cpp#L122
 	graphics_binding_gl.context = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT);
-#elif defined(X11_ENABLED)
+#else
+#if defined(EGL_ENABLED) && defined(WAYLAND_ENABLED)
+	if (display_server->get_name() == "Wayland") {
+		ERR_FAIL_COND_V_MSG(!egl_extension_enabled, p_next_pointer, "OpenXR cannot initialize on Wayland without the XR_MNDX_egl_enable extension.");
+
+		graphics_binding_egl.type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX;
+		graphics_binding_egl.next = p_next_pointer;
+
+		graphics_binding_egl.getProcAddress = eglGetProcAddress;
+		graphics_binding_egl.display = (void *)display_server->window_get_native_handle(DisplayServer::EGL_DISPLAY);
+		graphics_binding_egl.config = (void *)display_server->window_get_native_handle(DisplayServer::EGL_CONFIG);
+		graphics_binding_egl.context = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT);
+
+		return &graphics_binding_egl;
+	}
+#endif
+#if defined(X11_ENABLED)
 	graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
 	graphics_binding_gl.next = p_next_pointer;
 
@@ -175,8 +195,13 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex
 	graphics_binding_gl.visualid = 0;
 	graphics_binding_gl.glxFBConfig = 0;
 #endif
+#endif
 
+#if defined(WIN32) || defined(ANDROID_ENABLED) || defined(X11_ENABLED)
 	return &graphics_binding_gl;
+#else
+	return p_next_pointer;
+#endif
 }
 
 void OpenXROpenGLExtension::get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) {

+ 10 - 1
modules/openxr/extensions/platform/openxr_opengl_extension.h

@@ -64,8 +64,17 @@ private:
 	static XrGraphicsBindingOpenGLWin32KHR graphics_binding_gl;
 #elif defined(ANDROID_ENABLED)
 	static XrGraphicsBindingOpenGLESAndroidKHR graphics_binding_gl;
-#else // Linux/X11
+#elif defined(LINUXBSD_ENABLED)
+#ifdef X11_ENABLED
 	static XrGraphicsBindingOpenGLXlibKHR graphics_binding_gl;
+#endif
+#ifdef EGL_ENABLED
+	static XrGraphicsBindingEGLMNDX graphics_binding_egl;
+
+	bool egl_extension_enabled = false;
+#endif
+#else
+#error "OpenXR with OpenGL isn't supported on this platform"
 #endif
 
 	struct SwapchainGraphicsData {

+ 7 - 0
modules/openxr/openxr_platform_inc.h

@@ -49,6 +49,13 @@
 #else
 #define XR_USE_GRAPHICS_API_OPENGL
 #endif // ANDROID_ENABLED
+#if defined(LINUXBSD_ENABLED) && defined(EGL_ENABLED)
+#ifdef GLAD_ENABLED
+#include "thirdparty/glad/glad/egl.h"
+#else
+#include <EGL/egl.h>
+#endif // GLAD_ENABLED
+#endif // defined(LINUXBSD_ENABLED) && defined(EGL_ENABLED)
 #ifdef X11_ENABLED
 #define GL_GLEXT_PROTOTYPES 1
 #define GL3_PROTOTYPES 1

+ 8 - 0
platform/android/display_server_android.cpp

@@ -389,6 +389,14 @@ int64_t DisplayServerAndroid::window_get_native_handle(HandleType p_handle_type,
 			}
 			return 0;
 		}
+		case EGL_DISPLAY: {
+			// @todo Find a way to get this from the Java side.
+			return 0;
+		}
+		case EGL_CONFIG: {
+			// @todo Find a way to get this from the Java side.
+			return 0;
+		}
 #endif
 		default: {
 			return 0;

+ 12 - 0
platform/linuxbsd/wayland/display_server_wayland.cpp

@@ -627,6 +627,18 @@ int64_t DisplayServerWayland::window_get_native_handle(HandleType p_handle_type,
 			}
 			return 0;
 		} break;
+		case EGL_DISPLAY: {
+			if (egl_manager) {
+				return (int64_t)egl_manager->get_display(p_window);
+			}
+			return 0;
+		}
+		case EGL_CONFIG: {
+			if (egl_manager) {
+				return (int64_t)egl_manager->get_config(p_window);
+			}
+			return 0;
+		}
 #endif // GLES3_ENABLED
 
 		default: {

+ 12 - 0
platform/linuxbsd/x11/display_server_x11.cpp

@@ -1861,6 +1861,18 @@ int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, Win
 			}
 			return 0;
 		}
+		case EGL_DISPLAY: {
+			if (gl_manager_egl) {
+				return (int64_t)gl_manager_egl->get_display(p_window);
+			}
+			return 0;
+		}
+		case EGL_CONFIG: {
+			if (gl_manager_egl) {
+				return (int64_t)gl_manager_egl->get_config(p_window);
+			}
+			return 0;
+		}
 #endif
 		default: {
 			return 0;

+ 12 - 0
platform/macos/display_server_macos.mm

@@ -2676,6 +2676,18 @@ int64_t DisplayServerMacOS::window_get_native_handle(HandleType p_handle_type, W
 			}
 			return 0;
 		}
+		case EGL_DISPLAY: {
+			if (gl_manager_angle) {
+				return (int64_t)gl_manager_angle->get_display(p_window);
+			}
+			return 0;
+		}
+		case EGL_CONFIG: {
+			if (gl_manager_angle) {
+				return (int64_t)gl_manager_angle->get_config(p_window);
+			}
+			return 0;
+		}
 #endif
 		default: {
 			return 0;

+ 12 - 0
platform/windows/display_server_windows.cpp

@@ -1665,6 +1665,18 @@ int64_t DisplayServerWindows::window_get_native_handle(HandleType p_handle_type,
 			}
 			return 0;
 		}
+		case EGL_DISPLAY: {
+			if (gl_manager_angle) {
+				return (int64_t)gl_manager_angle->get_display(p_window);
+			}
+			return 0;
+		}
+		case EGL_CONFIG: {
+			if (gl_manager_angle) {
+				return (int64_t)gl_manager_angle->get_config(p_window);
+			}
+			return 0;
+		}
 #endif
 		default: {
 			return 0;

+ 2 - 0
servers/display_server.cpp

@@ -1149,6 +1149,8 @@ void DisplayServer::_bind_methods() {
 	BIND_ENUM_CONSTANT(WINDOW_HANDLE);
 	BIND_ENUM_CONSTANT(WINDOW_VIEW);
 	BIND_ENUM_CONSTANT(OPENGL_CONTEXT);
+	BIND_ENUM_CONSTANT(EGL_DISPLAY);
+	BIND_ENUM_CONSTANT(EGL_CONFIG);
 
 	BIND_ENUM_CONSTANT(TTS_UTTERANCE_STARTED);
 	BIND_ENUM_CONSTANT(TTS_UTTERANCE_ENDED);

+ 2 - 0
servers/display_server.h

@@ -82,6 +82,8 @@ public:
 		WINDOW_HANDLE,
 		WINDOW_VIEW,
 		OPENGL_CONTEXT,
+		EGL_DISPLAY,
+		EGL_CONFIG,
 	};
 
 	enum Context {