[gtk+] x11: Create legacy GLX contexts



commit 18cae47e17522a37477988d7e88055f7dc467df5
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Tue Oct 6 18:59:35 2015 +0100

    x11: Create legacy GLX contexts
    
    If GLX has support for the GLX_ARB_create_context_profile extension,
    then we use the GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; if it does
    not, we fall back to the old glXCreateNewContext() API.
    
    We use the shared GdkGLContext to decide whether the GLX context should
    use the legacy bit or not.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=756142

 gdk/x11/gdkglcontext-x11.c |  100 ++++++++++++++++++++++++++++++++++++-------
 1 files changed, 83 insertions(+), 17 deletions(-)
---
diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c
index 139fae6..acbdd52 100644
--- a/gdk/x11/gdkglcontext-x11.c
+++ b/gdk/x11/gdkglcontext-x11.c
@@ -554,12 +554,13 @@ static GLXContext
 create_gl3_context (GdkDisplay   *display,
                     GLXFBConfig   config,
                     GdkGLContext *share,
+                    int           profile,
                     int           flags,
                     int           major,
                     int           minor)
 {
   int attrib_list[] = {
-    GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+    GLX_CONTEXT_PROFILE_MASK_ARB, profile,
     GLX_CONTEXT_MAJOR_VERSION_ARB, major,
     GLX_CONTEXT_MINOR_VERSION_ARB, minor,
     GLX_CONTEXT_FLAGS_ARB, flags,
@@ -586,6 +587,31 @@ create_gl3_context (GdkDisplay   *display,
   return res;
 }
 
+static GLXContext
+create_legacy_context (GdkDisplay   *display,
+                       GLXFBConfig   config,
+                       GdkGLContext *share)
+{
+  GdkX11GLContext *share_x11 = NULL;
+  GLXContext res;
+
+  if (share != NULL)
+    share_x11 = GDK_X11_GL_CONTEXT (share);
+
+  gdk_x11_display_error_trap_push (display);
+
+  res = glXCreateNewContext (gdk_x11_display_get_xdisplay (display),
+                             config,
+                             GLX_RGBA_TYPE,
+                             share_x11 != NULL ? share_x11->glx_context : NULL,
+                             TRUE);
+
+  if (gdk_x11_display_error_trap_pop (display))
+    return NULL;
+
+  return res;
+}
+
 static gboolean
 gdk_x11_gl_context_realize (GdkGLContext  *context,
                             GError       **error)
@@ -598,7 +624,7 @@ gdk_x11_gl_context_realize (GdkGLContext  *context,
   DrawableInfo *info;
   GdkGLContext *share;
   GdkWindow *window;
-  gboolean debug_bit, compat_bit;
+  gboolean debug_bit, compat_bit, legacy_bit;
   int major, minor, flags;
 
   window = gdk_gl_context_get_window (context);
@@ -611,6 +637,16 @@ gdk_x11_gl_context_realize (GdkGLContext  *context,
   debug_bit = gdk_gl_context_get_debug_enabled (context);
   compat_bit = gdk_gl_context_get_forward_compatible (context);
 
+  /* If there is no glXCreateContextAttribsARB() then we default to legacy */
+  legacy_bit = !GDK_X11_DISPLAY (display)->has_glx_create_context;
+
+  /* We cannot share legacy contexts with core profile ones, so the
+   * shared context is the one that decides if we're going to create
+   * a legacy context or not.
+   */
+  if (share != NULL && gdk_gl_context_is_legacy (share))
+    legacy_bit = TRUE;
+
   flags = 0;
   if (debug_bit)
     flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
@@ -618,15 +654,51 @@ gdk_x11_gl_context_realize (GdkGLContext  *context,
     flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
 
   GDK_NOTE (OPENGL,
-            g_print ("Creating core GLX context (version:%d.%d, debug:%s, forward:%s)\n",
+            g_print ("Creating core GLX context (version:%d.%d, debug:%s, forward:%s, legacy:%s)\n",
                      major, minor,
                      debug_bit ? "yes" : "no",
-                     compat_bit ? "yes" : "no"));
+                     compat_bit ? "yes" : "no",
+                     legacy_bit ? "yes" : "no"));
+
+  /* If we have access to GLX_ARB_create_context_profile then we can ask for
+   * a compatibility profile; if we don't, then we have to fall back to the
+   * old GLX 1.3 API.
+   */
+  if (legacy_bit && !GDK_X11_DISPLAY (display)->has_glx_create_context)
+    {
+      GDK_NOTE (OPENGL, g_print ("Creating legacy GL context on request\n"));
+      context_x11->glx_context = create_legacy_context (display, context_x11->glx_config, share);
+    }
+  else
+    {
+      int profile = legacy_bit ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
+                               : GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+
+      /* We need to tweak the version, otherwise we may end up requesting
+       * a compatibility context with a minimum version of 3.2, which is
+       * an error
+       */
+      if (legacy_bit)
+        {
+          major = 3;
+          minor = 0;
+        }
+
+      GDK_NOTE (OPENGL, g_print ("Creating GL3 context\n"));
+      context_x11->glx_context = create_gl3_context (display,
+                                                     context_x11->glx_config,
+                                                     share,
+                                                     profile, flags, major, minor);
+
+      /* Fall back to legacy in case the GL3 context creation failed */
+      if (context_x11->glx_context == NULL)
+        {
+          GDK_NOTE (OPENGL, g_print ("Creating fallback legacy context\n"));
+          context_x11->glx_context = create_legacy_context (display, context_x11->glx_config, share);
+          legacy_bit = TRUE;
+        }
+    }
 
-  context_x11->glx_context = create_gl3_context (display,
-                                                 context_x11->glx_config,
-                                                 share,
-                                                 flags, major, minor);
   if (context_x11->glx_context == NULL)
     {
       g_set_error_literal (error, GDK_GL_ERROR,
@@ -635,6 +707,9 @@ gdk_x11_gl_context_realize (GdkGLContext  *context,
       return FALSE;
     }
 
+  /* Ensure that any other context is created with a legacy bit set */
+  gdk_gl_context_set_is_legacy (context, legacy_bit);
+
   xvisinfo = find_xvisinfo_for_fbconfig (display, context_x11->glx_config);
 
   info = get_glx_drawable_info (window->impl_window);
@@ -1179,15 +1254,6 @@ gdk_x11_window_create_gl_context (GdkWindow    *window,
       return NULL;
     }
 
-  if (!GDK_X11_DISPLAY (display)->has_glx_create_context)
-    {
-      g_set_error_literal (error, GDK_GL_ERROR,
-                           GDK_GL_ERROR_UNSUPPORTED_PROFILE,
-                           _("The GLX_ARB_create_context_profile extension "
-                             "needed to create core profiles is not available"));
-      return NULL;
-    }
-
   visual = gdk_window_get_visual (window);
   if (!find_fbconfig_for_visual (display, visual, &config, error))
     return NULL;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]