From: Benjamin Otte Date: Sun, 4 Jul 2021 23:57:03 +0000 (+0200) Subject: gdk: Add GdkDisplay::init_gl vfunc X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~3^2~9^2~20 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=430b6f8fb1a8d20a1c1744e291c1ae51fdd6faac;p=gtk4.git gdk: Add GdkDisplay::init_gl vfunc The vfunc is called to initialize GL and it returns a "base" context that GDK then uses as the context all others are shared with. So the GL context share tree now looks like: + context from init_gl - context1 - context2 ... So this is a flat tree now, the complexity is gone. The only caveat is that backends now need to create a GL context when initializing GL so some refactoring was needed. Two new functions have been added: * gdk_display_prepare_gl() This is public API and can be used to ensure that GL has been initialized or if not, retrieve an error to display (or debug-print). * gdk_display_get_gl_context() This is a private function to retrieve the base context from init_gl(). It replaces gdk_surface_get_shared_data_context(). --- diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index dbe8c4cf82..5891bbe5f0 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -80,6 +80,13 @@ enum { typedef struct _GdkDisplayPrivate GdkDisplayPrivate; struct _GdkDisplayPrivate { + /* The base context that all other contexts inherit from. + * This context is never exposed to public API and is + * allowed to have a %NULL surface. + */ + GdkGLContext *gl_context; + GError *gl_error; + guint rgba : 1; guint composited : 1; guint input_shapes : 1; @@ -129,10 +136,14 @@ gdk_display_real_make_default (GdkDisplay *display) { } -static void -gdk_display_real_opened (GdkDisplay *display) +static GdkGLContext * +gdk_display_default_init_gl (GdkDisplay *display, + GError **error) { - _gdk_display_manager_add_display (gdk_display_manager_get (), display); + g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, + _("The current backend does not support OpenGL")); + + return NULL; } static GdkSeat * @@ -144,6 +155,12 @@ gdk_display_real_get_default_seat (GdkDisplay *display) return display->seats->data; } +static void +gdk_display_real_opened (GdkDisplay *display) +{ + _gdk_display_manager_add_display (gdk_display_manager_get (), display); +} + static void gdk_display_class_init (GdkDisplayClass *class) { @@ -153,10 +170,11 @@ gdk_display_class_init (GdkDisplayClass *class) object_class->dispose = gdk_display_dispose; object_class->get_property = gdk_display_get_property; - class->get_app_launch_context = gdk_display_real_get_app_launch_context; - class->opened = gdk_display_real_opened; class->make_default = gdk_display_real_make_default; + class->get_app_launch_context = gdk_display_real_get_app_launch_context; + class->init_gl = gdk_display_default_init_gl; class->get_default_seat = gdk_display_real_get_default_seat; + class->opened = gdk_display_real_opened; /** * GdkDisplay:composited: (attributes org.gtk.Property.get=gdk_display_is_composited) @@ -327,11 +345,15 @@ static void gdk_display_dispose (GObject *object) { GdkDisplay *display = GDK_DISPLAY (object); + GdkDisplayPrivate *priv = gdk_display_get_instance_private (display); _gdk_display_manager_remove_display (gdk_display_manager_get (), display); g_queue_clear (&display->queued_events); + g_clear_object (&priv->gl_context); + g_clear_error (&priv->gl_error); + G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object); } @@ -1173,6 +1195,109 @@ gdk_display_get_keymap (GdkDisplay *display) return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display); } +static void +gdk_display_init_gl (GdkDisplay *self) +{ + GdkDisplayPrivate *priv = gdk_display_get_instance_private (self); + GdkGLContext *context; + + if (GDK_DISPLAY_DEBUG_CHECK (self, GL_DISABLE)) + { + g_set_error_literal (&priv->gl_error, GDK_GL_ERROR, + GDK_GL_ERROR_NOT_AVAILABLE, + _("GL support disabled via GDK_DEBUG")); + return; + } + + context = GDK_DISPLAY_GET_CLASS (self)->init_gl (self, &priv->gl_error); + if (context == NULL) + return; + + if (!gdk_gl_context_realize (context, &priv->gl_error)) + { + g_object_unref (context); + return; + } + + /* Only assign after realize, so GdkGLContext::realize() can use + * gdk_display_get_gl_context() == NULL to differentiate between + * the display's context and any other context. + */ + priv->gl_context = context; +} + +/** + * gdk_display_prepare_gl: + * @self: a `GdkDisplay` + * @error: return location for a `GError` + * + * Checks that OpenGL is available for @self and ensures that it is + * properly initialized. + * When this fails, an @error will be set describing the error and this + * function returns %FALSE. + * + * Note that even if this function succeeds, creating a `GdkGLContext` + * may still fail. + * + * This function is idempotent. Calling it multiple times will just + * return the same value or error. + * + * You never need to call this function, GDK will call it automatically + * as needed. But you can use it as a check when setting up code that + * might make use of OpenGL. + * + * Returns: %TRUE if the display supports OpenGL + * + * Since: 4.4 + **/ +gboolean +gdk_display_prepare_gl (GdkDisplay *self, + GError **error) +{ + GdkDisplayPrivate *priv = gdk_display_get_instance_private (self); + + g_return_val_if_fail (GDK_IS_DISPLAY (self), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + for (;;) + { + if (priv->gl_context) + return TRUE; + + if (priv->gl_error != NULL) + { + if (error) + *error = g_error_copy (priv->gl_error); + return FALSE; + } + + gdk_display_init_gl (self); + + /* try again */ + } +} + +/*< private > + * gdk_display_get_gl_context: + * @self: the `GdkDisplay` + * + * Gets the GL context returned from [vfunc@Gdk.Display.init_gl] + * previously. + * + * If that function has not been called yet or did fail, %NULL is + * returned. + * Call [method@Gdk.Display.prepare_gl] to avoid this. + * + * Returns: The `GdkGLContext` + */ +GdkGLContext * +gdk_display_get_gl_context (GdkDisplay *self) +{ + GdkDisplayPrivate *priv = gdk_display_get_instance_private (self); + + return priv->gl_context; +} + /*< private > * gdk_display_make_gl_context_current: * @display: a `GdkDisplay` diff --git a/gdk/gdkdisplay.h b/gdk/gdkdisplay.h index 97d8e7eee6..9fabac6b50 100644 --- a/gdk/gdkdisplay.h +++ b/gdk/gdkdisplay.h @@ -68,6 +68,10 @@ gboolean gdk_display_is_rgba (GdkDisplay *display); GDK_AVAILABLE_IN_ALL gboolean gdk_display_supports_input_shapes (GdkDisplay *display); +GDK_AVAILABLE_IN_4_4 +gboolean gdk_display_prepare_gl (GdkDisplay *self, + GError **error); + GDK_AVAILABLE_IN_ALL GdkDisplay *gdk_display_get_default (void); diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index 4aa99c30dd..a2913b50e9 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -140,6 +140,8 @@ struct _GdkDisplayClass GdkKeymap * (*get_keymap) (GdkDisplay *display); + GdkGLContext * (*init_gl) (GdkDisplay *display, + GError **error); gboolean (*make_gl_context_current) (GdkDisplay *display, GdkGLContext *context); @@ -206,6 +208,7 @@ GdkSurface * gdk_display_create_surface (GdkDisplay *display int width, int height); +GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display); gboolean gdk_display_make_gl_context_current (GdkDisplay *display, GdkGLContext *context); diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c index 8f562f7d1c..274ad99345 100644 --- a/gdk/gdksurface.c +++ b/gdk/gdksurface.c @@ -1065,59 +1065,14 @@ gdk_surface_get_mapped (GdkSurface *surface) return GDK_SURFACE_IS_MAPPED (surface); } -GdkGLContext * -gdk_surface_get_shared_data_gl_context (GdkSurface *surface) -{ - static int in_shared_data_creation; - GdkDisplay *display; - GdkGLContext *context; - - if (in_shared_data_creation) - return NULL; - - in_shared_data_creation = 1; - - display = gdk_surface_get_display (surface); - context = (GdkGLContext *)g_object_get_data (G_OBJECT (display), "gdk-gl-shared-data-context"); - if (context == NULL) - { - GError *error = NULL; - context = GDK_SURFACE_GET_CLASS (surface)->create_gl_context (surface, FALSE, NULL, &error); - if (context == NULL) - { - g_warning ("Failed to create shared context: %s", error->message); - g_clear_error (&error); - } - - gdk_gl_context_realize (context, &error); - if (context == NULL) - { - g_warning ("Failed to realize shared context: %s", error->message); - g_clear_error (&error); - } - - - g_object_set_data (G_OBJECT (display), "gdk-gl-shared-data-context", context); - } - - in_shared_data_creation = 0; - - return context; -} - GdkGLContext * gdk_surface_get_paint_gl_context (GdkSurface *surface, - GError **error) + GError **error) { GError *internal_error = NULL; - if (GDK_DISPLAY_DEBUG_CHECK (surface->display, GL_DISABLE)) - { - g_set_error_literal (error, GDK_GL_ERROR, - GDK_GL_ERROR_NOT_AVAILABLE, - _("GL support disabled via GDK_DEBUG")); - return NULL; - } + if (!gdk_display_prepare_gl (surface->display, error)) + return NULL; if (surface->gl_paint_context == NULL) { diff --git a/gdk/gdksurfaceprivate.h b/gdk/gdksurfaceprivate.h index 90f5bcba2d..c29827c34e 100644 --- a/gdk/gdksurfaceprivate.h +++ b/gdk/gdksurfaceprivate.h @@ -266,7 +266,6 @@ void _gdk_surface_update_size (GdkSurface *surface); GdkGLContext * gdk_surface_get_paint_gl_context (GdkSurface *surface, GError **error); -GdkGLContext * gdk_surface_get_shared_data_gl_context (GdkSurface *surface); gboolean gdk_surface_handle_event (GdkEvent *event); GdkSeat * gdk_surface_get_seat_from_event (GdkSurface *surface, diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c index 20041ac076..351ff574fd 100644 --- a/gdk/macos/gdkmacosdisplay.c +++ b/gdk/macos/gdkmacosdisplay.c @@ -637,6 +637,13 @@ gdk_macos_display_load_clipboard (GdkMacosDisplay *self) GDK_DISPLAY (self)->clipboard = _gdk_macos_clipboard_new (self); } +static GdkGLContext * +gdk_macos_display_init_gl (GdkDisplay *display, + GError **error) +{ + return _gdk_macos_gl_context_new (display, NULL, FALSE, NULL, error); +} + static gboolean gdk_macos_display_make_gl_context_current (GdkDisplay *display, GdkGLContext *gl_context) @@ -695,6 +702,7 @@ gdk_macos_display_class_init (GdkMacosDisplayClass *klass) display_class->get_name = gdk_macos_display_get_name; display_class->get_setting = gdk_macos_display_get_setting; display_class->has_pending = gdk_macos_display_has_pending; + display_class->init_gl = gdk_macos_display_init_gl; display_class->make_gl_context_current = gdk_macos_display_make_gl_context_current; display_class->notify_startup_complete = gdk_macos_display_notify_startup_complete; display_class->queue_events = gdk_macos_display_queue_events; diff --git a/gdk/macos/gdkmacosglcontext-private.h b/gdk/macos/gdkmacosglcontext-private.h index 97d209b6f7..8d5eea931c 100644 --- a/gdk/macos/gdkmacosglcontext-private.h +++ b/gdk/macos/gdkmacosglcontext-private.h @@ -19,12 +19,14 @@ #ifndef __GDK_MACOS_GL_CONTEXT_PRIVATE_H__ #define __GDK_MACOS_GL_CONTEXT_PRIVATE_H__ +#include "gdkmacosglcontext.h" + #include "gdkglcontextprivate.h" #include "gdkdisplayprivate.h" #include "gdksurface.h" #include "gdkinternals.h" -#include "gdkmacosglcontext.h" +#include "gdkmacosdisplay.h" #include "gdkmacossurface.h" #import @@ -55,7 +57,8 @@ struct _GdkMacosGLContextClass GdkGLContextClass parent_class; }; -GdkGLContext *_gdk_macos_gl_context_new (GdkMacosSurface *surface, +GdkGLContext *_gdk_macos_gl_context_new (GdkMacosDisplay *display, + GdkMacosSurface *surface, gboolean attached, GdkGLContext *share, GError **error); diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c index e4ef4abcb1..66f767c19d 100644 --- a/gdk/macos/gdkmacosglcontext.c +++ b/gdk/macos/gdkmacosglcontext.c @@ -170,12 +170,12 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context, { GdkMacosGLContext *self = (GdkMacosGLContext *)context; GdkSurface *surface; + GdkDisplay *display; NSOpenGLContext *shared_gl_context = nil; NSOpenGLContext *gl_context; NSOpenGLPixelFormat *pixelFormat; CGLContextObj cgl_context; GdkGLContext *shared; - GdkGLContext *shared_data; NSOpenGLContext *existing; GLint sync_to_framerate = 1; GLint validate = 0; @@ -192,21 +192,16 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context, gdk_gl_context_get_required_version (context, &major, &minor); surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context)); - shared = gdk_gl_context_get_shared_context (context); - shared_data = gdk_surface_get_shared_data_gl_context (surface); + display = gdk_gl_context_get_display (context); + shared = gdk_display_get_gl_context (display); if (shared != NULL) { if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared), error))) return FALSE; } - else if (shared_data != NULL) - { - if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared_data), error))) - return FALSE; - } - GDK_DISPLAY_NOTE (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)), + GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Creating NSOpenGLContext (version %d.%d)", major, minor)); @@ -253,7 +248,7 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context, GLint renderer_id = 0; [gl_context getValues:&renderer_id forParameter:NSOpenGLContextParameterCurrentRendererID]; - GDK_DISPLAY_NOTE (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)), + GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Created NSOpenGLContext[%p] using %s", gl_context, @@ -479,7 +474,8 @@ gdk_macos_gl_context_init (GdkMacosGLContext *self) } GdkGLContext * -_gdk_macos_gl_context_new (GdkMacosSurface *surface, +_gdk_macos_gl_context_new (GdkMacosDisplay *display, + GdkMacosSurface *surface, gboolean attached, GdkGLContext *share, GError **error) @@ -490,6 +486,7 @@ _gdk_macos_gl_context_new (GdkMacosSurface *surface, g_return_val_if_fail (!share || GDK_IS_MACOS_GL_CONTEXT (share), NULL); context = g_object_new (GDK_TYPE_MACOS_GL_CONTEXT, + "display", display, "surface", surface, "shared-context", share, NULL); diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c index 9a1f73835b..aa8df2f35e 100644 --- a/gdk/macos/gdkmacossurface.c +++ b/gdk/macos/gdkmacossurface.c @@ -369,7 +369,8 @@ gdk_macos_surface_create_gl_context (GdkSurface *surface, g_assert (GDK_IS_MACOS_SURFACE (self)); g_assert (!share || GDK_IS_GL_CONTEXT (share)); - return _gdk_macos_gl_context_new (self, attached, share, error); + return _gdk_macos_gl_context_new ((GdkMacosDisplay *) gdk_surface_get_display (surface), + self, attached, share, error); } static void diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index c27b165594..5d2d3826ae 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -969,6 +969,7 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass *class) display_class->create_surface = _gdk_wayland_display_create_surface; display_class->get_keymap = _gdk_wayland_display_get_keymap; + display_class->init_gl = gdk_wayland_display_init_gl; display_class->make_gl_context_current = gdk_wayland_display_make_gl_context_current; display_class->get_monitors = gdk_wayland_display_get_monitors; diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c index 3e8e8bf6f4..23e0105802 100644 --- a/gdk/wayland/gdkglcontext-wayland.c +++ b/gdk/wayland/gdkglcontext-wayland.c @@ -55,8 +55,7 @@ gdk_wayland_gl_context_realize (GdkGLContext *context, { GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context); GdkDisplay *display = gdk_gl_context_get_display (context); - GdkGLContext *share = gdk_gl_context_get_shared_context (context); - GdkGLContext *shared_data_context = gdk_surface_get_shared_data_gl_context (gdk_gl_context_get_surface (context)); + GdkGLContext *share = gdk_display_get_gl_context (display); GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); EGLContext ctx; EGLint context_attribs[N_EGL_ATTRS]; @@ -124,8 +123,7 @@ gdk_wayland_gl_context_realize (GdkGLContext *context, ctx = eglCreateContext (display_wayland->egl_display, display_wayland->egl_config, share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context - : shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT (shared_data_context)->egl_context - : EGL_NO_CONTEXT, + : EGL_NO_CONTEXT, context_attribs); /* If context creation failed without the ES bit, let's try again with it */ @@ -151,8 +149,7 @@ gdk_wayland_gl_context_realize (GdkGLContext *context, ctx = eglCreateContext (display_wayland->egl_display, display_wayland->egl_config, share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context - : shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT (shared_data_context)->egl_context - : EGL_NO_CONTEXT, + : EGL_NO_CONTEXT, context_attribs); } @@ -181,8 +178,7 @@ gdk_wayland_gl_context_realize (GdkGLContext *context, ctx = eglCreateContext (display_wayland->egl_display, display_wayland->egl_config, share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context - : shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT (shared_data_context)->egl_context - : EGL_NO_CONTEXT, + : EGL_NO_CONTEXT, context_attribs); } @@ -346,7 +342,7 @@ gdk_wayland_display_get_egl_display (GdkDisplay *display) g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), NULL); - if (!gdk_wayland_display_init_gl (display, NULL)) + if (!gdk_display_prepare_gl (display, NULL)) return NULL; display_wayland = GDK_WAYLAND_DISPLAY (display); @@ -428,7 +424,7 @@ get_eglconfig (EGLDisplay dpy) #undef MAX_EGL_ATTRS -gboolean +GdkGLContext * gdk_wayland_display_init_gl (GdkDisplay *display, GError **error) { @@ -436,16 +432,13 @@ gdk_wayland_display_init_gl (GdkDisplay *display, EGLint major, minor; EGLDisplay dpy; - if (display_wayland->egl_display) - return TRUE; - dpy = get_egl_display (display_wayland); if (dpy == NULL) { g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, _("Failed to create EGL display")); - return FALSE; + return NULL; } if (!eglInitialize (dpy, &major, &minor)) @@ -453,7 +446,7 @@ gdk_wayland_display_init_gl (GdkDisplay *display, g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, _("Could not initialize EGL display")); - return FALSE; + return NULL; } if (!eglBindAPI (EGL_OPENGL_API)) @@ -462,7 +455,7 @@ gdk_wayland_display_init_gl (GdkDisplay *display, g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, _("No GL implementation is available")); - return FALSE; + return NULL; } if (!epoxy_has_egl_extension (dpy, "EGL_KHR_create_context")) @@ -471,7 +464,7 @@ gdk_wayland_display_init_gl (GdkDisplay *display, g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_UNSUPPORTED_PROFILE, _("Core GL is not available on EGL implementation")); - return FALSE; + return NULL; } display_wayland->egl_config = get_eglconfig (dpy); @@ -481,7 +474,7 @@ gdk_wayland_display_init_gl (GdkDisplay *display, g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_UNSUPPORTED_FORMAT, _("No available configurations for the given pixel format")); - return FALSE; + return NULL; } display_wayland->egl_display = dpy; @@ -511,21 +504,19 @@ gdk_wayland_display_init_gl (GdkDisplay *display, eglQueryString (dpy, EGL_CLIENT_APIS), eglQueryString (dpy, EGL_EXTENSIONS))); - return TRUE; + return g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT, + "display", display, + NULL); } GdkGLContext * -gdk_wayland_surface_create_gl_context (GdkSurface *surface, +gdk_wayland_surface_create_gl_context (GdkSurface *surface, gboolean attached, GdkGLContext *share, GError **error) { - GdkDisplay *display = gdk_surface_get_display (surface); GdkWaylandGLContext *context; - if (!gdk_wayland_display_init_gl (display, error)) - return NULL; - context = g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT, "surface", surface, "shared-context", share, diff --git a/gdk/wayland/gdkglcontext-wayland.h b/gdk/wayland/gdkglcontext-wayland.h index 6e75a4bffd..d939a4ad39 100644 --- a/gdk/wayland/gdkglcontext-wayland.h +++ b/gdk/wayland/gdkglcontext-wayland.h @@ -44,9 +44,9 @@ struct _GdkWaylandGLContextClass GdkGLContextClass parent_class; }; -gboolean gdk_wayland_display_init_gl (GdkDisplay *display, +GdkGLContext * gdk_wayland_display_init_gl (GdkDisplay *display, GError **error); -GdkGLContext * gdk_wayland_surface_create_gl_context (GdkSurface *surface, +GdkGLContext * gdk_wayland_surface_create_gl_context (GdkSurface *surface, gboolean attach, GdkGLContext *share, GError **error); diff --git a/gdk/win32/gdkglcontext-win32.c b/gdk/win32/gdkglcontext-win32.c index 08c573b630..8f913f729d 100644 --- a/gdk/win32/gdkglcontext-win32.c +++ b/gdk/win32/gdkglcontext-win32.c @@ -906,8 +906,6 @@ static gboolean gdk_win32_gl_context_realize (GdkGLContext *context, GError **error) { - GdkGLContext *share = gdk_gl_context_get_shared_context (context); - GdkGLContext *shared_data_context; GdkWin32GLContext *context_win32 = GDK_WIN32_GL_CONTEXT (context); gboolean debug_bit, compat_bit, legacy_bit; @@ -922,11 +920,11 @@ gdk_win32_gl_context_realize (GdkGLContext *context, GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface); GdkDisplay *display = gdk_surface_get_display (surface); GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display); + GdkGLContext *share = gdk_display_get_gl_context (display); gdk_gl_context_get_required_version (context, &major, &minor); debug_bit = gdk_gl_context_get_debug_enabled (context); compat_bit = gdk_gl_context_get_forward_compatible (context); - shared_data_context = gdk_surface_get_shared_data_gl_context (surface); /* * A legacy context cannot be shared with core profile ones, so this means we @@ -976,7 +974,7 @@ gdk_win32_gl_context_realize (GdkGLContext *context, legacy_bit ? "yes" : "no")); hglrc = _create_gl_context (context_win32->gl_hdc, - share ? share : shared_data_context, + share, flags, major, minor, @@ -1018,7 +1016,7 @@ gdk_win32_gl_context_realize (GdkGLContext *context, ctx = _create_egl_context (win32_display->egl_disp, context_win32->egl_config, - share ? share : shared_data_context, + share, flags, major, minor, diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 4500513057..acefe43b54 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -1335,40 +1335,6 @@ set_sm_client_id (GdkDisplay *display, gdk_x11_get_xatom_by_name_for_display (display, "SM_CLIENT_ID")); } -static void -gdk_x11_display_query_default_visual (GdkX11Display *self, - Visual **out_visual, - int *out_depth) -{ - XVisualInfo template, *visinfo; - int n_visuals; - Display *dpy; - - dpy = gdk_x11_display_get_xdisplay (GDK_DISPLAY (self)); - - template.screen = self->screen->screen_num; - template.depth = 32; - template.red_mask = 0xff0000; - template.green_mask = 0x00ff00; - template.blue_mask = 0x0000ff; - - visinfo = XGetVisualInfo (dpy, - VisualScreenMask | VisualDepthMask - | VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask, - &template, - &n_visuals); - if (visinfo != NULL) - { - *out_visual = visinfo[0].visual; - *out_depth = visinfo[0].depth; - XFree (visinfo); - return; - } - - *out_visual = DefaultVisual (dpy, self->screen->screen_num); - *out_depth = DefaultDepth (dpy, self->screen->screen_num); -} - /** * gdk_x11_display_open: * @display_name: (nullable): name of the X display. @@ -1439,36 +1405,11 @@ gdk_x11_display_open (const char *display_name) /* If GL is available we want to pick better default/rgba visuals, * as we care about GLX details such as alpha/depth/stencil depth, * stereo and double buffering + * + * Note that this also sets up the leader surface while creating the inital + * GL context. */ - if (!gdk_x11_display_init_gl (display_x11, &display_x11->window_visual, &display_x11->window_depth, &display_x11->gl_error)) - gdk_x11_display_query_default_visual (display_x11, &display_x11->window_visual, &display_x11->window_depth); - - display_x11->window_colormap = XCreateColormap (xdisplay, - DefaultRootWindow (xdisplay), - display_x11->window_visual, - AllocNone); - gdk_display_set_rgba (display, display_x11->window_depth == 32); - - /* We need to initialize events after we have the screen - * structures in places - */ - _gdk_x11_xsettings_init (GDK_X11_SCREEN (display_x11->screen)); - - display_x11->device_manager = _gdk_x11_device_manager_new (display); - - gdk_event_init (display); - - display_x11->leader_gdk_surface = - _gdk_x11_display_create_surface (display, - GDK_SURFACE_TEMP, - NULL, - -100, -100, 1, 1); - - (_gdk_x11_surface_get_toplevel (display_x11->leader_gdk_surface))->is_leader = TRUE; - - display_x11->leader_window = GDK_SURFACE_XID (display_x11->leader_gdk_surface); - - display_x11->leader_window_title_set = FALSE; + gdk_display_prepare_gl (display, NULL); #ifdef HAVE_XFIXES if (XFixesQueryExtension (display_x11->xdisplay, @@ -2874,6 +2815,83 @@ gdk_boolean_handled_accumulator (GSignalInvocationHint *ihint, return continue_emission; } +static void +gdk_x11_display_query_default_visual (GdkX11Display *self, + Visual **out_visual, + int *out_depth) +{ + XVisualInfo template, *visinfo; + int n_visuals; + Display *dpy; + + dpy = gdk_x11_display_get_xdisplay (GDK_DISPLAY (self)); + + template.screen = self->screen->screen_num; + template.depth = 32; + template.red_mask = 0xff0000; + template.green_mask = 0x00ff00; + template.blue_mask = 0x0000ff; + + visinfo = XGetVisualInfo (dpy, + VisualScreenMask | VisualDepthMask + | VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask, + &template, + &n_visuals); + if (visinfo != NULL) + { + *out_visual = visinfo[0].visual; + *out_depth = visinfo[0].depth; + XFree (visinfo); + return; + } + + *out_visual = DefaultVisual (dpy, self->screen->screen_num); + *out_depth = DefaultDepth (dpy, self->screen->screen_num); +} + +static GdkGLContext * +gdk_x11_display_init_gl (GdkDisplay *display, + GError **error) +{ + GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); + Display *xdisplay = gdk_x11_display_get_xdisplay (display); + gboolean have_gl; + + have_gl = gdk_x11_display_init_gl_backend (display_x11, &display_x11->window_visual, &display_x11->window_depth, error); + if (!have_gl) + gdk_x11_display_query_default_visual (display_x11, &display_x11->window_visual, &display_x11->window_depth); + + display_x11->window_colormap = XCreateColormap (xdisplay, + DefaultRootWindow (xdisplay), + display_x11->window_visual, + AllocNone); + gdk_display_set_rgba (display, display_x11->window_depth == 32); + + /* We need to initialize events after we have the screen + * structures in places + */ + _gdk_x11_xsettings_init (GDK_X11_SCREEN (display_x11->screen)); + + display_x11->device_manager = _gdk_x11_device_manager_new (display); + + gdk_event_init (display); + + display_x11->leader_gdk_surface = + _gdk_x11_display_create_surface (display, + GDK_SURFACE_TEMP, + NULL, + -100, -100, 1, 1); + + (_gdk_x11_surface_get_toplevel (display_x11->leader_gdk_surface))->is_leader = TRUE; + display_x11->leader_window = GDK_SURFACE_XID (display_x11->leader_gdk_surface); + display_x11->leader_window_title_set = FALSE; + + if (!have_gl) + return NULL; + + return gdk_x11_surface_create_gl_context (display_x11->leader_gdk_surface, FALSE, NULL, error); +} + static void gdk_x11_display_class_init (GdkX11DisplayClass * class) { @@ -2904,6 +2922,7 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class) display_class->create_surface = _gdk_x11_display_create_surface; display_class->get_keymap = gdk_x11_display_get_keymap; + display_class->init_gl = gdk_x11_display_init_gl; display_class->make_gl_context_current = gdk_x11_display_make_gl_context_current; display_class->get_default_seat = gdk_x11_display_get_default_seat; diff --git a/gdk/x11/gdkglcontext-egl.c b/gdk/x11/gdkglcontext-egl.c index 56a17168b1..271e77c2f2 100644 --- a/gdk/x11/gdkglcontext-egl.c +++ b/gdk/x11/gdkglcontext-egl.c @@ -423,19 +423,16 @@ gdk_x11_gl_context_egl_realize (GdkGLContext *context, GdkX11Display *display_x11; GdkDisplay *display; GdkX11GLContextEGL *context_egl; - GdkGLContext *share, *shared_data_context; - GdkSurface *surface; + GdkGLContext *share; gboolean debug_bit, forward_bit, legacy_bit, use_es; int major, minor, i = 0; EGLint context_attrs[N_EGL_ATTRS]; - surface = gdk_gl_context_get_surface (context); - display = gdk_surface_get_display (surface); + display = gdk_gl_context_get_display (context); context_egl = GDK_X11_GL_CONTEXT_EGL (context); display_x11 = GDK_X11_DISPLAY (display); - share = gdk_gl_context_get_shared_context (context); - shared_data_context = gdk_surface_get_shared_data_gl_context (surface); + share = gdk_display_get_gl_context (display); gdk_gl_context_get_required_version (context, &major, &minor); debug_bit = gdk_gl_context_get_debug_enabled (context); @@ -503,9 +500,7 @@ gdk_x11_gl_context_egl_realize (GdkGLContext *context, display_x11->egl_config, share != NULL ? GDK_X11_GL_CONTEXT_EGL (share)->egl_context - : shared_data_context != NULL - ? GDK_X11_GL_CONTEXT_EGL (shared_data_context)->egl_context - : EGL_NO_CONTEXT, + : EGL_NO_CONTEXT, context_attrs); /* If we're not asking for a GLES context, and we don't have the legacy bit set @@ -528,9 +523,7 @@ gdk_x11_gl_context_egl_realize (GdkGLContext *context, display_x11->egl_config, share != NULL ? GDK_X11_GL_CONTEXT_EGL (share)->egl_context - : shared_data_context != NULL - ? GDK_X11_GL_CONTEXT_EGL (shared_data_context)->egl_context - : EGL_NO_CONTEXT, + : EGL_NO_CONTEXT, context_attrs); } diff --git a/gdk/x11/gdkglcontext-glx.c b/gdk/x11/gdkglcontext-glx.c index a1ecb68313..36b5e8a1b4 100644 --- a/gdk/x11/gdkglcontext-glx.c +++ b/gdk/x11/gdkglcontext-glx.c @@ -503,20 +503,18 @@ gdk_x11_gl_context_glx_realize (GdkGLContext *context, GdkDisplay *display; GdkX11GLContextGLX *context_glx; Display *dpy; + GdkSurface *surface; DrawableInfo *info; GdkGLContext *share; - GdkGLContext *shared_data_context; - GdkSurface *surface; gboolean debug_bit, compat_bit, legacy_bit, es_bit; int major, minor, flags; - surface = gdk_gl_context_get_surface (context); - display = gdk_surface_get_display (surface); + display = gdk_gl_context_get_display (context); dpy = gdk_x11_display_get_xdisplay (display); context_glx = GDK_X11_GL_CONTEXT_GLX (context); display_x11 = GDK_X11_DISPLAY (display); - share = gdk_gl_context_get_shared_context (context); - shared_data_context = gdk_surface_get_shared_data_gl_context (surface); + share = gdk_display_get_gl_context (display); + surface = gdk_gl_context_get_surface (context); gdk_gl_context_get_required_version (context, &major, &minor); debug_bit = gdk_gl_context_get_debug_enabled (context); @@ -556,7 +554,7 @@ gdk_x11_gl_context_glx_realize (GdkGLContext *context, if (legacy_bit && !GDK_X11_DISPLAY (display)->has_glx_create_context) { GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Creating legacy GL context on request")); - context_glx->glx_context = create_legacy_context (display, display_x11->glx_config, share ? share : shared_data_context); + context_glx->glx_context = create_legacy_context (display, display_x11->glx_config, share); } else { @@ -581,14 +579,14 @@ gdk_x11_gl_context_glx_realize (GdkGLContext *context, GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Creating GL3 context")); context_glx->glx_context = create_gl3_context (display, display_x11->glx_config, - share ? share : shared_data_context, + share, profile, flags, major, minor); /* Fall back to legacy in case the GL3 context creation failed */ if (context_glx->glx_context == NULL) { GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Creating fallback legacy context")); - context_glx->glx_context = create_legacy_context (display, display_x11->glx_config, share ? share : shared_data_context); + context_glx->glx_context = create_legacy_context (display, display_x11->glx_config, share); legacy_bit = TRUE; es_bit = FALSE; } diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c index c74a994c70..3585367596 100644 --- a/gdk/x11/gdkglcontext-x11.c +++ b/gdk/x11/gdkglcontext-x11.c @@ -103,10 +103,10 @@ gdk_x11_display_make_gl_context_current (GdkDisplay *display, } gboolean -gdk_x11_display_init_gl (GdkX11Display *self, - Visual **out_visual, - int *out_depth, - GError **error) +gdk_x11_display_init_gl_backend (GdkX11Display *self, + Visual **out_visual, + int *out_depth, + GError **error) { GdkDisplay *display G_GNUC_UNUSED = GDK_DISPLAY (self); diff --git a/gdk/x11/gdkglcontext-x11.h b/gdk/x11/gdkglcontext-x11.h index 5cc2ebf5d6..e62a4795d7 100644 --- a/gdk/x11/gdkglcontext-x11.h +++ b/gdk/x11/gdkglcontext-x11.h @@ -59,7 +59,7 @@ struct _GdkX11GLContextClass void (* bind_for_frame_fence) (GdkX11GLContext *self); }; -gboolean gdk_x11_display_init_gl (GdkX11Display *self, +gboolean gdk_x11_display_init_gl_backend (GdkX11Display *self, Visual **out_visual, int *out_depth, GError **error); diff --git a/gsk/ngl/gsknglrenderer.c b/gsk/ngl/gsknglrenderer.c index e343479abd..c84f112047 100644 --- a/gsk/ngl/gsknglrenderer.c +++ b/gsk/ngl/gsknglrenderer.c @@ -21,7 +21,7 @@ #include "config.h" #include -#include +#include #include #include @@ -105,7 +105,7 @@ gsk_ngl_renderer_realize (GskRenderer *renderer, !gdk_gl_context_realize (context, error)) goto failure; - if (!(shared_context = gdk_surface_get_shared_data_gl_context (surface))) + if (!(shared_context = gdk_display_get_gl_context (gdk_surface_get_display (surface)))) { g_set_error (error, GDK_GL_ERROR,