[gtk+] GL: Split GL context creation in two phases
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] GL: Split GL context creation in two phases
- Date: Mon, 9 Feb 2015 19:16:27 +0000 (UTC)
commit 22e6f37c9c00ca3e97fbd454774a178473a0c93e
Author: Emmanuele Bassi <ebassi gnome org>
Date: Tue Jan 27 21:23:23 2015 +0000
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
gdk/gdkglcontext.c | 59 +++++-
gdk/gdkglcontext.h | 18 ++-
gdk/gdkglcontextprivate.h | 3 +
gdk/gdkwindow.c | 31 +++-
gdk/gdkwindow.h | 1 -
gdk/gdkwindowimpl.h | 4 +-
gdk/wayland/gdkglcontext-wayland.c | 80 +++++---
gdk/x11/gdkglcontext-x11.c | 375 +++++++++++++++++++-----------------
gtk/gtkglarea.c | 17 ++-
9 files changed, 363 insertions(+), 225 deletions(-)
---
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 829e302..0c3f564 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);
}
}
diff --git a/gdk/gdkglcontext.h b/gdk/gdkglcontext.h
index be71ae4..3155948 100644
--- a/gdk/gdkglcontext.h
+++ b/gdk/gdkglcontext.h
@@ -43,18 +43,24 @@ GDK_AVAILABLE_IN_3_16
GType gdk_gl_context_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_16
-GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context);
+GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context);
GDK_AVAILABLE_IN_3_16
-GdkWindow * gdk_gl_context_get_window (GdkGLContext *context);
+GdkWindow * gdk_gl_context_get_window (GdkGLContext *context);
GDK_AVAILABLE_IN_3_16
-GdkGLProfile gdk_gl_context_get_profile (GdkGLContext *context);
+GdkGLProfile gdk_gl_context_get_profile (GdkGLContext *context);
+GDK_AVAILABLE_IN_3_16
+GdkGLContext * gdk_gl_context_get_shared_context (GdkGLContext *context);
+
+GDK_AVAILABLE_IN_3_16
+gboolean gdk_gl_context_realize (GdkGLContext *context,
+ GError **error);
GDK_AVAILABLE_IN_3_16
-void gdk_gl_context_make_current (GdkGLContext *context);
+void gdk_gl_context_make_current (GdkGLContext *context);
GDK_AVAILABLE_IN_3_16
-GdkGLContext * gdk_gl_context_get_current (void);
+GdkGLContext * gdk_gl_context_get_current (void);
GDK_AVAILABLE_IN_3_16
-void gdk_gl_context_clear_current (void);
+void gdk_gl_context_clear_current (void);
G_END_DECLS
diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h
index 4efface..f282539 100644
--- a/gdk/gdkglcontextprivate.h
+++ b/gdk/gdkglcontextprivate.h
@@ -40,6 +40,9 @@ struct _GdkGLContextClass
{
GObjectClass parent_class;
+ gboolean (* realize) (GdkGLContext *context,
+ GError **error);
+
void (* end_frame) (GdkGLContext *context,
cairo_region_t *painted,
cairo_region_t *damage);
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 3103367..9cc257b 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -2724,8 +2724,11 @@ gdk_window_ref_impl_surface (GdkWindow *window)
}
GdkGLContext *
-gdk_window_get_paint_gl_context (GdkWindow *window, GError **error)
+gdk_window_get_paint_gl_context (GdkWindow *window,
+ GError **error)
{
+ GError *internal_error = NULL;
+
if (_gdk_gl_flags & GDK_GL_DISABLE)
{
g_set_error_literal (error, GDK_GL_ERROR,
@@ -2741,21 +2744,36 @@ gdk_window_get_paint_gl_context (GdkWindow *window, GError **error)
TRUE,
GDK_GL_PROFILE_3_2_CORE,
NULL,
- error);
+ &internal_error);
if (window->impl_window->gl_paint_context == NULL &&
- g_error_matches (*error, GDK_GL_ERROR,
+ g_error_matches (internal_error, GDK_GL_ERROR,
GDK_GL_ERROR_UNSUPPORTED_PROFILE))
{
- g_clear_error (error);
+ g_clear_error (&internal_error);
window->impl_window->gl_paint_context =
GDK_WINDOW_IMPL_GET_CLASS (window->impl)->create_gl_context (window->impl_window,
TRUE,
GDK_GL_PROFILE_DEFAULT,
NULL,
- error);
+ &internal_error);
}
}
+ if (internal_error != NULL)
+ {
+ g_propagate_error (error, internal_error);
+ g_clear_object (&(window->impl_window->gl_paint_context));
+ return NULL;
+ }
+
+ gdk_gl_context_realize (window->impl_window->gl_paint_context, &internal_error);
+ if (internal_error != NULL)
+ {
+ g_propagate_error (error, internal_error);
+ g_clear_object (&(window->impl_window->gl_paint_context));
+ return NULL;
+ }
+
return window->impl_window->gl_paint_context;
}
@@ -2771,6 +2789,9 @@ gdk_window_get_paint_gl_context (GdkWindow *window, GError **error)
*
* If the creation of the #GdkGLContext failed, @error will be set.
*
+ * Before using the returned #GdkGLContext, you will need to
+ * call gdk_gl_context_make_current().
+ *
* Returns: (transfer full): the newly created #GdkGLContext, or
* %NULL on error
*
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index 74e23d2..85a8567 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -1116,7 +1116,6 @@ GdkGLContext * gdk_window_create_gl_context (GdkWindow *window,
GdkGLProfile profile,
GError **error);
-
G_END_DECLS
#endif /* __GDK_WINDOW_H__ */
diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h
index efdaa1f..1ac327f 100644
--- a/gdk/gdkwindowimpl.h
+++ b/gdk/gdkwindowimpl.h
@@ -296,6 +296,9 @@ struct _GdkWindowImplClass
GdkGLProfile profile,
GdkGLContext *share,
GError **error);
+ gboolean (* realize_gl_context) (GdkWindow *window,
+ GdkGLContext *context,
+ GError **error);
void (*invalidate_for_new_frame)(GdkWindow *window,
cairo_region_t *update_area);
};
@@ -303,7 +306,6 @@ struct _GdkWindowImplClass
/* Interface Functions */
GType gdk_window_impl_get_type (void) G_GNUC_CONST;
-
G_END_DECLS
#endif /* __GDK_WINDOW_IMPL_H__ */
diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c
index c8d4ed2..a5fa5df 100644
--- a/gdk/wayland/gdkglcontext-wayland.c
+++ b/gdk/wayland/gdkglcontext-wayland.c
@@ -100,6 +100,47 @@ gdk_wayland_window_invalidate_for_new_frame (GdkWindow *window,
}
}
+static gboolean
+gdk_wayland_gl_context_realize (GdkGLContext *context,
+ GError **error)
+{
+ 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);
+ GdkGLProfile profile = gdk_gl_context_get_profile (context);
+ GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+ EGLContext ctx;
+ EGLint context_attribs[3];
+ int i;
+
+ i = 0;
+ if (profile == GDK_GL_PROFILE_3_2_CORE)
+ {
+ context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
+ context_attribs[i++] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
+ }
+ context_attribs[i++] = EGL_NONE;
+
+ ctx = eglCreateContext (display_wayland->egl_display,
+ context_wayland->egl_config,
+ share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
+ : EGL_NO_CONTEXT,
+ context_attribs);
+ if (ctx == NULL)
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("Unable to create a GL context"));
+ return FALSE;
+ }
+
+ GDK_NOTE (OPENGL, g_print ("Created EGL context[%p]\n", ctx));
+
+ context_wayland->egl_context = ctx;
+
+ return TRUE;
+}
+
static void
gdk_wayland_gl_context_end_frame (GdkGLContext *context,
cairo_region_t *painted,
@@ -142,11 +183,13 @@ gdk_wayland_gl_context_end_frame (GdkGLContext *context,
static void
gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
{
- GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
- context_class->end_frame = gdk_wayland_gl_context_end_frame;
gobject_class->dispose = gdk_x11_gl_context_dispose;
+
+ context_class->realize = gdk_wayland_gl_context_realize;
+ context_class->end_frame = gdk_wayland_gl_context_end_frame;
}
static void
@@ -213,9 +256,9 @@ gdk_wayland_display_init_gl (GdkDisplay *display)
#define MAX_EGL_ATTRS 30
static gboolean
-find_eglconfig_for_window (GdkWindow *window,
- EGLConfig *egl_config_out,
- GError **error)
+find_eglconfig_for_window (GdkWindow *window,
+ EGLConfig *egl_config_out,
+ GError **error)
{
GdkDisplay *display = gdk_window_get_display (window);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
@@ -294,10 +337,7 @@ gdk_wayland_window_create_gl_context (GdkWindow *window,
GdkDisplay *display = gdk_window_get_display (window);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GdkWaylandGLContext *context;
- EGLContext ctx;
EGLConfig config;
- int i;
- EGLint context_attribs[3];
if (!gdk_wayland_display_init_gl (display))
{
@@ -322,29 +362,6 @@ gdk_wayland_window_create_gl_context (GdkWindow *window,
if (!find_eglconfig_for_window (window, &config, error))
return NULL;
- i = 0;
- if (profile == GDK_GL_PROFILE_3_2_CORE)
- {
- context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
- context_attribs[i++] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
- }
- context_attribs[i++] = EGL_NONE;
-
- ctx = eglCreateContext (display_wayland->egl_display,
- config,
- share ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context : EGL_NO_CONTEXT,
- context_attribs);
- if (ctx == NULL)
- {
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_NOT_AVAILABLE,
- _("Unable to create a GL context"));
- return NULL;
- }
-
- GDK_NOTE (OPENGL,
- g_print ("Created EGL context[%p]\n", ctx));
-
context = g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT,
"display", display,
"window", window,
@@ -353,7 +370,6 @@ gdk_wayland_window_create_gl_context (GdkWindow *window,
NULL);
context->egl_config = config;
- context->egl_context = ctx;
context->is_attached = attached;
return GDK_GL_CONTEXT (context);
diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c
index 6eed9f9..9f525ad 100644
--- a/gdk/x11/gdkglcontext-x11.c
+++ b/gdk/x11/gdkglcontext-x11.c
@@ -534,6 +534,185 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
return TRUE;
}
+static XVisualInfo *
+find_xvisinfo_for_fbconfig (GdkDisplay *display,
+ GLXFBConfig config)
+{
+ Display *dpy = gdk_x11_display_get_xdisplay (display);
+
+ return glXGetVisualFromFBConfig (dpy, config);
+}
+
+static GLXContext
+create_gl3_context (GdkDisplay *display,
+ GLXFBConfig config,
+ GdkGLContext *share)
+{
+ /* There are no profiles before OpenGL 3.2.
+ *
+ * The GLX_ARB_create_context_profile spec says:
+ *
+ * If the requested OpenGL version is less than 3.2,
+ * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
+ * of the context is determined solely by the requested version.
+ *
+ * Which means we can ask for the CORE_PROFILE_BIT without asking for
+ * a 3.2 version.
+ */
+ static const int attrib_list[] = {
+ GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+ GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
+ GLX_CONTEXT_MINOR_VERSION_ARB, 2,
+ None,
+ };
+
+ GdkX11GLContext *context_x11 = NULL;
+
+ if (share != NULL)
+ context_x11 = GDK_X11_GL_CONTEXT (share);
+
+ return glXCreateContextAttribsARB (gdk_x11_display_get_xdisplay (display),
+ config,
+ context_x11 != NULL ? context_x11->glx_context : NULL,
+ True,
+ attrib_list);
+}
+
+static GLXContext
+create_gl_context (GdkDisplay *display,
+ GLXFBConfig config,
+ GdkGLContext *share)
+{
+ GdkX11GLContext *context_x11 = NULL;
+
+ if (share != NULL)
+ context_x11 = GDK_X11_GL_CONTEXT (share);
+
+ return glXCreateNewContext (gdk_x11_display_get_xdisplay (display),
+ config,
+ GLX_RGBA_TYPE,
+ context_x11 != NULL ? context_x11->glx_context : NULL,
+ True);
+}
+
+static gboolean
+gdk_x11_gl_context_realize (GdkGLContext *context,
+ GError **error)
+{
+ GdkDisplay *display;
+ GdkX11GLContext *context_x11;
+ GLXWindow drawable;
+ XVisualInfo *xvisinfo;
+ Display *dpy;
+ DrawableInfo *info;
+ GdkGLProfile profile;
+ GdkGLContext *share;
+ GdkWindow *window;
+
+ window = gdk_gl_context_get_window (context);
+ display = gdk_window_get_display (window);
+ dpy = gdk_x11_display_get_xdisplay (display);
+ context_x11 = GDK_X11_GL_CONTEXT (context);
+ profile = gdk_gl_context_get_profile (context);
+ share = gdk_gl_context_get_shared_context (context);
+
+ /* we check for the presence of the GLX_ARB_create_context_profile
+ * extension before checking for a GLXFBConfig.
+ */
+ if (profile == GDK_GL_PROFILE_3_2_CORE)
+ {
+ GDK_NOTE (OPENGL, g_print ("Creating core GLX context\n"));
+ context_x11->glx_context = create_gl3_context (display, context_x11->glx_config, share);
+ }
+ else
+ {
+ /* GDK_GL_PROFILE_DEFAULT is currently
+ * equivalent to the LEGACY profile
+ */
+ profile = GDK_GL_PROFILE_LEGACY;
+ GDK_NOTE (OPENGL, g_print ("Creating legacy GLX context\n"));
+ context_x11->glx_context = create_gl_context (display, context_x11->glx_config, share);
+ }
+
+ if (context_x11->glx_context == NULL)
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("Unable to create a GL context"));
+ return FALSE;
+ }
+
+ xvisinfo = find_xvisinfo_for_fbconfig (display, context_x11->glx_config);
+
+ info = get_glx_drawable_info (window->impl_window);
+ if (info == NULL)
+ {
+ XSetWindowAttributes attrs;
+ unsigned long mask;
+
+ gdk_x11_display_error_trap_push (display);
+
+ info = g_slice_new0 (DrawableInfo);
+ info->display = display;
+ info->last_frame_counter = 0;
+
+ attrs.override_redirect = True;
+ attrs.colormap = XCreateColormap (dpy, DefaultRootWindow (dpy), xvisinfo->visual, AllocNone);
+ attrs.border_pixel = 0;
+ mask = CWOverrideRedirect | CWColormap | CWBorderPixel;
+ info->dummy_xwin = XCreateWindow (dpy, DefaultRootWindow (dpy),
+ -100, -100, 1, 1,
+ 0,
+ xvisinfo->depth,
+ CopyFromParent,
+ xvisinfo->visual,
+ mask,
+ &attrs);
+ XMapWindow(dpy, info->dummy_xwin);
+
+ if (GDK_X11_DISPLAY (display)->glx_version >= 13)
+ {
+ info->glx_drawable = glXCreateWindow (dpy, context_x11->glx_config,
+ gdk_x11_window_get_xid (window->impl_window),
+ NULL);
+ info->dummy_glx = glXCreateWindow (dpy, context_x11->glx_config, info->dummy_xwin, NULL);
+ }
+
+ if (gdk_x11_display_error_trap_pop (display))
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("Unable to create a GL context"));
+
+ XFree (xvisinfo);
+ drawable_info_free (info);
+ glXDestroyContext (dpy, context_x11->glx_context);
+ context_x11->glx_context = NULL;
+
+ return FALSE;
+ }
+
+ set_glx_drawable_info (window->impl_window, info);
+ }
+
+ XFree (xvisinfo);
+
+ if (context_x11->is_attached)
+ drawable = info->glx_drawable ? info->glx_drawable : gdk_x11_window_get_xid (window->impl_window);
+ else
+ drawable = info->dummy_glx ? info->dummy_glx : info->dummy_xwin;
+
+ context_x11->is_direct = glXIsDirect (dpy, context_x11->glx_context);
+ context_x11->drawable = drawable;
+
+ GDK_NOTE (OPENGL,
+ g_print ("Realized GLX context[%p], %s\n",
+ context_x11->glx_context,
+ context_x11->is_direct ? "direct" : "indirect"));
+
+ return TRUE;
+}
+
static void
gdk_x11_gl_context_dispose (GObject *gobject)
{
@@ -562,6 +741,7 @@ gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass)
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ context_class->realize = gdk_x11_gl_context_realize;
context_class->end_frame = gdk_x11_gl_context_end_frame;
context_class->texture_from_surface = gdk_x11_gl_context_texture_from_surface;
@@ -645,11 +825,10 @@ gdk_x11_screen_init_gl (GdkScreen *screen)
#define MAX_GLX_ATTRS 30
static gboolean
-find_fbconfig_for_visual (GdkDisplay *display,
- GdkVisual *visual,
- GLXFBConfig *fb_config_out,
- XVisualInfo **visinfo_out,
- GError **error)
+find_fbconfig_for_visual (GdkDisplay *display,
+ GdkVisual *visual,
+ GLXFBConfig *fb_config_out,
+ GError **error)
{
static int attrs[MAX_GLX_ATTRS];
Display *dpy = gdk_x11_display_get_xdisplay (display);
@@ -710,16 +889,15 @@ find_fbconfig_for_visual (GdkDisplay *display,
continue;
if (visinfo->visualid != xvisual_id)
- continue;
+ {
+ XFree (visinfo);
+ continue;
+ }
if (fb_config_out != NULL)
*fb_config_out = configs[i];
- if (visinfo_out != NULL)
- *visinfo_out = visinfo;
- else
- XFree (visinfo);
-
+ XFree (visinfo);
retval = TRUE;
goto out;
}
@@ -734,58 +912,6 @@ out:
return retval;
}
-static GLXContext
-create_gl3_context (GdkDisplay *display,
- GLXFBConfig config,
- GdkGLContext *share)
-{
- /* There are no profiles before OpenGL 3.2.
- *
- * The GLX_ARB_create_context_profile spec says:
- *
- * If the requested OpenGL version is less than 3.2,
- * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
- * of the context is determined solely by the requested version.
- *
- * Which means we can ask for the CORE_PROFILE_BIT without asking for
- * a 3.2 version.
- */
- static const int attrib_list[] = {
- GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
- GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
- GLX_CONTEXT_MINOR_VERSION_ARB, 2,
- None,
- };
-
- GdkX11GLContext *context_x11 = NULL;
-
- if (share != NULL)
- context_x11 = GDK_X11_GL_CONTEXT (share);
-
- return glXCreateContextAttribsARB (gdk_x11_display_get_xdisplay (display),
- config,
- context_x11 != NULL ? context_x11->glx_context : NULL,
- True,
- attrib_list);
-}
-
-static GLXContext
-create_gl_context (GdkDisplay *display,
- GLXFBConfig config,
- GdkGLContext *share)
-{
- GdkX11GLContext *context_x11 = NULL;
-
- if (share != NULL)
- context_x11 = GDK_X11_GL_CONTEXT (share);
-
- return glXCreateNewContext (gdk_x11_display_get_xdisplay (display),
- config,
- GLX_RGBA_TYPE,
- context_x11 != NULL ? context_x11->glx_context : NULL,
- True);
-}
-
struct glvisualinfo {
int supports_gl;
int double_buffer;
@@ -951,12 +1077,13 @@ save_cached_gl_visuals (GdkDisplay *display, int system, int rgba)
visualdata[1] = rgba;
gdk_x11_display_error_trap_push (display);
- XChangeProperty(dpy, DefaultRootWindow (dpy), gdk_x11_get_xatom_by_name_for_display (display,
"GDK_VISUALS"),
- XA_INTEGER, 32, PropModeReplace, (unsigned char *)visualdata, 2);
+ XChangeProperty (dpy, DefaultRootWindow (dpy),
+ gdk_x11_get_xatom_by_name_for_display (display, "GDK_VISUALS"),
+ XA_INTEGER, 32, PropModeReplace,
+ (unsigned char *)visualdata, 2);
gdk_x11_display_error_trap_pop_ignored (display);
}
-
void
_gdk_x11_screen_update_visuals_for_gl (GdkScreen *screen)
{
@@ -1038,27 +1165,24 @@ _gdk_x11_screen_update_visuals_for_gl (GdkScreen *screen)
x11_screen->rgba_visual ? gdk_x11_visual_get_xvisual
(x11_screen->rgba_visual)->visualid : 0);
}
-
GdkGLContext *
gdk_x11_window_create_gl_context (GdkWindow *window,
- gboolean attached,
- GdkGLProfile profile,
- GdkGLContext *share,
- GError **error)
+ gboolean attached,
+ GdkGLProfile profile,
+ GdkGLContext *share,
+ GError **error)
{
GdkDisplay *display;
GdkX11GLContext *context;
GdkVisual *visual;
GLXFBConfig config;
- GLXContext glx_context;
- GLXWindow drawable;
- gboolean is_direct;
- XVisualInfo *xvisinfo;
- Display *dpy;
- DrawableInfo *info;
display = gdk_window_get_display (window);
+ /* GDK_GL_PROFILE_DEFAULT is currently equivalent to the LEGACY profile */
+ if (profile == GDK_GL_PROFILE_DEFAULT)
+ profile = GDK_GL_PROFILE_LEGACY;
+
if (!gdk_x11_screen_init_gl (gdk_window_get_screen (window)))
{
g_set_error_literal (error, GDK_GL_ERROR,
@@ -1079,101 +1203,9 @@ gdk_x11_window_create_gl_context (GdkWindow *window,
}
visual = gdk_window_get_visual (window);
-
- if (!find_fbconfig_for_visual (display, visual, &config, &xvisinfo, error))
+ if (!find_fbconfig_for_visual (display, visual, &config, error))
return NULL;
- dpy = gdk_x11_display_get_xdisplay (display);
-
- /* we check for the presence of the GLX_ARB_create_context_profile
- * extension before checking for a GLXFBConfig.
- */
- if (profile == GDK_GL_PROFILE_3_2_CORE)
- {
- GDK_NOTE (OPENGL, g_print ("Creating core GLX context\n"));
- glx_context = create_gl3_context (display, config, share);
- }
- else
- {
- /* GDK_GL_PROFILE_DEFAULT is currently
- * equivalent to the LEGACY profile
- */
- profile = GDK_GL_PROFILE_LEGACY;
- GDK_NOTE (OPENGL, g_print ("Creating legacy GLX context\n"));
- glx_context = create_gl_context (display, config, share);
- }
-
- if (glx_context == NULL)
- {
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_NOT_AVAILABLE,
- _("Unable to create a GL context"));
- return NULL;
- }
-
- is_direct = glXIsDirect (dpy, glx_context);
-
- info = get_glx_drawable_info (window->impl_window);
- if (info == NULL)
- {
- XSetWindowAttributes attrs;
- unsigned long mask;
-
- gdk_x11_display_error_trap_push (display);
-
- info = g_slice_new0 (DrawableInfo);
- info->display = display;
- info->last_frame_counter = 0;
-
- attrs.override_redirect = True;
- attrs.colormap = XCreateColormap (dpy, DefaultRootWindow (dpy), xvisinfo->visual, AllocNone);
- attrs.border_pixel = 0;
- mask = CWOverrideRedirect | CWColormap | CWBorderPixel;
- info->dummy_xwin = XCreateWindow (dpy, DefaultRootWindow (dpy),
- -100, -100, 1, 1,
- 0,
- xvisinfo->depth,
- CopyFromParent,
- xvisinfo->visual,
- mask,
- &attrs);
- XMapWindow(dpy, info->dummy_xwin);
-
- if (GDK_X11_DISPLAY (display)->glx_version >= 13)
- {
- info->glx_drawable = glXCreateWindow (dpy, config,
- gdk_x11_window_get_xid (window->impl_window),
- NULL);
- info->dummy_glx = glXCreateWindow (dpy, config, info->dummy_xwin, NULL);
- }
-
- if (gdk_x11_display_error_trap_pop (display))
- {
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_NOT_AVAILABLE,
- _("Unable to create a GL context"));
-
- drawable_info_free (info);
- glXDestroyContext (dpy, glx_context);
-
- return NULL;
- }
-
- set_glx_drawable_info (window->impl_window, info);
- }
-
- XFree (xvisinfo);
-
- if (attached)
- drawable = info->glx_drawable ? info->glx_drawable : gdk_x11_window_get_xid (window->impl_window);
- else
- drawable = info->dummy_glx ? info->dummy_glx : info->dummy_xwin;
-
- GDK_NOTE (OPENGL,
- g_print ("Created GLX context[%p], %s\n",
- glx_context,
- is_direct ? "direct" : "indirect"));
-
context = g_object_new (GDK_TYPE_X11_GL_CONTEXT,
"display", display,
"window", window,
@@ -1183,10 +1215,7 @@ gdk_x11_window_create_gl_context (GdkWindow *window,
context->profile = profile;
context->glx_config = config;
- context->glx_context = glx_context;
- context->drawable = drawable;
context->is_attached = attached;
- context->is_direct = is_direct;
return GDK_GL_CONTEXT (context);
}
diff --git a/gtk/gtkglarea.c b/gtk/gtkglarea.c
index ee7a30f..b5f8a65 100644
--- a/gtk/gtkglarea.c
+++ b/gtk/gtkglarea.c
@@ -322,8 +322,21 @@ gtk_gl_area_real_create_context (GtkGLArea *area)
GError *error = NULL;
GdkGLContext *context;
- context = gdk_window_create_gl_context (gtk_widget_get_window (widget), priv->profile, &priv->error);
- gtk_gl_area_set_error (area, error);
+ context = gdk_window_create_gl_context (gtk_widget_get_window (widget), priv->profile, &error);
+ if (priv->error != NULL)
+ {
+ gtk_gl_area_set_error (area, error);
+ g_clear_object (&context);
+ return NULL;
+ }
+
+ gdk_gl_context_realize (context, &error);
+ if (priv->error != NULL)
+ {
+ gtk_gl_area_set_error (area, error);
+ g_clear_object (&context);
+ return NULL;
+ }
return context;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]