summaryrefslogtreecommitdiff
path: root/gdk/gdkdisplay.c
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2021-07-05 01:57:03 +0200
committerBenjamin Otte <otte@redhat.com>2021-07-22 16:23:56 +0200
commit430b6f8fb1a8d20a1c1744e291c1ae51fdd6faac (patch)
treed9d447bff24c22b0c7682cf3d3ac215303ea4509 /gdk/gdkdisplay.c
parentba3e80cbfac5ca8f7553344b80134b70f749a89a (diff)
downloadgtk+-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.c135
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`