[gtk/wip/otte/gl-hdr: 18/18] egl: Implement HDR support




commit cdc85232b22758b99b2574838bdfda473b978f27
Author: Benjamin Otte <otte redhat com>
Date:   Wed Oct 6 03:33:24 2021 +0200

    egl: Implement HDR support
    
    If EGL supports:
    * no-config contexts
    * >8bits pixel formats
    * (optionally) floating point pixel formats
    
    Then select such a profile as the HDR format and use it when HDR is
    requested.

 gdk/gdkdisplay.c        | 48 +++++++++++++++++++++++++++++++++++++++---------
 gdk/gdkdisplayprivate.h |  2 ++
 gdk/gdkglcontext.c      |  9 ++++++++-
 gdk/gdksurface.c        | 29 +++++++++++++++++++++++------
 gdk/gdksurfaceprivate.h |  2 ++
 5 files changed, 74 insertions(+), 16 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index cedd0856bc..25f940c47b 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -93,6 +93,7 @@ struct _GdkDisplayPrivate {
 #ifdef HAVE_EGL
   EGLDisplay egl_display;
   EGLConfig egl_config;
+  EGLConfig egl_config_hdr;
 #endif
 
   guint rgba : 1;
@@ -1437,6 +1438,14 @@ gdk_display_get_egl_config (GdkDisplay *self)
   return priv->egl_config;
 }
 
+gpointer
+gdk_display_get_egl_config_hdr (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)
@@ -1477,7 +1486,8 @@ out:
 #define MAX_EGL_ATTRS 30
 
 typedef enum {
-  GDK_EGL_CONFIG_PERFECT = (1 << 0)
+  GDK_EGL_CONFIG_PERFECT = (1 << 0),
+  GDK_EGL_CONFIG_HDR     = (1 << 1),
 } GdkEGLConfigCreateFlags;
 
 static EGLConfig
@@ -1502,14 +1512,21 @@ gdk_display_create_egl_config (GdkDisplay               *self,
   attrs[i++] = EGL_RGB_BUFFER;
 
   attrs[i++] = EGL_RED_SIZE;
-  attrs[i++] = 8;
+  attrs[i++] = (flags & GDK_EGL_CONFIG_HDR) ? 9 : 8;
   attrs[i++] = EGL_GREEN_SIZE;
-  attrs[i++] = 8;
+  attrs[i++] = (flags & GDK_EGL_CONFIG_HDR) ? 9 : 8;
   attrs[i++] = EGL_BLUE_SIZE;
-  attrs[i++] = 8;
+  attrs[i++] = (flags & GDK_EGL_CONFIG_HDR) ? 9 : 8;
   attrs[i++] = EGL_ALPHA_SIZE;
   attrs[i++] = 8;
 
+  if (flags & GDK_EGL_CONFIG_HDR &&
+      self->have_egl_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);
 
@@ -1700,23 +1717,36 @@ gdk_display_init_egl (GdkDisplay  *self,
     epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_swap_buffers_with_damage");
   self->have_egl_no_config_context =
     epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_no_config_context");
+  self->have_egl_pixel_format_float =
+    epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_pixel_format_float");
+
+  if (self->have_egl_no_config_context)
+    priv->egl_config_hdr = gdk_display_create_egl_config (self,
+                                                          GDK_EGL_CONFIG_HDR,
+                                                          error);
+  if (priv->egl_config_hdr == NULL)
+    priv->egl_config_hdr = priv->egl_config;
 
   GDK_DISPLAY_NOTE (self, OPENGL, {
       char *ext = describe_extensions (priv->egl_display);
-      char *cfg = describe_egl_config (priv->egl_display, priv->egl_config);
+      char *sdr_cfg = describe_egl_config (priv->egl_display, priv->egl_config);
+      char *hdr_cfg = describe_egl_config (priv->egl_display, priv->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"
-                 " - Selected fbconfig: %s",
+                 "\t%s\n"
+                 " - Selected fbconfig: %s\n"
+                 "        HDR 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);
+                 ext, sdr_cfg,
+                 priv->egl_config_hdr == priv->egl_config ? "none" : hdr_cfg);
+      g_free (hdr_cfg);
+      g_free (sdr_cfg);
       g_free (ext);
   });
 
diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h
index 3b7a18f4b3..4cb85b2ea4 100644
--- a/gdk/gdkdisplayprivate.h
+++ b/gdk/gdkdisplayprivate.h
@@ -109,6 +109,7 @@ struct _GdkDisplay
   guint have_egl_buffer_age : 1;
   guint have_egl_swap_buffers_with_damage : 1;
   guint have_egl_no_config_context : 1;
+  guint have_egl_pixel_format_float : 1;
 };
 
 struct _GdkDisplayClass
@@ -225,6 +226,7 @@ gboolean            gdk_display_init_egl              (GdkDisplay       *display
                                                        GError          **error);
 gpointer            gdk_display_get_egl_display       (GdkDisplay       *display);
 gpointer            gdk_display_get_egl_config        (GdkDisplay       *display);
+gpointer            gdk_display_get_egl_config_hdr    (GdkDisplay       *display);
 
 void                gdk_display_set_rgba              (GdkDisplay       *display,
                                                        gboolean          rgba);
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 73b82e8d41..11c3f77dd4 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -633,10 +633,18 @@ gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
                                  cairo_region_t *region)
 {
   GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
+  G_GNUC_UNUSED GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
   GdkSurface *surface;
   cairo_region_t *damage;
   int ww, wh;
 
+  surface = gdk_draw_context_get_surface (draw_context);
+
+#ifdef HAVE_EGL
+  if (priv->egl_context)
+    gdk_surface_ensure_egl_surface (surface, request_hdr);
+#endif
+
   damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);
 
   if (context->old_updated_area[1])
@@ -647,7 +655,6 @@ gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
   cairo_region_union (region, damage);
   cairo_region_destroy (damage);
 
-  surface = gdk_draw_context_get_surface (draw_context);
   ww = gdk_surface_get_width (surface) * gdk_surface_get_scale_factor (surface);
   wh = gdk_surface_get_height (surface) * gdk_surface_get_scale_factor (surface);
 
diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c
index c64c2a6a47..13d779a817 100644
--- a/gdk/gdksurface.c
+++ b/gdk/gdksurface.c
@@ -71,6 +71,7 @@ struct _GdkSurfacePrivate
   gpointer egl_native_window;
 #ifdef HAVE_EGL
   EGLSurface egl_surface;
+  gboolean egl_surface_hdr;
 #endif
 
   gpointer widget;
@@ -1103,19 +1104,35 @@ gdk_surface_get_egl_surface (GdkSurface *self)
 {
   GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
 
-  g_return_val_if_fail (priv->egl_native_window != NULL, NULL);
+  return priv->egl_surface;
+}
 
-  if (priv->egl_surface == NULL)
+void
+gdk_surface_ensure_egl_surface (GdkSurface *self,
+                                gboolean    hdr)
+{
+  GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
+  GdkDisplay *display = gdk_surface_get_display (self);
+
+  g_return_if_fail (priv->egl_native_window != NULL);
+
+  if (priv->egl_surface_hdr != hdr &&
+      priv->egl_surface != NULL &&
+      gdk_display_get_egl_config_hdr (display) != gdk_display_get_egl_config (display))
     {
-      GdkDisplay *display = gdk_surface_get_display (self);
+      eglDestroySurface (gdk_surface_get_display (self), priv->egl_surface);
+      priv->egl_surface = NULL;
+    }
 
+  if (priv->egl_surface == NULL)
+    {
       priv->egl_surface = eglCreateWindowSurface (gdk_display_get_egl_display (display),
-                                                  gdk_display_get_egl_config (display),
+                                                  hdr ? gdk_display_get_egl_config_hdr (display)
+                                                      : gdk_display_get_egl_config (display),
                                                   (EGLNativeWindowType) priv->egl_native_window,
                                                   NULL);
+      priv->egl_surface_hdr = hdr;
     }
-
-  return priv->egl_surface;
 #endif
 }
 
diff --git a/gdk/gdksurfaceprivate.h b/gdk/gdksurfaceprivate.h
index ec9f177e5e..c53368574d 100644
--- a/gdk/gdksurfaceprivate.h
+++ b/gdk/gdksurfaceprivate.h
@@ -294,6 +294,8 @@ void gdk_surface_get_geometry (GdkSurface *surface,
 
 void                    gdk_surface_set_egl_native_window       (GdkSurface             *self,
                                                                  gpointer                native_window);
+void                    gdk_surface_ensure_egl_surface          (GdkSurface             *self,
+                                                                 gboolean                hdr);
 gpointer /*EGLSurface*/ gdk_surface_get_egl_surface             (GdkSurface             *self);
 
 void                    gdk_surface_set_widget                  (GdkSurface             *self,


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