[gtk/matthiasc/color-profiles: 8/9] wayland: Allow picking sdr or hdr configs




commit ba439f73e3c93dde2fcd6d2a050a59941b9ca8c5
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Oct 1 14:21:23 2021 -0400

    wayland: Allow picking sdr or hdr configs
    
    Add gdk_wayland_surface_set_rendering which lets
    applications hint if they would prefer SDR or HDR
    rendering, or don't care. We then try to pick a
    suitable EGLConfig for creating the surface. This
    only works if we have the KHR_no_config_context
    extension available.

 gdk/wayland/gdkdisplay-wayland.h   |   3 +-
 gdk/wayland/gdkglcontext-wayland.c | 119 +++++++++++++++++++++----------------
 gdk/wayland/gdkprivate-wayland.h   |   3 +
 gdk/wayland/gdksurface-wayland.c   |  39 +++++++++++-
 gdk/wayland/gdkwaylandsurface.h    |  12 ++++
 5 files changed, 121 insertions(+), 55 deletions(-)
---
diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h
index 932f39cb6c..4789331ddd 100644
--- a/gdk/wayland/gdkdisplay-wayland.h
+++ b/gdk/wayland/gdkdisplay-wayland.h
@@ -152,7 +152,8 @@ struct _GdkWaylandDisplay
 
   /* egl info */
   EGLDisplay egl_display;
-  EGLConfig egl_config;
+  EGLConfig egl_config_sdr;
+  EGLConfig egl_config_hdr;
   int egl_major_version;
   int egl_minor_version;
 
diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c
index 80767ae387..da5410df9a 100644
--- a/gdk/wayland/gdkglcontext-wayland.c
+++ b/gdk/wayland/gdkglcontext-wayland.c
@@ -59,6 +59,7 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
   EGLContext ctx;
   EGLint context_attribs[N_EGL_ATTRS];
+  EGLConfig config;
   int major, minor, flags;
   gboolean debug_bit, forward_bit, legacy_bit, use_es;
   int i = 0;
@@ -121,8 +122,13 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
                                legacy_bit ? "yes" : "no",
                                use_es ? "yes" : "no"));
 
+  if (epoxy_has_egl_extension (display_wayland->egl_display, "KHR_no_config_context"))
+    config = EGL_NO_CONFIG_KHR;
+  else
+    config = display_wayland->egl_config_hdr;
+
   ctx = eglCreateContext (display_wayland->egl_display,
-                          display_wayland->egl_config,
+                          config,
                           share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
                                         : EGL_NO_CONTEXT,
                           context_attribs);
@@ -148,7 +154,7 @@ 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,
+                              config,
                               share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
                                             : EGL_NO_CONTEXT,
                               context_attribs);
@@ -177,7 +183,7 @@ 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,
+                              config,
                               share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
                                             : EGL_NO_CONTEXT,
                               context_attribs);
@@ -430,52 +436,56 @@ out:
 
 #define MAX_EGL_ATTRS   30
 
-static EGLConfig
-get_eglconfig (EGLDisplay dpy)
+static void
+get_eglconfig (EGLDisplay dpy,
+               EGLConfig *config_sdr,
+               EGLConfig *config_hdr)
 {
   EGLint attrs[MAX_EGL_ATTRS];
   EGLint n_configs;
   EGLConfig *configs;
-  int pass, i;
+  EGLint type_hdr;
+  int i;
 
-  n_configs = 0;
+  *config_sdr = 0;
+  *config_hdr = 0;
 
-  for (pass = 0; pass <= 1; pass++)
-    {
-      i = 0;
+  n_configs = 0;
 
-      attrs[i++] = EGL_SURFACE_TYPE;
-      attrs[i++] = EGL_WINDOW_BIT;
+  i = 0;
 
-      attrs[i++] = EGL_COLOR_BUFFER_TYPE;
-      attrs[i++] = EGL_RGB_BUFFER;
+  attrs[i++] = EGL_SURFACE_TYPE;
+  attrs[i++] = EGL_WINDOW_BIT;
 
-      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_COLOR_BUFFER_TYPE;
+  attrs[i++] = EGL_RGB_BUFFER;
 
-      if (pass == 0 && epoxy_has_egl_extension (dpy, "EGL_EXT_pixel_format_float"))
-        {
-          attrs[i++] = EGL_COLOR_COMPONENT_TYPE_EXT;
-          attrs[i++] = EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
-        }
+  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 (epoxy_has_egl_extension (dpy, "EGL_EXT_pixel_format_float"))
+    {
+      attrs[i++] = EGL_COLOR_COMPONENT_TYPE_EXT;
+      attrs[i++] = EGL_DONT_CARE;
+    }
 
-      eglChooseConfig (dpy, attrs, NULL, -1, &n_configs);
+  attrs[i++] = EGL_NONE;
+  g_assert (i < MAX_EGL_ATTRS);
 
-      if (n_configs > 0)
-        break;
-    }
+  eglChooseConfig (dpy, attrs, NULL, -1, &n_configs);
 
   configs = g_alloca (sizeof (EGLConfig) * n_configs);
 
+  eglChooseConfig (dpy, attrs, configs, n_configs, &n_configs);
+
+  type_hdr = 0;
+
   for (i = 0; i < n_configs; i++)
     {
       EGLint red, green, blue, alpha, type;
@@ -494,21 +504,20 @@ get_eglconfig (EGLDisplay dpy)
       else
         type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
 
-      if (type == EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT)
+      if (*config_sdr == 0 &&
+          type == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT &&
+          red == 8 && green == 8 && blue == 8 && alpha == 8)
         {
-          /* return the first fp16 config */
-          if (red == 16 && green == 16 && blue == 16 && alpha == 16)
-            return configs[i];
+          *config_sdr = configs[i];
         }
-      else
+
+      if ((type_hdr == 0 || type == EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT) &&
+          red == 16 && green == 16 && blue == 16 && alpha == 16)
         {
-          /* return the first rgba8 config */
-          if (red == 8 && green == 8 && blue == 8 && alpha == 8)
-            return configs[i];
+          *config_hdr = configs[i];
+          type_hdr = type;
         }
     }
-
-  return NULL;
 }
 
 #undef MAX_EGL_ATTRS
@@ -544,17 +553,20 @@ describe_extensions (EGLDisplay dpy)
   return g_strstrip (ext);
 }
 
-static char *
+char *
 describe_egl_config (EGLDisplay dpy,
                      EGLConfig  config)
 {
   EGLint red, green, blue, alpha, type;
 
+  if (!config)
+    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 ("Undisclosed");
+    return g_strdup ("Unknown");
 
   if (epoxy_has_egl_extension (dpy, "EGL_EXT_pixel_format_float"))
     {
@@ -657,14 +669,14 @@ gdk_wayland_display_init_gl (GdkDisplay  *display,
     }
 
   start_time2 = GDK_PROFILER_CURRENT_TIME;
-  display_wayland->egl_config = get_eglconfig (dpy);
+  get_eglconfig (dpy, &display_wayland->egl_config_sdr, &display_wayland->egl_config_hdr);
   gdk_profiler_end_mark (start_time2, "get_eglconfig", NULL);
-  if (!display_wayland->egl_config)
+  if (!display_wayland->egl_config_sdr && !display_wayland->egl_config_hdr)
     {
       eglTerminate (dpy);
       g_set_error_literal (error, GDK_GL_ERROR,
                            GDK_GL_ERROR_UNSUPPORTED_FORMAT,
-                           _("No available configurations for the given pixel format"));
+                           _("No available configurations"));
       return NULL;
     }
 
@@ -680,22 +692,25 @@ gdk_wayland_display_init_gl (GdkDisplay  *display,
 
   GDK_DISPLAY_NOTE (display, OPENGL, {
             char *ext = describe_extensions (dpy);
-            char *cfg = describe_egl_config (dpy, display_wayland->egl_config);
+            char *cfg_sdr = describe_egl_config (dpy, display_wayland->egl_config_sdr);
+            char *cfg_hdr = describe_egl_config (dpy, display_wayland->egl_config_hdr);
             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",
+                       " - SDR config: %s\n"
+                       " - HDR config: %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);
+                       ext, cfg_sdr, cfg_hdr);
             g_free (ext);
+            g_free (cfg_sdr);
+            g_free (cfg_hdr);
   });
 
   ctx = g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT,
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index df072b4f8f..e34e80ff8c 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -202,4 +202,7 @@ GdkSurface * create_dnd_surface (GdkDisplay *display);
 GdkModifierType gdk_wayland_keymap_get_gdk_modifiers (GdkKeymap *keymap,
                                                       guint32    mods);
 
+char * describe_egl_config (EGLDisplay dpy,
+                            EGLConfig  config);
+
 #endif /* __GDK_PRIVATE_WAYLAND_H__ */
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index 4d1951e66d..232b8d429e 100644
--- a/gdk/wayland/gdksurface-wayland.c
+++ b/gdk/wayland/gdksurface-wayland.c
@@ -123,6 +123,7 @@ struct _GdkWaylandSurface
   unsigned int awaiting_frame : 1;
   unsigned int awaiting_frame_frozen : 1;
   unsigned int is_drag_surface : 1;
+  unsigned int rendering : 2;
 
   int pending_buffer_offset_x;
   int pending_buffer_offset_y;
@@ -346,6 +347,7 @@ gdk_wayland_surface_init (GdkWaylandSurface *impl)
   impl->saved_width = -1;
   impl->saved_height = -1;
   impl->shortcuts_inhibitors = g_hash_table_new (NULL, NULL);
+  impl->rendering = GDK_RENDERING_NONE;
 }
 
 static void
@@ -4353,7 +4355,6 @@ gdk_wayland_surface_get_egl_surface (GdkSurface *surface)
 {
   GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
   GdkWaylandSurface *impl;
-  struct wl_egl_window *egl_window;
 
   g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (surface), NULL);
 
@@ -4361,10 +4362,33 @@ gdk_wayland_surface_get_egl_surface (GdkSurface *surface)
 
   if (impl->egl_surface == NULL)
     {
+      struct wl_egl_window *egl_window;
+      EGLConfig config;
+
       egl_window = gdk_wayland_surface_get_wl_egl_window (surface);
 
+      switch (impl->rendering)
+        {
+        case GDK_RENDERING_NONE:
+        case GDK_RENDERING_HDR:
+          if (display->egl_config_hdr)
+            config = display->egl_config_hdr;
+          else
+            config = display->egl_config_sdr;
+          break;
+        case GDK_RENDERING_SDR:
+          config = display->egl_config_sdr;
+          break;
+        default:
+          g_assert_not_reached ();
+        }
+
+      GDK_DISPLAY_NOTE (GDK_DISPLAY (display), OPENGL,
+                        g_message ("Create EGL surface with config: %s",
+                                   describe_egl_config (display->egl_display, config)));
+
       impl->egl_surface =
-        eglCreateWindowSurface (display->egl_display, display->egl_config, egl_window, NULL);
+        eglCreateWindowSurface (display->egl_display, config, egl_window, NULL);
     }
 
   return impl->egl_surface;
@@ -5176,3 +5200,14 @@ gdk_wayland_drag_surface_iface_init (GdkDragSurfaceInterface *iface)
   iface->present = gdk_wayland_drag_surface_present;
 }
 
+void
+gdk_wayland_surface_set_rendering (GdkSurface   *surface,
+                                   GdkRendering  rendering)
+{
+  GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
+
+  g_return_if_fail (GDK_IS_WAYLAND_SURFACE (surface));
+  g_return_if_fail (impl->egl_surface == 0);
+
+  impl->rendering = rendering;
+}
diff --git a/gdk/wayland/gdkwaylandsurface.h b/gdk/wayland/gdkwaylandsurface.h
index 851a4d5607..03fbc7237e 100644
--- a/gdk/wayland/gdkwaylandsurface.h
+++ b/gdk/wayland/gdkwaylandsurface.h
@@ -83,6 +83,18 @@ GDK_AVAILABLE_IN_ALL
 void                     gdk_wayland_toplevel_set_application_id (GdkToplevel *toplevel,
                                                                   const char  *application_id);
 
+typedef enum
+{
+  GDK_RENDERING_NONE,
+  GDK_RENDERING_SDR,
+  GDK_RENDERING_HDR,
+} GdkRendering;
+
+GDK_AVAILABLE_IN_4_6
+void                     gdk_wayland_surface_set_rendering              (GdkSurface   *surface,
+                                                                         GdkRendering  rendering);
+
+
 G_END_DECLS
 
 #endif /* __GDK_WAYLAND_SURFACE_H__ */


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