[gtk/matthiasc/color-profiles: 9/12] wayland: Implement set_hdr




commit dffaec48df16673e4edd8ee248a2162db0e19df0
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Oct 1 20:25:56 2021 -0400

    wayland: Implement set_hdr
    
    Keep both an HDR and an SDR EGLConfig around,
    and implement set_hdr by recreating the EGL surface
    with the right config.

 gdk/wayland/gdkdisplay-wayland.h   |  3 +-
 gdk/wayland/gdkglcontext-wayland.c | 80 +++++++++++++++++++++++++++++++-------
 gdk/wayland/gdksurface-wayland.c   | 46 ++++++++++++++++++++--
 3 files changed, 112 insertions(+), 17 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 ab36c44639..1a26a21ae1 100644
--- a/gdk/wayland/gdkglcontext-wayland.c
+++ b/gdk/wayland/gdkglcontext-wayland.c
@@ -436,13 +436,23 @@ 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 count;
-  EGLConfig config;
-  int i = 0;
+  EGLint n_configs;
+  EGLConfig *configs;
+  EGLint type_hdr;
+  int i;
+
+  *config_sdr = 0;
+  *config_hdr = 0;
+
+  n_configs = 0;
+
+  i = 0;
 
   attrs[i++] = EGL_SURFACE_TYPE;
   attrs[i++] = EGL_WINDOW_BIT;
@@ -459,14 +469,55 @@ get_eglconfig (EGLDisplay dpy)
   attrs[i++] = EGL_ALPHA_SIZE;
   attrs[i++] = 8;
 
+  if (epoxy_has_egl_extension (dpy, "EGL_EXT_pixel_format_float"))
+    {
+      attrs[i++] = EGL_COLOR_COMPONENT_TYPE_EXT;
+      attrs[i++] = EGL_DONT_CARE;
+    }
+
   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;
+  eglChooseConfig (dpy, attrs, NULL, -1, &n_configs);
+
+  configs = g_alloca (sizeof (EGLConfig) * n_configs);
 
-  return config;
+  eglChooseConfig (dpy, attrs, configs, n_configs, &n_configs);
+
+  type_hdr = 0;
+
+  for (i = 0; i < n_configs; i++)
+    {
+      EGLint red, green, blue, alpha, type;
+
+      if (!eglGetConfigAttrib (dpy, configs[i], EGL_RED_SIZE, &red) ||
+          !eglGetConfigAttrib (dpy, configs[i], EGL_GREEN_SIZE, &green) ||
+          !eglGetConfigAttrib (dpy, configs[i], EGL_BLUE_SIZE, &blue) ||
+          !eglGetConfigAttrib (dpy, configs[i], EGL_ALPHA_SIZE, &alpha))
+        continue;
+
+      if (epoxy_has_egl_extension (dpy, "EGL_EXT_pixel_format_float"))
+        {
+          if (!eglGetConfigAttrib (dpy, configs[i], EGL_COLOR_COMPONENT_TYPE_EXT, &type))
+            type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+        }
+      else
+        type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+
+      if (*config_sdr == 0 &&
+          type == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT &&
+          red == 8 && green == 8 && blue == 8 && alpha == 8)
+        {
+          *config_sdr = configs[i];
+        }
+
+      if ((type_hdr == 0 || type == EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT) &&
+          red == 16 && green == 16 && blue == 16 && alpha == 16)
+        {
+          *config_hdr = configs[i];
+          type_hdr = type;
+        }
+    }
 }
 
 #undef MAX_EGL_ATTRS
@@ -650,22 +701,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/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index 4d1951e66d..f7308d7c52 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 hdr : 1;
 
   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->hdr = FALSE;
 }
 
 static void
@@ -4262,6 +4264,33 @@ gdk_wayland_surface_supports_edge_constraints (GdkSurface *surface)
   return gtk_surface1_get_version (gtk_surface) >= GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION;
 }
 
+static void
+gdk_wayland_surface_set_hdr (GdkSurface *surface,
+                             gboolean    hdr)
+{
+  GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
+  GdkWaylandDisplay *display_wayland =
+    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
+
+  if (impl->hdr == hdr)
+    return;
+
+  if (!display_wayland->egl_config_hdr)
+    return;
+
+  impl->hdr = hdr;
+
+  if (impl->egl_surface)
+    {
+      GDK_DISPLAY_NOTE (GDK_DISPLAY (display_wayland), OPENGL,
+                        g_message ("Rendering changed to %s, resetting egl surface",
+                        hdr ? "HDR" : "SDR"));
+
+      eglDestroySurface (display_wayland->egl_display, impl->egl_surface);
+      impl->egl_surface = NULL;
+    }
+}
+
 static void
 gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
 {
@@ -4279,6 +4308,7 @@ gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
   impl_class->set_input_region = gdk_wayland_surface_set_input_region;
   impl_class->destroy = gdk_wayland_surface_destroy;
   impl_class->beep = gdk_wayland_surface_beep;
+  impl_class->set_hdr = gdk_wayland_surface_set_hdr;
 
   impl_class->destroy_notify = gdk_wayland_surface_destroy_notify;
   impl_class->drag_begin = _gdk_wayland_surface_drag_begin;
@@ -4353,7 +4383,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 +4390,22 @@ 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);
 
+      if (impl->hdr && display->egl_config_hdr)
+        config = display->egl_config_hdr;
+      else
+        config = display->egl_config_sdr;
+
+      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;
@@ -5175,4 +5216,3 @@ gdk_wayland_drag_surface_iface_init (GdkDragSurfaceInterface *iface)
 {
   iface->present = gdk_wayland_drag_surface_present;
 }
-


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