color-management-v1: add struct wlr_image_description_v1

This commit is contained in:
Simon Ser 2025-01-22 20:45:35 +01:00
parent 0ab3c1d060
commit 6d4737a7f6
2 changed files with 110 additions and 17 deletions

View file

@ -13,6 +13,13 @@
#include "color-management-v1-protocol.h"
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
uint32_t max_cll, max_fall; // cd/m², zero if unset
};
struct wlr_color_manager_v1_features {
bool icc_v2_v4;
bool parametric;
@ -54,6 +61,8 @@ struct wlr_color_manager_v1 {
struct wl_list outputs; // wlr_color_management_output_v1.link
uint32_t last_image_desc_identity;
struct wl_listener display_destroy;
} WLR_PRIVATE;
};

View file

@ -13,6 +13,7 @@
struct wlr_color_management_output_v1 {
struct wl_resource *resource;
struct wlr_output *output;
struct wlr_color_manager_v1 *manager;
struct wl_list link;
struct wl_listener output_destroy;
@ -29,10 +30,16 @@ struct wlr_color_management_surface_v1 {
struct wlr_color_management_surface_feedback_v1 {
struct wl_resource *resource;
struct wlr_surface *surface;
struct wlr_color_manager_v1 *manager;
struct wl_listener surface_destroy;
};
struct wlr_image_description_v1 {
struct wl_resource *resource;
struct wlr_image_description_v1_data data; // immutable
};
static void resource_handle_destroy(struct wl_client *client, struct wl_resource *resource) {
wl_resource_destroy(resource);
}
@ -65,8 +72,23 @@ static int32_t encode_cie1931_coord(float value) {
return round(value * 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) {
assert(wl_resource_instance_of(resource, &wp_image_description_v1_interface, &image_desc_impl));
return wl_resource_get_user_data(resource);
}
static void image_desc_handle_get_information(struct wl_client *client,
struct wl_resource *image_desc_resource, uint32_t id) {
struct wlr_image_description_v1 *image_desc = image_desc_from_resource(image_desc_resource);
if (image_desc == NULL) {
wl_resource_post_error(image_desc_resource,
WP_IMAGE_DESCRIPTION_V1_ERROR_NOT_READY,
"image description is in failed state");
return;
}
uint32_t version = wl_resource_get_version(image_desc_resource);
struct wl_resource *resource = wl_resource_create(client,
&wp_image_description_info_v1_interface, version, id);
@ -75,24 +97,19 @@ static void image_desc_handle_get_information(struct wl_client *client,
return;
}
enum wp_color_manager_v1_primaries primaries_named =
WP_COLOR_MANAGER_V1_PRIMARIES_SRGB;
enum wp_color_manager_v1_transfer_function transfer_function =
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB;
struct wlr_color_primaries primaries;
wlr_color_primaries_from_named(&primaries, named_primaries_to_wlr(primaries_named));
wlr_color_primaries_from_named(&primaries, named_primaries_to_wlr(image_desc->data.primaries_named));
struct wlr_color_luminances luminances;
wlr_color_transfer_function_get_default_luminance(transfer_function_to_wlr(transfer_function), &luminances);
wlr_color_transfer_function_get_default_luminance(transfer_function_to_wlr(image_desc->data.tf_named), &luminances);
wp_image_description_info_v1_send_primaries_named(resource, primaries_named);
wp_image_description_info_v1_send_primaries_named(resource, image_desc->data.primaries_named);
wp_image_description_info_v1_send_primaries(resource,
encode_cie1931_coord(primaries.red.x), encode_cie1931_coord(primaries.red.y),
encode_cie1931_coord(primaries.green.x), encode_cie1931_coord(primaries.green.y),
encode_cie1931_coord(primaries.blue.x), encode_cie1931_coord(primaries.blue.y),
encode_cie1931_coord(primaries.white.x), encode_cie1931_coord(primaries.white.y));
wp_image_description_info_v1_send_tf_named(resource, transfer_function);
wp_image_description_info_v1_send_tf_named(resource, image_desc->data.tf_named);
wp_image_description_info_v1_send_luminances(resource,
round(luminances.min * 10000), round(luminances.max),
round(luminances.reference));
@ -115,18 +132,54 @@ static const struct wp_image_description_v1_interface image_desc_impl = {
.get_information = image_desc_handle_get_information,
};
static void image_desc_create_ready(struct wl_resource *parent_resource, uint32_t id) {
static void image_desc_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_image_description_v1 *image_desc = image_desc_from_resource(resource);
free(image_desc);
}
static struct wl_resource *image_desc_create_resource(
struct wl_resource *parent_resource, uint32_t id) {
struct wl_client *client = wl_resource_get_client(parent_resource);
uint32_t version = wl_resource_get_version(parent_resource);
struct wl_resource *resource = wl_resource_create(client,
&wp_image_description_v1_interface, version, id);
if (!resource) {
wl_client_post_no_memory(client);
return wl_resource_create(client, &wp_image_description_v1_interface,
version, id);
}
static void image_desc_create_ready(struct wlr_color_manager_v1 *manager,
struct wl_resource *parent_resource, uint32_t id,
const struct wlr_image_description_v1_data *data) {
struct wlr_image_description_v1 *image_desc = calloc(1, sizeof(*image_desc));
if (image_desc == NULL) {
wl_resource_post_no_memory(parent_resource);
return;
}
image_desc->data = *data;
image_desc->resource = image_desc_create_resource(parent_resource, id);
if (!image_desc->resource) {
wl_resource_post_no_memory(parent_resource);
free(image_desc);
return;
}
wl_resource_set_implementation(image_desc->resource, &image_desc_impl,
image_desc, image_desc_handle_resource_destroy);
// TODO: de-duplicate identity
uint32_t identity = ++manager->last_image_desc_identity;
wp_image_description_v1_send_ready(image_desc->resource, identity);
}
static void image_desc_create_failed(struct wl_resource *parent_resource, uint32_t id,
enum wp_image_description_v1_cause cause, const char *msg) {
struct wl_resource *resource = image_desc_create_resource(parent_resource, id);
if (resource == NULL) {
wl_resource_post_no_memory(parent_resource);
return;
}
wl_resource_set_implementation(resource, &image_desc_impl, NULL, NULL);
wp_image_description_v1_send_ready(resource, 1);
wp_image_description_v1_send_failed(resource, cause, msg);
}
static const struct wp_color_management_output_v1_interface cm_output_impl;
@ -138,7 +191,19 @@ static struct wlr_color_management_output_v1 *cm_output_from_resource(struct wl_
static void cm_output_handle_get_image_description(struct wl_client *client,
struct wl_resource *cm_output_resource, uint32_t id) {
image_desc_create_ready(cm_output_resource, id);
struct wlr_color_management_output_v1 *cm_output = cm_output_from_resource(cm_output_resource);
if (cm_output == NULL) {
image_desc_create_failed(cm_output_resource, id,
WP_IMAGE_DESCRIPTION_V1_CAUSE_NO_OUTPUT,
"output has been destroyed");
return;
}
struct wlr_image_description_v1_data data = {
.tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB,
.primaries_named = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB,
};
image_desc_create_ready(cm_output->manager, cm_output_resource, id, &data);
}
static const struct wp_color_management_output_v1_interface cm_output_impl = {
@ -254,7 +319,21 @@ static struct wlr_color_management_surface_feedback_v1 *surface_feedback_from_re
static void surface_feedback_handle_get_preferred(struct wl_client *client,
struct wl_resource *surface_feedback_resource, uint32_t id) {
image_desc_create_ready(surface_feedback_resource, id);
struct wlr_color_management_surface_feedback_v1 *surface_feedback =
surface_feedback_from_resource(surface_feedback_resource);
if (surface_feedback == NULL) {
wl_resource_post_error(surface_feedback_resource,
WP_COLOR_MANAGEMENT_SURFACE_FEEDBACK_V1_ERROR_INERT,
"get_preferred sent on inert feedback surface");
return;
}
struct wlr_image_description_v1_data data = {
.tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB,
.primaries_named = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB,
};
image_desc_create_ready(surface_feedback->manager,
surface_feedback_resource, id, &data);
}
static const struct wp_color_management_surface_feedback_v1_interface surface_feedback_impl = {
@ -302,6 +381,8 @@ static void manager_handle_get_output(struct wl_client *client,
return;
}
cm_output->manager = manager;
uint32_t version = wl_resource_get_version(manager_resource);
cm_output->resource = wl_resource_create(client,
&wp_color_management_output_v1_interface, version, id);
@ -357,6 +438,7 @@ static void manager_handle_get_surface(struct wl_client *client,
static void manager_handle_get_surface_feedback(struct wl_client *client,
struct wl_resource *manager_resource, uint32_t id,
struct wl_resource *surface_resource) {
struct wlr_color_manager_v1 *manager = manager_from_resource(manager_resource);
struct wlr_surface *surface = wlr_surface_from_resource(surface_resource);
struct wlr_color_management_surface_feedback_v1 *surface_feedback =
@ -366,6 +448,8 @@ static void manager_handle_get_surface_feedback(struct wl_client *client,
return;
}
surface_feedback->manager = manager;
uint32_t version = wl_resource_get_version(manager_resource);
surface_feedback->resource = wl_resource_create(client,
&wp_color_management_surface_feedback_v1_interface, version, id);