diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2015-01-27 21:23:23 +0000 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2015-02-09 19:10:04 +0000 |
commit | 22e6f37c9c00ca3e97fbd454774a178473a0c93e (patch) | |
tree | 02f82bcbe93f6c324245abd7e532aae9ff85e796 /gdk/gdkglcontext.c | |
parent | 8f50148a34a4d44da8e0c3022e47aeaba4ee489d (diff) | |
download | gtk+-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.c | 59 |
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); } } |