diff options
author | Benjamin Otte <otte@redhat.com> | 2021-07-05 01:57:03 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2021-07-22 16:23:56 +0200 |
commit | 430b6f8fb1a8d20a1c1744e291c1ae51fdd6faac (patch) | |
tree | d9d447bff24c22b0c7682cf3d3ac215303ea4509 /gdk/gdkdisplay.c | |
parent | ba3e80cbfac5ca8f7553344b80134b70f749a89a (diff) | |
download | gtk+-430b6f8fb1a8d20a1c1744e291c1ae51fdd6faac.tar.gz |
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().
Diffstat (limited to 'gdk/gdkdisplay.c')
-rw-r--r-- | gdk/gdkdisplay.c | 135 |
1 files changed, 130 insertions, 5 deletions
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 * @@ -145,6 +156,12 @@ gdk_display_real_get_default_seat (GdkDisplay *display) } 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) { GObjectClass *object_class = G_OBJECT_CLASS (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` |