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 "gdkdisplayprivate.h" -#include "gdkmemorytextureprivate.h" -#include "gdkinternals.h" +#include "gdkdebug.h" +#include "gdkdisplayprivate.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" +}; + +/* + * 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; +} + +/* + * 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))