[gtk/wip/otte/shittymorph] gdk: Make sure only one GL backend is used
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/shittymorph] gdk: Make sure only one GL backend is used
- Date: Fri, 24 Sep 2021 00:04:17 +0000 (UTC)
commit 23acc993cced48fa1f21ac9f4881338100b1a15a
Author: Benjamin Otte <otte redhat com>
Date: Fri Sep 24 01:47:03 2021 +0200
gdk: Make sure only one GL backend is used
Creative people managed to create an X11 display and a Wayland display
at once, thereby getting EGL and GLX involved in a fight to the death
over the ownership of the glFoo() symbolspace.
A way to force such a fight with available tools here is (on Wayland)
running something like:
GTK_INSPECTOR_DISPLAY=:1 GTK_DEBUG=interactive gtk4-demo
Related: xdg-desktop-portal-gnome#5
gdk/gdkdisplay.c | 2 ++
gdk/gdkglcontext.c | 71 ++++++++++++++++++++++++++++++++++++--
gdk/gdkglcontextprivate.h | 14 ++++++++
gdk/macos/gdkmacosdisplay.c | 3 ++
gdk/macos/gdkmacosglcontext.c | 2 ++
gdk/wayland/gdkglcontext-wayland.c | 5 +++
gdk/win32/gdkglcontext-win32-egl.c | 5 +++
gdk/win32/gdkglcontext-win32-wgl.c | 5 +++
gdk/x11/gdkglcontext-egl.c | 5 +++
gdk/x11/gdkglcontext-glx.c | 5 +++
10 files changed, 115 insertions(+), 2 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 5067065b03..1f4b524250 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -1233,6 +1233,8 @@ gdk_display_init_gl (GdkDisplay *self)
*/
priv->gl_context = context;
+ gdk_gl_backend_use (GDK_GL_CONTEXT_GET_CLASS (context)->backend_type);
+
gdk_profiler_end_mark (before, "initialize OpenGL", NULL);
}
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 76be3c7ef9..9f8673627f 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -75,11 +75,13 @@
#include "config.h"
#include "gdkglcontextprivate.h"
+
+#include "gdkdebug.h"
#include "gdkdisplayprivate.h"
-#include "gdkmemorytextureprivate.h"
#include "gdkinternals.h"
-
#include "gdkintl.h"
+#include "gdkmemorytextureprivate.h"
+
#include "gdk-private.h"
#ifdef GDK_WINDOWING_WIN32
@@ -1354,3 +1356,68 @@ gdk_gl_context_use_es_bgra (GdkGLContext *context)
return FALSE;
}
+
+static GdkGLBackend the_gl_backend_type = GDK_GL_NONE;
+
+static const char *gl_backend_names[] = {
+ [GDK_GL_NONE] = "No GL (You should never read this)",
+ [GDK_GL_EGL] = "EGL",
+ [GDK_GL_GLX] = "X11 GLX",
+ [GDK_GL_WGL] = "Windows WGL",
+ [GDK_GL_CGL] = "Apple CGL"
+};
+
+/*<private>
+ * gdk_gl_backend_can_be_used:
+ * @backend_type: Type of backend to check
+ * @error: Return location for an error
+ *
+ * Checks if this backend type can be used. When multiple displays
+ * are opened that use different GL backends, conflicts can arise,
+ * so this function checks that all displays use compatible GL
+ * backends.
+ *
+ * Returns: %TRUE if the backend can still be used
+ */
+gboolean
+gdk_gl_backend_can_be_used (GdkGLBackend backend_type,
+ GError **error)
+{
+ if (the_gl_backend_type == GDK_GL_NONE ||
+ the_gl_backend_type == backend_type)
+ return TRUE;
+
+ g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
+ /* translators: This is about OpenGL backend names, like
+ * "Trying to use X11 GLX, but EGL is already in use" */
+ _("Trying to use %s, but %s is already in use"),
+ gl_backend_names[backend_type],
+ gl_backend_names[the_gl_backend_type]);
+ return FALSE;
+}
+
+/*<private>
+ * gdk_gl_backend_use:
+ * @backend_type: Type of backend
+ *
+ * Ensures that the backend in use is the given one. If another backend
+ * is already in use, this function will abort the program. It should
+ * have previously checked via gdk_gl_backend_can_be_used().
+ **/
+void
+gdk_gl_backend_use (GdkGLBackend backend_type)
+{
+ /* Check that the context class is properly initializing its backend type */
+ g_assert (backend_type != GDK_GL_NONE);
+
+ if (the_gl_backend_type == GDK_GL_NONE)
+ {
+ the_gl_backend_type = backend_type;
+ /* This is important!!!11eleven
+ * (But really: How do I print a message in 2 categories?) */
+ GDK_NOTE (OPENGL, g_print ("Using OpenGL backend %s\n", gl_backend_names[the_gl_backend_type]));
+ GDK_NOTE (MISC, g_message ("Using Opengl backend %s", gl_backend_names[the_gl_backend_type]));
+ }
+
+ g_assert (the_gl_backend_type == backend_type);
+}
diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h
index c8afedda02..050e757608 100644
--- a/gdk/gdkglcontextprivate.h
+++ b/gdk/gdkglcontextprivate.h
@@ -34,6 +34,14 @@ G_BEGIN_DECLS
#define GDK_EGL_MIN_VERSION_MAJOR (1)
#define GDK_EGL_MIN_VERSION_MINOR (4)
+typedef enum {
+ GDK_GL_NONE = 0,
+ GDK_GL_EGL,
+ GDK_GL_GLX,
+ GDK_GL_WGL,
+ GDK_GL_CGL
+} GdkGLBackend;
+
#define GDK_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GL_CONTEXT,
GdkGLContextClass))
#define GDK_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GL_CONTEXT))
#define GDK_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GL_CONTEXT,
GdkGLContextClass))
@@ -52,6 +60,8 @@ struct _GdkGLContextClass
{
GdkDrawContextClass parent_class;
+ GdkGLBackend backend_type;
+
gboolean (* realize) (GdkGLContext *context,
GError **error);
@@ -86,6 +96,10 @@ typedef struct {
guint use_es : 1;
} GdkGLContextPaintData;
+gboolean gdk_gl_backend_can_be_used (GdkGLBackend backend_type,
+ GError **error);
+void gdk_gl_backend_use (GdkGLBackend backend_type);
+
GdkGLContext * gdk_gl_context_new_for_surface (GdkSurface *surface);
void gdk_gl_context_set_is_legacy (GdkGLContext *context,
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
index 450ad2434d..051a921903 100644
--- a/gdk/macos/gdkmacosdisplay.c
+++ b/gdk/macos/gdkmacosdisplay.c
@@ -641,6 +641,9 @@ static GdkGLContext *
gdk_macos_display_init_gl (GdkDisplay *display,
GError **error)
{
+ if (!gdk_gl_backend_can_be_used (GDK_GL_CGL, error))
+ return FALSE;
+
return g_object_new (GDK_TYPE_MACOS_GL_CONTEXT,
"display", display,
NULL);
diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c
index 8e79f7688f..e959f0e30f 100644
--- a/gdk/macos/gdkmacosglcontext.c
+++ b/gdk/macos/gdkmacosglcontext.c
@@ -515,6 +515,8 @@ gdk_macos_gl_context_class_init (GdkMacosGLContextClass *klass)
gl_class->get_damage = gdk_macos_gl_context_get_damage;
gl_class->realize = gdk_macos_gl_context_real_realize;
+
+ gl_class->backend_type = GDK_GL_CGL;
}
static void
diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c
index 2cf7285fe5..f007ac6576 100644
--- a/gdk/wayland/gdkglcontext-wayland.c
+++ b/gdk/wayland/gdkglcontext-wayland.c
@@ -358,6 +358,8 @@ gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
context_class->make_current = gdk_wayland_gl_context_make_current;
context_class->clear_current = gdk_wayland_gl_context_clear_current;
context_class->get_damage = gdk_wayland_gl_context_get_damage;
+
+ context_class->backend_type = GDK_GL_EGL;
}
static void
@@ -475,6 +477,9 @@ gdk_wayland_display_init_gl (GdkDisplay *display,
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
G_GNUC_UNUSED gint64 start_time2;
+ if (!gdk_gl_backend_can_be_used (GDK_GL_EGL, error))
+ return FALSE;
+
if (!epoxy_has_egl ())
{
gboolean sandboxed = gdk_running_in_sandbox ();
diff --git a/gdk/win32/gdkglcontext-win32-egl.c b/gdk/win32/gdkglcontext-win32-egl.c
index cfc4417a9a..50f57ebe4f 100644
--- a/gdk/win32/gdkglcontext-win32-egl.c
+++ b/gdk/win32/gdkglcontext-win32-egl.c
@@ -256,6 +256,9 @@ gdk_win32_display_init_egl (GdkDisplay *display,
int best_idx = 0;
EGLDisplay egl_disp;
+ if (!gdk_gl_backend_can_be_used (GDK_GL_EGL, error))
+ return FALSE;
+
if (display_win32->egl_disp != EGL_NO_DISPLAY)
return TRUE;
@@ -488,6 +491,8 @@ gdk_win32_gl_context_egl_class_init (GdkWin32GLContextClass *klass)
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS(klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ context_class->backend_type = GDK_GL_EGL;
+
context_class->realize = gdk_win32_gl_context_egl_realize;
context_class->make_current = gdk_win32_gl_context_egl_make_current;
context_class->clear_current = gdk_win32_gl_context_egl_clear_current;
diff --git a/gdk/win32/gdkglcontext-win32-wgl.c b/gdk/win32/gdkglcontext-win32-wgl.c
index 3d05fb8907..31e0de7401 100644
--- a/gdk/win32/gdkglcontext-win32-wgl.c
+++ b/gdk/win32/gdkglcontext-win32-wgl.c
@@ -265,6 +265,9 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
HDC hdc;
+ if (!gdk_gl_backend_can_be_used (GDK_GL_WGL, error))
+ return FALSE;
+
if (display_win32->wgl_pixel_format != 0)
return TRUE;
@@ -697,6 +700,8 @@ gdk_win32_gl_context_wgl_class_init (GdkWin32GLContextWGLClass *klass)
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ context_class->backend_type = GDK_GL_WGL;
+
context_class->realize = gdk_win32_gl_context_wgl_realize;
context_class->make_current = gdk_win32_gl_context_wgl_make_current;
context_class->clear_current = gdk_win32_gl_context_wgl_clear_current;
diff --git a/gdk/x11/gdkglcontext-egl.c b/gdk/x11/gdkglcontext-egl.c
index eb5fd33724..9e3301adf8 100644
--- a/gdk/x11/gdkglcontext-egl.c
+++ b/gdk/x11/gdkglcontext-egl.c
@@ -642,6 +642,8 @@ gdk_x11_gl_context_egl_class_init (GdkX11GLContextEGLClass *klass)
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ context_class->backend_type = GDK_GL_EGL;
+
context_class->realize = gdk_x11_gl_context_egl_realize;
context_class->make_current = gdk_x11_gl_context_egl_make_current;
context_class->clear_current = gdk_x11_gl_context_egl_clear_current;
@@ -670,6 +672,9 @@ gdk_x11_display_init_egl (GdkX11Display *self,
Display *dpy;
int major, minor;
+ if (!gdk_gl_backend_can_be_used (GDK_GL_EGL, error))
+ return FALSE;
+
dpy = gdk_x11_display_get_xdisplay (display);
if (!epoxy_has_egl ())
diff --git a/gdk/x11/gdkglcontext-glx.c b/gdk/x11/gdkglcontext-glx.c
index 6e4c46abb1..bc1eeb94fb 100644
--- a/gdk/x11/gdkglcontext-glx.c
+++ b/gdk/x11/gdkglcontext-glx.c
@@ -692,6 +692,8 @@ gdk_x11_gl_context_glx_class_init (GdkX11GLContextGLXClass *klass)
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ context_class->backend_type = GDK_GL_GLX;
+
context_class->realize = gdk_x11_gl_context_glx_realize;
context_class->make_current = gdk_x11_gl_context_glx_make_current;
context_class->clear_current = gdk_x11_gl_context_glx_clear_current;
@@ -905,6 +907,9 @@ gdk_x11_display_init_glx (GdkX11Display *display_x11,
Display *dpy;
int screen_num;
+ if (!gdk_gl_backend_can_be_used (GDK_GL_GLX, error))
+ return FALSE;
+
dpy = gdk_x11_display_get_xdisplay (display);
if (!epoxy_has_glx (dpy))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]