summaryrefslogtreecommitdiff
path: root/gdk/gdkglcontext.c
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2015-01-27 21:23:23 +0000
committerEmmanuele Bassi <ebassi@gnome.org>2015-02-09 19:10:04 +0000
commit22e6f37c9c00ca3e97fbd454774a178473a0c93e (patch)
tree02f82bcbe93f6c324245abd7e532aae9ff85e796 /gdk/gdkglcontext.c
parent8f50148a34a4d44da8e0c3022e47aeaba4ee489d (diff)
downloadgtk+-22e6f37c9c00ca3e97fbd454774a178473a0c93e.tar.gz
GL: Split GL context creation in two phases
One of the major requests by OpenGL users has been the ability to specify settings when creating a GL context, like the version to use or whether the debug support should be enabled. We have a couple of requirements in terms of API: • avoid, if at all possible, the "C arrays of integers with attribute, value pairs", which are hard to write and hard to bind in non-C languages. • allow failing in a recoverable way. • do not make the GL context creation API a mess of arguments. Looking at prior art, it seems that a common pattern is to split the construction phase in two: • a first phase that creates a GL context wrapper object and does preliminary checks on the environment. • a second phase that creates the backend-specific GL object. We adopted a similar pattern: • gdk_window_create_gl_context() creates a GdkGLContext • gdk_gl_context_realize() creates the underlying resources Calling gdk_gl_context_make_current() also realizes the context, so simple GL users do not need to care. Advanced users will want to call gdk_window_create_gl_context(), set up the optional requirements, and then call gdk_gl_context_realize(). If either of these two steps fails, it's possible to recover by changing the requirements, or simply creating a new GdkGLContext instance. https://bugzilla.gnome.org/show_bug.cgi?id=741946
Diffstat (limited to 'gdk/gdkglcontext.c')
-rw-r--r--gdk/gdkglcontext.c59
1 files changed, 54 insertions, 5 deletions
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 829e302c82..0c3f564930 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -89,6 +89,7 @@ typedef struct {
guint use_texture_rectangle : 1;
guint has_gl_framebuffer_blit : 1;
guint has_frame_terminator : 1;
+ guint extensions_checked : 1;
GdkGLContextPaintData *paint_data;
} GdkGLContextPrivate;
@@ -389,19 +390,54 @@ gdk_gl_context_has_frame_terminator (GdkGLContext *context)
return priv->has_frame_terminator;
}
+/**
+ * gdk_gl_context_realize:
+ * @context: a #GdkGLContext
+ * @error: return location for a #GError
+ *
+ * Realizes the given #GdkGLContext.
+ *
+ * It is safe to call this function on a realized #GdkGLContext.
+ *
+ * Returns: %TRUE if the context is realized
+ *
+ * Since: 3.16
+ */
+gboolean
+gdk_gl_context_realize (GdkGLContext *context,
+ GError **error)
+{
+ GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+
+ g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), FALSE);
+
+ if (priv->realized)
+ return priv->realized;
+
+ priv->realized = GDK_GL_CONTEXT_GET_CLASS (context)->realize (context, error);
+
+ return priv->realized;
+}
+
static void
-gdk_gl_context_realize (GdkGLContext *context)
+gdk_gl_context_check_extensions (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
gboolean has_npot, has_texture_rectangle;
+ if (!priv->realized)
+ return;
+
+ if (priv->extensions_checked)
+ return;
+
has_npot = epoxy_has_gl_extension ("GL_ARB_texture_non_power_of_two");
has_texture_rectangle = epoxy_has_gl_extension ("GL_ARB_texture_rectangle");
priv->has_gl_framebuffer_blit = epoxy_has_gl_extension ("GL_EXT_framebuffer_blit");
priv->has_frame_terminator = epoxy_has_gl_extension ("GL_GREMEDY_frame_terminator");
- if (_gdk_gl_flags & GDK_GL_TEXTURE_RECTANGLE)
+ if (G_UNLIKELY (_gdk_gl_flags & GDK_GL_TEXTURE_RECTANGLE))
priv->use_texture_rectangle = TRUE;
else if (has_npot)
priv->use_texture_rectangle = FALSE;
@@ -410,7 +446,7 @@ gdk_gl_context_realize (GdkGLContext *context)
else
g_warning ("GL implementation doesn't support any form of non-power-of-two textures");
- priv->realized = TRUE;
+ priv->extensions_checked = TRUE;
}
/**
@@ -433,11 +469,24 @@ gdk_gl_context_make_current (GdkGLContext *context)
if (current == context)
return;
+ /* we need to realize the GdkGLContext if it wasn't explicitly realized */
+ if (!priv->realized)
+ {
+ GError *error = NULL;
+
+ gdk_gl_context_realize (context, &error);
+ if (error != NULL)
+ {
+ g_critical ("Could not realize the GL context: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+ }
+
if (gdk_display_make_gl_context_current (priv->display, context))
{
g_private_replace (&thread_current_context, g_object_ref (context));
- if (!priv->realized)
- gdk_gl_context_realize (context);
+ gdk_gl_context_check_extensions (context);
}
}