x11: Properly record the error when initializing GL
authorBenjamin Otte <otte@redhat.com>
Fri, 2 Jul 2021 01:21:14 +0000 (03:21 +0200)
committerBenjamin Otte <otte@redhat.com>
Thu, 22 Jul 2021 14:23:56 +0000 (16:23 +0200)
That way, we can give a useful error message when things break down for
users.

These error messages could still be improved in places (like looking at
the actual EGL error codes), but that seemed overkill.

gdk/x11/gdkdisplay-x11.c
gdk/x11/gdkdisplay-x11.h
gdk/x11/gdkglcontext-egl.c
gdk/x11/gdkglcontext-glx.c
gdk/x11/gdkglcontext-x11.c
gdk/x11/gdkglcontext-x11.h

index df893c0bbc13509019422fb1fec86781fe0dd873..4500513057fa2198e952471c4c3326ac6139807c 100644 (file)
@@ -1440,7 +1440,7 @@ gdk_x11_display_open (const char *display_name)
    * as we care about GLX details such as alpha/depth/stencil depth,
    * stereo and double buffering
    */
-  if (!gdk_x11_display_init_gl (display_x11, &display_x11->window_visual, &display_x11->window_depth))
+  if (!gdk_x11_display_init_gl (display_x11, &display_x11->window_visual, &display_x11->window_depth, &display_x11->gl_error))
     gdk_x11_display_query_default_visual (display_x11, &display_x11->window_visual, &display_x11->window_depth);
 
   display_x11->window_colormap = XCreateColormap (xdisplay,
@@ -1948,6 +1948,8 @@ gdk_x11_display_finalize (GObject *object)
 
   XCloseDisplay (display_x11->xdisplay);
 
+  g_clear_error (&display_x11->gl_error);
+
   /* error traps */
   while (display_x11->error_traps != NULL)
     {
index 067f34cca83fa2f32e6497bb74bfebafd33069d9..0bdc4488f01c1f1e50214f193a0dd7eaf3fd0493 100644 (file)
@@ -129,6 +129,9 @@ struct _GdkX11Display
   guint have_damage;
 #endif
 
+  /* If GL is not supported, store the error here */
+  GError *gl_error;
+
   /* GLX information */
   /* GLXFBConfig */ gpointer glx_config;
   int glx_version;
index fa795cec2e362b9ad459c53d6fe2e8011c083244..3df0919738a6aee4ba1ffdd48fdd195ce57e2de6 100644 (file)
@@ -132,10 +132,11 @@ visual_is_rgba (XVisualInfo *visinfo)
 
 #define MAX_EGL_ATTRS   30
 
-static void
+static gboolean
 gdk_x11_display_create_egl_config (GdkX11Display  *display,
                                    Visual        **out_visual,
-                                   int            *out_depth)
+                                   int            *out_depth,
+                                   GError        **error)
 {
   GdkX11Display *self = GDK_X11_DISPLAY (display);
   EGLint attrs[MAX_EGL_ATTRS];
@@ -170,14 +171,19 @@ gdk_x11_display_create_egl_config (GdkX11Display  *display,
   attrs[i++] = EGL_NONE;
   g_assert (i < MAX_EGL_ATTRS);
 
-  if (!eglChooseConfig (self->egl_display, attrs, NULL, -1, &alloced))
-    return;
+  if (!eglChooseConfig (self->egl_display, attrs, NULL, -1, &alloced) || alloced == 0)
+    {
+      g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("No EGL configuration available"));
+      return FALSE;
+    }
 
   configs = g_new (EGLConfig, alloced);
   if (!eglChooseConfig (self->egl_display, attrs, configs, alloced, &count))
     {
-      g_free (configs);
-      return;
+      g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("Failed to get EGL configurations"));
+      return FALSE;
     }
   g_warn_if_fail (alloced == count);
 
@@ -249,6 +255,16 @@ gdk_x11_display_create_egl_config (GdkX11Display  *display,
     }
 
   g_free (configs);
+
+  if (best_features == NO_VISUAL_FOUND)
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("No EGL configuration with required features found"));
+      return FALSE;
+    }
+
+  return TRUE;
 }
 
 #undef MAX_EGL_ATTRS
@@ -574,7 +590,8 @@ gdk_x11_gl_context_egl_init (GdkX11GLContextEGL *self)
 gboolean
 gdk_x11_display_init_egl (GdkX11Display  *self,
                           Visual        **out_visual,
-                          int            *out_depth)
+                          int            *out_depth,
+                          GError        **error)
 {
   GdkDisplay *display = GDK_DISPLAY (self);
   Display *dpy;
@@ -583,20 +600,32 @@ gdk_x11_display_init_egl (GdkX11Display  *self,
   dpy = gdk_x11_display_get_xdisplay (display);
 
   if (!epoxy_has_egl ())
-    return FALSE;
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("EGL is not supported"));
+      return FALSE;
+    }
 
   gdk_x11_display_create_egl_display (self);
   if (self->egl_display == NULL)
-    return FALSE;
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("Failed to create EGL display"));
+      return FALSE;
+    }
 
   if (!eglInitialize (self->egl_display, &major, &minor))
     {
       self->egl_display = NULL;
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("Could not initialize EGL display"));
       return FALSE;
     }
 
-  gdk_x11_display_create_egl_config (self, out_visual, out_depth);
-  if (self->egl_config == NULL)
+  if (!gdk_x11_display_create_egl_config (self, out_visual, out_depth, error))
     {
       eglTerminate (self->egl_display);
       self->egl_display = NULL;
index 9b112053f70074435c374ef4e135f8451cac1d99..a1ecb683131667497d8ee283c1b4118d705431da 100644 (file)
@@ -715,10 +715,11 @@ visual_is_rgba (XVisualInfo *visinfo)
 
 #define MAX_GLX_ATTRS   30
 
-static void
+static gboolean
 gdk_x11_display_create_glx_config (GdkX11Display  *self,
                                    Visual        **out_visual,
-                                   int            *out_depth)
+                                   int            *out_depth,
+                                   GError        **error)
 {
   GdkDisplay *display = GDK_DISPLAY (self);
   Display *dpy = gdk_x11_display_get_xdisplay (display);
@@ -758,7 +759,12 @@ gdk_x11_display_create_glx_config (GdkX11Display  *self,
 
   configs = glXChooseFBConfig (dpy, DefaultScreen (dpy), attrs, &count);
   if (configs == NULL || count == 0)
-    return;
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("No GLX configurations available"));
+      return FALSE;
+    }
 
   best_features = NO_VISUAL_FOUND;
 
@@ -824,6 +830,16 @@ gdk_x11_display_create_glx_config (GdkX11Display  *self,
     }
 
   XFree (configs);
+
+  if (best_features == NO_VISUAL_FOUND)
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("No GLX configuration with required features found"));
+      return FALSE;
+    }
+
+  return TRUE;
 }
 
 #undef MAX_GLX_ATTRS
@@ -942,6 +958,7 @@ gdk_x11_display_get_glx_version (GdkDisplay *display,
  * @display_x11: an X11 display that has not been inited yet. 
  * @out_visual: set to the Visual to be used with the returned config
  * @out_depth: set to the depth to be used with the returned config
+ * @error: Return location for error
  *
  * Initializes the cached GLX state for the given @screen.
  *
@@ -952,7 +969,8 @@ gdk_x11_display_get_glx_version (GdkDisplay *display,
 gboolean
 gdk_x11_display_init_glx (GdkX11Display  *display_x11,
                           Visual        **out_visual,
-                          int            *out_depth)
+                          int            *out_depth,
+                          GError        **error)
 {
   GdkDisplay *display = GDK_DISPLAY (display_x11);
   Display *dpy;
@@ -961,7 +979,12 @@ gdk_x11_display_init_glx (GdkX11Display  *display_x11,
   dpy = gdk_x11_display_get_xdisplay (display);
 
   if (!epoxy_has_glx (dpy))
-    return FALSE;
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("GLX is not supported"));
+      return FALSE;
+    }
 
   screen_num = display_x11->screen->screen_num;
 
@@ -1023,8 +1046,7 @@ gdk_x11_display_init_glx (GdkX11Display  *display_x11,
         XFree (data);
     }
 
-  gdk_x11_display_create_glx_config (display_x11, out_visual, out_depth);
-  if (display_x11->glx_config == NULL)
+  if (!gdk_x11_display_create_glx_config (display_x11, out_visual, out_depth, error))
     return FALSE;
 
   GDK_DISPLAY_NOTE (display, OPENGL,
index e4e24c88ab87f68a9b97f93ec3ba584567c04856..389faf629268ab1e7ae703caa1eef97c5ac0242d 100644 (file)
@@ -72,9 +72,9 @@ gdk_x11_surface_create_gl_context (GdkSurface    *surface,
     context = gdk_x11_gl_context_glx_new (surface, attached, share, error);
   else
     {
-      g_set_error_literal (error, GDK_GL_ERROR,
-                           GDK_GL_ERROR_NOT_AVAILABLE,
-                           _("No GL implementation is available"));
+      g_assert (display_x11->gl_error);
+      if (error)
+        *error = g_error_copy (display_x11->gl_error);
       return NULL;
     }
 
@@ -105,22 +105,41 @@ gdk_x11_display_make_gl_context_current (GdkDisplay   *display,
 gboolean
 gdk_x11_display_init_gl (GdkX11Display  *self,
                          Visual        **out_visual,
-                         int            *out_depth)
+                         int            *out_depth,
+                         GError        **error)
 {
   GdkDisplay *display G_GNUC_UNUSED = GDK_DISPLAY (self);
+  GError *egl_error = NULL;
+  GError *glx_error = NULL;
 
   if (GDK_DISPLAY_DEBUG_CHECK (display, GL_DISABLE))
-    return FALSE;
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("GL support disabled via GDK_DEBUG=gl-disable"));
+      return FALSE;
+    }
 
   if (!GDK_DISPLAY_DEBUG_CHECK (display, GL_GLX))
     {
       /* We favour EGL */
-      if (gdk_x11_display_init_egl (self, out_visual, out_depth))
+      if (gdk_x11_display_init_egl (self, out_visual, out_depth, &egl_error))
         return TRUE;
     }
 
-  if (gdk_x11_display_init_glx (self, out_visual, out_depth))
-    return TRUE;
+  if (gdk_x11_display_init_glx (self, out_visual, out_depth, &glx_error))
+    {
+      g_clear_error (&egl_error);
+      return TRUE;
+    }
+
+  if (egl_error)
+    {
+      *error = egl_error;
+      g_clear_error (&glx_error);
+    }
+  else
+    *error = glx_error;
 
   return FALSE;
 }
index acbc58a26065b40ad242532f9027c026444b38b9..1aa7fbe5451fd95706d6dcdd449dfc67cf8bb2a5 100644 (file)
@@ -61,7 +61,8 @@ struct _GdkX11GLContextClass
 
 gboolean                gdk_x11_display_init_gl                 (GdkX11Display *self,
                                                                  Visual       **out_visual,
-                                                                 int           *out_depth);
+                                                                 int           *out_depth,
+                                                                 GError       **error);
 
 GdkGLContext *          gdk_x11_surface_create_gl_context       (GdkSurface    *window,
                                                                  gboolean       attached,
@@ -79,7 +80,8 @@ typedef struct _GdkX11GLContextGLX      GdkX11GLContextGLX;
 
 gboolean                gdk_x11_display_init_glx                (GdkX11Display *display_x11,
                                                                  Visual       **out_visual,
-                                                                 int           *out_depth);
+                                                                 int           *out_depth,
+                                                                 GError       **error);
 void                    gdk_x11_surface_destroy_glx_drawable    (GdkX11Surface *self);
 
 GType                   gdk_x11_gl_context_glx_get_type         (void) G_GNUC_CONST;
@@ -100,7 +102,8 @@ typedef struct _GdkX11GLContextEGL      GdkX11GLContextEGL;
 
 gboolean                gdk_x11_display_init_egl                (GdkX11Display *display_x11,
                                                                  Visual       **out_visual,
-                                                                 int           *out_depth);
+                                                                 int           *out_depth,
+                                                                 GError       **error);
 void                    gdk_x11_surface_destroy_egl_surface     (GdkX11Surface *self);
 
 GType                   gdk_x11_gl_context_egl_get_type         (void) G_GNUC_CONST;