mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 06:00:22 +00:00
Merge branch 'wip/otte/for-main' into 'main'
wayland: Redo the image description code See merge request GNOME/gtk!7505
This commit is contained in:
commit
d301d16aee
@ -536,7 +536,7 @@ gdk_registry_handle_global (void *data,
|
||||
}
|
||||
else if (strcmp (interface, "xx_color_manager_v4") == 0)
|
||||
{
|
||||
display_wayland->color = gdk_wayland_color_new (registry, id, version);
|
||||
display_wayland->color = gdk_wayland_color_new (display_wayland, registry, id, version);
|
||||
}
|
||||
else if (strcmp (interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0)
|
||||
{
|
||||
|
@ -48,6 +48,7 @@ struct _GdkWaylandSurface
|
||||
|
||||
GdkWaylandPresentationTime *presentation_time;
|
||||
|
||||
unsigned int color_state_changed : 1;
|
||||
unsigned int initial_configure_received : 1;
|
||||
unsigned int has_uncommitted_ack_configure : 1;
|
||||
unsigned int has_pending_subsurface_commits : 1;
|
||||
|
@ -772,6 +772,20 @@ gdk_wayland_surface_sync_viewport (GdkSurface *surface)
|
||||
self->viewport_dirty = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_sync_color_state (GdkSurface *surface)
|
||||
{
|
||||
GdkWaylandSurface *self = GDK_WAYLAND_SURFACE (surface);
|
||||
|
||||
if (!self->color_state_changed)
|
||||
return;
|
||||
|
||||
gdk_wayland_color_surface_set_color_state (self->display_server.color,
|
||||
gdk_surface_get_color_state (surface));
|
||||
|
||||
self->color_state_changed = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_surface_sync (GdkSurface *surface)
|
||||
{
|
||||
@ -779,6 +793,7 @@ gdk_wayland_surface_sync (GdkSurface *surface)
|
||||
gdk_wayland_surface_sync_opaque_region (surface);
|
||||
gdk_wayland_surface_sync_input_region (surface);
|
||||
gdk_wayland_surface_sync_buffer_scale (surface);
|
||||
gdk_wayland_surface_sync_color_state (surface);
|
||||
gdk_wayland_surface_sync_viewport (surface);
|
||||
}
|
||||
|
||||
@ -791,6 +806,7 @@ gdk_wayland_surface_needs_commit (GdkSurface *surface)
|
||||
self->opaque_region_dirty ||
|
||||
self->input_region_dirty ||
|
||||
self->buffer_scale_dirty ||
|
||||
self->color_state_changed ||
|
||||
self->viewport_dirty;
|
||||
}
|
||||
|
||||
@ -910,7 +926,11 @@ preferred_changed (GdkWaylandColorSurface *color,
|
||||
GdkColorState *color_state,
|
||||
gpointer data)
|
||||
{
|
||||
gdk_surface_set_color_state (GDK_SURFACE (data), color_state);
|
||||
GdkWaylandSurface *self = GDK_WAYLAND_SURFACE (data);
|
||||
|
||||
gdk_surface_set_color_state (GDK_SURFACE (self), color_state);
|
||||
|
||||
self->color_state_changed = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1,11 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkwaylanddisplay.h"
|
||||
#include <wayland-client.h>
|
||||
|
||||
typedef struct _GdkWaylandColor GdkWaylandColor;
|
||||
|
||||
GdkWaylandColor * gdk_wayland_color_new (struct wl_registry *registry,
|
||||
GdkWaylandColor * gdk_wayland_color_new (GdkWaylandDisplay *display,
|
||||
struct wl_registry *registry,
|
||||
uint32_t id,
|
||||
uint32_t version);
|
||||
|
||||
|
@ -66,14 +66,10 @@ cicp_to_wl_transfer (uint tf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint cp, tf;
|
||||
struct xx_image_description_v4 *desc;
|
||||
} ImageDescEntry;
|
||||
|
||||
struct _GdkWaylandColor
|
||||
{
|
||||
GdkWaylandDisplay *display;
|
||||
|
||||
struct xx_color_manager_v4 *color_manager;
|
||||
struct {
|
||||
unsigned int intents;
|
||||
@ -82,9 +78,48 @@ struct _GdkWaylandColor
|
||||
unsigned int primaries;
|
||||
} color_manager_supported;
|
||||
|
||||
GArray *image_descs;
|
||||
GHashTable *cs_to_desc; /* GdkColorState => xx_image_description_v4 or NULL */
|
||||
GHashTable *id_to_cs; /* uint32 identifier => GdkColorState */
|
||||
};
|
||||
|
||||
static guint
|
||||
color_state_hash (gconstpointer data)
|
||||
{
|
||||
GdkColorState *cs = (GdkColorState *) data;
|
||||
const GdkCicp *cicp;
|
||||
|
||||
cicp = gdk_color_state_get_cicp (cs);
|
||||
if (cicp)
|
||||
{
|
||||
GdkCicp norm;
|
||||
gdk_cicp_normalize (cicp, &norm);
|
||||
return norm.color_primaries << 24 | norm.transfer_function;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
color_state_equal (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
GdkColorState *csa = (GdkColorState *) a;
|
||||
GdkColorState *csb = (GdkColorState *) b;
|
||||
const GdkCicp *cicpa, *cicpb;
|
||||
GdkCicp norma, normb;
|
||||
|
||||
cicpa = gdk_color_state_get_cicp (csa);
|
||||
cicpb = gdk_color_state_get_cicp (csb);
|
||||
if (cicpa == NULL || cicpb == NULL)
|
||||
return FALSE;
|
||||
|
||||
gdk_cicp_normalize (cicpa, &norma);
|
||||
gdk_cicp_normalize (cicpb, &normb);
|
||||
|
||||
return norma.color_primaries == normb.color_primaries &&
|
||||
norma.transfer_function == normb.transfer_function;
|
||||
}
|
||||
|
||||
static void
|
||||
xx_color_manager_v4_supported_intent (void *data,
|
||||
struct xx_color_manager_v4 *xx_color_manager_v4,
|
||||
@ -133,7 +168,8 @@ static struct xx_color_manager_v4_listener color_manager_listener = {
|
||||
};
|
||||
|
||||
GdkWaylandColor *
|
||||
gdk_wayland_color_new (struct wl_registry *registry,
|
||||
gdk_wayland_color_new (GdkWaylandDisplay *display,
|
||||
struct wl_registry *registry,
|
||||
uint32_t id,
|
||||
uint32_t version)
|
||||
{
|
||||
@ -141,7 +177,15 @@ gdk_wayland_color_new (struct wl_registry *registry,
|
||||
|
||||
color = g_new0 (GdkWaylandColor, 1);
|
||||
|
||||
color->image_descs = g_array_new (FALSE, FALSE, sizeof (ImageDescEntry));
|
||||
color->display = display;
|
||||
color->cs_to_desc = g_hash_table_new_full (color_state_hash,
|
||||
color_state_equal,
|
||||
(GDestroyNotify) gdk_color_state_unref,
|
||||
(GDestroyNotify) xx_image_description_v4_destroy);
|
||||
color->id_to_cs = g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal,
|
||||
NULL,
|
||||
(GDestroyNotify) gdk_color_state_unref);
|
||||
|
||||
color->color_manager = wl_registry_bind (registry,
|
||||
id,
|
||||
@ -160,13 +204,8 @@ gdk_wayland_color_free (GdkWaylandColor *color)
|
||||
{
|
||||
g_clear_pointer (&color->color_manager, xx_color_manager_v4_destroy);
|
||||
|
||||
for (int i = 0; i < color->image_descs->len; i++)
|
||||
{
|
||||
ImageDescEntry *e = &g_array_index (color->image_descs, ImageDescEntry, i);
|
||||
xx_image_description_v4_destroy (e->desc);
|
||||
}
|
||||
|
||||
g_array_unref (color->image_descs);
|
||||
g_hash_table_unref (color->cs_to_desc);
|
||||
g_hash_table_unref (color->id_to_cs);
|
||||
|
||||
g_free (color);
|
||||
}
|
||||
@ -177,60 +216,126 @@ gdk_wayland_color_get_color_manager (GdkWaylandColor *color)
|
||||
return (struct wl_proxy *) color->color_manager;
|
||||
}
|
||||
|
||||
typedef struct _CsImageDescListenerData {
|
||||
GdkWaylandColor *color;
|
||||
GdkColorState *color_state;
|
||||
gboolean sync;
|
||||
gboolean done;
|
||||
} CsImageDescListenerData;
|
||||
|
||||
static void
|
||||
std_image_desc_failed (void *data,
|
||||
struct xx_image_description_v4 *desc,
|
||||
uint32_t cause,
|
||||
const char *msg)
|
||||
cs_image_listener_data_free (CsImageDescListenerData *csi)
|
||||
{
|
||||
csi->done = TRUE;
|
||||
|
||||
if (csi->sync)
|
||||
return;
|
||||
|
||||
g_free (csi);
|
||||
}
|
||||
|
||||
static void
|
||||
cs_image_desc_failed (void *data,
|
||||
struct xx_image_description_v4 *desc,
|
||||
uint32_t cause,
|
||||
const char *msg)
|
||||
{
|
||||
CsImageDescListenerData *csi = data;
|
||||
|
||||
g_warning ("Failed to get one of the standard image descriptions: %s", msg);
|
||||
xx_image_description_v4_destroy (desc);
|
||||
|
||||
g_hash_table_insert (csi->color->cs_to_desc,
|
||||
gdk_color_state_ref (csi->color_state),
|
||||
NULL);
|
||||
|
||||
cs_image_listener_data_free (csi);
|
||||
}
|
||||
|
||||
static void
|
||||
std_image_desc_ready (void *data,
|
||||
struct xx_image_description_v4 *desc,
|
||||
uint32_t identity)
|
||||
cs_image_desc_ready (void *data,
|
||||
struct xx_image_description_v4 *desc,
|
||||
uint32_t identity)
|
||||
{
|
||||
struct xx_image_description_v4 **ptr = data;
|
||||
CsImageDescListenerData *csi = data;
|
||||
|
||||
*ptr = desc;
|
||||
g_hash_table_insert (csi->color->cs_to_desc,
|
||||
gdk_color_state_ref (csi->color_state),
|
||||
desc);
|
||||
g_hash_table_insert (csi->color->id_to_cs,
|
||||
GUINT_TO_POINTER (identity),
|
||||
gdk_color_state_ref (csi->color_state));
|
||||
|
||||
cs_image_listener_data_free (csi);
|
||||
}
|
||||
|
||||
static struct xx_image_description_v4_listener std_image_desc_listener = {
|
||||
std_image_desc_failed,
|
||||
std_image_desc_ready,
|
||||
static struct xx_image_description_v4_listener cs_image_desc_listener = {
|
||||
cs_image_desc_failed,
|
||||
cs_image_desc_ready,
|
||||
};
|
||||
|
||||
static void
|
||||
create_image_desc (GdkWaylandColor *color,
|
||||
uint32_t primaries,
|
||||
uint32_t transfer)
|
||||
GdkColorState *cs,
|
||||
gboolean sync)
|
||||
{
|
||||
CsImageDescListenerData data;
|
||||
struct xx_image_description_creator_params_v4 *creator;
|
||||
struct xx_image_description_v4 *desc;
|
||||
ImageDescEntry entry;
|
||||
ImageDescEntry *e;
|
||||
const GdkCicp *cicp;
|
||||
GdkCicp norm;
|
||||
uint32_t primaries, tf;
|
||||
|
||||
entry.cp = primaries;
|
||||
entry.tf = transfer;
|
||||
entry.desc = NULL;
|
||||
|
||||
g_array_append_val (color->image_descs, entry);
|
||||
e = &g_array_index (color->image_descs, ImageDescEntry, color->image_descs->len - 1);
|
||||
cicp = gdk_color_state_get_cicp (cs);
|
||||
if (!cicp)
|
||||
{
|
||||
GDK_DEBUG (MISC, "Unsupported color state %s: Not a CICP colorstate",
|
||||
gdk_color_state_get_name (cs));
|
||||
g_hash_table_insert (color->cs_to_desc, gdk_color_state_ref (cs), NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_cicp_normalize (cicp, &norm);
|
||||
primaries = cicp_to_wl_primaries (norm.color_primaries);
|
||||
tf = cicp_to_wl_transfer (norm.transfer_function);
|
||||
|
||||
if ((color->color_manager_supported.primaries & (1 << primaries)) == 0 ||
|
||||
(color->color_manager_supported.transfers & (1 << transfer)) == 0)
|
||||
return;
|
||||
(color->color_manager_supported.transfers & (1 << tf)) == 0)
|
||||
{
|
||||
GDK_DEBUG (MISC, "Unsupported color state %s: Primaries or transfer function unsupported",
|
||||
gdk_color_state_get_name (cs));
|
||||
g_hash_table_insert (color->cs_to_desc, gdk_color_state_ref (cs), NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
data.color = color;
|
||||
data.color_state = cs;
|
||||
data.sync = sync;
|
||||
data.done = FALSE;
|
||||
|
||||
creator = xx_color_manager_v4_new_parametric_creator (color->color_manager);
|
||||
|
||||
xx_image_description_creator_params_v4_set_primaries_named (creator, primaries);
|
||||
xx_image_description_creator_params_v4_set_tf_named (creator, transfer);
|
||||
xx_image_description_creator_params_v4_set_tf_named (creator, tf);
|
||||
|
||||
desc = xx_image_description_creator_params_v4_create (creator);
|
||||
|
||||
xx_image_description_v4_add_listener (desc, &std_image_desc_listener, &e->desc);
|
||||
if (sync)
|
||||
{
|
||||
struct wl_event_queue *event_queue;
|
||||
|
||||
event_queue = wl_display_create_queue (color->display->wl_display);
|
||||
wl_proxy_set_queue ((struct wl_proxy *) desc, event_queue);
|
||||
xx_image_description_v4_add_listener (desc, &cs_image_desc_listener, &data);
|
||||
while (!data.done)
|
||||
gdk_wayland_display_dispatch_queue (GDK_DISPLAY (color->display), event_queue);
|
||||
|
||||
wl_event_queue_destroy (event_queue);
|
||||
}
|
||||
else
|
||||
{
|
||||
xx_image_description_v4_add_listener (desc, &cs_image_desc_listener, g_memdup (&data, sizeof data));
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -298,26 +403,18 @@ gdk_wayland_color_prepare (GdkWaylandColor *color)
|
||||
|
||||
if (color->color_manager)
|
||||
{
|
||||
create_image_desc (color,
|
||||
XX_COLOR_MANAGER_V4_PRIMARIES_SRGB,
|
||||
XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB);
|
||||
create_image_desc (color, GDK_COLOR_STATE_SRGB, FALSE);
|
||||
|
||||
if (color->color_manager_supported.transfers & (1 << XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR))
|
||||
create_image_desc (color,
|
||||
XX_COLOR_MANAGER_V4_PRIMARIES_SRGB,
|
||||
XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR);
|
||||
create_image_desc (color, GDK_COLOR_STATE_SRGB_LINEAR, FALSE);
|
||||
|
||||
if (color->color_manager_supported.primaries & (1 << XX_COLOR_MANAGER_V4_PRIMARIES_BT2020))
|
||||
{
|
||||
if (color->color_manager_supported.transfers & (1 << XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ))
|
||||
create_image_desc (color,
|
||||
XX_COLOR_MANAGER_V4_PRIMARIES_BT2020,
|
||||
XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ);
|
||||
create_image_desc (color, GDK_COLOR_STATE_REC2100_PQ, FALSE);
|
||||
|
||||
if (color->color_manager_supported.transfers & (1 << XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR))
|
||||
create_image_desc (color,
|
||||
XX_COLOR_MANAGER_V4_PRIMARIES_BT2020,
|
||||
XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR);
|
||||
create_image_desc (color, GDK_COLOR_STATE_REC2100_LINEAR, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,6 +437,8 @@ typedef struct
|
||||
struct xx_image_description_v4 *image_desc;
|
||||
struct xx_image_description_info_v4 *info;
|
||||
|
||||
uint32_t identity;
|
||||
|
||||
int32_t icc;
|
||||
uint32_t icc_size;
|
||||
int32_t r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y;
|
||||
@ -378,7 +477,7 @@ gdk_color_state_from_image_description_bits (ImageDescription *desc)
|
||||
return gdk_color_state_new_for_cicp (&cicp, NULL);
|
||||
}
|
||||
else
|
||||
return GDK_COLOR_STATE_SRGB;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -390,13 +489,26 @@ image_desc_info_done (void *data,
|
||||
GdkColorState *cs;
|
||||
|
||||
cs = gdk_color_state_from_image_description_bits (desc);
|
||||
if (cs)
|
||||
{
|
||||
g_hash_table_insert (self->color->cs_to_desc,
|
||||
gdk_color_state_ref (cs),
|
||||
desc->image_desc);
|
||||
g_hash_table_insert (self->color->id_to_cs,
|
||||
GUINT_TO_POINTER (desc->identity),
|
||||
gdk_color_state_ref (cs));
|
||||
}
|
||||
else
|
||||
{
|
||||
cs = GDK_COLOR_STATE_SRGB;
|
||||
xx_image_description_v4_destroy (desc->image_desc);
|
||||
}
|
||||
|
||||
if (self->callback)
|
||||
self->callback (desc->surface, cs, self->data);
|
||||
|
||||
gdk_color_state_unref (cs);
|
||||
|
||||
xx_image_description_v4_destroy (desc->image_desc);
|
||||
xx_image_description_info_v4_destroy (desc->info);
|
||||
g_free (desc);
|
||||
}
|
||||
@ -466,10 +578,10 @@ image_desc_info_tf_named (void *data,
|
||||
|
||||
static void
|
||||
image_desc_info_luminances (void *data,
|
||||
struct xx_image_description_info_v4 *info,
|
||||
uint32_t min_lum,
|
||||
uint32_t max_lum,
|
||||
uint32_t ref_lum)
|
||||
struct xx_image_description_info_v4 *info,
|
||||
uint32_t min_lum,
|
||||
uint32_t max_lum,
|
||||
uint32_t ref_lum)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
|
||||
@ -566,8 +678,21 @@ image_desc_ready (void *data,
|
||||
uint32_t identity)
|
||||
{
|
||||
ImageDescription *desc = data;
|
||||
GdkWaylandColorSurface *self = desc->surface;
|
||||
GdkColorState *cs;
|
||||
|
||||
cs = g_hash_table_lookup (self->color->id_to_cs, GUINT_TO_POINTER (identity));
|
||||
if (cs)
|
||||
{
|
||||
self->callback (self, cs, self->data);
|
||||
|
||||
xx_image_description_v4_destroy (desc->image_desc);
|
||||
g_free (desc);
|
||||
return;
|
||||
}
|
||||
|
||||
desc->info = xx_image_description_v4_get_information (image_desc);
|
||||
desc->identity = identity;
|
||||
|
||||
xx_image_description_info_v4_add_listener (desc->info, &info_listener, desc);
|
||||
}
|
||||
@ -584,6 +709,9 @@ preferred_changed (void *data,
|
||||
GdkWaylandColorSurface *self = data;
|
||||
ImageDescription *desc;
|
||||
|
||||
if (!self->callback)
|
||||
return;
|
||||
|
||||
desc = g_new0 (ImageDescription, 1);
|
||||
|
||||
desc->surface = self;
|
||||
@ -616,6 +744,7 @@ gdk_wayland_color_surface_new (GdkWaylandColor *color,
|
||||
self->data = data;
|
||||
|
||||
xx_color_management_feedback_surface_v4_add_listener (self->feedback, &color_listener, self);
|
||||
preferred_changed (self, self->feedback);
|
||||
|
||||
return self;
|
||||
}
|
||||
@ -633,25 +762,19 @@ static struct xx_image_description_v4 *
|
||||
gdk_wayland_color_get_image_description (GdkWaylandColor *color,
|
||||
GdkColorState *cs)
|
||||
{
|
||||
const GdkCicp *params;
|
||||
GdkCicp normalized;
|
||||
gpointer result;
|
||||
|
||||
params = gdk_color_state_get_cicp (cs);
|
||||
gdk_cicp_normalize (params, &normalized);
|
||||
if (g_hash_table_lookup_extended (color->cs_to_desc, cs, NULL, &result))
|
||||
return result;
|
||||
|
||||
create_image_desc (color, cs, TRUE);
|
||||
|
||||
if (params)
|
||||
for (int i = 0; i < color->image_descs->len; i++)
|
||||
{
|
||||
ImageDescEntry *e = &g_array_index (color->image_descs, ImageDescEntry, i);
|
||||
if (wl_to_cicp_primaries (e->cp) == normalized.color_primaries &&
|
||||
wl_to_cicp_transfer (e->tf) == normalized.transfer_function)
|
||||
return e->desc;
|
||||
}
|
||||
|
||||
create_image_desc (color,
|
||||
cicp_to_wl_primaries (normalized.color_primaries),
|
||||
cicp_to_wl_transfer (normalized.transfer_function));
|
||||
return NULL;
|
||||
if (!g_hash_table_lookup_extended (color->cs_to_desc, cs, NULL, &result))
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user