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.
This commit is contained in:
Benjamin Otte 2021-10-06 03:33:24 +02:00
parent 5eb42dd9f3
commit cdc85232b2
5 changed files with 74 additions and 16 deletions

View File

@ -93,6 +93,7 @@ struct _GdkDisplayPrivate {
#ifdef HAVE_EGL #ifdef HAVE_EGL
EGLDisplay egl_display; EGLDisplay egl_display;
EGLConfig egl_config; EGLConfig egl_config;
EGLConfig egl_config_hdr;
#endif #endif
guint rgba : 1; guint rgba : 1;
@ -1437,6 +1438,14 @@ gdk_display_get_egl_config (GdkDisplay *self)
return priv->egl_config; 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 static EGLDisplay
gdk_display_create_egl_display (EGLenum platform, gdk_display_create_egl_display (EGLenum platform,
gpointer native_display) gpointer native_display)
@ -1477,7 +1486,8 @@ out:
#define MAX_EGL_ATTRS 30 #define MAX_EGL_ATTRS 30
typedef enum { typedef enum {
GDK_EGL_CONFIG_PERFECT = (1 << 0) GDK_EGL_CONFIG_PERFECT = (1 << 0),
GDK_EGL_CONFIG_HDR = (1 << 1),
} GdkEGLConfigCreateFlags; } GdkEGLConfigCreateFlags;
static EGLConfig static EGLConfig
@ -1502,14 +1512,21 @@ gdk_display_create_egl_config (GdkDisplay *self,
attrs[i++] = EGL_RGB_BUFFER; attrs[i++] = EGL_RGB_BUFFER;
attrs[i++] = EGL_RED_SIZE; attrs[i++] = EGL_RED_SIZE;
attrs[i++] = 8; attrs[i++] = (flags & GDK_EGL_CONFIG_HDR) ? 9 : 8;
attrs[i++] = EGL_GREEN_SIZE; attrs[i++] = EGL_GREEN_SIZE;
attrs[i++] = 8; attrs[i++] = (flags & GDK_EGL_CONFIG_HDR) ? 9 : 8;
attrs[i++] = EGL_BLUE_SIZE; attrs[i++] = EGL_BLUE_SIZE;
attrs[i++] = 8; attrs[i++] = (flags & GDK_EGL_CONFIG_HDR) ? 9 : 8;
attrs[i++] = EGL_ALPHA_SIZE; attrs[i++] = EGL_ALPHA_SIZE;
attrs[i++] = 8; 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; attrs[i++] = EGL_NONE;
g_assert (i < MAX_EGL_ATTRS); 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"); epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_swap_buffers_with_damage");
self->have_egl_no_config_context = self->have_egl_no_config_context =
epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_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, { GDK_DISPLAY_NOTE (self, OPENGL, {
char *ext = describe_extensions (priv->egl_display); 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" g_message ("EGL API version %d.%d found\n"
" - Vendor: %s\n" " - Vendor: %s\n"
" - Version: %s\n" " - Version: %s\n"
" - Client APIs: %s\n" " - Client APIs: %s\n"
" - Extensions:\n" " - Extensions:\n"
"\t%s" "\t%s\n"
" - Selected fbconfig: %s", " - Selected fbconfig: %s\n"
" HDR fbconfig: %s",
major, minor, major, minor,
eglQueryString (priv->egl_display, EGL_VENDOR), eglQueryString (priv->egl_display, EGL_VENDOR),
eglQueryString (priv->egl_display, EGL_VERSION), eglQueryString (priv->egl_display, EGL_VERSION),
eglQueryString (priv->egl_display, EGL_CLIENT_APIS), eglQueryString (priv->egl_display, EGL_CLIENT_APIS),
ext, cfg); ext, sdr_cfg,
g_free (cfg); priv->egl_config_hdr == priv->egl_config ? "none" : hdr_cfg);
g_free (hdr_cfg);
g_free (sdr_cfg);
g_free (ext); g_free (ext);
}); });

View File

@ -109,6 +109,7 @@ struct _GdkDisplay
guint have_egl_buffer_age : 1; guint have_egl_buffer_age : 1;
guint have_egl_swap_buffers_with_damage : 1; guint have_egl_swap_buffers_with_damage : 1;
guint have_egl_no_config_context : 1; guint have_egl_no_config_context : 1;
guint have_egl_pixel_format_float : 1;
}; };
struct _GdkDisplayClass struct _GdkDisplayClass
@ -225,6 +226,7 @@ gboolean gdk_display_init_egl (GdkDisplay *display
GError **error); GError **error);
gpointer gdk_display_get_egl_display (GdkDisplay *display); gpointer gdk_display_get_egl_display (GdkDisplay *display);
gpointer gdk_display_get_egl_config (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, void gdk_display_set_rgba (GdkDisplay *display,
gboolean rgba); gboolean rgba);

View File

@ -633,10 +633,18 @@ gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *region) cairo_region_t *region)
{ {
GdkGLContext *context = GDK_GL_CONTEXT (draw_context); GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
G_GNUC_UNUSED GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkSurface *surface; GdkSurface *surface;
cairo_region_t *damage; cairo_region_t *damage;
int ww, wh; 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); damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);
if (context->old_updated_area[1]) 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_union (region, damage);
cairo_region_destroy (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); ww = gdk_surface_get_width (surface) * gdk_surface_get_scale_factor (surface);
wh = gdk_surface_get_height (surface) * gdk_surface_get_scale_factor (surface); wh = gdk_surface_get_height (surface) * gdk_surface_get_scale_factor (surface);

View File

@ -71,6 +71,7 @@ struct _GdkSurfacePrivate
gpointer egl_native_window; gpointer egl_native_window;
#ifdef HAVE_EGL #ifdef HAVE_EGL
EGLSurface egl_surface; EGLSurface egl_surface;
gboolean egl_surface_hdr;
#endif #endif
gpointer widget; gpointer widget;
@ -1103,19 +1104,35 @@ gdk_surface_get_egl_surface (GdkSurface *self)
{ {
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self); GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
g_return_val_if_fail (priv->egl_native_window != NULL, NULL); return priv->egl_surface;
}
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))
{
eglDestroySurface (gdk_surface_get_display (self), priv->egl_surface);
priv->egl_surface = NULL;
}
if (priv->egl_surface == NULL) if (priv->egl_surface == NULL)
{ {
GdkDisplay *display = gdk_surface_get_display (self);
priv->egl_surface = eglCreateWindowSurface (gdk_display_get_egl_display (display), 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, (EGLNativeWindowType) priv->egl_native_window,
NULL); NULL);
priv->egl_surface_hdr = hdr;
} }
return priv->egl_surface;
#endif #endif
} }

View File

@ -294,6 +294,8 @@ void gdk_surface_get_geometry (GdkSurface *surface,
void gdk_surface_set_egl_native_window (GdkSurface *self, void gdk_surface_set_egl_native_window (GdkSurface *self,
gpointer native_window); gpointer native_window);
void gdk_surface_ensure_egl_surface (GdkSurface *self,
gboolean hdr);
gpointer /*EGLSurface*/ gdk_surface_get_egl_surface (GdkSurface *self); gpointer /*EGLSurface*/ gdk_surface_get_egl_surface (GdkSurface *self);
void gdk_surface_set_widget (GdkSurface *self, void gdk_surface_set_widget (GdkSurface *self,