Merge branch 'create-windows-scrgb' into 'master'

Draft: color_management_v1: add create windows scrgb

See merge request wlroots/wlroots!5143
This commit is contained in:
Christopher Snowhill 2026-04-03 04:43:35 +00:00
commit 617f3ad033
5 changed files with 105 additions and 12 deletions

View file

@ -29,6 +29,9 @@ struct wlr_image_description_v1_data {
float min, max; // cd/m² float min, max; // cd/m²
} mastering_luminance; } mastering_luminance;
bool has_luminances;
struct wlr_color_luminances luminances; // cd/m²
uint32_t max_cll, max_fall; // cd/m², zero if unset uint32_t max_cll, max_fall; // cd/m², zero if unset
}; };
@ -94,6 +97,9 @@ void wlr_color_manager_v1_set_surface_preferred_image_description(
struct wlr_color_manager_v1 *manager, struct wlr_surface *surface, struct wlr_color_manager_v1 *manager, struct wlr_surface *surface,
const struct wlr_image_description_v1_data *data); const struct wlr_image_description_v1_data *data);
void wlr_color_manager_v1_get_luminances(const struct wlr_image_description_v1_data *img_desc,
struct wlr_color_luminances *lum);
/** /**
* Convert a protocol transfer function to enum wlr_color_transfer_function. * Convert a protocol transfer function to enum wlr_color_transfer_function.
* Aborts if there is no matching wlroots entry. * Aborts if there is no matching wlroots entry.

View file

@ -196,6 +196,9 @@ struct wlr_scene_buffer {
enum wlr_color_encoding color_encoding; enum wlr_color_encoding color_encoding;
enum wlr_color_range color_range; enum wlr_color_range color_range;
bool has_luminances;
struct wlr_color_luminances luminances;
struct { struct {
uint64_t active_outputs; uint64_t active_outputs;
struct wlr_texture *texture; struct wlr_texture *texture;
@ -570,6 +573,9 @@ void wlr_scene_buffer_set_color_encoding(struct wlr_scene_buffer *scene_buffer,
void wlr_scene_buffer_set_color_range(struct wlr_scene_buffer *scene_buffer, void wlr_scene_buffer_set_color_range(struct wlr_scene_buffer *scene_buffer,
enum wlr_color_range range); enum wlr_color_range range);
void wlr_scene_buffer_set_luminances(struct wlr_scene_buffer *scene_buffer,
const struct wlr_color_luminances *lum);
/** /**
* Calls the buffer's frame_done signal. * Calls the buffer's frame_done signal.
*/ */

View file

@ -12,6 +12,7 @@
#include <wlr/types/wlr_single_pixel_buffer_v1.h> #include <wlr/types/wlr_single_pixel_buffer_v1.h>
#include <wlr/util/transform.h> #include <wlr/util/transform.h>
#include "types/wlr_scene.h" #include "types/wlr_scene.h"
#include "render/color.h"
static double get_surface_preferred_buffer_scale(struct wlr_surface *surface) { static double get_surface_preferred_buffer_scale(struct wlr_surface *surface) {
double scale = 1; double scale = 1;
@ -278,11 +279,14 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) {
enum wlr_color_transfer_function tf = WLR_COLOR_TRANSFER_FUNCTION_GAMMA22; enum wlr_color_transfer_function tf = WLR_COLOR_TRANSFER_FUNCTION_GAMMA22;
enum wlr_color_named_primaries primaries = WLR_COLOR_NAMED_PRIMARIES_SRGB; enum wlr_color_named_primaries primaries = WLR_COLOR_NAMED_PRIMARIES_SRGB;
struct wlr_color_luminances luminances;
wlr_color_transfer_function_get_default_luminance(tf, &luminances);
const struct wlr_image_description_v1_data *img_desc = const struct wlr_image_description_v1_data *img_desc =
wlr_surface_get_image_description_v1_data(surface); wlr_surface_get_image_description_v1_data(surface);
if (img_desc != NULL) { if (img_desc != NULL) {
tf = wlr_color_manager_v1_transfer_function_to_wlr(img_desc->tf_named); tf = wlr_color_manager_v1_transfer_function_to_wlr(img_desc->tf_named);
primaries = wlr_color_manager_v1_primaries_to_wlr(img_desc->primaries_named); primaries = wlr_color_manager_v1_primaries_to_wlr(img_desc->primaries_named);
wlr_color_manager_v1_get_luminances(img_desc, &luminances);
} }
enum wlr_color_encoding color_encoding = WLR_COLOR_ENCODING_NONE; enum wlr_color_encoding color_encoding = WLR_COLOR_ENCODING_NONE;
@ -307,6 +311,7 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) {
wlr_scene_buffer_set_primaries(scene_buffer, primaries); wlr_scene_buffer_set_primaries(scene_buffer, primaries);
wlr_scene_buffer_set_color_encoding(scene_buffer, color_encoding); wlr_scene_buffer_set_color_encoding(scene_buffer, color_encoding);
wlr_scene_buffer_set_color_range(scene_buffer, color_range); wlr_scene_buffer_set_color_range(scene_buffer, color_range);
wlr_scene_buffer_set_luminances(scene_buffer, &luminances);
scene_buffer_unmark_client_buffer(scene_buffer); scene_buffer_unmark_client_buffer(scene_buffer);

View file

@ -1148,6 +1148,20 @@ void wlr_scene_buffer_set_color_range(struct wlr_scene_buffer *scene_buffer,
scene_node_update(&scene_buffer->node, NULL); scene_node_update(&scene_buffer->node, NULL);
} }
void wlr_scene_buffer_set_luminances(struct wlr_scene_buffer *scene_buffer,
const struct wlr_color_luminances *lum) {
if (scene_buffer->has_luminances &&
scene_buffer->luminances.min == lum->min &&
scene_buffer->luminances.max == lum->max &&
scene_buffer->luminances.reference == lum->reference) {
return;
}
scene_buffer->has_luminances = true;
scene_buffer->luminances = *lum;
scene_node_update(&scene_buffer->node, NULL);
}
static struct wlr_texture *scene_buffer_get_texture( static struct wlr_texture *scene_buffer_get_texture(
struct wlr_scene_buffer *scene_buffer, struct wlr_renderer *renderer) { struct wlr_scene_buffer *scene_buffer, struct wlr_renderer *renderer) {
if (scene_buffer->buffer == NULL || scene_buffer->texture != NULL) { if (scene_buffer->buffer == NULL || scene_buffer->texture != NULL) {
@ -1495,8 +1509,12 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren
} }
struct wlr_color_luminances src_lum, srgb_lum; struct wlr_color_luminances src_lum, srgb_lum;
wlr_color_transfer_function_get_default_luminance( if (scene_buffer->has_luminances) {
scene_buffer->transfer_function, &src_lum); src_lum = scene_buffer->luminances;
} else {
wlr_color_transfer_function_get_default_luminance(
scene_buffer->transfer_function, &src_lum);
}
wlr_color_transfer_function_get_default_luminance( wlr_color_transfer_function_get_default_luminance(
WLR_COLOR_TRANSFER_FUNCTION_SRGB, &srgb_lum); WLR_COLOR_TRANSFER_FUNCTION_SRGB, &srgb_lum);
float luminance_multiplier = get_luminance_multiplier(&src_lum, &srgb_lum); float luminance_multiplier = get_luminance_multiplier(&src_lum, &srgb_lum);

View file

@ -93,6 +93,7 @@ static bool img_desc_data_equal(const struct wlr_image_description_v1_data *a,
a->primaries_named != b->primaries_named || a->primaries_named != b->primaries_named ||
a->has_mastering_display_primaries != b->has_mastering_display_primaries || a->has_mastering_display_primaries != b->has_mastering_display_primaries ||
a->has_mastering_luminance != b->has_mastering_luminance || a->has_mastering_luminance != b->has_mastering_luminance ||
a->has_luminances != b->has_luminances ||
a->max_cll != b->max_cll || a->max_cll != b->max_cll ||
a->max_fall != b->max_fall) { a->max_fall != b->max_fall) {
return false; return false;
@ -106,6 +107,12 @@ static bool img_desc_data_equal(const struct wlr_image_description_v1_data *a,
a->mastering_luminance.max != b->mastering_luminance.max)) { a->mastering_luminance.max != b->mastering_luminance.max)) {
return false; return false;
} }
if (a->has_luminances &&
(a->luminances.min != b->luminances.min ||
a->luminances.max != b->luminances.max ||
a->luminances.reference != b->luminances.reference)) {
return false;
}
return true; return true;
} }
@ -146,8 +153,7 @@ static void image_desc_handle_get_information(struct wl_client *client,
wlr_color_manager_v1_primaries_to_wlr(image_desc->data.primaries_named)); wlr_color_manager_v1_primaries_to_wlr(image_desc->data.primaries_named));
struct wlr_color_luminances luminances; struct wlr_color_luminances luminances;
wlr_color_transfer_function_get_default_luminance( wlr_color_manager_v1_get_luminances(&image_desc->data, &luminances);
wlr_color_manager_v1_transfer_function_to_wlr(image_desc->data.tf_named), &luminances);
wp_image_description_info_v1_send_primaries_named(resource, image_desc->data.primaries_named); wp_image_description_info_v1_send_primaries_named(resource, image_desc->data.primaries_named);
wp_image_description_info_v1_send_primaries(resource, wp_image_description_info_v1_send_primaries(resource,
@ -608,9 +614,33 @@ static void image_desc_creator_params_handle_set_primaries(struct wl_client *cli
static void image_desc_creator_params_handle_set_luminances(struct wl_client *client, static void image_desc_creator_params_handle_set_luminances(struct wl_client *client,
struct wl_resource *params_resource, uint32_t min_lum, struct wl_resource *params_resource, uint32_t min_lum,
uint32_t max_lum, uint32_t reference_lum) { uint32_t max_lum, uint32_t reference_lum) {
wl_resource_post_error(params_resource, struct wlr_image_description_creator_params_v1 *params =
WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_UNSUPPORTED_FEATURE, image_desc_creator_params_from_resource(params_resource);
"set_luminances is not supported"); if (!params->manager->features.set_luminances) {
wl_resource_post_error(params_resource,
WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_UNSUPPORTED_FEATURE,
"set_luminances is not supported");
return;
}
if (params->data.has_luminances) {
wl_resource_post_error(params_resource,
WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET,
"luminances already set");
return;
}
params->data.has_luminances = true;
params->data.luminances.min = (float)min_lum / 10000;
params->data.luminances.max = max_lum;
params->data.luminances.reference = reference_lum;
if (params->data.luminances.max <= params->data.luminances.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_mastering_display_primaries( static void image_desc_creator_params_handle_set_mastering_display_primaries(
@ -878,9 +908,25 @@ static void manager_handle_create_parametric_creator(struct wl_client *client,
static void manager_handle_create_windows_scrgb(struct wl_client *client, static void manager_handle_create_windows_scrgb(struct wl_client *client,
struct wl_resource *manager_resource, uint32_t id) { struct wl_resource *manager_resource, uint32_t id) {
wl_resource_post_error(manager_resource, struct wlr_color_manager_v1 *manager = manager_from_resource(manager_resource);
WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, if (!manager->features.windows_scrgb) {
"get_windows_scrgb is not supported"); wl_resource_post_error(manager_resource,
WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE,
"get_windows_scrgb is not supported");
return;
}
struct wlr_image_description_v1_data data = {
.tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR,
.primaries_named = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB,
.has_luminances = true,
.luminances = (struct wlr_color_luminances){
.min = 0.02,
.max = 80,
.reference = 203,
},
};
image_desc_create_ready(manager, manager_resource, id, &data, false);
} }
static const struct wp_color_manager_v1_interface manager_impl = { static const struct wp_color_manager_v1_interface manager_impl = {
@ -972,9 +1018,7 @@ struct wlr_color_manager_v1 *wlr_color_manager_v1_create(struct wl_display *disp
assert(!options->features.icc_v2_v4); assert(!options->features.icc_v2_v4);
assert(!options->features.set_primaries); assert(!options->features.set_primaries);
assert(!options->features.set_tf_power); assert(!options->features.set_tf_power);
assert(!options->features.set_luminances);
assert(!options->features.extended_target_volume); assert(!options->features.extended_target_volume);
assert(!options->features.windows_scrgb);
struct wlr_color_manager_v1 *manager = calloc(1, sizeof(*manager)); struct wlr_color_manager_v1 *manager = calloc(1, sizeof(*manager));
if (manager == NULL) { if (manager == NULL) {
@ -1159,3 +1203,17 @@ wlr_color_manager_v1_primaries_list_from_renderer(struct wlr_renderer *renderer,
*len = sizeof(list) / sizeof(list[0]); *len = sizeof(list) / sizeof(list[0]);
return out; return out;
} }
void wlr_color_manager_v1_get_luminances(const struct wlr_image_description_v1_data *img_desc,
struct wlr_color_luminances *lum) {
if (img_desc->has_luminances) {
*lum = img_desc->luminances;
if (img_desc->tf_named == WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ) {
lum->max = lum->min + 10000;
}
return;
}
wlr_color_transfer_function_get_default_luminance(
wlr_color_manager_v1_transfer_function_to_wlr(img_desc->tf_named), lum);
}