From 1b793b7acdc717f2cf3de6ee734d08648f69ac66 Mon Sep 17 00:00:00 2001 From: Joan Torres Date: Mon, 5 Aug 2024 13:02:47 +0200 Subject: [PATCH] color: update color-management protocol to xx-v4 The main differences is the split of cm_surface functionality with cm_surface and cm_feedback_surface. There can only be one cm_surface to set, unset image descriptions. When cm_surface is destroyed, the image description is automatically unset. There can be multiple feedback_surfaces for one surface though. Now the "preferred_changed" signal can be an initial event. Creator params now have a new request: set_luminances. Signed-off-by: Joan Torres --- clients/window.c | 68 +-- include/libweston/libweston.h | 5 +- libweston/color-management.c | 303 ++++++----- libweston/color-properties.c | 70 +-- libweston/compositor.c | 18 +- protocol/color-management-v1.xml | 842 +++++++++++++++++++------------ tests/color-management-test.c | 214 ++++---- 7 files changed, 907 insertions(+), 613 deletions(-) diff --git a/clients/window.c b/clients/window.c index 9fb46105..106742ec 100644 --- a/clients/window.c +++ b/clients/window.c @@ -91,7 +91,7 @@ struct display { struct wl_data_device_manager *data_device_manager; struct text_cursor_position *text_cursor_position; struct xdg_wm_base *xdg_shell; - struct xx_color_manager_v2 *color_manager; + struct xx_color_manager_v4 *color_manager; struct zwp_tablet_manager_v2 *tablet_manager; struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; struct zwp_pointer_constraints_v1 *pointer_constraints; @@ -217,7 +217,7 @@ struct surface { struct wl_callback *frame_cb; uint32_t last_time; - struct xx_color_management_surface_v2 *cm_surface; + struct xx_color_management_surface_v4 *cm_surface; struct rectangle allocation; struct rectangle server_allocation; @@ -480,7 +480,7 @@ struct shm_pool { }; struct cm_image_description { - struct xx_image_description_v2 *image_desc; + struct xx_image_description_v4 *image_desc; enum cm_image_desc_status { CM_IMAGE_DESC_NOT_CREATED = 0, CM_IMAGE_DESC_READY, @@ -493,27 +493,27 @@ render_intent_info_table[] = { { .intent = RENDER_INTENT_PERCEPTUAL, .desc = "Perceptual", - .protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_PERCEPTUAL, + .protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL, }, { .intent = RENDER_INTENT_RELATIVE, .desc = "Media-relative colorimetric", - .protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_RELATIVE, + .protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE, }, { .intent = RENDER_INTENT_RELATIVE_BPC, .desc = "Media-relative colorimetric + black point compensation", - .protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_RELATIVE_BPC, + .protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE_BPC, }, { .intent = RENDER_INTENT_SATURATION, .desc = "Saturation", - .protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_SATURATION, + .protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_SATURATION, }, { .intent = RENDER_INTENT_ABSOLUTE, .desc = "ICC-absolute colorimetric", - .protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_ABSOLUTE, + .protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_ABSOLUTE, }, }; @@ -568,7 +568,7 @@ debug_print(void *proxy, int line, const char *func, const char *fmt, ...) #endif static void -cm_image_desc_ready(void *data, struct xx_image_description_v2 *xx_image_description_v2, +cm_image_desc_ready(void *data, struct xx_image_description_v4 *xx_image_description_v4, uint32_t identity) { struct cm_image_description *cm_image_desc = data; @@ -577,7 +577,7 @@ cm_image_desc_ready(void *data, struct xx_image_description_v2 *xx_image_descrip } static void -cm_image_desc_failed(void *data, struct xx_image_description_v2 *xx_image_description_v2, +cm_image_desc_failed(void *data, struct xx_image_description_v4 *xx_image_description_v4, uint32_t cause, const char *msg) { struct cm_image_description *cm_image_desc = data; @@ -588,7 +588,7 @@ cm_image_desc_failed(void *data, struct xx_image_description_v2 *xx_image_descri cm_image_desc->status = CM_IMAGE_DESC_FAILED; } -static const struct xx_image_description_v2_listener cm_image_desc_listener = { +static const struct xx_image_description_v4_listener cm_image_desc_listener = { .ready = cm_image_desc_ready, .failed = cm_image_desc_failed, }; @@ -610,10 +610,10 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd, uint32_t length, uint32_t offset, enum render_intent intent, char **err_msg) { - struct xx_image_description_creator_icc_v2 *icc_creator; + struct xx_image_description_creator_icc_v4 *icc_creator; struct display *display = widget->window->display; struct surface *surface = widget->surface; - struct xx_color_manager_v2 *color_manager_wrapper; + struct xx_color_manager_v4 *color_manager_wrapper; struct wl_event_queue *queue; struct cm_image_description cm_image_desc; const struct render_intent_info *intent_info; @@ -623,11 +623,11 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd, str_printf(err_msg, "%s extension not supported by the Wayland " \ "compositor, ignoring image color profile.", - xx_color_manager_v2_interface.name); + xx_color_manager_v4_interface.name); return false; } - if (!((display->color_manager_features >> XX_COLOR_MANAGER_V2_FEATURE_ICC_V2_V4) & 1)) { + if (!((display->color_manager_features >> XX_COLOR_MANAGER_V4_FEATURE_ICC_V2_V4) & 1)) { str_printf(err_msg, "Wayland compositor does not support creating image " \ "descriptions from ICC files, ignoring color profile."); @@ -650,15 +650,15 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd, wl_proxy_set_queue((struct wl_proxy *)color_manager_wrapper, queue); /* Create ICC image description creator and set the ICC file. */ - icc_creator = xx_color_manager_v2_new_icc_creator(color_manager_wrapper); + icc_creator = xx_color_manager_v4_new_icc_creator(color_manager_wrapper); wl_proxy_wrapper_destroy(color_manager_wrapper); - xx_image_description_creator_icc_v2_set_icc_file(icc_creator, + xx_image_description_creator_icc_v4_set_icc_file(icc_creator, icc_fd, offset, length); /* Create the image description. It will also destroy the ICC creator. */ cm_image_desc.status = CM_IMAGE_DESC_NOT_CREATED; - cm_image_desc.image_desc = xx_image_description_creator_icc_v2_create(icc_creator); - xx_image_description_v2_add_listener(cm_image_desc.image_desc, + cm_image_desc.image_desc = xx_image_description_creator_icc_v4_create(icc_creator); + xx_image_description_v4_add_listener(cm_image_desc.image_desc, &cm_image_desc_listener, &cm_image_desc); /* Wait until compositor creates the image description or gracefully @@ -666,7 +666,7 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd, while (ret != -1 && cm_image_desc.status == CM_IMAGE_DESC_NOT_CREATED) ret = wl_display_dispatch_queue(display->display, queue); if (ret == -1) { - xx_image_description_v2_destroy(cm_image_desc.image_desc); + xx_image_description_v4_destroy(cm_image_desc.image_desc); wl_event_queue_destroy(queue); str_printf(err_msg, "Disconnected from the Wayland compositor, " \ @@ -677,7 +677,7 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd, /* Gracefully failed to create image description. Error already printed * in the handler. */ if (cm_image_desc.status == CM_IMAGE_DESC_FAILED) { - xx_image_description_v2_destroy(cm_image_desc.image_desc); + xx_image_description_v4_destroy(cm_image_desc.image_desc); wl_event_queue_destroy(queue); str_printf(err_msg, "Image description creation gracefully failed."); @@ -687,14 +687,14 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd, if (!surface->cm_surface) surface->cm_surface = - xx_color_manager_v2_get_surface(display->color_manager, + xx_color_manager_v4_get_surface(display->color_manager, surface->surface); - xx_color_management_surface_v2_set_image_description(surface->cm_surface, + xx_color_management_surface_v4_set_image_description(surface->cm_surface, cm_image_desc.image_desc, intent_info->protocol_intent); - xx_image_description_v2_destroy(cm_image_desc.image_desc); + xx_image_description_v4_destroy(cm_image_desc.image_desc); wl_event_queue_destroy(queue); return true; @@ -1578,7 +1578,7 @@ surface_destroy(struct surface *surface) wp_viewport_destroy(surface->viewport); if (surface->cm_surface) - xx_color_management_surface_v2_destroy(surface->cm_surface); + xx_color_management_surface_v4_destroy(surface->cm_surface); wl_surface_destroy(surface->surface); @@ -6671,7 +6671,7 @@ display_bind_tablets(struct display *d, uint32_t id) } static void -cm_supported_intent(void *data, struct xx_color_manager_v2 *xx_color_manager_v2, +cm_supported_intent(void *data, struct xx_color_manager_v4 *xx_color_manager_v4, uint32_t render_intent) { struct display *d = data; @@ -6680,7 +6680,7 @@ cm_supported_intent(void *data, struct xx_color_manager_v2 *xx_color_manager_v2, } static void -cm_supported_feature(void *data, struct xx_color_manager_v2 *xx_color_manager_v2, +cm_supported_feature(void *data, struct xx_color_manager_v4 *xx_color_manager_v4, uint32_t feature) { struct display *d = data; @@ -6689,20 +6689,20 @@ cm_supported_feature(void *data, struct xx_color_manager_v2 *xx_color_manager_v2 } static void -cm_supported_tf_named(void *data, struct xx_color_manager_v2 *xx_color_manager_v2, +cm_supported_tf_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4, uint32_t tf_code) { /* unused in this file */ } static void -cm_supported_primaries_named(void *data, struct xx_color_manager_v2 *xx_color_manager_v2, +cm_supported_primaries_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4, uint32_t primaries_code) { /* unused in this file */ } -static const struct xx_color_manager_v2_listener cm_listener = { +static const struct xx_color_manager_v4_listener cm_listener = { .supported_intent = cm_supported_intent, .supported_feature = cm_supported_feature, .supported_tf_named = cm_supported_tf_named, @@ -6777,11 +6777,11 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, &wp_viewporter_interface, 1); } else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) { display_bind_tablets(d, id); - } else if (strcmp(interface, "xx_color_manager_v2") == 0) { + } else if (strcmp(interface, "xx_color_manager_v4") == 0) { d->color_manager = wl_registry_bind(registry, id, - &xx_color_manager_v2_interface, 1); - xx_color_manager_v2_add_listener(d->color_manager, + &xx_color_manager_v4_interface, 1); + xx_color_manager_v4_add_listener(d->color_manager, &cm_listener, d); } @@ -7005,7 +7005,7 @@ display_destroy(struct display *display) xdg_wm_base_destroy(display->xdg_shell); if (display->color_manager) - xx_color_manager_v2_destroy(display->color_manager); + xx_color_manager_v4_destroy(display->color_manager); if (display->shm) wl_shm_destroy(display->shm); diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 557764fb..7a01a29e 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -2049,11 +2049,12 @@ struct weston_surface { struct weston_color_profile *preferred_color_profile; const struct weston_render_intent_info *render_intent; - /* xx_color_manager_v1.get_color_management_surface + /* xx_color_manager_v1.get_feedback_color_management_surface * * When a client uses this request, we add the wl_resource we create to * this list. */ - struct wl_list cm_surface_resource_list; + struct wl_list cm_feedback_surface_resource_list; + struct wl_resource *cm_surface; }; struct weston_subsurface { diff --git a/libweston/color-management.c b/libweston/color-management.c index 9994ec28..d30c8581 100644 --- a/libweston/color-management.c +++ b/libweston/color-management.c @@ -111,13 +111,13 @@ weston_cm_send_icc_file(struct cm_image_desc_info *cm_image_desc_info, return; } - xx_image_description_info_v2_send_icc_file(cm_image_desc_info->owner, + xx_image_description_info_v4_send_icc_file(cm_image_desc_info->owner, fd, len); } /** * For a parametric image description, sends its - * enum xx_color_manager_v2_primaries code to the client. + * enum xx_color_manager_v4_primaries code to the client. * * This is a helper function that should be used by the color plugin * that owns the color profile and has information about it. @@ -129,7 +129,7 @@ WL_EXPORT void weston_cm_send_primaries_named(struct cm_image_desc_info *cm_image_desc_info, const struct weston_color_primaries_info *primaries_info) { - xx_image_description_info_v2_send_primaries_named(cm_image_desc_info->owner, + xx_image_description_info_v4_send_primaries_named(cm_image_desc_info->owner, primaries_info->protocol_primaries); } @@ -147,7 +147,7 @@ WL_EXPORT void weston_cm_send_primaries(struct cm_image_desc_info *cm_image_desc_info, const struct weston_color_gamut *color_gamut) { - xx_image_description_info_v2_send_primaries(cm_image_desc_info->owner, + xx_image_description_info_v4_send_primaries(cm_image_desc_info->owner, /* red */ round(color_gamut->primary[0].x * 10000), round(color_gamut->primary[0].y * 10000), @@ -164,7 +164,7 @@ weston_cm_send_primaries(struct cm_image_desc_info *cm_image_desc_info, /** * For a parametric image description, sends its - * enum xx_color_manager_v2_transfer_function code to the client. + * enum xx_color_manager_v4_transfer_function code to the client. * * This is a helper function that should be used by the color plugin * that owns the color profile and has information about it. @@ -176,7 +176,7 @@ WL_EXPORT void weston_cm_send_tf_named(struct cm_image_desc_info *cm_image_desc_info, const struct weston_color_tf_info *tf_info) { - xx_image_description_info_v2_send_tf_named(cm_image_desc_info->owner, + xx_image_description_info_v4_send_tf_named(cm_image_desc_info->owner, tf_info->protocol_tf); } @@ -217,7 +217,7 @@ image_description_info_create(struct wl_client *client, uint32_t version, cm_image_desc_info->compositor = compositor; cm_image_desc_info->owner = - wl_resource_create(client, &xx_image_description_info_v2_interface, + wl_resource_create(client, &xx_image_description_info_v4_interface, version, cm_image_desc_info_id); if (!cm_image_desc_info->owner) { free(cm_image_desc_info); @@ -249,7 +249,7 @@ image_description_get_information(struct wl_client *client, * to create it. */ if (!cm_image_desc) { wl_resource_post_error(cm_image_desc_res, - XX_IMAGE_DESCRIPTION_V2_ERROR_NOT_READY, + XX_IMAGE_DESCRIPTION_V4_ERROR_NOT_READY, "we gracefully failed to create this image " \ "description"); return; @@ -258,7 +258,7 @@ image_description_get_information(struct wl_client *client, /* Invalid image description for this request, as it isn't ready yet. */ if (!cm_image_desc->cprof) { wl_resource_post_error(cm_image_desc_res, - XX_IMAGE_DESCRIPTION_V2_ERROR_NOT_READY, + XX_IMAGE_DESCRIPTION_V4_ERROR_NOT_READY, "image description not ready yet"); return; } @@ -267,7 +267,7 @@ image_description_get_information(struct wl_client *client, * that get_information() request should be invalid. */ if (!cm_image_desc->supports_get_info) { wl_resource_post_error(cm_image_desc_res, - XX_IMAGE_DESCRIPTION_V2_ERROR_NO_INFORMATION, + XX_IMAGE_DESCRIPTION_V4_ERROR_NO_INFORMATION, "get_information is not allowed for this " "image description"); return; @@ -289,7 +289,7 @@ image_description_get_information(struct wl_client *client, success = cm_image_desc->cm->send_image_desc_info(cm_image_desc_info, cm_image_desc->cprof); if (success) - xx_image_description_info_v2_send_done(cm_image_desc_info->owner); + xx_image_description_info_v4_send_done(cm_image_desc_info->owner); /* All info sent, so destroy the object. */ wl_resource_destroy(cm_image_desc_info->owner); @@ -327,7 +327,7 @@ image_description_resource_destroy(struct wl_resource *cm_image_desc_res) cm_image_desc_destroy(cm_image_desc); } -static const struct xx_image_description_v2_interface +static const struct xx_image_description_v4_interface image_description_implementation = { .destroy = image_description_destroy, .get_information = image_description_get_information, @@ -348,7 +348,7 @@ cm_image_desc_create(struct weston_color_manager *cm, cm_image_desc = xzalloc(sizeof(*cm_image_desc)); cm_image_desc->owner = - wl_resource_create(client, &xx_image_description_v2_interface, + wl_resource_create(client, &xx_image_description_v4_interface, version, image_description_id); if (!cm_image_desc->owner) { free(cm_image_desc); @@ -400,7 +400,7 @@ cm_output_get_image_description(struct wl_client *client, * create only the resource and send the failed event. */ if (!head) { cm_image_desc_res = - wl_resource_create(client, &xx_image_description_v2_interface, + wl_resource_create(client, &xx_image_description_v4_interface, version, image_description_id); if (!cm_image_desc_res) { wl_resource_post_no_memory(cm_output_res); @@ -411,8 +411,8 @@ cm_output_get_image_description(struct wl_client *client, &image_description_implementation, NULL, image_description_resource_destroy); - xx_image_description_v2_send_failed(cm_image_desc_res, - XX_IMAGE_DESCRIPTION_V2_CAUSE_NO_OUTPUT, + xx_image_description_v4_send_failed(cm_image_desc_res, + XX_IMAGE_DESCRIPTION_V4_CAUSE_NO_OUTPUT, "the wl_output global no longer exists"); return; } @@ -436,7 +436,7 @@ cm_output_get_image_description(struct wl_client *client, return; } - xx_image_description_v2_send_ready(cm_image_desc->owner, + xx_image_description_v4_send_ready(cm_image_desc->owner, cm_image_desc->cprof->id); } @@ -474,7 +474,7 @@ cm_output_resource_destroy(struct wl_resource *cm_output_res) wl_list_remove(wl_resource_get_link(cm_output_res)); } -static const struct xx_color_management_output_v2_interface +static const struct xx_color_management_output_v4_interface cm_output_implementation = { .destroy = cm_output_destroy, .get_image_description = cm_output_get_image_description, @@ -506,7 +506,7 @@ weston_output_send_image_description_changed(struct weston_output *output) * notifies that the output image description changed. */ wl_list_for_each(head, &output->head_list, output_link) { wl_resource_for_each(res, &head->cm_output_resource_list) - xx_color_management_output_v2_send_image_description_changed(res); + xx_color_management_output_v4_send_image_description_changed(res); /* wl_output.done should be sent after collecting all the * changes related to the output. But in Weston we are lacking @@ -536,7 +536,7 @@ cm_get_output(struct wl_client *client, struct wl_resource *cm_res, uint32_t version = wl_resource_get_version(cm_res); struct wl_resource *res; - res = wl_resource_create(client, &xx_color_management_output_v2_interface, + res = wl_resource_create(client, &xx_color_management_output_v4_interface, version, cm_output_id); if (!res) { wl_resource_post_no_memory(cm_res); @@ -579,8 +579,9 @@ cm_surface_set_image_description(struct wl_client *client, /* The surface might have been already gone, in such case cm_surface is * inert. */ if (!surface) { + /* TODO: This error will be surface intert in the future */ wl_resource_post_error(cm_surface_res, - XX_COLOR_MANAGEMENT_SURFACE_V2_ERROR_INERT, + XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "the wl_surface has already been destroyed"); return; } @@ -597,10 +598,9 @@ cm_surface_set_image_description(struct wl_client *client, /* Invalid image description for this request, as it isn't ready yet. */ if (!cm_image_desc->cprof) { - /* TODO: the version of the xx protocol that we are using still - * does not have an error for this. Fix when we update to the - * next version. */ - wl_resource_post_no_memory(cm_surface_res); + wl_resource_post_error(cm_surface_res, + XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, + "the image description is not ready"); return; } @@ -610,14 +610,14 @@ cm_surface_set_image_description(struct wl_client *client, protocol_render_intent); if (!render_intent) { wl_resource_post_error(cm_surface_res, - XX_COLOR_MANAGEMENT_SURFACE_V2_ERROR_RENDER_INTENT, + XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_RENDER_INTENT, "unknown render intent"); return; } if (!((cm->supported_rendering_intents >> render_intent->intent) & 1)) { wl_resource_post_error(cm_surface_res, - XX_COLOR_MANAGEMENT_SURFACE_V2_ERROR_RENDER_INTENT, + XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_RENDER_INTENT, "unsupported render intent"); return; } @@ -643,8 +643,9 @@ cm_surface_unset_image_description(struct wl_client *client, /* The surface might have been already gone, in such case cm_surface is * inert. */ if (!surface) { + /* TODO: This error will be surface intert in the future */ wl_resource_post_error(cm_surface_res, - XX_COLOR_MANAGEMENT_SURFACE_V2_ERROR_INERT, + XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "the wl_surface has already been destroyed"); return; } @@ -654,42 +655,6 @@ cm_surface_unset_image_description(struct wl_client *client, surface->pending.render_intent = NULL; } -/** - * Called by clients when they want to know the preferred image description of - * the surface. - */ -static void -cm_surface_get_preferred(struct wl_client *client, struct wl_resource *cm_surface_res, - uint32_t image_description_id) -{ - struct weston_surface *surface = wl_resource_get_user_data(cm_surface_res); - uint32_t version = wl_resource_get_version(cm_surface_res); - struct weston_color_manager *cm; - struct cm_image_desc *cm_image_desc; - - /* The surface might have been already gone, in such case cm_surface is - * inert. */ - if (!surface) { - wl_resource_post_error(cm_surface_res, - XX_COLOR_MANAGEMENT_SURFACE_V2_ERROR_INERT, - "the wl_surface has already been destroyed"); - return; - } - - cm = surface->compositor->color_manager; - - cm_image_desc = cm_image_desc_create(cm, surface->preferred_color_profile, - client, version, image_description_id, - YES_GET_INFO); - if (!cm_image_desc) { - wl_resource_post_no_memory(cm_surface_res); - return; - } - - xx_image_description_v2_send_ready(cm_image_desc->owner, - cm_image_desc->cprof->id); -} - /** * Client will not use the cm_surface anymore, so we destroy its resource. */ @@ -715,46 +680,21 @@ cm_surface_resource_destroy(struct wl_resource *cm_surface_res) if (!surface) return; - /* We are destroying the cm_surface_res, so simply remove it from - * weston_surface::cm_surface_resource_list. */ - wl_list_remove(wl_resource_get_link(cm_surface_res)); + surface->cm_surface = NULL; - /* TODO: if wl_list_empty(&surface->cm_surface_resource_list), we need - * to unset_image_description for the surface. The protocol states that - * we need to do that after the last cm_surface object for a wl_surface - * is destroyed. - * - * We still didn't add the code for that because there are discussions - * on the protocol upstream to allow a single cm_surface per surface. - * Once that reaches a conclusion and the changes land on the xx version - * of the protocol, we need to update this. - */ + /* Do the same as unset_image_description */ + weston_color_profile_unref(surface->pending.color_profile); + surface->pending.color_profile = NULL; + surface->pending.render_intent = NULL; } -static const struct xx_color_management_surface_v2_interface +static const struct xx_color_management_surface_v4_interface cm_surface_implementation = { .destroy = cm_surface_destroy, .set_image_description = cm_surface_set_image_description, .unset_image_description = cm_surface_unset_image_description, - .get_preferred = cm_surface_get_preferred, }; -/** - * Notifies clients that their surface preferred image description changed. - * - * \param surface The surface that changed its preferred image description. - */ -void -weston_surface_send_preferred_image_description_changed(struct weston_surface *surface) -{ - struct wl_resource *res; - - /* For each resource, send the event that notifies that the surface - * preferred image description changed. */ - wl_resource_for_each(res, &surface->cm_surface_resource_list) - xx_color_management_surface_v2_send_preferred_changed(res); -} - /** * Client called get_surface(). We already have the backing object, so just * create a resource for the client. @@ -767,7 +707,14 @@ cm_get_surface(struct wl_client *client, struct wl_resource *cm_res, uint32_t version = wl_resource_get_version(cm_res); struct wl_resource *res; - res = wl_resource_create(client, &xx_color_management_surface_v2_interface, + if (surface->cm_surface) { + wl_resource_post_error(cm_res, + XX_COLOR_MANAGER_V4_ERROR_SURFACE_EXISTS, + "surface already requested"); + return; + } + + res = wl_resource_create(client, &xx_color_management_surface_v4_interface, version, cm_surface_id); if (!res) { wl_resource_post_no_memory(cm_res); @@ -776,7 +723,122 @@ cm_get_surface(struct wl_client *client, struct wl_resource *cm_res, wl_resource_set_implementation(res, &cm_surface_implementation, surface, cm_surface_resource_destroy); - wl_list_insert(&surface->cm_surface_resource_list, wl_resource_get_link(res)); + + surface->cm_surface = res; +} + +/** + * Client will not use the cm_feedback_surface anymore, so we destroy its resource. + */ +static void +cm_feedback_surface_destroy(struct wl_client *client, + struct wl_resource *cm_feedback_surface_res) +{ + wl_resource_destroy(cm_feedback_surface_res); +} + +/** + * Called by clients when they want to know the preferred image description of + * the surface. + */ +static void +cm_feedback_surface_get_preferred(struct wl_client *client, + struct wl_resource *cm_feedback_surface_res, + uint32_t image_description_id) +{ + struct weston_surface *surface = wl_resource_get_user_data(cm_feedback_surface_res); + uint32_t version = wl_resource_get_version(cm_feedback_surface_res); + struct weston_color_manager *cm; + struct cm_image_desc *cm_image_desc; + + /* The surface might have been already gone, in such case cm_feedback_surface is + * inert. */ + if (!surface) { + wl_resource_post_error(cm_feedback_surface_res, + XX_COLOR_MANAGEMENT_FEEDBACK_SURFACE_V4_ERROR_INERT, + "the wl_surface has already been destroyed"); + return; + } + + cm = surface->compositor->color_manager; + + cm_image_desc = cm_image_desc_create(cm, surface->preferred_color_profile, + client, version, image_description_id, + YES_GET_INFO); + if (!cm_image_desc) { + wl_resource_post_no_memory(cm_feedback_surface_res); + return; + } + + xx_image_description_v4_send_ready(cm_image_desc->owner, + cm_image_desc->cprof->id); +} + +static const struct xx_color_management_feedback_surface_v4_interface +cm_feedback_surface_implementation = { + .destroy = cm_feedback_surface_destroy, + .get_preferred = cm_feedback_surface_get_preferred, +}; + +/** + * Resource destruction function for the cm_feedback_surface. + */ +static void +cm_feedback_surface_resource_destroy(struct wl_resource *cm_feedback_surface_res) +{ + struct weston_surface *surface = wl_resource_get_user_data(cm_feedback_surface_res); + + /* For inert cm_feedback_surface, we don't have to do anything. + * + * We already did what was necessary when cm_feedback_surface became + * inert, in the surface destruction process (in weston_surface_unref(), + * which is the surface destruction function). */ + if (!surface) + return; + + /* We are destroying the cm_feedback_surface_res, so simply remove it from + * weston_surface::cm_feedback_surface_resource_list. */ + wl_list_remove(wl_resource_get_link(cm_feedback_surface_res)); +} + +/** + * Notifies clients that their surface preferred image description changed. + * + * \param surface The surface that changed its preferred image description. + */ +void +weston_surface_send_preferred_image_description_changed(struct weston_surface *surface) +{ + struct wl_resource *res; + + /* For each resource, send the event that notifies that the surface + * preferred image description changed. */ + wl_resource_for_each(res, &surface->cm_feedback_surface_resource_list) + xx_color_management_feedback_surface_v4_send_preferred_changed(res); +} + +/** + * Client called get_feedback_surface(). We already have the backing object, so just + * create a resource for the client. + */ +static void +cm_get_feedback_surface(struct wl_client *client, struct wl_resource *cm_res, + uint32_t cm_surface_id, struct wl_resource *surface_res) +{ + struct weston_surface *surface = wl_resource_get_user_data(surface_res); + uint32_t version = wl_resource_get_version(cm_res); + struct wl_resource *res; + + res = wl_resource_create(client, &xx_color_management_feedback_surface_v4_interface, + version, cm_surface_id); + if (!res) { + wl_resource_post_no_memory(cm_res); + return; + } + + wl_resource_set_implementation(res, &cm_feedback_surface_implementation, + surface, cm_feedback_surface_resource_destroy); + wl_list_insert(&surface->cm_feedback_surface_resource_list, wl_resource_get_link(res)); } /** @@ -794,14 +856,14 @@ cm_creator_icc_set_icc_file(struct wl_client *client, const char *err_msg; if (cm_creator_icc->icc_data_length > 0) { - err_code = XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_ALREADY_SET; + err_code = XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_ALREADY_SET; err_msg = "ICC file was already set"; goto err; } /* Length should be in the (0, 4MB] interval */ if (length == 0 || length > (4 * 1024 * 1024)) { - err_code = XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_BAD_SIZE; + err_code = XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_BAD_SIZE; err_msg = "invalid ICC file size"; goto err; } @@ -809,14 +871,14 @@ cm_creator_icc_set_icc_file(struct wl_client *client, /* Fd should be readable. */ flags = fcntl(icc_profile_fd, F_GETFL); if ((flags & O_ACCMODE) == O_WRONLY) { - err_code = XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_BAD_FD; + err_code = XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_BAD_FD; err_msg = "ICC fd is not readable"; goto err; } /* Fd should be seekable. */ if (lseek(icc_profile_fd, 0, SEEK_CUR) < 0) { - err_code = XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_BAD_FD; + err_code = XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_BAD_FD; err_msg = "ICC fd is not seekable"; goto err; } @@ -872,8 +934,8 @@ create_image_description_color_profile_from_icc_creator(struct cm_image_desc *cm bool ret; if (!do_length_and_offset_fit(cm_creator_icc)) { - xx_image_description_v2_send_failed(cm_image_desc->owner, - XX_IMAGE_DESCRIPTION_V2_CAUSE_OPERATING_SYSTEM, + xx_image_description_v4_send_failed(cm_image_desc->owner, + XX_IMAGE_DESCRIPTION_V4_CAUSE_OPERATING_SYSTEM, "length + offset does not fit off_t"); return -1; } @@ -907,8 +969,8 @@ create_image_description_color_profile_from_icc_creator(struct cm_image_desc *cm /* Reading the ICC failed */ free(icc_prof_data); str_printf(&err_msg, "failed to read ICC file: %s", strerror(errno)); - xx_image_description_v2_send_failed(cm_image_desc->owner, - XX_IMAGE_DESCRIPTION_V2_CAUSE_OPERATING_SYSTEM, + xx_image_description_v4_send_failed(cm_image_desc->owner, + XX_IMAGE_DESCRIPTION_V4_CAUSE_OPERATING_SYSTEM, err_msg); free(err_msg); return -1; @@ -919,7 +981,7 @@ create_image_description_color_profile_from_icc_creator(struct cm_image_desc *cm * the given ICC file don't simply change. */ free(icc_prof_data); wl_resource_post_error(cm_creator_icc->owner, - XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_OUT_OF_FILE, + XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_OUT_OF_FILE, "tried to read ICC beyond EOF"); return -1; } @@ -942,15 +1004,15 @@ create_image_description_color_profile_from_icc_creator(struct cm_image_desc *cm * color-manager plugins and decide if we should gracefully fail * or return a protocol error. */ - xx_image_description_v2_send_failed(cm_image_desc->owner, - XX_IMAGE_DESCRIPTION_V2_CAUSE_UNSUPPORTED, + xx_image_description_v4_send_failed(cm_image_desc->owner, + XX_IMAGE_DESCRIPTION_V4_CAUSE_UNSUPPORTED, err_msg); free(err_msg); return -1; } cm_image_desc->cprof = cprof; - xx_image_description_v2_send_ready(cm_image_desc->owner, + xx_image_description_v4_send_ready(cm_image_desc->owner, cm_image_desc->cprof->id); return 0; } @@ -974,7 +1036,7 @@ cm_creator_icc_create(struct wl_client *client, struct wl_resource *resource, if (cm_creator_icc->icc_data_length == 0) { wl_resource_post_error(resource, - XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_INCOMPLETE_SET, + XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_INCOMPLETE_SET, "trying to create image description before " \ "setting the ICC file"); return; @@ -1020,7 +1082,7 @@ cm_creator_icc_destructor(struct wl_resource *resource) free(cm_creator_icc); } -static const struct xx_image_description_creator_icc_v2_interface +static const struct xx_image_description_creator_icc_v4_interface cm_creator_icc_implementation = { .create = cm_creator_icc_create, .set_icc_file = cm_creator_icc_set_icc_file, @@ -1039,7 +1101,7 @@ cm_new_image_description_creator_icc(struct wl_client *client, struct wl_resourc uint32_t version = wl_resource_get_version(cm_res); if (!((cm->supported_color_features >> WESTON_COLOR_FEATURE_ICC) & 1)) { - wl_resource_post_error(cm_res, XX_COLOR_MANAGER_V2_ERROR_UNSUPPORTED_FEATURE, + wl_resource_post_error(cm_res, XX_COLOR_MANAGER_V4_ERROR_UNSUPPORTED_FEATURE, "creating ICC image description creator is " \ "still unsupported"); return; @@ -1051,7 +1113,7 @@ cm_new_image_description_creator_icc(struct wl_client *client, struct wl_resourc cm_creator_icc->icc_profile_fd = -1; cm_creator_icc->owner = - wl_resource_create(client, &xx_image_description_creator_icc_v2_interface, + wl_resource_create(client, &xx_image_description_creator_icc_v4_interface, version, cm_creator_icc_id); if (!cm_creator_icc->owner) goto err; @@ -1074,7 +1136,7 @@ cm_new_image_description_creator_params(struct wl_client *client, struct wl_reso uint32_t cm_creator_params_id) { /* Still unsupported. */ - wl_resource_post_error(cm_res, XX_COLOR_MANAGER_V2_ERROR_UNSUPPORTED_FEATURE, + wl_resource_post_error(cm_res, XX_COLOR_MANAGER_V4_ERROR_UNSUPPORTED_FEATURE, "creating parametric image description creator is " \ "still unsupported"); } @@ -1089,11 +1151,12 @@ cm_destroy(struct wl_client *client, struct wl_resource *cm_res) wl_resource_destroy(cm_res); } -static const struct xx_color_manager_v2_interface +static const struct xx_color_manager_v4_interface color_manager_implementation = { .destroy = cm_destroy, .get_output = cm_get_output, .get_surface = cm_get_surface, + .get_feedback_surface = cm_get_feedback_surface, .new_icc_creator = cm_new_image_description_creator_icc, .new_parametric_creator = cm_new_image_description_creator_params, }; @@ -1112,7 +1175,7 @@ bind_color_management(struct wl_client *client, void *data, uint32_t version, const struct weston_render_intent_info *render_intent; unsigned int i; - resource = wl_resource_create(client, &xx_color_manager_v2_interface, + resource = wl_resource_create(client, &xx_color_manager_v4_interface, version, id); if (!resource) { wl_client_post_no_memory(client); @@ -1127,7 +1190,7 @@ bind_color_management(struct wl_client *client, void *data, uint32_t version, if (!((cm->supported_color_features >> i) & 1)) continue; feature_info = weston_color_feature_info_from(compositor, i); - xx_color_manager_v2_send_supported_feature(resource, + xx_color_manager_v4_send_supported_feature(resource, feature_info->protocol_feature); } @@ -1136,7 +1199,7 @@ bind_color_management(struct wl_client *client, void *data, uint32_t version, if (!((cm->supported_rendering_intents >> i) & 1)) continue; render_intent = weston_render_intent_info_from(compositor, i); - xx_color_manager_v2_send_supported_intent(resource, + xx_color_manager_v4_send_supported_intent(resource, render_intent->protocol_intent); } } @@ -1144,7 +1207,7 @@ bind_color_management(struct wl_client *client, void *data, uint32_t version, /** Advertise color-management support * * Calling this initializes the color-management protocol support, so that - * xx_color_manager_v2_interface will be advertised to clients. Essentially it + * xx_color_manager_v4_interface will be advertised to clients. Essentially it * creates a global. Do not call this function multiple times in the * compositor's lifetime. There is no way to deinit explicitly, globals will be * reaped when the wl_display gets destroyed. @@ -1162,7 +1225,7 @@ weston_compositor_enable_color_management_protocol(struct weston_compositor *com WESTON_RENDER_INTENT_PERCEPTUAL); if (!wl_global_create(compositor->wl_display, - &xx_color_manager_v2_interface, + &xx_color_manager_v4_interface, version, compositor, bind_color_management)) return -1; diff --git a/libweston/color-properties.c b/libweston/color-properties.c index d49e207d..7b53a948 100644 --- a/libweston/color-properties.c +++ b/libweston/color-properties.c @@ -50,32 +50,32 @@ static const struct weston_color_feature_info color_feature_info_table[] = { .feature = WESTON_COLOR_FEATURE_ICC, .desc = "Allow clients to use the new_icc_creator request " \ "from the CM&HDR protocol extension", - .protocol_feature = XX_COLOR_MANAGER_V2_FEATURE_ICC_V2_V4, + .protocol_feature = XX_COLOR_MANAGER_V4_FEATURE_ICC_V2_V4, }, { .feature = WESTON_COLOR_FEATURE_PARAMETRIC, .desc = "Allow clients to use the new_parametric_creator " \ "request from the CM&HDR protocol extension", - .protocol_feature = XX_COLOR_MANAGER_V2_FEATURE_PARAMETRIC, + .protocol_feature = XX_COLOR_MANAGER_V4_FEATURE_PARAMETRIC, }, { .feature = WESTON_COLOR_FEATURE_SET_PRIMARIES, .desc = "Allow clients to use the parametric set_primaries " \ "request from the CM&HDR protocol extension", - .protocol_feature = XX_COLOR_MANAGER_V2_FEATURE_SET_PRIMARIES, + .protocol_feature = XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES, }, { .feature = WESTON_COLOR_FEATURE_SET_TF_POWER, .desc = "Allow clients to use the parametric set_tf_power " \ "request from the CM&HDR protocol extension", - .protocol_feature = XX_COLOR_MANAGER_V2_FEATURE_SET_TF_POWER, + .protocol_feature = XX_COLOR_MANAGER_V4_FEATURE_SET_TF_POWER, }, { .feature = WESTON_COLOR_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES, .desc = "Allow clients to use the parametric " \ "set_mastering_display_primaries request from the " \ "CM&HDR protocol extension", - .protocol_feature = XX_COLOR_MANAGER_V2_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES, + .protocol_feature = XX_COLOR_MANAGER_V4_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES, }, { .feature = WESTON_COLOR_FEATURE_EXTENDED_TARGET_VOLUME, @@ -84,7 +84,7 @@ static const struct weston_color_feature_info color_feature_info_table[] = { "primary color volume. This can only be supported when feature " \ "WESTON_COLOR_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES " \ "is supported", - .protocol_feature = XX_COLOR_MANAGER_V2_FEATURE_EXTENDED_TARGET_VOLUME, + .protocol_feature = XX_COLOR_MANAGER_V4_FEATURE_EXTENDED_TARGET_VOLUME, }, }; @@ -92,35 +92,35 @@ static const struct weston_render_intent_info render_intent_info_table[] = { { .intent = WESTON_RENDER_INTENT_PERCEPTUAL, .desc = "Perceptual", - .protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_PERCEPTUAL, + .protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL, LCMS_INTENT(INTENT_PERCEPTUAL), .bps = false, }, { .intent = WESTON_RENDER_INTENT_RELATIVE, .desc = "Media-relative colorimetric", - .protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_RELATIVE, + .protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE, LCMS_INTENT(INTENT_RELATIVE_COLORIMETRIC), .bps = false, }, { .intent = WESTON_RENDER_INTENT_SATURATION, .desc = "Saturation", - .protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_SATURATION, + .protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_SATURATION, LCMS_INTENT(INTENT_SATURATION), .bps = false, }, { .intent = WESTON_RENDER_INTENT_ABSOLUTE, .desc = "ICC-absolute colorimetric", - .protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_ABSOLUTE, + .protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_ABSOLUTE, LCMS_INTENT(INTENT_ABSOLUTE_COLORIMETRIC), .bps = false, }, { .intent = WESTON_RENDER_INTENT_RELATIVE_BPC, .desc = "Media-relative colorimetric + black point compensation", - .protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_RELATIVE_BPC, + .protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE_BPC, LCMS_INTENT(INTENT_RELATIVE_COLORIMETRIC), .bps = true, }, @@ -131,7 +131,7 @@ static const struct weston_color_primaries_info color_primaries_info_table[] = { .primaries = WESTON_PRIMARIES_CICP_SRGB, .desc = "Color primaries for the sRGB color space as defined by " \ "the BT.709 standard", - .protocol_primaries = XX_COLOR_MANAGER_V2_PRIMARIES_SRGB, + .protocol_primaries = XX_COLOR_MANAGER_V4_PRIMARIES_SRGB, .color_gamut = { .primary = { { 0.64, 0.33 }, /* RGB order */ { 0.30, 0.60 }, @@ -143,7 +143,7 @@ static const struct weston_color_primaries_info color_primaries_info_table[] = { { .primaries = WESTON_PRIMARIES_CICP_PAL_M, .desc = "Color primaries for PAL-M as defined by the BT.470 standard", - .protocol_primaries = XX_COLOR_MANAGER_V2_PRIMARIES_PAL_M, + .protocol_primaries = XX_COLOR_MANAGER_V4_PRIMARIES_PAL_M, .color_gamut = { .primary = { { 0.67, 0.33 }, /* RGB order */ { 0.21, 0.71 }, @@ -155,7 +155,7 @@ static const struct weston_color_primaries_info color_primaries_info_table[] = { { .primaries = WESTON_PRIMARIES_CICP_PAL, .desc = "Color primaries for PAL as defined by the BT.601 standard", - .protocol_primaries = XX_COLOR_MANAGER_V2_PRIMARIES_PAL, + .protocol_primaries = XX_COLOR_MANAGER_V4_PRIMARIES_PAL, .color_gamut = { .primary = { { 0.64, 0.33 }, /* RGB order */ { 0.29, 0.60 }, @@ -167,7 +167,7 @@ static const struct weston_color_primaries_info color_primaries_info_table[] = { { .primaries = WESTON_PRIMARIES_CICP_NTSC, .desc = "Color primaries for NTSC as defined by the BT.601 standard", - .protocol_primaries = XX_COLOR_MANAGER_V2_PRIMARIES_NTSC, + .protocol_primaries = XX_COLOR_MANAGER_V4_PRIMARIES_NTSC, .color_gamut = { .primary = { { 0.630, 0.340 }, /* RGB order */ { 0.310, 0.595 }, @@ -179,7 +179,7 @@ static const struct weston_color_primaries_info color_primaries_info_table[] = { { .primaries = WESTON_PRIMARIES_CICP_GENERIC_FILM, .desc = "Generic film with color filters using Illuminant C", - .protocol_primaries = XX_COLOR_MANAGER_V2_PRIMARIES_GENERIC_FILM, + .protocol_primaries = XX_COLOR_MANAGER_V4_PRIMARIES_GENERIC_FILM, .color_gamut = { .primary = { { 0.681, 0.319 }, /* RGB order */ { 0.243, 0.692 }, @@ -192,7 +192,7 @@ static const struct weston_color_primaries_info color_primaries_info_table[] = { .primaries = WESTON_PRIMARIES_CICP_BT2020, .desc = "Color primaries as defined by the BT.2020 and BT.2100 " \ "standard", - .protocol_primaries = XX_COLOR_MANAGER_V2_PRIMARIES_BT2020, + .protocol_primaries = XX_COLOR_MANAGER_V4_PRIMARIES_BT2020, .color_gamut = { .primary = { { 0.708, 0.292 }, /* RGB order */ { 0.170, 0.797 }, @@ -204,7 +204,7 @@ static const struct weston_color_primaries_info color_primaries_info_table[] = { { .primaries = WESTON_PRIMARIES_CICP_CIE1931_XYZ, .desc = "Color primaries of the full CIE 1931 XYZ color space", - .protocol_primaries = XX_COLOR_MANAGER_V2_PRIMARIES_CIE1931_XYZ, + .protocol_primaries = XX_COLOR_MANAGER_V4_PRIMARIES_CIE1931_XYZ, .color_gamut = { .primary = { { 1.0, 0.0 }, /* RGB order */ { 0.0, 1.0 }, @@ -217,7 +217,7 @@ static const struct weston_color_primaries_info color_primaries_info_table[] = { .primaries = WESTON_PRIMARIES_CICP_DCI_P3, .desc = "Color primaries of the DCI P3 color space as defined by " \ "the SMPTE RP 431 standard", - .protocol_primaries = XX_COLOR_MANAGER_V2_PRIMARIES_DCI_P3, + .protocol_primaries = XX_COLOR_MANAGER_V4_PRIMARIES_DCI_P3, .color_gamut = { .primary = { { 0.680, 0.320 }, /* RGB order */ { 0.265, 0.690 }, @@ -230,7 +230,7 @@ static const struct weston_color_primaries_info color_primaries_info_table[] = { .primaries = WESTON_PRIMARIES_CICP_DISPLAY_P3, .desc = "Color primaries of Display P3 variant of the DCI-P3 color " \ "space as defined by the SMPTE EG 432 standard", - .protocol_primaries = XX_COLOR_MANAGER_V2_PRIMARIES_DISPLAY_P3, + .protocol_primaries = XX_COLOR_MANAGER_V4_PRIMARIES_DISPLAY_P3, .color_gamut = { .primary = { { 0.680, 0.320 }, /* RGB order */ { 0.265, 0.690 }, @@ -243,7 +243,7 @@ static const struct weston_color_primaries_info color_primaries_info_table[] = { .primaries = WESTON_PRIMARIES_ADOBE_RGB, .desc = "Color primaries of the Adobe RGB color space as defined " \ "by the ISO 12640 standard", - .protocol_primaries = XX_COLOR_MANAGER_V2_PRIMARIES_ADOBE_RGB, + .protocol_primaries = XX_COLOR_MANAGER_V4_PRIMARIES_ADOBE_RGB, .color_gamut = { .primary = { { 0.64, 0.33 }, /* RGB order */ { 0.21, 0.71 }, @@ -258,85 +258,85 @@ static const struct weston_color_tf_info color_tf_info_table[] = { { .tf = WESTON_TF_LINEAR, .desc = "Linear transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LINEAR, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_GAMMA22, .desc = "Assumed display gamma 2.2 transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_GAMMA22, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA22, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_GAMMA28, .desc = "Assumed display gamma 2.8 transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_GAMMA28, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA28, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_SRGB, .desc = "sRGB piece-wise transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_SRGB, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_EXT_SRGB, .desc = "Extended sRGB piece-wise transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_EXT_SRGB, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_EXT_SRGB, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_BT709, .desc = "BT.709 transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_BT709, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_BT709, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_BT1361, .desc = "BT.1361 extended transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_BT1361, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_BT1361, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_ST240, .desc = "SMPTE ST 240 transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_ST240, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST240, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_ST428, .desc = "SMPTE ST 428 transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_ST428, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST428, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_ST2084_PQ, .desc = "Perceptual quantizer transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_ST2084_PQ, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_LOG_100, .desc = "Logarithmic 100:1 transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LOG_100, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LOG_100, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_LOG_316, .desc = "Logarithmic (100*Sqrt(10) : 1) transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_LOG_316, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LOG_316, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_XVYCC, .desc = "IEC 61966-2-4 transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_XVYCC, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_XVYCC, .has_parameters = NO_PARAMETERS, }, { .tf = WESTON_TF_HLG, .desc = "Hybrid log-gamma transfer function", - .protocol_tf = XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_HLG, + .protocol_tf = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_HLG, .has_parameters = NO_PARAMETERS, }, { diff --git a/libweston/compositor.c b/libweston/compositor.c index db6476b6..77ede354 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -1002,7 +1002,8 @@ weston_surface_create(struct weston_compositor *compositor) surface->current_protection = WESTON_HDCP_DISABLE; surface->protection_mode = WESTON_SURFACE_PROTECTION_MODE_RELAXED; - wl_list_init(&surface->cm_surface_resource_list); + wl_list_init(&surface->cm_feedback_surface_resource_list); + surface->cm_surface = NULL; /* The surfaces start with no color profile and render intent. It's up * to the color manager what to do with that. Later, clients are able to @@ -2705,7 +2706,7 @@ weston_surface_unref(struct weston_surface *surface) struct wl_resource *cb, *next; struct weston_view *ev, *nv; struct weston_pointer_constraint *constraint, *next_constraint; - struct wl_resource *cm_surface_res, *cm_surface_res_tmp; + struct wl_resource *cm_feedback_surface_res, *cm_feedback_surface_res_tmp; struct weston_paint_node *pnode, *pntmp; if (!surface) @@ -2761,12 +2762,15 @@ weston_surface_unref(struct weston_surface *surface) weston_color_profile_unref(surface->color_profile); weston_color_profile_unref(surface->preferred_color_profile); - wl_resource_for_each_safe(cm_surface_res, cm_surface_res_tmp, - &surface->cm_surface_resource_list) { - wl_list_remove(wl_resource_get_link(cm_surface_res)); - wl_list_init(wl_resource_get_link(cm_surface_res)); - wl_resource_set_user_data(cm_surface_res, NULL); + wl_resource_for_each_safe(cm_feedback_surface_res, + cm_feedback_surface_res_tmp, + &surface->cm_feedback_surface_resource_list) { + wl_list_remove(wl_resource_get_link(cm_feedback_surface_res)); + wl_list_init(wl_resource_get_link(cm_feedback_surface_res)); + wl_resource_set_user_data(cm_feedback_surface_res, NULL); } + if (surface->cm_surface) + wl_resource_set_user_data(surface->cm_surface, NULL); free(surface); } diff --git a/protocol/color-management-v1.xml b/protocol/color-management-v1.xml index fcd4107d..17f217ce 100644 --- a/protocol/color-management-v1.xml +++ b/protocol/color-management-v1.xml @@ -4,7 +4,8 @@ Copyright 2019 Sebastian Wick Copyright 2019 Erwin Burema Copyright 2020 AMD - Copyright 2020, 2022, 2023 Collabora, Ltd. + Copyright 2020-2024 Collabora, Ltd. + Copyright 2024 Xaver Hugl Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -64,7 +65,7 @@ protocol. - + A global interface used for getting color management extensions for wl_surface and wl_output objects, and for creating client defined image @@ -75,13 +76,16 @@ - Destroy the xx_color_manager_v2 object. This does not affect any other + Destroy the xx_color_manager_v4 object. This does not affect any other objects in any way. - + + @@ -89,17 +93,21 @@ See the ICC.1:2022 specification from the International Color Consortium for more details about rendering intents. - The principles of ICC defined rendering intents apply with all types - of image descriptions, not only those with ICC file profiles. + The principles of ICC defined rendering intents apply with all types of + image descriptions, not only those with ICC file profiles. Compositors must support the perceptual rendering intent. Other rendering intents are optional. - - - - + + + + @@ -107,18 +115,23 @@ - - - - - + + + + + + - The compositor supports set_mastering_display_primaries request - with a target color volume fully contained inside the primary - color volume. + The compositor supports set_mastering_display_primaries request with a + target color volume fully contained inside the primary color volume. - + The compositor additionally supports target color volumes that extend outside of the primary color volume. @@ -131,19 +144,23 @@ - Named color primaries used to encode well-known sets of primaries. - H.273 is the authority, when it comes to the exact values of primaries and authoritative specifications, - where an equivalent code point exists. + Named color primaries used to encode well-known sets of primaries. H.273 + is the authority, when it comes to the exact values of primaries and + authoritative specifications, where an equivalent code point exists. + Descriptions do list the specifications for convenience. + Color primaries as defined by - Rec. ITU-R BT.709-6 - - Rec. ITU-R BT.1361-0 conventional colour gamut system and extended colour gamut system (historical) + - Rec. ITU-R BT.1361-0 conventional colour gamut system and extended + colour gamut system (historical) - IEC 61966-2-1 sRGB or sYCC - IEC 61966-2-4 - - Society of Motion Picture and Television Engineers (SMPTE) RP 177 (1993) Annex B + - Society of Motion Picture and Television Engineers (SMPTE) RP 177 + (1993) Annex B Equivalent to H.273 ColourPrimaries code point 1. @@ -151,8 +168,10 @@ Color primaries as defined by - Rec. ITU-R BT.470-6 System M (historical) - - United States National Television System Committee 1953 Recommendation for transmission standards for color television - - United States Federal Communications Commission (2003) Title 47 Code of Federal Regulations 73.682 (a)(20) + - United States National Television System Committee 1953 + Recommendation for transmission standards for color television + - United States Federal Communications Commission (2003) Title 47 Code + of Federal Regulations 73.682 (a)(20) Equivalent to H.273 ColourPrimaries code point 4. @@ -193,7 +212,8 @@ - Color primaries as defined as the maximum of the CIE 1931 XYZ color space by + Color primaries as defined as the maximum of the CIE 1931 XYZ color + space by - SMPTE ST 428-1 - (CIE 1931 XYZ as in ISO 11664-1) Equivalent to H.273 ColourPrimaries code point 10. @@ -201,27 +221,36 @@ - Color primaries as defined by Digital Cinema System and published in SMPTE RP 431-2 (2011). - Equivalent to H.273 ColourPrimaries code point 11. + Color primaries as defined by Digital Cinema System and published in + SMPTE RP 431-2 (2011). Equivalent to H.273 ColourPrimaries code point + 11. - Color primaries as defined by Digital Cinema System and published in SMPTE EG 432-1 (2010). + Color primaries as defined by Digital Cinema System and published in + SMPTE EG 432-1 (2010). Equivalent to H.273 ColourPrimaries code point 12. - Color primaries as defined by Adobe as "Adobe RGB" and later published by ISO 12640-4 (2011). + Color primaries as defined by Adobe as "Adobe RGB" and later published + by ISO 12640-4 (2011). - Named Transfer Functions. + Named transfer functions used to encode well-known transfer + characteristics. H.273 is the authority, when it comes to the exact + formulas and authoritative specifications, where an equivalent code + point exists. + + Descriptions do list the specifications for convenience. + Transfer characteristics as defined by @@ -234,8 +263,10 @@ Transfer characteristics as defined by - Rec. ITU-R BT.470-6 System M (historical) - - United States National Television System Committee 1953 Recommendation for transmission standards for color television - - United States Federal Communications Commission (2003) Title 47 Code of Federal Regulations 73.682 (a) (20) + - United States National Television System Committee 1953 + Recommendation for transmission standards for color television + - United States Federal Communications Commission (2003) Title 47 Code + of Federal Regulations 73.682 (a) (20) - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM Equivalent to H.273 TransferCharacteristics code point 4. @@ -290,14 +321,16 @@ Transfer characteristics as defined by - IEC 61966-2-1 sRGB - Equivalent to H.273 TransferCharacteristics code point 13 with MatrixCoefficients set to 0. + Equivalent to H.273 TransferCharacteristics code point 13 with + MatrixCoefficients set to 0. Transfer characteristics as defined by - IEC 61966-2-1 sYCC - Equivalent to H.273 TransferCharacteristics code point 13 with MatrixCoefficients set to anything but 0. + Equivalent to H.273 TransferCharacteristics code point 13 with + MatrixCoefficients set to anything but 0. @@ -306,6 +339,11 @@ - SMPTE ST 2084 (2014) for 10-, 12-, 14- and 16-bit systems - Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system Equivalent to H.273 TransferCharacteristics code point 16. + + This TF implies these default luminances + - primary color volume minimum: 0.005 cd/m² + - primary color volume maximum: 10000 cd/m² + - reference white: 203 cd/m² @@ -321,31 +359,55 @@ - ARIB STD-B67 (2015) - Rec. ITU-R BT.2100-2 hybrid log-gamma (HLG) system Equivalent to H.273 TransferCharacteristics code point 18. + + This TF implies these default luminances + - primary color volume minimum: 0.005 cd/m² + - primary color volume maximum: 1000 cd/m² + - reference white: 203 cd/m² + Note: HLG is a scene referred signal. All absolute luminance values + used here for HLG assume a 1000 cd/m² display. - This creates a new xx_color_management_output_v2 object for the + This creates a new xx_color_management_output_v4 object for the given wl_output. - See the xx_color_management_output_v2 interface for more details. + See the xx_color_management_output_v4 interface for more details. - + - This creates a new color xx_color_management_surface_v2 object for the + If a xx_color_management_surface_v4 object already exists for the given + wl_surface, the protocol error surface_exists is raised. + + This creates a new color xx_color_management_surface_v4 object for the given wl_surface. - See the xx_color_management_surface_v2 interface for more details. + See the xx_color_management_surface_v4 interface for more details. - + + + + + + + This creates a new color xx_color_management_feedback_surface_v4 object + for the given wl_surface. + + See the xx_color_management_feedback_surface_v4 interface for more + details. + + + @@ -354,15 +416,15 @@ Makes a new ICC-based image description creator object with all properties initially unset. The client can then use the object's interface to define all the required properties for an image description - and finally create a xx_image_description_v2 object. + and finally create a xx_image_description_v4 object. This request can be used when the compositor advertises - xx_color_manager_v2.feature.icc_v2_v4. + xx_color_manager_v4.feature.icc_v2_v4. Otherwise this request raises the protocol error unsupported_feature. - @@ -371,22 +433,22 @@ Makes a new parametric image description creator object with all properties initially unset. The client can then use the object's interface to define all the required properties for an image description - and finally create a xx_image_description_v2 object. + and finally create a xx_image_description_v4 object. This request can be used when the compositor advertises - xx_color_manager_v2.feature.parametric. + xx_color_manager_v4.feature.parametric. Otherwise this request raises the protocol error unsupported_feature. - - When this object is created, it shall immediately send this event - once for each rendering intent the compositor supports. + When this object is created, it shall immediately send this event once + for each rendering intent the compositor supports. - When this object is created, it shall immediately send this event - once for each compositor supported feature listed in the enumeration. + When this object is created, it shall immediately send this event once + for each compositor supported feature listed in the enumeration. - + - When this object is created, it shall immediately send this event - once for each named transfer function the compositor - supports with the parametric image description creator. + When this object is created, it shall immediately send this event once + for each named transfer function the compositor supports with the + parametric image description creator. - + - When this object is created, it shall immediately send this event - once for each named set of primaries the compositor - supports with the parametric image description creator. + When this object is created, it shall immediately send this event once + for each named set of primaries the compositor supports with the + parametric image description creator. - + - + - A xx_color_management_output_v2 describes the color properties of an + A xx_color_management_output_v4 describes the color properties of an output. - The xx_color_management_output_v2 is associated with the wl_output global + The xx_color_management_output_v4 is associated with the wl_output global underlying the wl_output object. Therefore the client destroying the wl_output object has no impact, but the compositor removing the output - global makes the xx_color_management_output_v2 object inert. + global makes the xx_color_management_output_v4 object inert. - Destroy the color xx_color_management_output_v2 object. This does not + Destroy the color xx_color_management_output_v4 object. This does not affect any remaining protocol objects. - This event is sent whenever the image description of the - output changed, followed by one wl_output.done event common to - output events across all extensions. + This event is sent whenever the image description of the output changed, + followed by one wl_output.done event common to output events across all + extensions. - If the client wants to use the updated image description, it needs - to do get_image_description again, because image description objects - are immutable. + If the client wants to use the updated image description, it needs to do + get_image_description again, because image description objects are + immutable. - This creates a new xx_image_description_v2 object for the current image description - of the output. There always is exactly one image description active for an - output so the client should destroy the image description created by earlier - invocations of this request. This request is usually sent as a reaction - to the image_description_changed event or when creating a - xx_color_management_output_v2 object. + This creates a new xx_image_description_v4 object for the current image + description of the output. There always is exactly one image description + active for an output so the client should destroy the image description + created by earlier invocations of this request. This request is usually + sent as a reaction to the image_description_changed event or when + creating a xx_color_management_output_v4 object. - The created xx_image_description_v2 object preserves the image description - of the output from the time the object was created. + The image description of an output represents the color encoding the + output expects. There might be performance and power advantages, as well + as improved color reproduction, if a content update matches the image + description of the output it is being shown on. If a content update is + shown on any other output than the one it matches the image description + of, then the color reproduction on those outputs might be considerably + worse. + + The created xx_image_description_v4 object preserves the image + description of the output from the time the object was created. The resulting image description object allows get_information request. - If this protocol object is inert, the resulting image - description object shall immediately deliver the - xx_image_description_v2.failed event with the no_output cause. + If this protocol object is inert, the resulting image description object + shall immediately deliver the xx_image_description_v4.failed event with + the no_output cause. If the interface version is inadequate for the output's image - description, meaning that the client does not support all the - events needed to deliver the crucial information, the resulting image + description, meaning that the client does not support all the events + needed to deliver the crucial information, the resulting image description object shall immediately deliver the - xx_image_description_v2.failed event with the low_version cause. + xx_image_description_v4.failed event with the low_version cause. Otherwise the object shall immediately deliver the ready event. - + - + - A xx_color_management_surface_v2 allows the client to set the color + A xx_color_management_surface_v4 allows the client to set the color space and HDR properties of a surface. - If the wl_surface associated with the xx_color_management_surface_v2 is - destroyed, the xx_color_management_surface_v2 object becomes inert. + If the wl_surface associated with the xx_color_management_surface_v4 is + destroyed, the xx_color_management_surface_v4 object becomes inert. - Destroy the xx_color_management_surface_v2 object. - - When the last xx_color_management_surface_v2 object for a wl_surface - is destroyed, it does the same as unset_image_description. + Destroy the xx_color_management_surface_v4 object and do the same as + unset_image_description. - - - + + @@ -517,12 +590,21 @@ It is the client's responsibility to understand the image description it sets on a surface, and to provide content that matches that image - description. + description. Compositors might convert images to match their own or any + other image descriptions. + + Image description whose creation gracefully failed (received + xx_image_description_v4.failed) are forbidden in this request, and in + such case the protocol error image_description is raised. + + All image descriptions whose creation succeeded (received + xx_image_description_v4.ready) are allowed and must always be accepted + by the compositor. A rendering intent provides the client's preference on how content colors should be mapped to each output. The render_intent value must be one advertised by the compositor with - xx_color_manager_v2.render_intent event, otherwise the protocol error + xx_color_manager_v4.render_intent event, otherwise the protocol error render_intent is raised. By default, a surface does not have an associated image description @@ -532,8 +614,10 @@ requirements. - - + @@ -541,20 +625,40 @@ This request removes any image description from the surface. See set_image_description for how a compositor handles a surface without - an image description. This is double-buffered state, see + an image description. This is double-buffered state, see wl_surface.commit. + + + + + A xx_color_management_feedback_surface_v4 allows the client to get the + preferred color description of a surface. + + If the wl_surface associated with this object is destroyed, the + xx_color_management_feedback_surface_v4 object becomes inert. + + + + + Destroy the xx_color_management_feedback_surface_v4 object. + + + + + + + - + The preferred image description is the one which likely has the most performance and/or quality benefits for the compositor if used by the client for its wl_surface contents. This event is sent whenever the compositor changes the wl_surface's preferred image description. - This is not an initial event. - This event is merely a notification. When the client wants to know what the preferred image description is, it shall use the get_preferred request. @@ -572,15 +676,21 @@ If this protocol object is inert, the protocol error inert is raised. - This creates a new xx_image_description_v2 object for the currently + The preferred image description represents the compositor's preferred + color encoding for this wl_surface at the current time. There might be + performance and power advantages, as well as improved color + reproduction, if the image description of a content update matches the + preferred image description. + + This creates a new xx_image_description_v4 object for the currently preferred image description for the wl_surface. The client should stop using and destroy the image descriptions created by earlier invocations of this request for the associated wl_surface. This request is usually sent as a reaction to the preferred_changed - event or when creating a xx_color_management_surface_v2 object if - the client is capable of adapting to image descriptions. + event or when creating a xx_color_management_feedback_surface_v4 object + if the client is capable of adapting to image descriptions. - The created xx_image_description_v2 object preserves the preferred image + The created xx_image_description_v4 object preserves the preferred image description of the wl_surface from the time the object was created. The resulting image description object allows get_information request. @@ -589,18 +699,19 @@ description, meaning that the client does not support all the events needed to deliver the crucial information, the resulting image description object shall immediately deliver the - xx_image_description_v2.failed event with the low_version cause, + xx_image_description_v4.failed event with the low_version cause, otherwise the object shall immediately deliver the ready event. - + - + This type of object is used for collecting all the information required - to create a xx_image_description_v2 object from an ICC file. A complete + to create a xx_image_description_v4 object from an ICC file. A complete set of required parameters consists of these properties: - ICC file @@ -618,11 +729,16 @@ - - - - - + + + + + @@ -637,18 +753,19 @@ If the particular combination of the information is not supported by the compositor, the resulting image description object shall - immediately deliver the xx_image_description_v2.failed event with the + immediately deliver the xx_image_description_v4.failed event with the 'unsupported' cause. If a valid image description was created from the - information, the xx_image_description_v2.ready event will eventually + information, the xx_image_description_v4.ready event will eventually be sent instead. - This request destroys the xx_image_description_creator_icc_v2 object. + This request destroys the xx_image_description_creator_icc_v4 object. The resulting image description object does not allow get_information request. - + @@ -656,37 +773,36 @@ Sets the ICC profile file to be used as the basis of the image description. - The data shall be found through the given fd at the given offset, - having the given length. The fd must seekable and readable. Violating - these requirements raises the bad_fd protocol error. + The data shall be found through the given fd at the given offset, having + the given length. The fd must seekable and readable. Violating these + requirements raises the bad_fd protocol error. If reading the data fails due to an error independent of the client, the - compositor shall send the xx_image_description_v2.failed event on the - created xx_image_description_v2 with the 'operating_system' cause. + compositor shall send the xx_image_description_v4.failed event on the + created xx_image_description_v4 with the 'operating_system' cause. - The maximum size of the ICC profile is 4 MB. If length is greater - than that or zero, the protocol error bad_size is raised. - If offset + length exceeds the file size, the protocol error - out_of_file is raised. + The maximum size of the ICC profile is 4 MB. If length is greater than + that or zero, the protocol error bad_size is raised. If offset + length + exceeds the file size, the protocol error out_of_file is raised. A compositor may read the file at any time starting from this request and only until whichever happens first: - - If create request was issued, the xx_image_description_v2 object + - If create request was issued, the xx_image_description_v4 object delivers either failed or ready event; or - if create request was not issued, this - xx_image_description_creator_icc_v2 object is destroyed. + xx_image_description_creator_icc_v4 object is destroyed. A compositor shall not modify the contents of the file, and the fd may be sealed for writes and size changes. The client must ensure to its best ability that the data does not change while the compositor is reading it. - The data must represent a valid ICC profile. - The ICC profile version must be 2 or 4, it must be a 3 channel profile - and the class must be 'display'. - Violating these requirements will not result in a protocol error but - will eventually send the xx_image_description_v2.failed event on the - created xx_image_description_v2 with the 'unsupported' cause. + The data must represent a valid ICC profile. The ICC profile version + must be 2 or 4, it must be a 3 channel profile and the class must be + Display or ColorSpace. Violating these requirements will not result in a + protocol error but will eventually send the + xx_image_description_v4.failed event on the created + xx_image_description_v4 with the 'unsupported' cause. See the International Color Consortium specification ICC.1:2022 for more details about ICC profiles. @@ -695,22 +811,27 @@ already_set is raised. - - - + + + - + This type of object is used for collecting all the parameters required - to create a xx_image_description_v2 object. A complete set of required + to create a xx_image_description_v4 object. A complete set of required parameters consists of these properties: - transfer characteristic function (tf) - chromaticities of primaries and white point (primary color volume) The following properties are optional and have a well-defined default if not explicitly set: + - primary color volume luminance range + - reference white luminance level - mastering display primaries and white point (target color volume) - mastering luminance range - maximum content light level @@ -730,13 +851,22 @@ - - - - - - - + + + + + + + + @@ -748,56 +878,68 @@ complete, the protocol error incomplete_set is raised. For the definition of a complete set, see the description of this interface. + Also, the combination of the parameter set is verified. If the set is + not consistent, the protocol error inconsistent_set is raised. + If the particular combination of the parameter set is not supported by the compositor, the resulting image description object shall - immediately deliver the xx_image_description_v2.failed event with the + immediately deliver the xx_image_description_v4.failed event with the 'unsupported' cause. If a valid image description was created from the - parameter set, the xx_image_description_v2.ready event will eventually + parameter set, the xx_image_description_v4.ready event will eventually be sent instead. - This request destroys the xx_image_description_creator_params_v2 + This request destroys the xx_image_description_creator_params_v4 object. The resulting image description object does not allow get_information request. - + - Sets the transfer characteristic using explicitly enumerated named functions. + Sets the transfer characteristic using explicitly enumerated named + functions. - Only names advertised with xx_color_manager_v2 - event supported_tf_named are allowed. Other values shall raise the - protocol error invalid_tf. + When the resulting image description is attached to an image, the + content should be encoded and decoded according to the industry standard + practices for the transfer characteristic. + + Only names advertised with xx_color_manager_v4 event supported_tf_named + are allowed. Other values shall raise the protocol error invalid_tf. If transfer characteristic has already been set on this object, the protocol error already_set is raised. - + - Sets the color component transfer characteristic to a power curve - with the given exponent. This curve represents the conversion from - electrical to optical pixel or color values. + Sets the color component transfer characteristic to a power curve with + the given exponent. This curve represents the conversion from electrical + to optical pixel or color values. - The curve exponent shall be multiplied by 10000 to get the argument - eexp value to carry the precision of 4 decimals. + When the resulting image description is attached to an image, the + content should be encoded with the inverse of the power curve. - The curve exponent must be at least 1.0 and at most 10.0. Otherwise - the protocol error invalid_tf is raised. + The curve exponent shall be multiplied by 10000 to get the argument eexp + value to carry the precision of 4 decimals. + + The curve exponent must be at least 1.0 and at most 10.0. Otherwise the + protocol error invalid_tf is raised. If transfer characteristic has already been set on this object, the protocol error already_set is raised. This request can be used when the compositor advertises - xx_color_manager_v2.feature.set_tf_power. Otherwise this request raises - the protocol error invalid_tf. + xx_color_manager_v4.feature.set_tf_power. Otherwise this request raises + the protocol error unsupported_feature. @@ -806,45 +948,99 @@ Sets the color primaries and white point using explicitly named sets. - This describes the primary color volume which is the basis - for color value encoding. + This describes the primary color volume which is the basis for color + value encoding. - Only names advertised with xx_color_manager_v2 - event supported_primaries_named are allowed. Other values shall raise the + Only names advertised with xx_color_manager_v4 event + supported_primaries_named are allowed. Other values shall raise the protocol error invalid_primaries. If primaries have already been set on this object, the protocol error already_set is raised. - + - Sets the color primaries and white point using CIE 1931 xy - chromaticity coordinates. This describes the primary color volume - which is the basis for color value encoding. + Sets the color primaries and white point using CIE 1931 xy chromaticity + coordinates. This describes the primary color volume which is the basis + for color value encoding. - Each coordinate value is multiplied by 10000 to get the argument - value to carry precision of 4 decimals. + Each coordinate value is multiplied by 10000 to get the argument value + to carry precision of 4 decimals. If primaries have already been set on this object, the protocol error already_set is raised. This request can be used if the compositor advertises - xx_color_manager_v2.feature.set_primaries. Otherwise this request - raises the protocol error invalid_primaries. + xx_color_manager_v4.feature.set_primaries. Otherwise this request raises + the protocol error unsupported_feature. - - - - - - - - + + + + + + + + + + + + + Sets the primary color volume luminance range and the reference white + luminance level. + + The default luminances are + - primary color volume minimum: 0.2 cd/m² + - primary color volume maximum: 80 cd/m² + - reference white: 80 cd/m² + + Setting a named transfer characteristic can imply other default + luminances. + + The default luminances get overwritten when this request is used. + + 'min_lum' and 'max_lum' specify the minimum and maximum luminances of + the primary color volume as reproduced by the targeted display. + + 'reference_lum' specifies the luminance of the reference white as + reproduced by the targeted display, and reflects the targeted viewing + environment. + + Compositors should make sure that all content is anchored, meaning that + an input signal level of 'reference_lum' on one image description and + another input signal level of 'reference_lum' on another image + description should produce the same output level, even though the + 'reference_lum' on both image representations can be different. + + If 'max_lum' is less than the 'reference_lum', or 'reference_lum' is + less than or equal to 'min_lum', the protocol error invalid_luminance is + raised. + + The minimum luminance is multiplied by 10000 to get the argument + 'min_lum' value and carries precision of 4 decimals. The maximum + luminance and reference white luminance values are unscaled. + + If the primary color volume luminance range and the reference white + luminance level have already been set on this object, the protocol error + already_set is raised. + + This request can be used if the compositor advertises + xx_color_manager_v4.feature.set_luminances. Otherwise this request + raises the protocol error unsupported_feature. + + + + + @@ -855,8 +1051,8 @@ The mastering display primaries define the target color volume. - If mastering display primaries are not explicitly set, the target - color volume is assumed to be equal to the primary color volume. + If mastering display primaries are not explicitly set, the target color + volume is assumed to be equal to the primary color volume. The target color volume is defined by all tristimulus values between 0.0 and 1.0 (inclusive) of the color space defined by the given mastering @@ -875,36 +1071,35 @@ has to be chosen (e.g. floating point to exceed the primary color volume, or abusing limited quantization range as with xvYCC). - Each coordinate value is multiplied by 10000 to get the argument - value to carry precision of 4 decimals. + Each coordinate value is multiplied by 10000 to get the argument value + to carry precision of 4 decimals. - If mastering display primaries have already been set on this object, - the protocol error already_set is raised. + If mastering display primaries have already been set on this object, the + protocol error already_set is raised. This request can be used if the compositor advertises - xx_color_manager_v2.feature.set_mastering_display_primaries. - Otherwise this request raises the protocol error invalid_mastering. - The advertisement implies support only for target color - volumes fully contained within the primary color volume. + xx_color_manager_v4.feature.set_mastering_display_primaries. Otherwise + this request raises the protocol error unsupported_feature. The + advertisement implies support only for target color volumes fully + contained within the primary color volume. - If a compositor additionally supports target color volume exceeding - the primary color volume, it must advertise - xx_color_manager_v2.feature.extended_target_volume. - If a client uses target color volume exceeding the primary color volume - and the compositor does not support it, the result is implementation - defined. Compositors are recommended to detect this case and fail the - image description gracefully, but it may as well result in color - artifacts. + If a compositor additionally supports target color volume exceeding the + primary color volume, it must advertise + xx_color_manager_v4.feature.extended_target_volume. If a client uses + target color volume exceeding the primary color volume and the + compositor does not support it, the result is implementation defined. + Compositors are recommended to detect this case and fail the image + description gracefully, but it may as well result in color artifacts. - - - - - - - - + + + + + + + + @@ -913,11 +1108,6 @@ process as the minimum and maximum absolute luminance L. This is compatible with the SMPTE ST 2086 definition of HDR static metadata. - This can only be set when set_tf_cicp is used to set the transfer - characteristic to Rec. ITU-R BT.2100-2 perceptual quantization system. - Otherwise, 'create' request shall raise inconsistent_set protocol - error. - The mastering luminance range is undefined by default. If max L is less than or equal to min L, the protocol error @@ -953,8 +1143,7 @@ This can only be set when set_tf_cicp is used to set the transfer characteristic to Rec. ITU-R BT.2100-2 perceptual quantization system. - Otherwise, 'create' request shall raise inconsistent_set protocol - error. + Otherwise, 'create' request shall raise inconsistent_set protocol error. max_fall is undefined by default. @@ -963,15 +1152,15 @@ - + - An image description carries information about the color encoding used - on a surface when attached to a wl_surface via - xx_color_management_surface_v2.set_image_description. A compositor can - use this information to decode pixel values into colorimetrically - meaningful quantities. + An image description carries information about the color encoding used on + a surface when attached to a wl_surface via + xx_color_management_surface_v4.set_image_description. A compositor can use + this information to decode pixel values into colorimetrically meaningful + quantities. - Note, that the xx_image_description_v2 object is not ready to be used + Note, that the xx_image_description_v4 object is not ready to be used immediately after creation. The object eventually delivers either the 'ready' or the 'failed' event, specified in all requests creating it. The object is deemed "ready" after receiving the 'ready' event. @@ -981,61 +1170,70 @@ protocol error. Attempts to use an object which is not ready through other interfaces shall raise protocol errors defined there. - Once created and regardless of how it was created, a xx_image_description_v2 - object always refers to one fixed image description. It cannot change - after creation. + Once created and regardless of how it was created, a + xx_image_description_v4 object always refers to one fixed image + description. It cannot change after creation. Destroy this object. It is safe to destroy an object which is not ready. - Destroying a xx_image_description_v2 object has no side-effects, not - even if a xx_color_management_surface_v2.set_image_description has - not yet been followed by a wl_surface.commit. + Destroying a xx_image_description_v4 object has no side-effects, not + even if a xx_color_management_surface_v4.set_image_description has not + yet been followed by a wl_surface.commit. - - + + - - - - + + + + - If creating a xx_image_description_v2 object fails for a reason that - is not defined as a protocol error, this event is sent. - The requests that create image description objects define whether - and when this can occur. Only such creation requests can trigger this - event. This event cannot be triggered after the image description was + If creating a xx_image_description_v4 object fails for a reason that is + not defined as a protocol error, this event is sent. + + The requests that create image description objects define whether and + when this can occur. Only such creation requests can trigger this event. + This event cannot be triggered after the image description was successfully formed. - Once this event has been sent, the xx_image_description_v2 object will + Once this event has been sent, the xx_image_description_v4 object will never become ready and it can only be destroyed. - - + + - Once this event has been sent, the xx_image_description_v2 object is + Once this event has been sent, the xx_image_description_v4 object is deemed "ready". Ready objects can be used to send requests and can be used through other interfaces. - Every ready xx_image_description_v2 protocol object refers to an + Every ready xx_image_description_v4 protocol object refers to an underlying image description record in the compositor. Multiple protocol objects may end up referring to the same record. Clients may identify these "copies" by comparing their id numbers: if the numbers from two @@ -1044,15 +1242,15 @@ cannot have the same id number simultaneously. The id number does not change during the lifetime of the image description record. - The id number is valid only as long as the protocol object is alive. - If all protocol objects referring to the same image description record - are destroyed, the id number may be recycled for a different image + The id number is valid only as long as the protocol object is alive. If + all protocol objects referring to the same image description record are + destroyed, the id number may be recycled for a different image description record. Image description id number is not a protocol object id. Zero is - reserved as an invalid id number. It shall not be possible for a - client to refer to an image description by its id number in protocol. - The id numbers might not be portable between Wayland connections. + reserved as an invalid id number. It shall not be possible for a client + to refer to an image description by its id number in protocol. The id + numbers might not be portable between Wayland connections. This identity allows clients to de-duplicate image description records and avoid get_information request if they already have the image @@ -1064,7 +1262,7 @@ - Creates a xx_image_description_info_v2 object which delivers the + Creates a xx_image_description_info_v4 object which delivers the information that makes up the image description. Not all image description protocol objects allow get_information @@ -1073,20 +1271,21 @@ error no_information is raised. - + - + Sends all matching events describing an image description object exactly once and finally sends the 'done' event. - Once a xx_image_description_info_v2 object has delivered a 'done' event - it is automatically destroyed. + Once a xx_image_description_info_v4 object has delivered a 'done' event it + is automatically destroyed. - Every xx_image_description_info_v2 created from the same - xx_image_description_v2 shall always return the exact same data. + Every xx_image_description_info_v4 created from the same + xx_image_description_v4 shall always return the exact same data. @@ -1114,41 +1313,42 @@ - Delivers the primary color volume primaries and white point - using CIE 1931 xy chromaticity coordinates. + Delivers the primary color volume primaries and white point using CIE + 1931 xy chromaticity coordinates. - Each coordinate value is multiplied by 10000 to get the argument - value to carry precision of 4 decimals. + Each coordinate value is multiplied by 10000 to get the argument value + to carry precision of 4 decimals. - - - - - - - - + + + + + + + + - Delivers the primary color volume primaries and white point using a + Delivers the primary color volume primaries and white point using an explicitly enumerated named set. - + - The color component transfer characteristic of this image description - is a pure power curve. This event provides the exponent of the power + The color component transfer characteristic of this image description is + a pure power curve. This event provides the exponent of the power function. This curve represents the conversion from electrical to optical pixel or color values. - The curve exponent has been multiplied by 10000 to get the argument - eexp value to carry the precision of 4 decimals. + The curve exponent has been multiplied by 10000 to get the argument eexp + value to carry the precision of 4 decimals. @@ -1160,46 +1360,64 @@ named function. - + + + + + + Delivers the primary color volume luminance range and the reference + white luminance level. + + The minimum luminance is multiplied by 10000 to get the argument + 'min_lum' value and carries precision of 4 decimals. The maximum + luminance and reference white luminance values are unscaled. + + + + + - Provides the color primaries and white point of the target - color volume using CIE 1931 xy chromaticity coordinates. This is - compatible with the SMPTE ST 2086 definition of HDR static metadata - for mastering displays. + Provides the color primaries and white point of the target color volume + using CIE 1931 xy chromaticity coordinates. This is compatible with the + SMPTE ST 2086 definition of HDR static metadata for mastering displays. - While primary color volume is about how color is encoded, the - target color volume is the actually displayable color volume. - If target color volume is equal to the primary color volume, - then this event is not sent. + While primary color volume is about how color is encoded, the target + color volume is the actually displayable color volume. If target color + volume is equal to the primary color volume, then this event is not + sent. - Each coordinate value is multiplied by 10000 to get the argument - value to carry precision of 4 decimals. + Each coordinate value is multiplied by 10000 to get the argument value + to carry precision of 4 decimals. - - - - - - - - + + + + + + + + - Provides the luminance range that the image description is targeting - as the minimum and maximum absolute luminance L. This is compatible - with the SMPTE ST 2086 definition of HDR static metadata. + Provides the luminance range that the image description is targeting as + the minimum and maximum absolute luminance L. This is compatible with + the SMPTE ST 2086 definition of HDR static metadata. This luminance range is only theoretical and may not correspond to the luminance of light emitted on an actual display. - Min L value is multiplied by 10000 to get the argument min_lum value - and carry precision of 4 decimals. Max L value is unscaled for max_lum. + Min L value is multiplied by 10000 to get the argument min_lum value and + carry precision of 4 decimals. Max L value is unscaled for max_lum. @@ -1215,7 +1433,8 @@ luminance of light emitted on an actual display. - + @@ -1227,7 +1446,8 @@ luminance of light emitted on an actual display. - + diff --git a/tests/color-management-test.c b/tests/color-management-test.c index 9414d8f5..9501134d 100644 --- a/tests/color-management-test.c +++ b/tests/color-management-test.c @@ -65,7 +65,7 @@ const struct lcms_pipeline pipeline_sRGB = { }; struct image_description { - struct xx_image_description_v2 *xx_image_descr; + struct xx_image_description_v4 *xx_image_descr; enum image_description_status { CM_IMAGE_DESC_NOT_CREATED = 0, @@ -81,9 +81,9 @@ struct image_description { uint32_t icc_size; /* For parametric images descriptions. */ - enum xx_color_manager_v2_primaries primaries_named; + enum xx_color_manager_v4_primaries primaries_named; struct weston_color_gamut primaries; - enum xx_color_manager_v2_transfer_function tf_named; + enum xx_color_manager_v4_transfer_function tf_named; float tf_power; struct weston_color_gamut target_primaries; float target_min_lum, target_max_lum; @@ -92,7 +92,7 @@ struct image_description { }; struct image_description_info { - struct xx_image_description_info_v2 *xx_image_description_info; + struct xx_image_description_info_v4 *xx_image_description_info; struct image_description *image_descr; /* Bitfield that holds what events the compositor has sent us through @@ -102,10 +102,11 @@ struct image_description_info { }; struct color_manager { - struct xx_color_manager_v2 *manager; + struct xx_color_manager_v4 *manager; - struct xx_color_management_output_v2 *output; - struct xx_color_management_surface_v2 *surface; + struct xx_color_management_output_v4 *output; + struct xx_color_management_surface_v4 *surface; + struct xx_color_management_feedback_surface_v4 *feedback_surface; struct wl_list image_descr_list; /* image_description::link */ @@ -130,12 +131,12 @@ static void image_description_destroy(struct image_description *image_descr) { wl_list_remove(&image_descr->link); - xx_image_description_v2_destroy(image_descr->xx_image_descr); + xx_image_description_v4_destroy(image_descr->xx_image_descr); free(image_descr); } static void -image_descr_ready(void *data, struct xx_image_description_v2 *xx_image_description_v2, +image_descr_ready(void *data, struct xx_image_description_v4 *xx_image_description_v4, uint32_t identity) { struct image_description *image_descr = data; @@ -144,7 +145,7 @@ image_descr_ready(void *data, struct xx_image_description_v2 *xx_image_descripti } static void -image_descr_failed(void *data, struct xx_image_description_v2 *xx_image_description_v2, +image_descr_failed(void *data, struct xx_image_description_v4 *xx_image_description_v4, uint32_t cause, const char *msg) { struct image_description *image_descr = data; @@ -155,7 +156,7 @@ image_descr_failed(void *data, struct xx_image_description_v2 *xx_image_descript " cause: %u, msg: %s\n", cause, msg); } -static const struct xx_image_description_v2_listener +static const struct xx_image_description_v4_listener image_descr_iface = { .ready = image_descr_ready, .failed = image_descr_failed, @@ -173,9 +174,9 @@ image_descr_info_received(struct image_description_info *image_descr_info, static void image_descr_info_primaries(void *data, - struct xx_image_description_info_v2 *xx_image_description_info_v2, - 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) + struct xx_image_description_info_v4 *xx_image_description_info_v4, + int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, + int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) { struct image_description_info *image_descr_info = data; struct image_description *image_descr = image_descr_info->image_descr; @@ -196,7 +197,7 @@ image_descr_info_primaries(void *data, static void image_descr_info_primaries_named(void *data, - struct xx_image_description_info_v2 *xx_image_description_info_v2, + struct xx_image_description_info_v4 *xx_image_description_info_v4, uint32_t primaries) { struct image_description_info *image_descr_info = data; @@ -210,7 +211,7 @@ image_descr_info_primaries_named(void *data, static void image_descr_info_tf_named(void *data, - struct xx_image_description_info_v2 *xx_image_description_info_v2, + struct xx_image_description_info_v4 *xx_image_description_info_v4, uint32_t tf) { struct image_description_info *image_descr_info = data; @@ -224,7 +225,7 @@ image_descr_info_tf_named(void *data, static void image_descr_info_tf_power(void *data, - struct xx_image_description_info_v2 *xx_image_description_info_v2, + struct xx_image_description_info_v4 *xx_image_description_info_v4, uint32_t tf_power) { struct image_description_info *image_descr_info = data; @@ -238,9 +239,9 @@ image_descr_info_tf_power(void *data, static void image_descr_info_target_primaries(void *data, - struct xx_image_description_info_v2 *xx_image_description_info_v2, - 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) + struct xx_image_description_info_v4 *xx_image_description_info_v4, + int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, + int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) { struct image_description_info *image_descr_info = data; struct image_description *image_descr = image_descr_info->image_descr; @@ -260,7 +261,7 @@ image_descr_info_target_primaries(void *data, static void image_descr_info_target_luminance(void *data, - struct xx_image_description_info_v2 *xx_image_description_info_v2, + struct xx_image_description_info_v4 *xx_image_description_info_v4, uint32_t min_lum, uint32_t max_lum) { struct image_description_info *image_descr_info = data; @@ -275,7 +276,7 @@ image_descr_info_target_luminance(void *data, static void image_descr_info_target_max_cll(void *data, - struct xx_image_description_info_v2 *xx_image_description_info_v2, + struct xx_image_description_info_v4 *xx_image_description_info_v4, uint32_t maxCLL) { struct image_description_info *image_descr_info = data; @@ -289,7 +290,7 @@ image_descr_info_target_max_cll(void *data, static void image_descr_info_target_max_fall(void *data, - struct xx_image_description_info_v2 *xx_image_description_info_v2, + struct xx_image_description_info_v4 *xx_image_description_info_v4, uint32_t maxFALL) { struct image_description_info *image_descr_info = data; @@ -303,7 +304,7 @@ image_descr_info_target_max_fall(void *data, static void image_descr_info_icc_file_event(void *data, - struct xx_image_description_info_v2 *xx_image_description_info_v2, + struct xx_image_description_info_v4 *xx_image_description_info_v4, int32_t icc_fd, uint32_t icc_size) { struct image_description_info *image_descr_info = data; @@ -361,19 +362,19 @@ are_events_received_valid(struct image_description_info *image_descr_info) /* If we received tf named and exp power, they must match. */ if (received_tf_named && received_tf_power) { - if (image_descr->tf_named != XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_GAMMA22 && - image_descr->tf_named != XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_GAMMA28) { + if (image_descr->tf_named != XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA22 && + image_descr->tf_named != XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA28) { testlog(" Error: parametric image description tf " \ "named is not pure power-law, but still received " \ "tf power event\n"); return false; - } else if (image_descr->tf_named == XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_GAMMA22 && + } else if (image_descr->tf_named == XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA22 && image_descr->tf_power != 2.2f) { testlog(" Error: parametric image description tf named " \ "is pure power-law 2.2, but tf power received is %f\n", image_descr->tf_power); return false; - } else if (image_descr->tf_named == XX_COLOR_MANAGER_V2_TRANSFER_FUNCTION_GAMMA28 && + } else if (image_descr->tf_named == XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA28 && image_descr->tf_power != 2.8f) { testlog(" Error: parametric image description tf named " \ "is pure power-law 2.8, but tf power received is %f\n", @@ -390,12 +391,12 @@ are_events_received_valid(struct image_description_info *image_descr_info) static void image_descr_info_done(void *data, - struct xx_image_description_info_v2 *xx_image_description_info_v2) + struct xx_image_description_info_v4 *xx_image_description_info_v4) { struct image_description_info *image_descr_info = data; struct image_description *image_descr = image_descr_info->image_descr; - testlog("Image description info %p done:\n", xx_image_description_info_v2); + testlog("Image description info %p done:\n", xx_image_description_info_v4); assert(are_events_received_valid(image_descr_info)); @@ -458,7 +459,7 @@ image_descr_info_done(void *data, testlog(" Target maxFALL: %.4f\n", image_descr->target_max_fall); } -static const struct xx_image_description_info_v2_listener +static const struct xx_image_description_info_v4_listener image_descr_info_iface = { .primaries = image_descr_info_primaries, .primaries_named = image_descr_info_primaries_named, @@ -473,7 +474,7 @@ image_descr_info_iface = { }; static void -cm_supported_intent(void *data, struct xx_color_manager_v2 *xx_color_manager_v2, +cm_supported_intent(void *data, struct xx_color_manager_v4 *xx_color_manager_v4, uint32_t render_intent) { struct color_manager *cm = data; @@ -482,7 +483,7 @@ cm_supported_intent(void *data, struct xx_color_manager_v2 *xx_color_manager_v2, } static void -cm_supported_feature(void *data, struct xx_color_manager_v2 *xx_color_manager_v2, +cm_supported_feature(void *data, struct xx_color_manager_v4 *xx_color_manager_v4, uint32_t feature) { struct color_manager *cm = data; @@ -491,7 +492,7 @@ cm_supported_feature(void *data, struct xx_color_manager_v2 *xx_color_manager_v2 } static void -cm_supported_tf_named(void *data, struct xx_color_manager_v2 *xx_color_manager_v2, +cm_supported_tf_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4, uint32_t tf_code) { /* only used to create image descriptions using parameters, which is @@ -499,14 +500,14 @@ cm_supported_tf_named(void *data, struct xx_color_manager_v2 *xx_color_manager_v } static void -cm_supported_primaries_named(void *data, struct xx_color_manager_v2 *xx_color_manager_v2, +cm_supported_primaries_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4, uint32_t primaries_code) { /* only used to create image descriptions using parameters, which is * still unsupported by Weston. */ } -static const struct xx_color_manager_v2_listener +static const struct xx_color_manager_v4_listener cm_iface = { .supported_intent = cm_supported_intent, .supported_feature = cm_supported_feature, @@ -522,28 +523,32 @@ color_manager_init(struct color_manager *cm, struct client *client) wl_list_init(&cm->image_descr_list); cm->manager = bind_to_singleton_global(client, - &xx_color_manager_v2_interface, + &xx_color_manager_v4_interface, 1); - xx_color_manager_v2_add_listener(cm->manager, &cm_iface, cm); + xx_color_manager_v4_add_listener(cm->manager, &cm_iface, cm); - cm->output = xx_color_manager_v2_get_output(cm->manager, + cm->output = xx_color_manager_v4_get_output(cm->manager, client->output->wl_output); - cm->surface = xx_color_manager_v2_get_surface(cm->manager, + cm->surface = xx_color_manager_v4_get_surface(cm->manager, client->surface->wl_surface); + cm->feedback_surface = + xx_color_manager_v4_get_feedback_surface(cm->manager, + client->surface->wl_surface); + client_roundtrip(client); /* For now, Weston only supports the ICC image description creator. All * the parametric parts of the protocol are still unsupported. */ - assert(cm->supported_features == (1 << XX_COLOR_MANAGER_V2_FEATURE_ICC_V2_V4)); + assert(cm->supported_features == (1 << XX_COLOR_MANAGER_V4_FEATURE_ICC_V2_V4)); /* Weston supports all rendering intents. */ - assert(cm->supported_rendering_intents == ((1 << XX_COLOR_MANAGER_V2_RENDER_INTENT_PERCEPTUAL) | - (1 << XX_COLOR_MANAGER_V2_RENDER_INTENT_RELATIVE) | - (1 << XX_COLOR_MANAGER_V2_RENDER_INTENT_SATURATION) | - (1 << XX_COLOR_MANAGER_V2_RENDER_INTENT_ABSOLUTE) | - (1 << XX_COLOR_MANAGER_V2_RENDER_INTENT_RELATIVE_BPC))); + assert(cm->supported_rendering_intents == ((1 << XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL) | + (1 << XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE) | + (1 << XX_COLOR_MANAGER_V4_RENDER_INTENT_SATURATION) | + (1 << XX_COLOR_MANAGER_V4_RENDER_INTENT_ABSOLUTE) | + (1 << XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE_BPC))); } static void @@ -554,9 +559,10 @@ color_manager_fini(struct color_manager *cm) wl_list_for_each_safe(image_descr, tmp, &cm->image_descr_list, link) image_description_destroy(image_descr); - xx_color_management_output_v2_destroy(cm->output); - xx_color_management_surface_v2_destroy(cm->surface); - xx_color_manager_v2_destroy(cm->manager); + xx_color_management_output_v4_destroy(cm->output); + xx_color_management_surface_v4_destroy(cm->surface); + xx_color_management_feedback_surface_v4_destroy(cm->feedback_surface); + xx_color_manager_v4_destroy(cm->manager); } static struct image_description * @@ -565,9 +571,9 @@ get_output_image_description(struct color_manager *cm) struct image_description *image_descr = image_description_create(); image_descr->xx_image_descr = - xx_color_management_output_v2_get_image_description(cm->output); + xx_color_management_output_v4_get_image_description(cm->output); - xx_image_description_v2_add_listener(image_descr->xx_image_descr, + xx_image_description_v4_add_listener(image_descr->xx_image_descr, &image_descr_iface, image_descr); wl_list_insert(&cm->image_descr_list, &image_descr->link); @@ -581,9 +587,9 @@ get_surface_preferred_image_description(struct color_manager *cm) struct image_description *image_descr = image_description_create(); image_descr->xx_image_descr = - xx_color_management_surface_v2_get_preferred(cm->surface); + xx_color_management_feedback_surface_v4_get_preferred(cm->feedback_surface); - xx_image_description_v2_add_listener(image_descr->xx_image_descr, + xx_image_description_v4_add_listener(image_descr->xx_image_descr, &image_descr_iface, image_descr); wl_list_insert(&cm->image_descr_list, &image_descr->link); @@ -593,7 +599,7 @@ get_surface_preferred_image_description(struct color_manager *cm) static struct image_description * create_icc_based_image_description(struct color_manager *cm, - struct xx_image_description_creator_icc_v2 *image_descr_creator_icc, + struct xx_image_description_creator_icc_v4 *image_descr_creator_icc, const char *icc_path) { struct image_description *image_descr = image_description_create(); @@ -605,12 +611,12 @@ create_icc_based_image_description(struct color_manager *cm, assert(fstat(icc_fd, &st) == 0); - xx_image_description_creator_icc_v2_set_icc_file(image_descr_creator_icc, + xx_image_description_creator_icc_v4_set_icc_file(image_descr_creator_icc, icc_fd, 0, st.st_size); image_descr->xx_image_descr = - xx_image_description_creator_icc_v2_create(image_descr_creator_icc); + xx_image_description_creator_icc_v4_create(image_descr_creator_icc); - xx_image_description_v2_add_listener(image_descr->xx_image_descr, + xx_image_description_v4_add_listener(image_descr->xx_image_descr, &image_descr_iface, image_descr); wl_list_insert(&cm->image_descr_list, &image_descr->link); @@ -684,7 +690,7 @@ TEST(smoke_test) static void image_descr_info_destroy(struct image_description_info *image_descr_info) { - xx_image_description_info_v2_destroy(image_descr_info->xx_image_description_info); + xx_image_description_info_v4_destroy(image_descr_info->xx_image_description_info); free(image_descr_info); } @@ -698,9 +704,9 @@ image_descr_get_information(struct image_description *image_descr) image_descr_info->image_descr = image_descr; image_descr_info->xx_image_description_info = - xx_image_description_v2_get_information(image_descr->xx_image_descr); + xx_image_description_v4_get_information(image_descr->xx_image_descr); - xx_image_description_info_v2_add_listener(image_descr_info->xx_image_description_info, + xx_image_description_info_v4_add_listener(image_descr_info->xx_image_description_info, &image_descr_info_iface, image_descr_info); @@ -767,17 +773,17 @@ TEST(create_parametric_image_description_creator_object) { struct client *client; struct color_manager cm; - struct xx_image_description_creator_params_v2 *param_creator; + struct xx_image_description_creator_params_v4 *param_creator; client = create_client_and_test_surface(100, 100, 100, 100); color_manager_init(&cm, client); /* Parametric image description creator is still unsupported */ - param_creator = xx_color_manager_v2_new_parametric_creator(cm.manager); - expect_protocol_error(client, &xx_color_manager_v2_interface, - XX_COLOR_MANAGER_V2_ERROR_UNSUPPORTED_FEATURE); + param_creator = xx_color_manager_v4_new_parametric_creator(cm.manager); + expect_protocol_error(client, &xx_color_manager_v4_interface, + XX_COLOR_MANAGER_V4_ERROR_UNSUPPORTED_FEATURE); - xx_image_description_creator_params_v2_destroy(param_creator); + xx_image_description_creator_params_v4_destroy(param_creator); color_manager_fini(&cm); client_destroy(client); } @@ -786,14 +792,14 @@ TEST(create_image_description_before_setting_icc_file) { struct client *client; struct color_manager cm; - struct xx_image_description_creator_icc_v2 *image_descr_creator_icc; - struct xx_image_description_v2 *image_desc; + struct xx_image_description_creator_icc_v4 *image_descr_creator_icc; + struct xx_image_description_v4 *image_desc; client = create_client_and_test_surface(100, 100, 100, 100); color_manager_init(&cm, client); image_descr_creator_icc = - xx_color_manager_v2_new_icc_creator(cm.manager); + xx_color_manager_v4_new_icc_creator(cm.manager); /* Try creating image description based on ICC profile but without * setting the ICC file, what should fail. @@ -801,11 +807,11 @@ TEST(create_image_description_before_setting_icc_file) * We expect a protocol error from unknown object, because the * image_descr_creator_icc wl_proxy will get destroyed with the create * call below. It is a destructor request. */ - image_desc = xx_image_description_creator_icc_v2_create(image_descr_creator_icc); + image_desc = xx_image_description_creator_icc_v4_create(image_descr_creator_icc); expect_protocol_error(client, NULL, - XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_INCOMPLETE_SET); + XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_INCOMPLETE_SET); - xx_image_description_v2_destroy(image_desc); + xx_image_description_v4_destroy(image_desc); color_manager_fini(&cm); client_destroy(client); } @@ -814,7 +820,7 @@ TEST(set_unreadable_icc_fd) { struct client *client; struct color_manager cm; - struct xx_image_description_creator_icc_v2 *image_descr_creator_icc; + struct xx_image_description_creator_icc_v4 *image_descr_creator_icc; int32_t icc_fd; struct stat st; @@ -822,7 +828,7 @@ TEST(set_unreadable_icc_fd) color_manager_init(&cm, client); image_descr_creator_icc = - xx_color_manager_v2_new_icc_creator(cm.manager); + xx_color_manager_v4_new_icc_creator(cm.manager); /* The file is being open with WRITE, not READ permission. So the * compositor should complain. */ @@ -831,13 +837,13 @@ TEST(set_unreadable_icc_fd) assert(fstat(icc_fd, &st) == 0); /* Try setting the bad ICC file fd, it should fail. */ - xx_image_description_creator_icc_v2_set_icc_file(image_descr_creator_icc, + xx_image_description_creator_icc_v4_set_icc_file(image_descr_creator_icc, icc_fd, 0, st.st_size); - expect_protocol_error(client, &xx_image_description_creator_icc_v2_interface, - XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_BAD_FD); + expect_protocol_error(client, &xx_image_description_creator_icc_v4_interface, + XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_BAD_FD); close(icc_fd); - xx_image_description_creator_icc_v2_destroy(image_descr_creator_icc); + xx_image_description_creator_icc_v4_destroy(image_descr_creator_icc); color_manager_fini(&cm); client_destroy(client); } @@ -846,26 +852,26 @@ TEST(set_bad_icc_size_zero) { struct client *client; struct color_manager cm; - struct xx_image_description_creator_icc_v2 *image_descr_creator_icc; + struct xx_image_description_creator_icc_v4 *image_descr_creator_icc; int32_t icc_fd; client = create_client_and_test_surface(100, 100, 100, 100); color_manager_init(&cm, client); image_descr_creator_icc = - xx_color_manager_v2_new_icc_creator(cm.manager); + xx_color_manager_v4_new_icc_creator(cm.manager); icc_fd = open(srgb_icc_profile_path, O_RDONLY); assert(icc_fd >= 0); /* Try setting ICC file with a bad size, it should fail. */ - xx_image_description_creator_icc_v2_set_icc_file(image_descr_creator_icc, + xx_image_description_creator_icc_v4_set_icc_file(image_descr_creator_icc, icc_fd, 0, 0); - expect_protocol_error(client, &xx_image_description_creator_icc_v2_interface, - XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_BAD_SIZE); + expect_protocol_error(client, &xx_image_description_creator_icc_v4_interface, + XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_BAD_SIZE); close(icc_fd); - xx_image_description_creator_icc_v2_destroy(image_descr_creator_icc); + xx_image_description_creator_icc_v4_destroy(image_descr_creator_icc); color_manager_fini(&cm); client_destroy(client); } @@ -874,28 +880,28 @@ TEST(set_bad_icc_non_seekable) { struct client *client; struct color_manager cm; - struct xx_image_description_creator_icc_v2 *image_descr_creator_icc; + struct xx_image_description_creator_icc_v4 *image_descr_creator_icc; int32_t fds[2]; client = create_client_and_test_surface(100, 100, 100, 100); color_manager_init(&cm, client); image_descr_creator_icc = - xx_color_manager_v2_new_icc_creator(cm.manager); + xx_color_manager_v4_new_icc_creator(cm.manager); /* We need a non-seekable file, and pipes are non-seekable. */ assert(pipe(fds) >= 0); /* Pretend that it has a valid size of 1024 bytes. That still should * fail because the fd is non-seekable. */ - xx_image_description_creator_icc_v2_set_icc_file(image_descr_creator_icc, + xx_image_description_creator_icc_v4_set_icc_file(image_descr_creator_icc, fds[0], 0, 1024); - expect_protocol_error(client, &xx_image_description_creator_icc_v2_interface, - XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_BAD_FD); + expect_protocol_error(client, &xx_image_description_creator_icc_v4_interface, + XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_BAD_FD); close(fds[0]); close(fds[1]); - xx_image_description_creator_icc_v2_destroy(image_descr_creator_icc); + xx_image_description_creator_icc_v4_destroy(image_descr_creator_icc); color_manager_fini(&cm); client_destroy(client); } @@ -904,7 +910,7 @@ TEST(set_icc_twice) { struct client *client; struct color_manager cm; - struct xx_image_description_creator_icc_v2 *image_descr_creator_icc; + struct xx_image_description_creator_icc_v4 *image_descr_creator_icc; int32_t icc_fd; struct stat st; @@ -912,24 +918,24 @@ TEST(set_icc_twice) color_manager_init(&cm, client); image_descr_creator_icc = - xx_color_manager_v2_new_icc_creator(cm.manager); + xx_color_manager_v4_new_icc_creator(cm.manager); icc_fd = open(srgb_icc_profile_path, O_RDONLY); assert(icc_fd >= 0); assert(fstat(icc_fd, &st) == 0); - xx_image_description_creator_icc_v2_set_icc_file(image_descr_creator_icc, + xx_image_description_creator_icc_v4_set_icc_file(image_descr_creator_icc, icc_fd, 0, st.st_size); client_roundtrip(client); /* Set the ICC again, what should fail. */ - xx_image_description_creator_icc_v2_set_icc_file(image_descr_creator_icc, + xx_image_description_creator_icc_v4_set_icc_file(image_descr_creator_icc, icc_fd, 0, st.st_size); - expect_protocol_error(client, &xx_image_description_creator_icc_v2_interface, - XX_IMAGE_DESCRIPTION_CREATOR_ICC_V2_ERROR_ALREADY_SET); + expect_protocol_error(client, &xx_image_description_creator_icc_v4_interface, + XX_IMAGE_DESCRIPTION_CREATOR_ICC_V4_ERROR_ALREADY_SET); close(icc_fd); - xx_image_description_creator_icc_v2_destroy(image_descr_creator_icc); + xx_image_description_creator_icc_v4_destroy(image_descr_creator_icc); color_manager_fini(&cm); client_destroy(client); } @@ -938,7 +944,7 @@ TEST(create_icc_image_description_no_info) { struct client *client; struct color_manager cm; - struct xx_image_description_creator_icc_v2 *image_descr_creator_icc; + struct xx_image_description_creator_icc_v4 *image_descr_creator_icc; struct image_description *image_descr; struct image_description_info *image_descr_info; @@ -946,7 +952,7 @@ TEST(create_icc_image_description_no_info) color_manager_init(&cm, client); image_descr_creator_icc = - xx_color_manager_v2_new_icc_creator(cm.manager); + xx_color_manager_v4_new_icc_creator(cm.manager); /* Create image description based on ICC profile */ image_descr = create_icc_based_image_description(&cm, image_descr_creator_icc, @@ -956,8 +962,8 @@ TEST(create_icc_image_description_no_info) /* Get image description information, and that should fail. Images * descriptions that we create do not accept this request. */ image_descr_info = image_descr_get_information(image_descr); - expect_protocol_error(client, &xx_image_description_v2_interface, - XX_IMAGE_DESCRIPTION_V2_ERROR_NO_INFORMATION); + expect_protocol_error(client, &xx_image_description_v4_interface, + XX_IMAGE_DESCRIPTION_V4_ERROR_NO_INFORMATION); image_descr_info_destroy(image_descr_info); color_manager_fini(&cm); @@ -968,14 +974,14 @@ TEST(set_surface_image_description) { struct client *client; struct color_manager cm; - struct xx_image_description_creator_icc_v2 *image_descr_creator_icc; + struct xx_image_description_creator_icc_v4 *image_descr_creator_icc; struct image_description *image_descr; client = create_client_and_test_surface(100, 100, 100, 100); color_manager_init(&cm, client); image_descr_creator_icc = - xx_color_manager_v2_new_icc_creator(cm.manager); + xx_color_manager_v4_new_icc_creator(cm.manager); /* Create image description based on ICC profile */ image_descr = create_icc_based_image_description(&cm, image_descr_creator_icc, @@ -983,9 +989,9 @@ TEST(set_surface_image_description) wait_until_image_description_ready(client, image_descr); /* Set surface image description */ - xx_color_management_surface_v2_set_image_description(cm.surface, + xx_color_management_surface_v4_set_image_description(cm.surface, image_descr->xx_image_descr, - XX_COLOR_MANAGER_V2_RENDER_INTENT_PERCEPTUAL); + XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL); client_roundtrip(client); color_manager_fini(&cm);