[gtk/wip/otte/gl-hdr: 7/12] egl: Move initialization code and port Wayland




commit 540cb31d7c8cc6502906d85feeda29e4f1b15ef9
Author: Benjamin Otte <otte redhat com>
Date:   Sun Oct 3 06:22:21 2021 +0200

    egl: Move initialization code and port Wayland
    
    Moves the EGL initialization code to gdk/ so it can be shared between
    backends.
    
    Also port the Wayland backend to this code, so I know that it works.

 gdk/gdkdisplay.c                   | 351 +++++++++++++++++++++++++++++++++++++
 gdk/gdkdisplayprivate.h            |  17 +-
 gdk/wayland/gdkdisplay-wayland.h   |   4 -
 gdk/wayland/gdkglcontext-wayland.c | 316 ++++-----------------------------
 gdk/wayland/gdksurface-wayland.c   |  13 +-
 5 files changed, 408 insertions(+), 293 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 71d47f1d30..6d47f7011a 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -36,6 +36,7 @@
 #include "gdkglcontextprivate.h"
 #include "gdkmonitorprivate.h"
 
+#include <epoxy/egl.h>
 #include <math.h>
 
 /**
@@ -87,6 +88,9 @@ struct _GdkDisplayPrivate {
   GdkGLContext *gl_context;
   GError *gl_error;
 
+  EGLDisplay egl_display;
+  EGLConfig egl_config;
+
   guint rgba : 1;
   guint composited : 1;
   guint input_shapes : 1;
@@ -146,6 +150,24 @@ gdk_display_default_init_gl (GdkDisplay  *display,
   return NULL;
 }
 
+static guint
+gdk_display_default_rate_egl_config (GdkDisplay *display,
+                                     gpointer    egl_display,
+                                     gpointer    config)
+{
+  guint distance = 0;
+  int tmp;
+
+  if (!eglGetConfigAttrib (egl_display, config, EGL_SAMPLE_BUFFERS, &tmp) || tmp != 0)
+    distance += 0x20000;
+
+  if (!eglGetConfigAttrib (egl_display, config, EGL_DEPTH_SIZE, &tmp) || tmp != 0 ||
+      !eglGetConfigAttrib (egl_display, config, EGL_STENCIL_SIZE, &tmp) || tmp != 0)
+    distance += 0x10000;
+
+  return distance;
+}
+    
 static GdkSeat *
 gdk_display_real_get_default_seat (GdkDisplay *display)
 {
@@ -173,6 +195,7 @@ gdk_display_class_init (GdkDisplayClass *class)
   class->make_default = gdk_display_real_make_default;
   class->get_app_launch_context = gdk_display_real_get_app_launch_context;
   class->init_gl = gdk_display_default_init_gl;
+  class->rate_egl_config = gdk_display_default_rate_egl_config;
   class->get_default_seat = gdk_display_real_get_default_seat;
   class->opened = gdk_display_real_opened;
 
@@ -352,6 +375,7 @@ gdk_display_dispose (GObject *object)
   g_queue_clear (&display->queued_events);
 
   g_clear_object (&priv->gl_context);
+  g_clear_pointer (&priv->egl_display, eglTerminate);
   g_clear_error (&priv->gl_error);
 
   G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
@@ -1312,6 +1336,333 @@ gdk_display_get_gl_context (GdkDisplay *self)
   return priv->gl_context;
 }
 
+#ifdef G_ENABLE_DEBUG
+static int
+strvcmp (gconstpointer p1,
+         gconstpointer p2)
+{
+  const char * const *s1 = p1;
+  const char * const *s2 = p2;
+
+  return strcmp (*s1, *s2);
+}
+
+static char *
+describe_extensions (EGLDisplay egl_display)
+{
+  const char *extensions;
+  char **exts;
+  char *ext;
+
+  extensions = eglQueryString (egl_display, EGL_EXTENSIONS);
+
+  exts = g_strsplit (extensions, " ", -1);
+  qsort (exts, g_strv_length (exts), sizeof (char *), strvcmp);
+
+  ext = g_strjoinv ("\n\t", exts);
+  if (ext[0] == '\n')
+    ext[0] = ' ';
+
+  g_strfreev (exts);
+
+  return g_strstrip (ext);
+}
+
+static char *
+describe_egl_config (EGLDisplay egl_display,
+                     EGLConfig  egl_config)
+{
+  EGLint red, green, blue, alpha, type;
+
+  if (egl_config == NULL)
+    return g_strdup ("-");
+
+  if (!eglGetConfigAttrib (egl_display, egl_config, EGL_RED_SIZE, &red) ||
+      !eglGetConfigAttrib (egl_display, egl_config, EGL_GREEN_SIZE, &green) ||
+      !eglGetConfigAttrib (egl_display, egl_config, EGL_BLUE_SIZE, &blue) ||
+      !eglGetConfigAttrib (egl_display, egl_config, EGL_ALPHA_SIZE, &alpha))
+    return g_strdup ("Unknown");
+
+  if (epoxy_has_egl_extension (egl_display, "EGL_EXT_pixel_format_float"))
+    {
+      if (!eglGetConfigAttrib (egl_display, egl_config, EGL_COLOR_COMPONENT_TYPE_EXT, &type))
+        type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+    }
+  else
+    type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+
+  return g_strdup_printf ("R%dG%dB%dA%d%s", red, green, blue, alpha, type == 
EGL_COLOR_COMPONENT_TYPE_FIXED_EXT ? "" : " float");
+}
+#endif
+
+/*<private>
+ * gdk_display_get_egl_display:
+ * @self: a display
+ *
+ * Retrieves the EGL display connection object for the given GDK display.
+ *
+ * This function returns `NULL` if GL is not supported or GDK is using
+ * a different OpenGL framework than EGL.
+ *
+ * Returns: (nullable): the EGL display object
+ */
+gpointer
+gdk_display_get_egl_display (GdkDisplay *self)
+{
+  GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (self), NULL);
+
+  if (!priv->egl_display &&
+      !gdk_display_prepare_gl (self, NULL))
+    return NULL;
+
+  return priv->egl_display;
+}
+
+gpointer
+gdk_display_get_egl_config (GdkDisplay *self)
+{
+  GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
+
+  return priv->egl_config;
+}
+
+static EGLDisplay
+gdk_display_create_egl_display (EGLenum  platform,
+                                gpointer native_display)
+{
+  G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
+  EGLDisplay egl_display = NULL;
+
+  if (epoxy_has_egl_extension (NULL, "EGL_KHR_platform_base"))
+    {
+      PFNEGLGETPLATFORMDISPLAYPROC getPlatformDisplay =
+        (void *) eglGetProcAddress ("eglGetPlatformDisplay");
+
+      if (getPlatformDisplay != NULL)
+        egl_display = getPlatformDisplay (platform, native_display, NULL);
+      if (egl_display != NULL)
+        goto out;
+    }
+
+  if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base"))
+    {
+      PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay =
+        (void *) eglGetProcAddress ("eglGetPlatformDisplayEXT");
+
+      if (getPlatformDisplay != NULL)
+        egl_display = getPlatformDisplay (platform, native_display, NULL);
+      if (egl_display != NULL)
+        goto out;
+    }
+
+  egl_display = eglGetDisplay ((EGLNativeDisplayType) native_display);
+
+out:
+  gdk_profiler_end_mark (start_time, "Create EGL display", NULL);
+
+  return egl_display;
+}
+
+#define MAX_EGL_ATTRS 30
+
+typedef enum {
+  GDK_EGL_CONFIG_PERFECT = (1 << 0)
+} GdkEGLConfigCreateFlags;
+
+static EGLConfig
+gdk_display_create_egl_config (GdkDisplay               *self,
+                               GdkEGLConfigCreateFlags   flags,
+                               GError                  **error)
+{
+  GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
+  G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
+  EGLint attrs[MAX_EGL_ATTRS];
+  EGLConfig *configs;
+  EGLint count, alloced;
+  EGLConfig best_config;
+  guint best_score;
+
+  int i = 0;
+
+  attrs[i++] = EGL_SURFACE_TYPE;
+  attrs[i++] = EGL_WINDOW_BIT;
+
+  attrs[i++] = EGL_COLOR_BUFFER_TYPE;
+  attrs[i++] = EGL_RGB_BUFFER;
+
+  attrs[i++] = EGL_RED_SIZE;
+  attrs[i++] = 8;
+  attrs[i++] = EGL_GREEN_SIZE;
+  attrs[i++] = 8;
+  attrs[i++] = EGL_BLUE_SIZE;
+  attrs[i++] = 8;
+  attrs[i++] = EGL_ALPHA_SIZE;
+  attrs[i++] = 8;
+
+  attrs[i++] = EGL_NONE;
+  g_assert (i < MAX_EGL_ATTRS);
+
+  if (!eglChooseConfig (priv->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 NULL;
+    }
+
+  configs = g_new (EGLConfig, alloced);
+  if (!eglChooseConfig (priv->egl_display, attrs, configs, alloced, &count))
+    {
+      g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("Failed to get EGL configurations"));
+      return NULL;
+    }
+  g_warn_if_fail (alloced == count);
+
+  best_score = G_MAXUINT;
+  best_config = NULL;
+
+  for (i = 0; i < count; i++)
+    {
+      guint score = GDK_DISPLAY_GET_CLASS (self)->rate_egl_config (self, priv->egl_display, configs[i]);
+
+      if (score < best_score)
+        {
+          best_score = score;
+          best_config = configs[i];
+        }
+
+      if (score == 0)
+        break;
+    }
+
+  g_free (configs);
+
+  gdk_profiler_end_mark (start_time, "Create EGL config", NULL);
+
+  if (best_score == G_MAXUINT)
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("No EGL configuration with required features found"));
+      return NULL;
+    }
+  else if ((flags & GDK_EGL_CONFIG_PERFECT) && best_score != 0)
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("No perfect EGL configuration found"));
+      return NULL;
+    }
+
+  return best_config;
+}
+
+#undef MAX_EGL_ATTRS
+
+
+gboolean
+gdk_display_init_egl (GdkDisplay  *self,
+                      int          platform,
+                      gpointer     native_display,
+                      gboolean     allow_any,
+                      GError     **error)
+{
+  GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
+  G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
+  G_GNUC_UNUSED gint64 start_time2;
+  int major, minor;
+
+  if (!gdk_gl_backend_can_be_used (GDK_GL_EGL, error))
+    return FALSE;
+
+  if (!epoxy_has_egl ())
+    {
+      gboolean sandboxed = gdk_running_in_sandbox ();
+
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           sandboxed ? _("libEGL not available in this sandbox")
+                                     : _("libEGL not available"));
+      return FALSE;
+    }
+
+  priv->egl_display = gdk_display_create_egl_display (platform, native_display);
+
+  if (priv->egl_display == NULL)
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("Failed to create EGL display"));
+      return FALSE;
+    }
+
+  start_time2 = GDK_PROFILER_CURRENT_TIME;
+  if (!eglInitialize (priv->egl_display, &major, &minor))
+    {
+      priv->egl_display = NULL;
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("Could not initialize EGL display"));
+      return FALSE;
+    }
+  gdk_profiler_end_mark (start_time2, "eglInitialize", NULL);
+
+  if (major < GDK_EGL_MIN_VERSION_MAJOR ||
+      (major == GDK_EGL_MIN_VERSION_MAJOR && minor < GDK_EGL_MIN_VERSION_MINOR))
+    {
+      g_clear_pointer (&priv->egl_display, eglTerminate);
+      g_set_error (error, GDK_GL_ERROR,
+                   GDK_GL_ERROR_NOT_AVAILABLE,
+                   _("EGL version %d.%d is too old. GTK requires %d.%d"),
+                   major, minor, GDK_EGL_MIN_VERSION_MAJOR, GDK_EGL_MIN_VERSION_MINOR);
+      return FALSE;
+    }
+
+  if (!epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_surfaceless_context"))
+    {
+      g_clear_pointer (&priv->egl_display, eglTerminate);
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_UNSUPPORTED_PROFILE,
+                           _("Surfaceless contexts are not supported on this EGL implementation"));
+      return FALSE;
+    }
+
+  priv->egl_config = gdk_display_create_egl_config (self,
+                                                    allow_any ? 0 : GDK_EGL_CONFIG_PERFECT,
+                                                    error);
+  if (priv->egl_config == NULL)
+    {
+      g_clear_pointer (&priv->egl_display, eglTerminate);
+      return FALSE;
+    }
+
+  GDK_DISPLAY_NOTE (self, OPENGL, {
+      char *ext = describe_extensions (priv->egl_display);
+      char *cfg = describe_egl_config (priv->egl_display, priv->egl_config);
+      g_message ("EGL API version %d.%d found\n"
+                 " - Vendor: %s\n"
+                 " - Version: %s\n"
+                 " - Client APIs: %s\n"
+                 " - Extensions:\n"
+                 "\t%s"
+                 " - Selected fbconfig: %s",
+                 major, minor,
+                 eglQueryString (priv->egl_display, EGL_VENDOR),
+                 eglQueryString (priv->egl_display, EGL_VERSION),
+                 eglQueryString (priv->egl_display, EGL_CLIENT_APIS),
+                 ext, cfg);
+      g_free (cfg);
+      g_free (ext);
+  });
+
+
+  gdk_profiler_end_mark (start_time, "init EGL", NULL);
+
+  return TRUE;
+}
+
 GdkDebugFlags
 gdk_display_get_debug_flags (GdkDisplay *display)
 {
diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h
index a85b275db7..dd0b1359b2 100644
--- a/gdk/gdkdisplayprivate.h
+++ b/gdk/gdkdisplayprivate.h
@@ -140,10 +140,15 @@ struct _GdkDisplayClass
 
   GdkKeymap *                (*get_keymap)         (GdkDisplay    *display);
 
-  GdkGLContext *         (*init_gl)                    (GdkDisplay        *display,
+  GdkGLContext *         (* init_gl)                   (GdkDisplay        *display,
                                                         GError           **error);
+  /* Returns the distance from a perfect score EGL config.
+   * GDK chooses the one with the *LOWEST* score */
+  guint                  (* rate_egl_config)           (GdkDisplay        *display,
+                                                        gpointer           egl_display,
+                                                        gpointer           egl_config);
 
-  GdkSeat *              (*get_default_seat)           (GdkDisplay     *display);
+  GdkSeat *              (*get_default_seat)           (GdkDisplay        *display);
 
   GListModel *           (*get_monitors)               (GdkDisplay     *self);
   GdkMonitor *           (*get_monitor_at_surface)     (GdkDisplay     *display,
@@ -208,6 +213,14 @@ GdkSurface *        gdk_display_create_surface        (GdkDisplay       *display
 
 GdkGLContext *      gdk_display_get_gl_context        (GdkDisplay       *display);
 
+gboolean            gdk_display_init_egl              (GdkDisplay       *display,
+                                                       int /*EGLenum*/   platform,
+                                                       gpointer          native_display,
+                                                       gboolean          allow_any,
+                                                       GError          **error);
+gpointer            gdk_display_get_egl_display       (GdkDisplay       *display);
+gpointer            gdk_display_get_egl_config        (GdkDisplay       *display);
+
 void                gdk_display_set_rgba              (GdkDisplay       *display,
                                                        gboolean          rgba);
 void                gdk_display_set_composited        (GdkDisplay       *display,
diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h
index 932f39cb6c..265bcd1883 100644
--- a/gdk/wayland/gdkdisplay-wayland.h
+++ b/gdk/wayland/gdkdisplay-wayland.h
@@ -151,10 +151,6 @@ struct _GdkWaylandDisplay
   gint64 last_bell_time_ms;
 
   /* egl info */
-  EGLDisplay egl_display;
-  EGLConfig egl_config;
-  int egl_major_version;
-  int egl_minor_version;
 
   guint have_egl_buffer_age : 1;
   guint have_egl_swap_buffers_with_damage : 1;
diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c
index e256277add..2f239ee929 100644
--- a/gdk/wayland/gdkglcontext-wayland.c
+++ b/gdk/wayland/gdkglcontext-wayland.c
@@ -56,7 +56,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
   GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
   GdkDisplay *display = gdk_gl_context_get_display (context);
   GdkGLContext *share = gdk_display_get_gl_context (display);
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+  EGLDisplay egl_display = gdk_display_get_egl_display (display);
+  EGLConfig egl_config = gdk_display_get_egl_config (display);
   EGLContext ctx;
   EGLint context_attribs[N_EGL_ATTRS];
   int major, minor, flags;
@@ -121,8 +122,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
                                legacy_bit ? "yes" : "no",
                                use_es ? "yes" : "no"));
 
-  ctx = eglCreateContext (display_wayland->egl_display,
-                          display_wayland->egl_config,
+  ctx = eglCreateContext (egl_display,
+                          egl_config,
                           share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
                                         : EGL_NO_CONTEXT,
                           context_attribs);
@@ -147,8 +148,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
 
       GDK_DISPLAY_NOTE (display, OPENGL,
                 g_message ("eglCreateContext failed, switching to OpenGLĀ ES"));
-      ctx = eglCreateContext (display_wayland->egl_display,
-                              display_wayland->egl_config,
+      ctx = eglCreateContext (egl_display,
+                              egl_config,
                               share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
                                             : EGL_NO_CONTEXT,
                               context_attribs);
@@ -176,8 +177,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
 
       GDK_DISPLAY_NOTE (display, OPENGL,
                 g_message ("eglCreateContext failed, switching to legacy"));
-      ctx = eglCreateContext (display_wayland->egl_display,
-                              display_wayland->egl_config,
+      ctx = eglCreateContext (egl_display,
+                              egl_config,
                               share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
                                             : EGL_NO_CONTEXT,
                               context_attribs);
@@ -216,7 +217,7 @@ gdk_wayland_gl_context_get_damage (GdkGLContext *context)
     {
       egl_surface = gdk_wayland_surface_get_egl_surface (surface);
       gdk_gl_context_make_current (context);
-      eglQuerySurface (display_wayland->egl_display, egl_surface,
+      eglQuerySurface (gdk_display_get_egl_display (display), egl_surface,
                        EGL_BUFFER_AGE_EXT, &buffer_age);
 
       switch (buffer_age)
@@ -252,9 +253,8 @@ static gboolean
 gdk_wayland_gl_context_clear_current (GdkGLContext *context)
 {
   GdkDisplay *display = gdk_gl_context_get_display (context);
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
 
-  return eglMakeCurrent (display_wayland->egl_display,
+  return eglMakeCurrent (gdk_display_get_egl_display (display),
                          EGL_NO_SURFACE,
                          EGL_NO_SURFACE,
                          EGL_NO_CONTEXT);
@@ -266,7 +266,6 @@ gdk_wayland_gl_context_make_current (GdkGLContext *context,
 {
   GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
   GdkDisplay *display = gdk_gl_context_get_display (context);
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
   EGLSurface egl_surface;
 
   if (!surfaceless)
@@ -274,7 +273,7 @@ gdk_wayland_gl_context_make_current (GdkGLContext *context,
   else
     egl_surface = EGL_NO_SURFACE;
 
-  return eglMakeCurrent (display_wayland->egl_display,
+  return eglMakeCurrent (gdk_display_get_egl_display (display),
                          egl_surface,
                          egl_surface,
                          context_wayland->egl_context);
@@ -333,11 +332,11 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
           rects[j++] = rect.width * scale;
           rects[j++] = rect.height * scale;
         }
-      eglSwapBuffersWithDamageEXT (display_wayland->egl_display, egl_surface, rects, n_rects);
+      eglSwapBuffersWithDamageEXT (gdk_display_get_egl_display (display), egl_surface, rects, n_rects);
       g_free (heap_rects);
     }
   else
-    eglSwapBuffers (display_wayland->egl_display, egl_surface);
+    eglSwapBuffers (gdk_display_get_egl_display (display), egl_surface);
 
   gdk_wayland_surface_notify_committed (surface);
 }
@@ -380,289 +379,44 @@ gdk_wayland_gl_context_init (GdkWaylandGLContext *self)
 gpointer
 gdk_wayland_display_get_egl_display (GdkDisplay *display)
 {
-  GdkWaylandDisplay *display_wayland;
-
   g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), NULL);
 
-  if (!gdk_display_prepare_gl (display, NULL))
-    return NULL;
-
-  display_wayland = GDK_WAYLAND_DISPLAY (display);
-
-  return display_wayland->egl_display;
-}
-
-static EGLDisplay
-get_egl_display (GdkWaylandDisplay *display_wayland)
-{
-  EGLDisplay dpy = NULL;
-
-  if (epoxy_has_egl_extension (NULL, "EGL_KHR_platform_base"))
-    {
-      PFNEGLGETPLATFORMDISPLAYPROC getPlatformDisplay =
-        (void *) eglGetProcAddress ("eglGetPlatformDisplay");
-
-      if (getPlatformDisplay != NULL)
-        dpy = getPlatformDisplay (EGL_PLATFORM_WAYLAND_EXT,
-                                  display_wayland->wl_display,
-                                  NULL);
-      if (dpy != NULL)
-        goto out;
-    }
-
-  if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base"))
-    {
-      PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay =
-        (void *) eglGetProcAddress ("eglGetPlatformDisplayEXT");
-
-      if (getPlatformDisplay != NULL)
-        dpy = getPlatformDisplay (EGL_PLATFORM_WAYLAND_EXT,
-                                  display_wayland->wl_display,
-                                  NULL);
-      if (dpy != NULL)
-        goto out;
-    }
-
-  dpy = eglGetDisplay ((EGLNativeDisplayType) display_wayland->wl_display);
-
-out:
-  return dpy;
+  return gdk_display_get_egl_display (display);
 }
 
-#define MAX_EGL_ATTRS   30
-
-static EGLConfig
-get_eglconfig (EGLDisplay dpy)
-{
-  EGLint attrs[MAX_EGL_ATTRS];
-  EGLint count;
-  EGLConfig config;
-  int i = 0;
-
-  attrs[i++] = EGL_SURFACE_TYPE;
-  attrs[i++] = EGL_WINDOW_BIT;
-
-  attrs[i++] = EGL_COLOR_BUFFER_TYPE;
-  attrs[i++] = EGL_RGB_BUFFER;
-
-  attrs[i++] = EGL_RED_SIZE;
-  attrs[i++] = 8;
-  attrs[i++] = EGL_GREEN_SIZE;
-  attrs[i++] = 8;
-  attrs[i++] = EGL_BLUE_SIZE;
-  attrs[i++] = 8;
-  attrs[i++] = EGL_ALPHA_SIZE;
-  attrs[i++] = 8;
-
-  attrs[i++] = EGL_NONE;
-  g_assert (i < MAX_EGL_ATTRS);
-
-  /* Pick first valid configuration i guess? */
-  if (!eglChooseConfig (dpy, attrs, &config, 1, &count) || count < 1)
-     return NULL;
-
-  return config;
-}
-
-#undef MAX_EGL_ATTRS
-
-#ifdef G_ENABLE_DEBUG
-static int
-strvcmp (gconstpointer p1,
-         gconstpointer p2)
-{
-  const char * const *s1 = p1;
-  const char * const *s2 = p2;
-
-  return strcmp (*s1, *s2);
-}
-
-static char *
-describe_extensions (EGLDisplay dpy)
-{
-  const char *extensions;
-  char **exts;
-  char *ext;
-
-  extensions = eglQueryString (dpy, EGL_EXTENSIONS);
-
-  exts = g_strsplit (extensions, " ", -1);
-  qsort (exts, g_strv_length (exts), sizeof (char *), strvcmp);
-
-  ext = g_strjoinv ("\n\t", exts);
-  if (ext[0] == '\n')
-    ext[0] = ' ';
-
-  g_strfreev (exts);
-
-  return g_strstrip (ext);
-}
-
-static char *
-describe_egl_config (EGLDisplay dpy,
-                     EGLConfig  config)
-{
-  EGLint red, green, blue, alpha, type;
-
-  if (config == 0)
-    return g_strdup ("-");
-
-  if (!eglGetConfigAttrib (dpy, config, EGL_RED_SIZE, &red) ||
-      !eglGetConfigAttrib (dpy, config, EGL_GREEN_SIZE, &green) ||
-      !eglGetConfigAttrib (dpy, config, EGL_BLUE_SIZE, &blue) ||
-      !eglGetConfigAttrib (dpy, config, EGL_ALPHA_SIZE, &alpha))
-    return g_strdup ("Unknown");
-
-  if (epoxy_has_egl_extension (dpy, "EGL_EXT_pixel_format_float"))
-    {
-      if (!eglGetConfigAttrib (dpy, config, EGL_COLOR_COMPONENT_TYPE_EXT, &type))
-        type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
-    }
-  else
-    type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
-
-  return g_strdup_printf ("R%dG%dB%dA%d%s", red, green, blue, alpha, type == 
EGL_COLOR_COMPONENT_TYPE_FIXED_EXT ? "" : " float");
-}
-#endif
-
 GdkGLContext *
 gdk_wayland_display_init_gl (GdkDisplay  *display,
                              GError     **error)
 {
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
-  EGLint major, minor;
-  EGLDisplay dpy;
-  GdkGLContext *ctx;
-  G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
-  G_GNUC_UNUSED gint64 start_time2;
-
-  if (!gdk_gl_backend_can_be_used (GDK_GL_EGL, error))
-    return FALSE;
-
-  if (!epoxy_has_egl ())
-    {
-      gboolean sandboxed = gdk_running_in_sandbox ();
-
-      g_set_error_literal (error, GDK_GL_ERROR,
-                           GDK_GL_ERROR_NOT_AVAILABLE,
-                           sandboxed ? _("libEGL not available in this sandbox")
-                                     : _("libEGL not available"));
-      return NULL;
-    }
-
-  start_time2 = GDK_PROFILER_CURRENT_TIME;
-  dpy = get_egl_display (display_wayland);
-  gdk_profiler_end_mark (start_time, "get_egl_display", NULL);
-  if (dpy == NULL)
-    {
-      gboolean sandboxed = gdk_running_in_sandbox ();
-
-      g_set_error_literal (error, GDK_GL_ERROR,
-                           GDK_GL_ERROR_NOT_AVAILABLE,
-                           sandboxed ? _("Sandbox does not provide an OpenGL implementation")
-                                     : _("No OpenGL implementation available"));
-      return NULL;
-    }
-
-  start_time2 = GDK_PROFILER_CURRENT_TIME;
-  if (!eglInitialize (dpy, &major, &minor))
-    {
-      g_set_error_literal (error, GDK_GL_ERROR,
-                           GDK_GL_ERROR_NOT_AVAILABLE,
-                           _("Could not initialize EGL display"));
-      return NULL;
-    }
-  gdk_profiler_end_mark (start_time2, "eglInitialize", NULL);
-
-  if (major < GDK_EGL_MIN_VERSION_MAJOR ||
-      (major == GDK_EGL_MIN_VERSION_MAJOR && minor < GDK_EGL_MIN_VERSION_MINOR))
-    {
-      eglTerminate (dpy);
-      g_set_error (error, GDK_GL_ERROR,
-                   GDK_GL_ERROR_NOT_AVAILABLE,
-                   _("EGL version %d.%d is too old. GTK requires %d.%d"),
-                   major, minor, GDK_EGL_MIN_VERSION_MAJOR, GDK_EGL_MIN_VERSION_MINOR);
-      return NULL;
-    }
+  GdkWaylandDisplay *self = GDK_WAYLAND_DISPLAY (display);
+  EGLDisplay egl_display;
+
+  if (!gdk_display_init_egl (display, 
+                             EGL_PLATFORM_WAYLAND_EXT,
+                             self->wl_display,
+                             TRUE,
+                             error))
+    return NULL;
 
-  start_time2 = GDK_PROFILER_CURRENT_TIME;
   if (!eglBindAPI (EGL_OPENGL_API))
     {
-      eglTerminate (dpy);
       g_set_error_literal (error, GDK_GL_ERROR,
                            GDK_GL_ERROR_NOT_AVAILABLE,
                            _("No GL implementation is available"));
       return NULL;
     }
-  gdk_profiler_end_mark (start_time2, "eglBindAPI", NULL);
 
-  if (!epoxy_has_egl_extension (dpy, "EGL_KHR_create_context"))
-    {
-      eglTerminate (dpy);
-      g_set_error_literal (error, GDK_GL_ERROR,
-                           GDK_GL_ERROR_UNSUPPORTED_PROFILE,
-                           _("Core GL is not available on EGL implementation"));
-      return NULL;
-    }
+  egl_display = gdk_display_get_egl_display (display);
 
-  if (!epoxy_has_egl_extension (dpy, "EGL_KHR_surfaceless_context"))
-    {
-      eglTerminate (dpy);
-      g_set_error_literal (error, GDK_GL_ERROR,
-                           GDK_GL_ERROR_UNSUPPORTED_PROFILE,
-                           _("Surfaceless contexts are not supported on this EGL implementation"));
-      return NULL;
-    }
+  self->have_egl_buffer_age =
+    epoxy_has_egl_extension (egl_display, "EGL_EXT_buffer_age");
 
-  start_time2 = GDK_PROFILER_CURRENT_TIME;
-  display_wayland->egl_config = get_eglconfig (dpy);
-  gdk_profiler_end_mark (start_time2, "get_eglconfig", NULL);
-  if (!display_wayland->egl_config)
-    {
-      eglTerminate (dpy);
-      g_set_error_literal (error, GDK_GL_ERROR,
-                           GDK_GL_ERROR_UNSUPPORTED_FORMAT,
-                           _("No available configurations for the given pixel format"));
-      return NULL;
-    }
+  self->have_egl_swap_buffers_with_damage =
+    epoxy_has_egl_extension (egl_display, "EGL_EXT_swap_buffers_with_damage");
 
-  display_wayland->egl_display = dpy;
-  display_wayland->egl_major_version = major;
-  display_wayland->egl_minor_version = minor;
-
-  display_wayland->have_egl_buffer_age =
-    epoxy_has_egl_extension (dpy, "EGL_EXT_buffer_age");
-
-  display_wayland->have_egl_swap_buffers_with_damage =
-    epoxy_has_egl_extension (dpy, "EGL_EXT_swap_buffers_with_damage");
-
-  GDK_DISPLAY_NOTE (display, OPENGL, {
-            char *ext = describe_extensions (dpy);
-            char *cfg = describe_egl_config (dpy, display_wayland->egl_config);
-            g_message ("EGL API version %d.%d found\n"
-                       " - Vendor: %s\n"
-                       " - Version: %s\n"
-                       " - Client APIs: %s\n"
-                       " - Extensions:\n"
-                       "\t%s\n"
-                       " - Selected fbconfig: %s",
-                       display_wayland->egl_major_version,
-                       display_wayland->egl_minor_version,
-                       eglQueryString (dpy, EGL_VENDOR),
-                       eglQueryString (dpy, EGL_VERSION),
-                       eglQueryString (dpy, EGL_CLIENT_APIS),
-                       ext, cfg);
-            g_free (cfg);
-            g_free (ext);
-  });
-
-  ctx = g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT,
-                      "display", display,
-                      NULL);
-
-  gdk_profiler_end_mark (start_time, "init Wayland GL", NULL);
-
-  return ctx;
+  return g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT,
+                       "display", display,
+                       NULL);
 }
 
 static void
@@ -675,16 +429,14 @@ gdk_wayland_gl_context_dispose (GObject *gobject)
       GdkGLContext *context = GDK_GL_CONTEXT (gobject);
       GdkSurface *surface = gdk_gl_context_get_surface (context);
       GdkDisplay *display = gdk_surface_get_display (surface);
-      GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+      EGLDisplay *egl_display = gdk_display_get_egl_display (display);
 
       if (eglGetCurrentContext () == context_wayland->egl_context)
-        eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
-                       EGL_NO_CONTEXT);
+        eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 
       GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Destroying EGL context"));
 
-      eglDestroyContext (display_wayland->egl_display,
-                         context_wayland->egl_context);
+      eglDestroyContext (egl_display, context_wayland->egl_context);
       context_wayland->egl_context = NULL;
     }
 
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index 4d1951e66d..c1f1357165 100644
--- a/gdk/wayland/gdksurface-wayland.c
+++ b/gdk/wayland/gdksurface-wayland.c
@@ -2893,7 +2893,8 @@ unmap_popups_for_surface (GdkSurface *surface)
 static void
 gdk_wayland_surface_hide_surface (GdkSurface *surface)
 {
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
+  GdkDisplay *display = gdk_surface_get_display (surface);
+  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
 
   unmap_popups_for_surface (surface);
@@ -2902,7 +2903,7 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
     {
       if (impl->egl_surface)
         {
-          eglDestroySurface (display_wayland->egl_display, impl->egl_surface);
+          eglDestroySurface (gdk_display_get_egl_display (display), impl->egl_surface);
           impl->egl_surface = NULL;
         }
 
@@ -4351,7 +4352,7 @@ gdk_wayland_surface_get_wl_egl_window (GdkSurface *surface)
 EGLSurface
 gdk_wayland_surface_get_egl_surface (GdkSurface *surface)
 {
-  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
+  GdkDisplay *display = gdk_surface_get_display (surface);
   GdkWaylandSurface *impl;
   struct wl_egl_window *egl_window;
 
@@ -4363,8 +4364,10 @@ gdk_wayland_surface_get_egl_surface (GdkSurface *surface)
     {
       egl_window = gdk_wayland_surface_get_wl_egl_window (surface);
 
-      impl->egl_surface =
-        eglCreateWindowSurface (display->egl_display, display->egl_config, egl_window, NULL);
+      impl->egl_surface = eglCreateWindowSurface (gdk_display_get_egl_display (display),
+                                                  gdk_display_get_egl_config (display),
+                                                  egl_window,
+                                                  NULL);
     }
 
   return impl->egl_surface;


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