From 95c85af87c157bbc86149a9375f6933798ae0318 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 24 Jan 2025 17:31:50 +0100 Subject: [PATCH] color-management-v1: add support for mastering display metadata --- include/wlr/types/wlr_color_management_v1.h | 9 ++ types/wlr_color_management_v1.c | 93 +++++++++++++++++++-- 2 files changed, 95 insertions(+), 7 deletions(-) diff --git a/include/wlr/types/wlr_color_management_v1.h b/include/wlr/types/wlr_color_management_v1.h index 1be842eb6..68b1d317d 100644 --- a/include/wlr/types/wlr_color_management_v1.h +++ b/include/wlr/types/wlr_color_management_v1.h @@ -10,6 +10,7 @@ #define WLR_TYPES_WLR_COLOR_MANAGEMENT_V1_H #include +#include #include "color-management-v1-protocol.h" @@ -19,6 +20,14 @@ struct wlr_image_description_v1_data { uint32_t tf_named; // enum wp_color_manager_v1_transfer_function, zero if unset uint32_t primaries_named; // enum wp_color_manager_v1_primaries, zero if unset + bool has_mastering_display_primaries; + struct wlr_color_primaries mastering_display_primaries; + + bool has_mastering_luminance; + struct { + float min, max; // cd/m² + } mastering_luminance; + uint32_t max_cll, max_fall; // cd/m², zero if unset }; diff --git a/types/wlr_color_management_v1.c b/types/wlr_color_management_v1.c index d9892d3b5..5c210df26 100644 --- a/types/wlr_color_management_v1.c +++ b/types/wlr_color_management_v1.c @@ -87,6 +87,10 @@ static int32_t encode_cie1931_coord(float value) { return round(value * 1000 * 1000); } +static float decode_cie1931_coord(int32_t raw) { + return (float)raw / (1000 * 1000); +} + static const struct wp_image_description_v1_interface image_desc_impl; static struct wlr_image_description_v1 *image_desc_from_resource(struct wl_resource *resource) { @@ -404,6 +408,31 @@ image_desc_creator_params_from_resource(struct wl_resource *resource) { return wl_resource_get_user_data(resource); } +static bool check_mastering_luminance_range(struct wl_resource *params_resource, + const struct wlr_image_description_v1_data *data, + float value, const char *name) { + if (!data->has_mastering_luminance || value == 0) { + return true; + } + + if (value <= data->mastering_luminance.min) { + wl_resource_post_error(params_resource, + WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INVALID_LUMINANCE, + "%s must be greater than min L of the mastering luminance range", + name); + return false; + } + if (value > data->mastering_luminance.max) { + wl_resource_post_error(params_resource, + WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INVALID_LUMINANCE, + "%s must be less or equal to max L of the mastering luminance range", + name); + return false; + } + + return true; +} + static void image_desc_creator_params_handle_create(struct wl_client *client, struct wl_resource *params_resource, uint32_t id) { struct wlr_image_description_creator_params_v1 *params = @@ -430,6 +459,14 @@ static void image_desc_creator_params_handle_create(struct wl_client *client, return; } + if (!check_mastering_luminance_range(params_resource, ¶ms->data, params->data.max_cll, "max_cll") || + !check_mastering_luminance_range(params_resource, ¶ms->data, params->data.max_fall, "max_fall")) { + return; + } + + // TODO: check that the target color volume is contained within the + // primary color volume + image_desc_create_ready(params->manager, params_resource, id, ¶ms->data, false); } @@ -519,16 +556,59 @@ static void image_desc_creator_params_handle_set_mastering_display_primaries( struct wl_client *client, struct wl_resource *params_resource, 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) { - wl_resource_post_error(params_resource, - WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_UNSUPPORTED_FEATURE, - "set_mastering_display_primaries is not supported"); + struct wlr_image_description_creator_params_v1 *params = + image_desc_creator_params_from_resource(params_resource); + if (!params->manager->features.set_mastering_display_primaries) { + wl_resource_post_error(params_resource, + WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_UNSUPPORTED_FEATURE, + "set_mastering_display_primaries is not supported"); + return; + } + + if (params->data.has_mastering_display_primaries) { + wl_resource_post_error(params_resource, + WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, + "mastering display primaries already set"); + return; + } + + params->data.has_mastering_display_primaries = true; + params->data.mastering_display_primaries = (struct wlr_color_primaries){ + .red = { decode_cie1931_coord(r_x), decode_cie1931_coord(r_y) }, + .green = { decode_cie1931_coord(g_x), decode_cie1931_coord(g_y) }, + .blue = { decode_cie1931_coord(b_x), decode_cie1931_coord(b_y) }, + .white = { decode_cie1931_coord(w_x), decode_cie1931_coord(w_y) }, + }; } static void image_desc_creator_params_handle_set_mastering_luminance(struct wl_client *client, struct wl_resource *params_resource, uint32_t min_lum, uint32_t max_lum) { - wl_resource_post_error(params_resource, - WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_UNSUPPORTED_FEATURE, - "set_mastering_luminance is not supported"); + struct wlr_image_description_creator_params_v1 *params = + image_desc_creator_params_from_resource(params_resource); + if (!params->manager->features.set_mastering_display_primaries) { + wl_resource_post_error(params_resource, + WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_UNSUPPORTED_FEATURE, + "set_mastering_luminance is not supported"); + return; + } + + if (params->data.has_mastering_luminance) { + wl_resource_post_error(params_resource, + WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET, + "mastering luminance already set"); + return; + } + + params->data.has_mastering_luminance = true; + params->data.mastering_luminance.min = (float)min_lum / 10000; + params->data.mastering_luminance.max = max_lum; + + if (params->data.mastering_luminance.max <= params->data.mastering_luminance.min) { + wl_resource_post_error(params_resource, + WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INVALID_LUMINANCE, + "max luminance must be greater than min luminance"); + return; + } } static void image_desc_creator_params_handle_set_max_cll(struct wl_client *client, @@ -822,7 +902,6 @@ struct wlr_color_manager_v1 *wlr_color_manager_v1_create(struct wl_display *disp assert(!options->features.set_primaries); assert(!options->features.set_tf_power); assert(!options->features.set_luminances); - assert(!options->features.set_mastering_display_primaries); assert(!options->features.extended_target_volume); assert(!options->features.windows_scrgb);