Fixed EGL support for X11

This commit is contained in:
2025-03-23 10:48:45 +08:00
parent 676ef45897
commit 77def2c519

View File

@@ -1,4 +1,4 @@
From d1611b3578c0344a9b08d4981e1357560869ff1f Mon Sep 17 00:00:00 2001
From d4ef511a569ee071a98924a3e7314cc2cd06ec50 Mon Sep 17 00:00:00 2001
From: Sergey Lapin <slapinid@gmail.com>
Date: Thu, 20 Mar 2025 21:49:14 +0300
Subject: [PATCH] Made GLES work on X11
@@ -6,7 +6,7 @@ Subject: [PATCH] Made GLES work on X11
---
core/SCsub | 2 +-
.../gles2/rasterizer_canvas_base_gles2.cpp | 3 +
drivers/gles2/rasterizer_gles2.cpp | 10 +
drivers/gles2/rasterizer_gles2.cpp | 13 +
drivers/gles2/rasterizer_storage_gles2.cpp | 6 +
drivers/gles2/shader_gles2.cpp | 6 +-
modules/denoise/config.py | 2 +-
@@ -17,12 +17,12 @@ Subject: [PATCH] Made GLES work on X11
modules/webm/config.py | 2 +-
modules/webm/libvpx/SCsub | 4 +-
platform/x11es/SCsub | 27 +
platform/x11es/context_gl_x11.cpp | 306 ++
platform/x11es/context_gl_x11.h | 89 +
platform/x11es/context_gl_x11.cpp | 480 ++
platform/x11es/context_gl_x11.h | 101 +
platform/x11es/crash_handler_x11.cpp | 173 +
platform/x11es/crash_handler_x11.h | 47 +
platform/x11es/detect.py | 433 ++
platform/x11es/detect_prime.cpp | 246 +
platform/x11es/detect_prime.cpp | 315 ++
platform/x11es/detect_prime.h | 38 +
platform/x11es/godot_x11.cpp | 83 +
platform/x11es/joypad_linux.cpp | 595 +++
@@ -32,13 +32,13 @@ Subject: [PATCH] Made GLES work on X11
platform/x11es/libudev-so_wrap.c | 829 +++
platform/x11es/libudev-so_wrap.h | 376 ++
platform/x11es/logo.png | Bin 0 -> 1679 bytes
platform/x11es/os_x11.cpp | 4493 +++++++++++++++++
platform/x11es/os_x11.cpp | 4497 +++++++++++++++++
platform/x11es/os_x11.h | 398 ++
platform/x11es/platform_config.h | 49 +
platform/x11es/platform_x11_builders.py | 18 +
platform/x11es/power_x11.cpp | 571 +++
platform/x11es/power_x11.h | 65 +
34 files changed, 11006 insertions(+), 11 deletions(-)
34 files changed, 11268 insertions(+), 11 deletions(-)
create mode 100644 platform/x11es/SCsub
create mode 100644 platform/x11es/context_gl_x11.cpp
create mode 100644 platform/x11es/context_gl_x11.h
@@ -90,24 +90,27 @@ index 8615dc2e64..3abf65732b 100644
#endif
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index c8eb0c7509..cbd11af2de 100644
index c8eb0c7509..4f03728350 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -79,6 +79,9 @@
@@ -79,6 +79,12 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif
+#define EGL
+#ifndef EGL
+#if !defined(OPENGL_ENABLED) && defined(X11_ENABLED)
+#include <GL/glx.h>
+#endif
+#endif
#if defined(MINGW_ENABLED) || defined(_MSC_VER)
#define strcpy strcpy_s
@@ -246,10 +249,17 @@ void RasterizerGLES2::initialize() {
@@ -246,10 +252,17 @@ void RasterizerGLES2::initialize() {
}
#else
if (OS::get_singleton()->is_stdout_verbose()) {
+#ifdef X11_ENABLED
+#if defined(X11_ENABLED) && !defined(EGL)
+ DebugMessageCallbackARB callback = (DebugMessageCallbackARB)glXGetProcAddress((const GLubyte *)"glDebugMessageCallback");
+ if (!callback) {
+ callback = (DebugMessageCallbackARB)glXGetProcAddress((const GLubyte *)"glDebugMessageCallbackKHR");
@@ -315,10 +318,10 @@ index 0000000000..3777596c80
+ env.AddPostAction(prog, run_in_subprocess(platform_x11_builders.make_debug_x11))
diff --git a/platform/x11es/context_gl_x11.cpp b/platform/x11es/context_gl_x11.cpp
new file mode 100644
index 0000000000..ab5d655408
index 0000000000..66e1289f98
--- /dev/null
+++ b/platform/x11es/context_gl_x11.cpp
@@ -0,0 +1,306 @@
@@ -0,0 +1,480 @@
+/**************************************************************************/
+/* context_gl_x11.cpp */
+/**************************************************************************/
@@ -349,6 +352,7 @@ index 0000000000..ab5d655408
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#undef NDEBUG
+#include "context_gl_x11.h"
+
+#ifdef X11_ENABLED
@@ -356,43 +360,81 @@ index 0000000000..ab5d655408
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <cassert>
+
+#ifndef EGL
+#define GLX_GLXEXT_PROTOTYPES
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#else
+#include <EGL/egl.h>
+#endif
+
+#ifndef EGL
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+
+typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
+#endif
+
+struct ContextGL_X11_Private {
+#ifndef EGL
+ ::GLXContext glx_context;
+ ::GLXContext glx_context_offscreen;
+#else
+ EGLDisplay egl_display;
+ EGLSurface egl_surface;
+ EGLContext egl_context;
+ EGLContext egl_context_offscreen;
+#endif
+};
+
+void ContextGL_X11::release_current() {
+#ifndef EGL
+ glXMakeCurrent(x11_display, None, nullptr);
+#else
+ eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+#endif
+}
+
+void ContextGL_X11::make_current() {
+#ifndef EGL
+ glXMakeCurrent(x11_display, x11_window, p->glx_context);
+#else
+ eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, p->egl_context);
+#endif
+}
+
+bool ContextGL_X11::is_offscreen_available() const {
+#ifndef EGL
+ return p->glx_context_offscreen;
+#else
+ return p->egl_context_offscreen;
+#endif
+}
+
+void ContextGL_X11::make_offscreen_current() {
+#ifndef EGL
+ glXMakeCurrent(x11_display, x11_window, p->glx_context_offscreen);
+#else
+ eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, p->egl_context_offscreen);
+#endif
+}
+
+void ContextGL_X11::release_offscreen_current() {
+#ifndef EGL
+ glXMakeCurrent(x11_display, None, NULL);
+#else
+ eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+#endif
+}
+
+void ContextGL_X11::swap_buffers() {
+#ifndef EGL
+ glXSwapBuffers(x11_display, x11_window);
+#else
+ eglSwapBuffers(p->egl_display, p->egl_surface);
+#endif
+}
+
+static bool ctxErrorOccurred = false;
@@ -415,6 +457,7 @@ index 0000000000..ab5d655408
+}
+
+Error ContextGL_X11::initialize() {
+#ifndef EGL
+ //const char *extensions = glXQueryExtensionsString(x11_display, DefaultScreen(x11_display));
+
+ GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte *)"glXCreateContextAttribsARB");
@@ -536,6 +579,107 @@ index 0000000000..ab5d655408
+ glXMakeCurrent(x11_display, x11_window, p->glx_context);
+
+ XFree(vi);
+#else
+ p->egl_display = eglGetDisplay((EGLNativeDisplayType)x11_display);
+ if (p->egl_display == EGL_NO_DISPLAY) {
+ print_error("Got no EGL display.");
+ assert(false);
+ }
+
+ if (!eglInitialize(p->egl_display, &egl_major,
+ &egl_minor)) {
+ print_error("Unable to initialize EGL");
+ assert(false);
+ }
+ print_line("Initialized EGL version " + itos(egl_major) + "." + itos(egl_minor));
+ EGLint egl_config_constraints[] = { EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_NONE };
+ EGLConfig egl_conf;
+ EGLint num_config;
+ if (!eglChooseConfig(p->egl_display, egl_config_constraints, &egl_conf, 1,
+ &num_config)) {
+ print_error("Failed to choose config (eglError: " + itos(eglGetError()) + ")");
+ assert(false);
+ }
+ if (num_config == 0) {
+ print_error("No egl config found");
+ assert(false);
+ }
+ XVisualInfo x11_visual_info_template;
+ if (!eglGetConfigAttrib(p->egl_display,
+ egl_conf,
+ EGL_NATIVE_VISUAL_ID,
+ (EGLint*) &x11_visual_info_template.visualid))
+ {
+ print_error("Can't get visual from config");
+ assert(false);
+ }
+ print_line("native visual id: " + itos(x11_visual_info_template.visualid));
+ int num_visuals;
+ XVisualInfo *vi = XGetVisualInfo(x11_display,
+ VisualIDMask,
+ &x11_visual_info_template,
+ &num_visuals);
+ print_line("num visuals: " + itos(num_visuals));
+ if (num_visuals > 0) {
+ assert(vi);
+ assert(vi->screen);
+ assert(vi->visual);
+ XSetWindowAttributes swa;
+ swa.colormap = XCreateColormap(x11_display, RootWindow(x11_display, vi->screen), vi->visual, AllocNone);
+ assert(swa.colormap);
+ swa.border_pixel = 0;
+ swa.event_mask = StructureNotifyMask;
+ unsigned long valuemask = CWBorderPixel | CWColormap | CWEventMask;
+ swa.background_pixmap = None;
+ swa.background_pixel = 0;
+ swa.border_pixmap = None;
+ valuemask |= CWBackPixel;
+ x11_window = XCreateWindow(x11_display, RootWindow(x11_display, vi->screen), 0, 0, OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height, 0, vi->depth, InputOutput, vi->visual, valuemask, &swa);
+ } else {
+ XSetWindowAttributes swa;
+ swa.border_pixel = 0;
+ swa.event_mask = StructureNotifyMask;
+ unsigned long valuemask = CWBorderPixel | CWEventMask;
+ swa.background_pixmap = None;
+ swa.background_pixel = 0;
+ swa.border_pixmap = None;
+ valuemask |= CWBackPixel;
+ x11_window = XCreateWindow(x11_display, DefaultRootWindow(x11_display), 0, 0, OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &swa);
+ }
+ XStoreName(x11_display, x11_window, "Godot Engine");
+
+ ERR_FAIL_COND_V(!x11_window, ERR_UNCONFIGURED);
+ set_class_hint(x11_display, x11_window);
+
+ if (!OS::get_singleton()->is_no_window_mode_enabled()) {
+ XMapWindow(x11_display, x11_window);
+ }
+ p->egl_surface =
+ eglCreateWindowSurface(p->egl_display, egl_conf, x11_window, NULL);
+
+ //// egl-contexts collect all state descriptions needed required for operation
+ EGLint ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+ p->egl_context = eglCreateContext(p->egl_display, egl_conf,
+ EGL_NO_CONTEXT, ctxattr);
+ if (p->egl_context == EGL_NO_CONTEXT) {
+ print_error("Unable to create EGL context (eglError: " + itos(eglGetError()));
+ assert(false);
+ }
+ p->egl_context_offscreen = eglCreateContext(p->egl_display, egl_conf,
+ EGL_NO_CONTEXT, ctxattr);
+
+ XSync(x11_display, False);
+ eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, p->egl_context);
+ if (vi)
+ XFree(vi);
+
+#endif
+
+ return OK;
+}
@@ -554,6 +698,7 @@ index 0000000000..ab5d655408
+ return xwa.height;
+}
+
+#ifndef EGL
+void *ContextGL_X11::get_glx_context() {
+ if (p != nullptr) {
+ return p->glx_context;
@@ -561,8 +706,18 @@ index 0000000000..ab5d655408
+ return nullptr;
+ }
+}
+#else
+void *ContextGL_X11::get_egl_context() {
+ if (p != nullptr) {
+ return p->egl_context;
+ } else {
+ return nullptr;
+ }
+}
+#endif
+
+void ContextGL_X11::set_use_vsync(bool p_use) {
+#ifndef EGL
+ static bool setup = false;
+ static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
+ static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalMESA = nullptr;
@@ -592,6 +747,10 @@ index 0000000000..ab5d655408
+ } else {
+ return;
+ }
+#else
+ int val = p_use ? 1 : 0;
+ eglSwapInterval(p->egl_display, val);
+#endif
+ use_vsync = p_use;
+}
+bool ContextGL_X11::is_using_vsync() const {
@@ -603,23 +762,41 @@ index 0000000000..ab5d655408
+ default_video_mode = p_default_video_mode;
+ x11_display = p_x11_display;
+
+#ifndef EGL
+ context_type = p_context_type;
+
+#endif
+ double_buffer = false;
+ direct_render = false;
+#ifndef EGL
+ glx_minor = glx_major = 0;
+#else
+ egl_minor = egl_major = 0;
+#endif
+ p = memnew(ContextGL_X11_Private);
+#ifndef EGL
+ p->glx_context = nullptr;
+ p->glx_context_offscreen = nullptr;
+#else
+ p->egl_display = EGL_NO_DISPLAY;
+ p->egl_surface = EGL_NO_SURFACE;
+ p->egl_context = EGL_NO_CONTEXT;
+ p->egl_context_offscreen = EGL_NO_CONTEXT;
+#endif
+ use_vsync = false;
+}
+
+ContextGL_X11::~ContextGL_X11() {
+ release_current();
+#ifndef EGL
+ glXDestroyContext(x11_display, p->glx_context);
+ if (p->glx_context_offscreen) {
+ glXDestroyContext(x11_display, p->glx_context_offscreen);
+ }
+#else
+ eglDestroyContext(p->egl_display, p->egl_context);
+ eglDestroyContext(p->egl_display, p->egl_context_offscreen);
+
+#endif
+ memdelete(p);
+}
+
@@ -627,10 +804,10 @@ index 0000000000..ab5d655408
+#endif
diff --git a/platform/x11es/context_gl_x11.h b/platform/x11es/context_gl_x11.h
new file mode 100644
index 0000000000..7ac2d2d97c
index 0000000000..769ee374ea
--- /dev/null
+++ b/platform/x11es/context_gl_x11.h
@@ -0,0 +1,89 @@
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* context_gl_x11.h */
+/**************************************************************************/
@@ -671,6 +848,10 @@ index 0000000000..7ac2d2d97c
+#include "core/os/os.h"
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrender.h>
+#define EGL
+#ifdef EGL
+#include <EGL/egl.h>
+#endif
+
+struct ContextGL_X11_Private;
+
@@ -690,9 +871,13 @@ index 0000000000..7ac2d2d97c
+ ::Window &x11_window;
+ bool double_buffer;
+ bool direct_render;
+#ifndef EGL
+ int glx_minor, glx_major;
+ bool use_vsync;
+ ContextType context_type;
+#else
+ int egl_minor, egl_major;
+#endif
+ bool use_vsync;
+
+public:
+ void release_current();
@@ -700,7 +885,11 @@ index 0000000000..7ac2d2d97c
+ void swap_buffers();
+ int get_window_width();
+ int get_window_height();
+#ifndef EGL
+ void *get_glx_context();
+#else
+ void *get_egl_context();
+#endif
+
+ bool is_offscreen_available() const;
+ void make_offscreen_current();
@@ -1393,10 +1582,10 @@ index 0000000000..39271b3037
+ env.Append(LIBS=["atomic"])
diff --git a/platform/x11es/detect_prime.cpp b/platform/x11es/detect_prime.cpp
new file mode 100644
index 0000000000..49dfd207cc
index 0000000000..48a4049383
--- /dev/null
+++ b/platform/x11es/detect_prime.cpp
@@ -0,0 +1,246 @@
@@ -0,0 +1,315 @@
+/**************************************************************************/
+/* detect_prime.cpp */
+/**************************************************************************/
@@ -1436,9 +1625,15 @@ index 0000000000..49dfd207cc
+#include "core/ustring.h"
+
+#include <stdlib.h>
+#define EGL
+
+#ifndef EGL
+#include <GL/gl.h>
+#include <GL/glx.h>
+#else
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#endif
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
@@ -1447,11 +1642,14 @@ index 0000000000..49dfd207cc
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <cassert>
+
+#ifndef EGL
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+
+typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
+#endif
+
+struct vendor {
+ const char *glxvendor;
@@ -1474,6 +1672,7 @@ index 0000000000..49dfd207cc
+void create_context() {
+ Display *x11_display = XOpenDisplay(nullptr);
+ Window x11_window;
+#ifndef EGL
+ GLXContext glx_context;
+
+ GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte *)"glXCreateContextAttribsARB");
@@ -1525,6 +1724,65 @@ index 0000000000..49dfd207cc
+ }
+
+ glXMakeCurrent(x11_display, x11_window, glx_context);
+#else
+ EGLDisplay egl_display = eglGetDisplay((EGLNativeDisplayType)x11_display);
+ if (egl_display == EGL_NO_DISPLAY)
+ exit(1);
+ int egl_major, egl_minor;
+ if (!eglInitialize(egl_display, &egl_major,
+ &egl_minor))
+ exit(1);
+ EGLint egl_config_constraints[] = { EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_ALPHA_SIZE, 0,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_NONE };
+ EGLConfig egl_conf;
+ EGLint num_config;
+ if (!eglChooseConfig(egl_display, egl_config_constraints, &egl_conf, 1,
+ &num_config))
+ exit(1);
+ if (num_config > 0)
+ exit(1);
+ XVisualInfo x11_visual_info_template;
+ if (!eglGetConfigAttrib(egl_display,
+ egl_conf,
+ EGL_NATIVE_VISUAL_ID,
+ (EGLint*) &x11_visual_info_template.visualid))
+ exit(1);
+ int num_visuals;
+ XVisualInfo *vi = XGetVisualInfo(x11_display,
+ VisualIDMask,
+ &x11_visual_info_template,
+ &num_visuals);
+ assert(vi);
+ XSetWindowAttributes swa;
+ swa.event_mask = StructureNotifyMask;
+ swa.border_pixel = 0;
+ unsigned long valuemask = CWBorderPixel | CWColormap | CWEventMask;
+ swa.colormap = XCreateColormap(x11_display, RootWindow(x11_display, vi->screen), vi->visual, AllocNone);
+ x11_window = XCreateWindow(x11_display, RootWindow(x11_display, vi->screen), 0, 0, 10, 10, 0, vi->depth, InputOutput, vi->visual, valuemask, &swa);
+
+ if (!x11_window) {
+ exit(1);
+ }
+ EGLSurface egl_surface =
+ eglCreateWindowSurface(egl_display, egl_conf, x11_window, NULL);
+
+ //// egl-contexts collect all state descriptions needed required for operation
+ EGLint ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+ EGLContext egl_context = eglCreateContext(egl_display, egl_conf,
+ EGL_NO_CONTEXT, ctxattr);
+ if (egl_context == EGL_NO_CONTEXT) {
+ print_error("Unable to create EGL context (eglError: " + itos(eglGetError()));
+ assert(false);
+ }
+ eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
+
+#endif
+
+ XFree(vi);
+}
+
@@ -5794,10 +6052,10 @@ HcmV?d00001
diff --git a/platform/x11es/os_x11.cpp b/platform/x11es/os_x11.cpp
new file mode 100644
index 0000000000..1d8c9badfb
index 0000000000..26e3f1c4f9
--- /dev/null
+++ b/platform/x11es/os_x11.cpp
@@ -0,0 +1,4493 @@
@@ -0,0 +1,4497 @@
+/**************************************************************************/
+/* os_x11.cpp */
+/**************************************************************************/
@@ -7826,7 +8084,11 @@ index 0000000000..1d8c9badfb
+ case WINDOW_VIEW:
+ return nullptr; // Do we have a value to return here?
+ case OPENGL_CONTEXT:
+#ifndef EGL
+ return context_gl->get_glx_context();
+#else
+ return context_gl->get_egl_context();
+#endif
+ default:
+ return nullptr;
+ }