egl: Make sure highest possible GL version is created
authorBenjamin Otte <otte@redhat.com>
Tue, 25 Apr 2023 18:08:33 +0000 (20:08 +0200)
committerBenjamin Otte <otte@redhat.com>
Thu, 27 Apr 2023 00:13:32 +0000 (02:13 +0200)
The EGL spec states:

    The context returned must be the specified version, or a later
    version which is backwards compatible with that version.
    Even if a later version is returned, the specified version
    must correspond to a defined version of the client API.

GTK has so far been relying on EGL implementations returning a
later version, because that is what Mesa does.
But ANGLE does not do that and only provides the minimum version, which
means Windows EGL has been forced to use a lower EGL version for no
reason.

So fix this and try versions in order from highest to lowest.

gdk/gdkglcontext.c
gdk/gdkglcontextprivate.h
gdk/gdkglversionprivate.h

index 8deca9ea1d1df79535ad27eb981cff7c75a60121..96eaac8d308606a057cdfb8b618478a1a330dc8d 100644 (file)
@@ -287,8 +287,11 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
   EGLConfig egl_config;
   EGLContext ctx;
   EGLint context_attribs[N_EGL_ATTRS], i = 0, flags = 0;
+  gsize major_idx, minor_idx;
   gboolean debug_bit, forward_bit;
   GdkGLVersion min, version;
+  const GdkGLVersion* supported_versions;
+  gsize j;
   G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
 
   if (!gdk_gl_context_is_api_allowed (context, api, NULL))
@@ -328,9 +331,9 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
     flags &= ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
 
   context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION;
-  context_attribs[i++] = gdk_gl_version_get_major (&version);
+  major_idx = i++;
   context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION;
-  context_attribs[i++] = gdk_gl_version_get_minor (&version);
+  minor_idx = i++;
   context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
   context_attribs[i++] = flags;
 
@@ -345,17 +348,27 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
                      legacy ? "yes" : "no",
                      api == GDK_GL_API_GLES ? "yes" : "no");
 
-  ctx = eglCreateContext (egl_display,
-                          egl_config,
-                          share ? share_priv->egl_context : EGL_NO_CONTEXT,
-                          context_attribs);
+  supported_versions = gdk_gl_versions_get_for_api (api);
+  for (j = 0; gdk_gl_version_greater_equal (&supported_versions[j], &version); j++)
+    {
+      context_attribs [major_idx] = gdk_gl_version_get_major (&supported_versions[j]);
+      context_attribs [minor_idx] = gdk_gl_version_get_minor (&supported_versions[j]);
+
+      ctx = eglCreateContext (egl_display,
+                              egl_config,
+                              share ? share_priv->egl_context : EGL_NO_CONTEXT,
+                              context_attribs);
+      if (ctx != NULL)
+        break;
+    }
 
   if (ctx == NULL)
-      return 0;
+    return 0;
 
   GDK_DISPLAY_DEBUG (display, OPENGL, "Created EGL context[%p]", ctx);
 
   priv->egl_context = ctx;
+  gdk_gl_context_set_version (context, &supported_versions[j]);
   gdk_gl_context_set_is_legacy (context, legacy);
 
   if (epoxy_has_egl_extension (egl_display, "EGL_KHR_swap_buffers_with_damage"))
@@ -1132,6 +1145,15 @@ gdk_gl_context_is_legacy (GdkGLContext *context)
   return priv->is_legacy;
 }
 
+void
+gdk_gl_context_set_version (GdkGLContext       *context,
+                            const GdkGLVersion *version)
+{
+  GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+
+  priv->gl_version = *version;
+}
+
 void
 gdk_gl_context_set_is_legacy (GdkGLContext *context,
                               gboolean      is_legacy)
@@ -1493,7 +1515,8 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
   if (priv->extensions_checked)
     return;
 
-  gdk_gl_version_init_epoxy (&priv->gl_version);
+  if (!gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (0, 0)))
+    gdk_gl_version_init_epoxy (&priv->gl_version);
 
   priv->has_debug_output = epoxy_has_gl_extension ("GL_ARB_debug_output") ||
                            epoxy_has_gl_extension ("GL_KHR_debug");
index 139a3a2bc79749dae828ee25c5fac837cd84b0cf..24809f88efe74eaadb6f2a8ee19695ab3cf0fad2 100644 (file)
@@ -99,11 +99,13 @@ void                    gdk_gl_context_clear_current_if_surface (GdkSurface
 GdkGLContext *          gdk_gl_context_new                      (GdkDisplay      *display,
                                                                  GdkSurface      *surface);
 
-gboolean                gdk_gl_context_is_api_allowed           (GdkGLContext    *self,
-                                                                 GdkGLAPI         api,
-                                                                 GError         **error);
-void                    gdk_gl_context_set_is_legacy            (GdkGLContext    *context,
-                                                                 gboolean         is_legacy);
+gboolean                gdk_gl_context_is_api_allowed           (GdkGLContext           *self,
+                                                                 GdkGLAPI                api,
+                                                                 GError                **error);
+void                    gdk_gl_context_set_version              (GdkGLContext           *context,
+                                                                 const GdkGLVersion     *version);
+void                    gdk_gl_context_set_is_legacy            (GdkGLContext           *context,
+                                                                 gboolean                is_legacy);
 gboolean                gdk_gl_context_check_gl_version         (GdkGLContext           *context,
                                                                  const GdkGLVersion     *gl_version,
                                                                  const GdkGLVersion     *gles_version);
index 4ea97bceb6eae20af91ac42f641059b0d996d9b8..3b1f8352df9bd2f4b3b59fec88308c14aabee282 100644 (file)
@@ -20,7 +20,7 @@
 
 #pragma once
 
-#include <glib.h>
+#include <gdkenums.h>
 
 G_BEGIN_DECLS
 
@@ -52,6 +52,46 @@ struct _GdkGLVersion
 #define GDK_GL_VERSION_INIT(maj,min) (GdkGLVersion) { maj, min }
 #define GDK_GL_VERSION_STRING(str) GDK_GL_VERSION_INIT(str[0] - '0', str[2] - '0')
 
+static const GdkGLVersion supported_gl_versions[] = {
+  GDK_GL_VERSION_INIT (4, 6),
+  GDK_GL_VERSION_INIT (4, 5),
+  GDK_GL_VERSION_INIT (4, 4),
+  GDK_GL_VERSION_INIT (4, 3),
+  GDK_GL_VERSION_INIT (4, 2),
+  GDK_GL_VERSION_INIT (4, 1),
+  GDK_GL_VERSION_INIT (4, 0),
+  GDK_GL_VERSION_INIT (3, 3),
+  GDK_GL_VERSION_INIT (3, 2),
+  GDK_GL_VERSION_INIT (3, 1),
+  GDK_GL_VERSION_INIT (3, 0),
+
+  GDK_GL_VERSION_INIT (0, 0)
+};
+
+static const GdkGLVersion supported_gles_versions[] = {
+  GDK_GL_VERSION_INIT (3, 2),
+  GDK_GL_VERSION_INIT (3, 1),
+  GDK_GL_VERSION_INIT (3, 0),
+  GDK_GL_VERSION_INIT (2, 0),
+
+  GDK_GL_VERSION_INIT (0, 0)
+};
+
+static inline const GdkGLVersion *
+gdk_gl_versions_get_for_api (GdkGLAPI api)
+{
+  switch (api)
+    {
+      case GDK_GL_API_GL:
+        return supported_gl_versions;
+      case GDK_GL_API_GLES:
+        return supported_gles_versions;
+      default:
+        g_assert_not_reached ();
+        return NULL;
+    }
+}
+
 static inline int
 gdk_gl_version_get_major (const GdkGLVersion *self)
 {