Merge branch 'wayland-color-states' into 'main'
Wayland color management See merge request GNOME/gtk!7444
This commit is contained in:
@@ -52,6 +52,7 @@
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdkdihedralprivate.h"
|
||||
#include "gdktoplevel-wayland-private.h"
|
||||
#include "gdkwaylandcolor-private.h"
|
||||
#include <wayland/pointer-gestures-unstable-v1-client-protocol.h>
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
|
||||
@@ -533,6 +534,10 @@ gdk_registry_handle_global (void *data,
|
||||
&wp_presentation_interface,
|
||||
MIN (version, 1));
|
||||
}
|
||||
else if (strcmp (interface, "xx_color_manager_v2") == 0)
|
||||
{
|
||||
display_wayland->color = gdk_wayland_color_new (registry, id, version);
|
||||
}
|
||||
else if (strcmp (interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0)
|
||||
{
|
||||
display_wayland->single_pixel_buffer =
|
||||
@@ -693,6 +698,12 @@ _gdk_wayland_display_open (const char *display_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (display_wayland->color)
|
||||
{
|
||||
if (!gdk_wayland_color_prepare (display_wayland->color))
|
||||
g_clear_pointer (&display_wayland->color, gdk_wayland_color_free );
|
||||
}
|
||||
|
||||
gdk_display_emit_opened (display);
|
||||
|
||||
return display;
|
||||
@@ -753,6 +764,7 @@ gdk_wayland_display_dispose (GObject *object)
|
||||
g_clear_pointer (&display_wayland->single_pixel_buffer, wp_single_pixel_buffer_manager_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->linux_dmabuf, zwp_linux_dmabuf_v1_destroy);
|
||||
g_clear_pointer (&display_wayland->dmabuf_formats_info, dmabuf_formats_info_free);
|
||||
g_clear_pointer (&display_wayland->color, gdk_wayland_color_free);
|
||||
|
||||
g_clear_pointer (&display_wayland->shm, wl_shm_destroy);
|
||||
g_clear_pointer (&display_wayland->wl_registry, wl_registry_destroy);
|
||||
|
||||
@@ -59,6 +59,7 @@ G_BEGIN_DECLS
|
||||
|
||||
#define GDK_ZWP_POINTER_GESTURES_V1_VERSION 3
|
||||
|
||||
typedef struct _GdkWaylandColor GdkWaylandColor;
|
||||
typedef struct _GdkWaylandSelection GdkWaylandSelection;
|
||||
|
||||
typedef struct {
|
||||
@@ -123,6 +124,7 @@ struct _GdkWaylandDisplay
|
||||
struct wp_viewporter *viewporter;
|
||||
struct wp_presentation *presentation;
|
||||
struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer;
|
||||
GdkWaylandColor *color;
|
||||
|
||||
GList *async_roundtrips;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "gdksubsurfaceprivate.h"
|
||||
|
||||
#include "gdkwaylandcolor-private.h"
|
||||
#include "wayland-client-protocol.h"
|
||||
|
||||
typedef struct _GdkWaylandSubsurface GdkWaylandSubsurface;
|
||||
@@ -20,6 +21,7 @@ struct _GdkWaylandSubsurface
|
||||
struct wl_surface *surface;
|
||||
struct wl_subsurface *subsurface;
|
||||
struct wp_viewport *viewport;
|
||||
GdkWaylandColorSurface *color;
|
||||
|
||||
GdkTexture *texture;
|
||||
cairo_rectangle_int_t dest;
|
||||
|
||||
@@ -48,6 +48,7 @@ gdk_wayland_subsurface_finalize (GObject *object)
|
||||
g_clear_pointer (&self->frame_callback, wl_callback_destroy);
|
||||
g_clear_pointer (&self->opaque_region, wl_region_destroy);
|
||||
g_clear_pointer (&self->viewport, wp_viewport_destroy);
|
||||
g_clear_pointer (&self->color, gdk_wayland_color_surface_free);
|
||||
g_clear_pointer (&self->subsurface, wl_subsurface_destroy);
|
||||
g_clear_pointer (&self->surface, wl_surface_destroy);
|
||||
g_clear_pointer (&self->bg_viewport, wp_viewport_destroy);
|
||||
@@ -411,6 +412,7 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||
gboolean needs_commit = FALSE;
|
||||
gboolean background_changed = FALSE;
|
||||
gboolean needs_bg_commit = FALSE;
|
||||
gboolean color_state_changed = FALSE;
|
||||
|
||||
if (sibling)
|
||||
will_be_above = sibling->above_parent;
|
||||
@@ -542,6 +544,14 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||
"[%p] 🗙 Texture has background, but no single-pixel buffer support",
|
||||
self);
|
||||
}
|
||||
else if (self->color &&
|
||||
!gdk_wayland_color_surface_can_set_color_state (self->color, gdk_texture_get_color_state (texture)))
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (gdk_surface_get_display (sub->parent), OFFLOAD,
|
||||
"[%p] 🗙 Texture colorstate %s not supported",
|
||||
self,
|
||||
gdk_color_state_get_name (gdk_texture_get_color_state (texture)));
|
||||
}
|
||||
else
|
||||
{
|
||||
gboolean was_transparent;
|
||||
@@ -551,6 +561,12 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||
else
|
||||
was_transparent = FALSE;
|
||||
|
||||
if (self->texture && texture)
|
||||
color_state_changed = !gdk_color_state_equal (gdk_texture_get_color_state (self->texture),
|
||||
gdk_texture_get_color_state (texture));
|
||||
else
|
||||
color_state_changed = TRUE;
|
||||
|
||||
if (g_set_object (&self->texture, texture))
|
||||
{
|
||||
buffer = get_wl_buffer (self, texture);
|
||||
@@ -568,7 +584,7 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||
}
|
||||
|
||||
GDK_DISPLAY_DEBUG (gdk_surface_get_display (sub->parent), OFFLOAD,
|
||||
"[%p] %s Attaching %s (%dx%d) at %d %d %d %d%s%s%s",
|
||||
"[%p] %s Attaching %s (%dx%d, %s) at %d %d %d %d%s%s%s",
|
||||
self,
|
||||
G_OBJECT_TYPE_NAME (texture),
|
||||
will_be_above
|
||||
@@ -576,11 +592,12 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||
: (has_background ? "▼" : "▽"),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture),
|
||||
gdk_color_state_get_name (gdk_texture_get_color_state (texture)),
|
||||
self->dest.x, self->dest.y,
|
||||
self->dest.width, self->dest.height,
|
||||
transform != GDK_DIHEDRAL_NORMAL ? " (" : "",
|
||||
transform != GDK_DIHEDRAL_NORMAL ? gdk_dihedral_get_name (transform) : "",
|
||||
transform != GDK_DIHEDRAL_NORMAL ? " )" : ""
|
||||
transform != GDK_DIHEDRAL_NORMAL ? ")" : ""
|
||||
);
|
||||
result = TRUE;
|
||||
}
|
||||
@@ -643,6 +660,10 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||
0, 0,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
|
||||
if (self->color && color_state_changed)
|
||||
gdk_wayland_color_surface_set_color_state (self->color, gdk_texture_get_color_state (texture));
|
||||
|
||||
needs_commit = TRUE;
|
||||
}
|
||||
|
||||
@@ -891,6 +912,9 @@ gdk_wayland_surface_create_subsurface (GdkSurface *surface)
|
||||
sub->subsurface = wl_subcompositor_get_subsurface (disp->subcompositor,
|
||||
sub->surface,
|
||||
impl->display_server.wl_surface);
|
||||
if (disp->color)
|
||||
sub->color = gdk_wayland_color_surface_new (disp->color, sub->surface, NULL, NULL);
|
||||
|
||||
sub->viewport = wp_viewporter_get_viewport (disp->viewporter, sub->surface);
|
||||
|
||||
/* No input, please */
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkwaylandcolor-private.h"
|
||||
|
||||
typedef enum _PopupState
|
||||
{
|
||||
@@ -39,6 +40,7 @@ struct _GdkWaylandSurface
|
||||
struct wl_egl_window *egl_window;
|
||||
struct wp_fractional_scale_v1 *fractional_scale;
|
||||
struct wp_viewport *viewport;
|
||||
GdkWaylandColorSurface *color;
|
||||
} display_server;
|
||||
|
||||
struct wl_event_queue *event_queue;
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
|
||||
#include "gsk/gskrectprivate.h"
|
||||
|
||||
|
||||
/**
|
||||
* GdkWaylandSurface:
|
||||
*
|
||||
@@ -906,6 +905,14 @@ static const struct wl_surface_listener surface_listener = {
|
||||
surface_preferred_buffer_transform,
|
||||
};
|
||||
|
||||
static void
|
||||
preferred_changed (GdkWaylandColorSurface *color,
|
||||
GdkColorState *color_state,
|
||||
gpointer data)
|
||||
{
|
||||
gdk_surface_set_color_state (GDK_SURFACE (data), color_state);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_create_wl_surface (GdkSurface *surface)
|
||||
{
|
||||
@@ -930,6 +937,12 @@ gdk_wayland_surface_create_wl_surface (GdkSurface *surface)
|
||||
wp_viewporter_get_viewport (display_wayland->viewporter, wl_surface);
|
||||
}
|
||||
|
||||
if (display_wayland->color)
|
||||
self->display_server.color = gdk_wayland_color_surface_new (display_wayland->color,
|
||||
wl_surface,
|
||||
preferred_changed,
|
||||
self);
|
||||
|
||||
self->display_server.wl_surface = wl_surface;
|
||||
}
|
||||
|
||||
@@ -983,6 +996,7 @@ gdk_wayland_surface_destroy_wl_surface (GdkWaylandSurface *self)
|
||||
|
||||
g_clear_pointer (&self->display_server.viewport, wp_viewport_destroy);
|
||||
g_clear_pointer (&self->display_server.fractional_scale, wp_fractional_scale_v1_destroy);
|
||||
g_clear_pointer (&self->display_server.color, gdk_wayland_color_surface_free);
|
||||
|
||||
g_clear_pointer (&self->display_server.wl_surface, wl_surface_destroy);
|
||||
|
||||
|
||||
37
gdk/wayland/gdkwaylandcolor-private.h
Normal file
37
gdk/wayland/gdkwaylandcolor-private.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include <wayland-client.h>
|
||||
|
||||
typedef struct _GdkWaylandColor GdkWaylandColor;
|
||||
|
||||
GdkWaylandColor * gdk_wayland_color_new (struct wl_registry *registry,
|
||||
uint32_t id,
|
||||
uint32_t version);
|
||||
|
||||
void gdk_wayland_color_free (GdkWaylandColor *color);
|
||||
|
||||
gboolean gdk_wayland_color_prepare (GdkWaylandColor *color);
|
||||
|
||||
struct wl_proxy * gdk_wayland_color_get_color_manager (GdkWaylandColor *color);
|
||||
|
||||
|
||||
typedef struct _GdkWaylandColorSurface GdkWaylandColorSurface;
|
||||
|
||||
typedef void (* GdkColorStateChanged) (GdkWaylandColorSurface *self,
|
||||
GdkColorState *cs,
|
||||
gpointer data);
|
||||
|
||||
GdkWaylandColorSurface *
|
||||
gdk_wayland_color_surface_new (GdkWaylandColor *color,
|
||||
struct wl_surface *wl_surface,
|
||||
GdkColorStateChanged callback,
|
||||
gpointer data);
|
||||
|
||||
void gdk_wayland_color_surface_free (GdkWaylandColorSurface *self);
|
||||
|
||||
void gdk_wayland_color_surface_set_color_state (GdkWaylandColorSurface *self,
|
||||
GdkColorState *cs);
|
||||
|
||||
gboolean gdk_wayland_color_surface_can_set_color_state (GdkWaylandColorSurface *self,
|
||||
GdkColorState *cs);
|
||||
583
gdk/wayland/gdkwaylandcolor.c
Normal file
583
gdk/wayland/gdkwaylandcolor.c
Normal file
@@ -0,0 +1,583 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkwaylandcolor-private.h"
|
||||
#include "gdksurface-wayland-private.h"
|
||||
#include <gdk/wayland/xx-color-management-v2-client-protocol.h>
|
||||
|
||||
|
||||
struct _GdkWaylandColor
|
||||
{
|
||||
struct xx_color_manager_v2 *color_manager;
|
||||
struct {
|
||||
unsigned int intents;
|
||||
unsigned int features;
|
||||
unsigned int transfers;
|
||||
unsigned int primaries;
|
||||
} color_manager_supported;
|
||||
struct xx_image_description_v2 *srgb;
|
||||
struct xx_image_description_v2 *srgb_linear;
|
||||
struct xx_image_description_v2 *rec2100_pq;
|
||||
struct xx_image_description_v2 *rec2100_linear;
|
||||
};
|
||||
|
||||
static void
|
||||
xx_color_manager_v2_supported_intent (void *data,
|
||||
struct xx_color_manager_v2 *xx_color_manager_v2,
|
||||
uint32_t render_intent)
|
||||
{
|
||||
GdkWaylandColor *color = data;
|
||||
|
||||
color->color_manager_supported.intents |= (1 << render_intent);
|
||||
}
|
||||
|
||||
static void
|
||||
xx_color_manager_v2_supported_feature (void *data,
|
||||
struct xx_color_manager_v2 *xx_color_manager_v2,
|
||||
uint32_t feature)
|
||||
{
|
||||
GdkWaylandColor *color = data;
|
||||
|
||||
color->color_manager_supported.features |= (1 << feature);
|
||||
}
|
||||
|
||||
static void
|
||||
xx_color_manager_v2_supported_tf_named (void *data,
|
||||
struct xx_color_manager_v2 *xx_color_manager_v2,
|
||||
uint32_t tf)
|
||||
{
|
||||
GdkWaylandColor *color = data;
|
||||
|
||||
color->color_manager_supported.transfers |= (1 << tf);
|
||||
}
|
||||
|
||||
static void
|
||||
xx_color_manager_v2_supported_primaries_named (void *data,
|
||||
struct xx_color_manager_v2 *xx_color_manager_v2,
|
||||
uint32_t primaries)
|
||||
{
|
||||
GdkWaylandColor *color = data;
|
||||
|
||||
color->color_manager_supported.primaries |= (1 << primaries);
|
||||
}
|
||||
|
||||
static struct xx_color_manager_v2_listener color_manager_listener = {
|
||||
xx_color_manager_v2_supported_intent,
|
||||
xx_color_manager_v2_supported_feature,
|
||||
xx_color_manager_v2_supported_tf_named,
|
||||
xx_color_manager_v2_supported_primaries_named,
|
||||
};
|
||||
|
||||
GdkWaylandColor *
|
||||
gdk_wayland_color_new (struct wl_registry *registry,
|
||||
uint32_t id,
|
||||
uint32_t version)
|
||||
{
|
||||
GdkWaylandColor *color;
|
||||
|
||||
color = g_new0 (GdkWaylandColor, 1);
|
||||
|
||||
color->color_manager = wl_registry_bind (registry,
|
||||
id,
|
||||
&xx_color_manager_v2_interface,
|
||||
MIN (version, 2));
|
||||
|
||||
xx_color_manager_v2_add_listener (color->color_manager,
|
||||
&color_manager_listener,
|
||||
color);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_color_free (GdkWaylandColor *color)
|
||||
{
|
||||
g_clear_pointer (&color->color_manager, xx_color_manager_v2_destroy);
|
||||
g_clear_pointer (&color->srgb, xx_image_description_v2_destroy);
|
||||
g_clear_pointer (&color->srgb_linear, xx_image_description_v2_destroy);
|
||||
g_clear_pointer (&color->rec2100_pq, xx_image_description_v2_destroy);
|
||||
g_clear_pointer (&color->rec2100_linear, xx_image_description_v2_destroy);
|
||||
g_free (color);
|
||||
}
|
||||
|
||||
struct wl_proxy *
|
||||
gdk_wayland_color_get_color_manager (GdkWaylandColor *color)
|
||||
{
|
||||
return (struct wl_proxy *) color->color_manager;
|
||||
}
|
||||
|
||||
static void
|
||||
std_image_desc_failed (void *data,
|
||||
struct xx_image_description_v2 *desc,
|
||||
uint32_t cause,
|
||||
const char *msg)
|
||||
{
|
||||
g_warning ("Failed to get one of the standard image descriptions: %s", msg);
|
||||
xx_image_description_v2_destroy (desc);
|
||||
}
|
||||
|
||||
static void
|
||||
std_image_desc_ready (void *data,
|
||||
struct xx_image_description_v2 *desc,
|
||||
uint32_t identity)
|
||||
{
|
||||
struct xx_image_description_v2 **ptr = data;
|
||||
|
||||
*ptr = desc;
|
||||
}
|
||||
|
||||
static struct xx_image_description_v2_listener std_image_desc_listener = {
|
||||
std_image_desc_failed,
|
||||
std_image_desc_ready,
|
||||
};
|
||||
|
||||
static void
|
||||
create_image_desc (GdkWaylandColor *color,
|
||||
uint32_t primaries,
|
||||
uint32_t tf,
|
||||
struct xx_image_description_v2 **out_desc)
|
||||
{
|
||||
struct xx_image_description_creator_params_v2 *creator;
|
||||
struct xx_image_description_v2 *desc;
|
||||
|
||||
creator = xx_color_manager_v2_new_parametric_creator (color->color_manager);
|
||||
|
||||
xx_image_description_creator_params_v2_set_primaries_named (creator, primaries);
|
||||
xx_image_description_creator_params_v2_set_tf_named (creator, tf);
|
||||
|
||||
desc = xx_image_description_creator_params_v2_create (creator);
|
||||
|
||||
xx_image_description_v2_add_listener (desc, &std_image_desc_listener, out_desc);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_wayland_color_prepare (GdkWaylandColor *color)
|
||||
{
|
||||
if (color->color_manager)
|
||||
{
|
||||
const char *intents[] = {
|
||||
"perceptual", "relative", "saturation", "absolute", "relative-bpc"
|
||||
};
|
||||
const char *features[] = {
|
||||
"icc-v2-v4", "parametric", "set-primaries", "set-tf-power",
|
||||
"set-mastering-display-primaries", "extended-target-volume"
|
||||
};
|
||||
const char *tf[] = {
|
||||
"bt709", "gamma22", "gamma28", "st240", "linear", "log100",
|
||||
"log316", "xvycc", "bt1361", "srgb", "ext-srgb", "pq", "st428", "hlg"
|
||||
};
|
||||
const char *primaries[] = {
|
||||
"srgb", "pal-m", "pal", "ntsc", "generic-film", "bt2020", "xyz",
|
||||
"dci-p3", "display-p3", "adobe-rgb",
|
||||
};
|
||||
|
||||
for (int i = 0; i < G_N_ELEMENTS (intents); i++)
|
||||
{
|
||||
GDK_DEBUG (MISC, "Rendering intent %d (%s): %s",
|
||||
i, intents[i], color->color_manager_supported.intents & (1 << i) ? "✓" : "✗");
|
||||
}
|
||||
|
||||
for (int i = 0; i < G_N_ELEMENTS (features); i++)
|
||||
{
|
||||
GDK_DEBUG (MISC, "Feature %d (%s): %s",
|
||||
i, features[i], color->color_manager_supported.features & (1 << i) ? "✓" : "✗");
|
||||
}
|
||||
|
||||
for (int i = 0; i < G_N_ELEMENTS (tf); i++)
|
||||
{
|
||||
GDK_DEBUG (MISC, "Transfer function %d (%s): %s",
|
||||
i, tf[i], color->color_manager_supported.transfers & (1 << i) ? "✓" : "✗");
|
||||
}
|
||||
|
||||
for (int i = 0; i < G_N_ELEMENTS (primaries); i++)
|
||||
{
|
||||
GDK_DEBUG (MISC, "Primaries %d (%s): %s",
|
||||
i, primaries[i], color->color_manager_supported.primaries& (1 << i) ? "✓" : "✗");
|
||||
}
|
||||
}
|
||||
|
||||
if (color->color_manager &&
|
||||
!(color->color_manager_supported.intents & (1 << XX_COLOR_MANAGER_V2_RENDER_INTENT_PERCEPTUAL)))
|
||||
{
|
||||
GDK_DEBUG (MISC, "Not using color management: Missing perceptual render intent");
|
||||
g_clear_pointer (&color->color_manager, xx_color_manager_v2_destroy);
|
||||
}
|
||||
|
||||
if (color->color_manager &&
|
||||
(!(color->color_manager_supported.features & (1 << XX_COLOR_MANAGER_V2_FEATURE_PARAMETRIC)) ||
|
||||
!(color->color_manager_supported.transfers & (1 << XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_SRGB)) ||
|
||||
!(color->color_manager_supported.primaries & (1 << XX_COLOR_MANAGER_V2_PRIMARIES_SRGB))))
|
||||
|
||||
{
|
||||
GDK_DEBUG (MISC, "Not using color management: Can't create srgb image description");
|
||||
g_clear_pointer (&color->color_manager, xx_color_manager_v2_destroy);
|
||||
}
|
||||
|
||||
if (color->color_manager)
|
||||
{
|
||||
create_image_desc (color,
|
||||
XX_COLOR_MANAGER_V2_PRIMARIES_SRGB,
|
||||
XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_SRGB,
|
||||
&color->srgb);
|
||||
|
||||
if (color->color_manager_supported.transfers & (1 << XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LINEAR))
|
||||
create_image_desc (color,
|
||||
XX_COLOR_MANAGER_V2_PRIMARIES_SRGB,
|
||||
XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LINEAR,
|
||||
&color->srgb_linear);
|
||||
|
||||
if (color->color_manager_supported.primaries & (1 << XX_COLOR_MANAGER_V2_PRIMARIES_BT2020))
|
||||
{
|
||||
if (color->color_manager_supported.transfers & (1 << XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_ST2084_PQ))
|
||||
create_image_desc (color,
|
||||
XX_COLOR_MANAGER_V2_PRIMARIES_BT2020,
|
||||
XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_ST2084_PQ,
|
||||
&color->rec2100_pq);
|
||||
|
||||
if (color->color_manager_supported.transfers & (1 << XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LINEAR))
|
||||
create_image_desc (color,
|
||||
XX_COLOR_MANAGER_V2_PRIMARIES_BT2020,
|
||||
XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LINEAR,
|
||||
&color->rec2100_linear);
|
||||
}
|
||||
}
|
||||
|
||||
return color->color_manager != NULL;
|
||||
}
|
||||
|
||||
struct _GdkWaylandColorSurface
|
||||
{
|
||||
GdkWaylandColor *color;
|
||||
struct xx_color_management_surface_v2 *surface;
|
||||
GdkColorStateChanged callback;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdkWaylandColorSurface *surface;
|
||||
|
||||
struct xx_image_description_v2 *image_desc;
|
||||
struct xx_image_description_info_v2 *info;
|
||||
|
||||
int32_t icc;
|
||||
uint32_t icc_size;
|
||||
uint32_t r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y;
|
||||
uint32_t primaries;
|
||||
uint32_t tf_power;
|
||||
uint32_t tf_named;
|
||||
uint32_t target_r_x, target_r_y, target_g_x, target_g_y, target_b_x, target_b_y, target_w_x, target_w_y;
|
||||
uint32_t target_min_lum, target_max_lum;
|
||||
uint32_t target_max_cll, target_max_fall;
|
||||
|
||||
unsigned int has_icc : 1;
|
||||
unsigned int has_primaries : 1;
|
||||
unsigned int has_primaries_named : 1;
|
||||
unsigned int has_tf_power : 1;
|
||||
unsigned int has_tf_named : 1;
|
||||
unsigned int has_target_primaries : 1;
|
||||
unsigned int has_target_luminance : 1;
|
||||
unsigned int has_target_max_cll : 1;
|
||||
unsigned int has_target_max_fall : 1;
|
||||
} ImageDescription;
|
||||
|
||||
static GdkColorState *
|
||||
gdk_color_state_from_image_description_bits (ImageDescription *desc)
|
||||
{
|
||||
GdkColorState *cs = GDK_COLOR_STATE_SRGB;
|
||||
|
||||
if (desc->has_primaries_named && desc->has_tf_named)
|
||||
{
|
||||
if (desc->primaries == XX_COLOR_MANAGER_V2_PRIMARIES_SRGB &&
|
||||
desc->tf_named == XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_SRGB)
|
||||
{
|
||||
cs = GDK_COLOR_STATE_SRGB;
|
||||
}
|
||||
else if (desc->primaries == XX_COLOR_MANAGER_V2_PRIMARIES_SRGB &&
|
||||
desc->tf_named == XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LINEAR)
|
||||
{
|
||||
cs = GDK_COLOR_STATE_SRGB_LINEAR;
|
||||
}
|
||||
else if (desc->primaries == XX_COLOR_MANAGER_V2_PRIMARIES_BT2020 &&
|
||||
desc->tf_named == XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_ST2084_PQ)
|
||||
{
|
||||
cs = GDK_COLOR_STATE_REC2100_PQ;
|
||||
}
|
||||
else if (desc->primaries == XX_COLOR_MANAGER_V2_PRIMARIES_BT2020 &&
|
||||
desc->tf_named == XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LINEAR)
|
||||
{
|
||||
cs = GDK_COLOR_STATE_REC2100_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
return cs;
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_info_done (void *data,
|
||||
struct xx_image_description_info_v2 *info)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
GdkWaylandColorSurface *self = desc->surface;
|
||||
GdkColorState *cs;
|
||||
|
||||
cs = gdk_color_state_from_image_description_bits (desc);
|
||||
|
||||
if (self->callback)
|
||||
self->callback (desc->surface, cs, self->data);
|
||||
|
||||
gdk_color_state_unref (cs);
|
||||
|
||||
xx_image_description_v2_destroy (desc->image_desc);
|
||||
xx_image_description_info_v2_destroy (desc->info);
|
||||
g_free (desc);
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_info_icc_file (void *data,
|
||||
struct xx_image_description_info_v2 *info,
|
||||
int32_t icc,
|
||||
uint32_t icc_size)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
desc->icc = icc;
|
||||
desc->icc_size = icc_size;
|
||||
desc->has_icc = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_info_primaries (void *data,
|
||||
struct xx_image_description_info_v2 *info,
|
||||
uint32_t r_x, uint32_t r_y,
|
||||
uint32_t g_x, uint32_t g_y,
|
||||
uint32_t b_x, uint32_t b_y,
|
||||
uint32_t w_x, uint32_t w_y)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
desc->r_x = r_x; desc->r_y = r_y;
|
||||
desc->g_x = g_x; desc->r_y = g_y;
|
||||
desc->b_x = b_x; desc->r_y = b_y;
|
||||
desc->w_x = w_x; desc->r_y = w_y;
|
||||
desc->has_primaries = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_info_primaries_named (void *data,
|
||||
struct xx_image_description_info_v2 *info,
|
||||
uint32_t primaries)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
desc->primaries = primaries;
|
||||
desc->has_primaries_named = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_info_tf_power (void *data,
|
||||
struct xx_image_description_info_v2 *info,
|
||||
uint32_t tf_power)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
desc->tf_power = tf_power;
|
||||
desc->has_tf_power = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_info_tf_named (void *data,
|
||||
struct xx_image_description_info_v2 *info,
|
||||
uint32_t tf)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
desc->tf_named = tf;
|
||||
desc->has_tf_named = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_info_target_primaries (void *data,
|
||||
struct xx_image_description_info_v2 *info,
|
||||
uint32_t r_x, uint32_t r_y,
|
||||
uint32_t g_x, uint32_t g_y,
|
||||
uint32_t b_x, uint32_t b_y,
|
||||
uint32_t w_x, uint32_t w_y)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
desc->target_r_x = r_x; desc->target_r_y = r_y;
|
||||
desc->target_g_x = g_x; desc->target_r_y = g_y;
|
||||
desc->target_b_x = b_x; desc->target_r_y = b_y;
|
||||
desc->target_w_x = w_x; desc->target_r_y = w_y;
|
||||
desc->has_target_primaries = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_info_target_luminance (void *data,
|
||||
struct xx_image_description_info_v2 *info,
|
||||
uint32_t min_lum,
|
||||
uint32_t max_lum)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
desc->target_min_lum = min_lum;
|
||||
desc->target_max_lum = max_lum;
|
||||
desc->has_target_luminance = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_info_target_max_cll (void *data,
|
||||
struct xx_image_description_info_v2 *info,
|
||||
uint32_t max_cll)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
desc->target_max_cll = max_cll;
|
||||
desc->has_target_max_cll = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_info_target_max_fall (void *data,
|
||||
struct xx_image_description_info_v2 *info,
|
||||
uint32_t max_fall)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
desc->target_max_fall = max_fall;
|
||||
desc->has_target_max_fall = 1;
|
||||
}
|
||||
|
||||
static struct xx_image_description_info_v2_listener info_listener = {
|
||||
image_desc_info_done,
|
||||
image_desc_info_icc_file,
|
||||
image_desc_info_primaries,
|
||||
image_desc_info_primaries_named,
|
||||
image_desc_info_tf_power,
|
||||
image_desc_info_tf_named,
|
||||
image_desc_info_target_primaries,
|
||||
image_desc_info_target_luminance,
|
||||
image_desc_info_target_max_cll,
|
||||
image_desc_info_target_max_fall,
|
||||
};
|
||||
|
||||
static void
|
||||
image_desc_failed (void *data,
|
||||
struct xx_image_description_v2 *image_desc,
|
||||
uint32_t cause,
|
||||
const char *msg)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
GdkWaylandColorSurface *self = desc->surface;
|
||||
|
||||
self->callback (self, GDK_COLOR_STATE_SRGB, self->data);
|
||||
|
||||
xx_image_description_v2_destroy (desc->image_desc);
|
||||
g_free (desc);
|
||||
}
|
||||
|
||||
static void
|
||||
image_desc_ready (void *data,
|
||||
struct xx_image_description_v2 *image_desc,
|
||||
uint32_t identity)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
desc->info = xx_image_description_v2_get_information (image_desc);
|
||||
|
||||
xx_image_description_info_v2_add_listener (desc->info, &info_listener, desc);
|
||||
}
|
||||
|
||||
static const struct xx_image_description_v2_listener image_desc_listener = {
|
||||
image_desc_failed,
|
||||
image_desc_ready
|
||||
};
|
||||
|
||||
static void
|
||||
preferred_changed (void *data,
|
||||
struct xx_color_management_surface_v2 *color_mgmt_surface)
|
||||
{
|
||||
GdkWaylandColorSurface *self = data;
|
||||
ImageDescription *desc;
|
||||
|
||||
desc = g_new0 (ImageDescription, 1);
|
||||
|
||||
desc->surface = self;
|
||||
|
||||
desc->image_desc = xx_color_management_surface_v2_get_preferred (self->surface);
|
||||
|
||||
xx_image_description_v2_add_listener (desc->image_desc, &image_desc_listener, desc);
|
||||
}
|
||||
|
||||
static const struct xx_color_management_surface_v2_listener color_listener = {
|
||||
preferred_changed,
|
||||
};
|
||||
|
||||
GdkWaylandColorSurface *
|
||||
gdk_wayland_color_surface_new (GdkWaylandColor *color,
|
||||
struct wl_surface *wl_surface,
|
||||
GdkColorStateChanged callback,
|
||||
gpointer data)
|
||||
{
|
||||
GdkWaylandColorSurface *self;
|
||||
|
||||
self = g_new0 (GdkWaylandColorSurface, 1);
|
||||
|
||||
self->color = color;
|
||||
|
||||
self->surface = xx_color_manager_v2_get_surface (color->color_manager, wl_surface);
|
||||
|
||||
self->callback = callback;
|
||||
self->data = data;
|
||||
|
||||
xx_color_management_surface_v2_add_listener (self->surface, &color_listener, self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_color_surface_free (GdkWaylandColorSurface *self)
|
||||
{
|
||||
xx_color_management_surface_v2_destroy (self->surface);
|
||||
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
|
||||
static struct xx_image_description_v2 *
|
||||
gdk_wayland_color_get_image_description (GdkWaylandColor *color,
|
||||
GdkColorState *cs)
|
||||
{
|
||||
if (gdk_color_state_equal (cs, GDK_COLOR_STATE_SRGB))
|
||||
return color->srgb;
|
||||
else if (gdk_color_state_equal (cs, GDK_COLOR_STATE_SRGB_LINEAR))
|
||||
return color->srgb_linear;
|
||||
else if (gdk_color_state_equal (cs, GDK_COLOR_STATE_REC2100_PQ))
|
||||
return color->rec2100_pq;
|
||||
else if (gdk_color_state_equal (cs, GDK_COLOR_STATE_REC2100_LINEAR))
|
||||
return color->rec2100_linear;
|
||||
else
|
||||
return color->srgb;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_color_surface_set_color_state (GdkWaylandColorSurface *self,
|
||||
GdkColorState *cs)
|
||||
{
|
||||
struct xx_image_description_v2 *desc;
|
||||
|
||||
desc = gdk_wayland_color_get_image_description (self->color, cs);
|
||||
|
||||
if (desc)
|
||||
xx_color_management_surface_v2_set_image_description (self->surface,
|
||||
desc,
|
||||
XX_COLOR_MANAGER_V2_RENDER_INTENT_PERCEPTUAL);
|
||||
else
|
||||
xx_color_management_surface_v2_unset_image_description (self->surface);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_wayland_color_surface_can_set_color_state (GdkWaylandColorSurface *self,
|
||||
GdkColorState *cs)
|
||||
{
|
||||
return gdk_wayland_color_get_image_description (self->color, cs) != NULL;
|
||||
}
|
||||
@@ -23,6 +23,7 @@ gdk_wayland_sources = files([
|
||||
'gdktoplevel-wayland.c',
|
||||
'gdkpopup-wayland.c',
|
||||
'gdkvulkancontext-wayland.c',
|
||||
'gdkwaylandcolor.c',
|
||||
'gdkwaylandpresentationtime.c',
|
||||
'wm-button-layout-translation.c',
|
||||
])
|
||||
@@ -145,6 +146,11 @@ proto_sources = [
|
||||
'stability': 'staging',
|
||||
'version': 1,
|
||||
},
|
||||
{
|
||||
'name': 'xx-color-management',
|
||||
'stability': 'private',
|
||||
'version': 2,
|
||||
},
|
||||
]
|
||||
|
||||
gdk_wayland_gen_headers = []
|
||||
|
||||
1233
gdk/wayland/protocol/xx-color-management-v2.xml
Normal file
1233
gdk/wayland/protocol/xx-color-management-v2.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -67,6 +67,7 @@
|
||||
#include <epoxy/egl.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "wayland/gdkdisplay-wayland.h"
|
||||
#include "wayland/gdkwaylandcolor-private.h"
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_BROADWAY
|
||||
@@ -695,6 +696,7 @@ add_wayland_protocols (GdkDisplay *display,
|
||||
append_wayland_protocol_row (gen, (struct wl_proxy *)d->viewporter);
|
||||
append_wayland_protocol_row (gen, (struct wl_proxy *)d->presentation);
|
||||
append_wayland_protocol_row (gen, (struct wl_proxy *)d->single_pixel_buffer);
|
||||
append_wayland_protocol_row (gen, gdk_wayland_color_get_color_manager (d->color));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user