Merge branch 'edid-color-metadata' into 'master'

Draft: output, backend/drm: add wlr_output.color_primaries

See merge request wlroots/wlroots!5096
This commit is contained in:
Simon Ser 2025-10-29 11:55:09 +00:00
commit 58a9c3b1c2
7 changed files with 60 additions and 3 deletions

View file

@ -50,6 +50,14 @@ enum wlr_output_mode_aspect_ratio get_picture_aspect_ratio(const drmModeModeInfo
}
}
static void copy_chromaticity_cie1931(struct wlr_color_cie1931_xy *dst,
const struct di_chromaticity_cie1931 *src) {
*dst = (struct wlr_color_cie1931_xy){
.x = src->x,
.y = src->y,
};
}
void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) {
struct wlr_output *output = &conn->output;
@ -83,6 +91,15 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data)
output->model = di_info_get_model(info);
output->serial = di_info_get_serial(info);
const struct di_color_primaries *primaries = di_info_get_default_color_primaries(info);
if (primaries->has_primaries && primaries->has_default_white_point) {
copy_chromaticity_cie1931(&conn->color_primaries.red, &primaries->primary[0]);
copy_chromaticity_cie1931(&conn->color_primaries.green, &primaries->primary[1]);
copy_chromaticity_cie1931(&conn->color_primaries.blue, &primaries->primary[2]);
copy_chromaticity_cie1931(&conn->color_primaries.white, &primaries->default_white);
output->color_primaries = &conn->color_primaries;
}
const struct di_supported_signal_colorimetry *colorimetry = di_info_get_supported_signal_colorimetry(info);
bool has_bt2020 = colorimetry->bt2020_cycc || colorimetry->bt2020_ycc || colorimetry->bt2020_rgb;
if (conn->props.colorspace != 0 && has_bt2020) {
@ -93,6 +110,9 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data)
if (conn->props.hdr_output_metadata != 0 && hdr_static_metadata->type1 && hdr_static_metadata->pq) {
output->supported_transfer_functions |= WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ;
}
output->min_luminance = hdr_static_metadata->desired_content_min_luminance;
output->max_luminance = hdr_static_metadata->desired_content_max_luminance;
output->max_fall = hdr_static_metadata->desired_content_max_frame_avg_luminance;
di_info_destroy(info);
}

View file

@ -195,6 +195,7 @@ struct wlr_drm_connector {
drmModeConnection status;
uint32_t id;
uint64_t max_bpc_bounds[2];
struct wlr_color_primaries color_primaries; // might be zero
struct wlr_drm_lease *lease;
struct wlr_drm_crtc *crtc;

View file

@ -426,6 +426,9 @@ struct wlr_vk_render_pass {
bool has_primaries;
struct wlr_color_primaries primaries;
bool has_luminances;
struct wlr_color_luminances luminances;
struct wlr_drm_syncobj_timeline *signal_timeline;
uint64_t signal_point;

View file

@ -37,6 +37,8 @@ struct wlr_buffer_pass_options {
struct wlr_color_transform *color_transform;
/** Primaries describing the color volume of the destination buffer */
const struct wlr_color_primaries *primaries;
/** Luminances for the destination buffer */
const struct wlr_color_luminances *luminances;
/* Signal a timeline synchronization point when the render pass completes.
*

View file

@ -197,6 +197,9 @@ struct wlr_output {
uint32_t supported_primaries; // bitfield of enum wlr_color_named_primaries
uint32_t supported_transfer_functions; // bitfield of enum wlr_color_transfer_function
const struct wlr_color_primaries *color_primaries; // NULL if unset
float min_luminance, max_luminance, max_fall; // cd/m², zero if unset
bool enabled;
float scale;
enum wl_output_subpixel subpixel;

View file

@ -254,7 +254,11 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
struct wlr_color_luminances srgb_lum, dst_lum;
wlr_color_transfer_function_get_default_luminance(
WLR_COLOR_TRANSFER_FUNCTION_SRGB, &srgb_lum);
wlr_color_transfer_function_get_default_luminance(tf, &dst_lum);
if (pass->has_luminances) {
dst_lum = pass->luminances;
} else {
wlr_color_transfer_function_get_default_luminance(tf, &dst_lum);
}
frag_pcr_data.luminance_multiplier = get_luminance_multiplier(&srgb_lum, &dst_lum);
}
bind_pipeline(pass, pipeline);
@ -1243,6 +1247,10 @@ struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *rend
pass->has_primaries = true;
pass->primaries = *options->primaries;
}
if (options != NULL && options->luminances != NULL) {
pass->has_luminances = true;
pass->luminances = *options->luminances;
}
rect_union_init(&pass->updated_region);

View file

@ -2359,12 +2359,31 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
struct wlr_color_transform *color_transform = NULL;
const struct wlr_color_primaries *primaries = NULL;
const struct wlr_color_luminances *target_luminances = NULL;
struct wlr_color_primaries primaries_value;
struct wlr_color_luminances target_luminances_value;
const struct wlr_output_image_description *img_desc = output_pending_image_description(output, state);
if (img_desc != NULL) {
color_transform = wlr_color_transform_init_linear_to_inverse_eotf(img_desc->transfer_function);
wlr_color_primaries_from_named(&primaries_value, img_desc->primaries);
primaries = &primaries_value;
struct wlr_color_primaries zero_primaries = {0};
if (memcmp(&img_desc->mastering_display_primaries, &zero_primaries, sizeof(zero_primaries)) != 0) {
primaries = &img_desc->mastering_display_primaries;
} else {
wlr_color_primaries_from_named(&primaries_value, img_desc->primaries);
primaries = &primaries_value;
}
if (img_desc->mastering_luminance.min != 0 || img_desc->mastering_luminance.max != 0) {
struct wlr_color_luminances default_lum = {0};
wlr_color_transfer_function_get_default_luminance(img_desc->transfer_function, &default_lum);
target_luminances_value = (struct wlr_color_luminances){
.min = img_desc->mastering_luminance.min,
.max = img_desc->mastering_luminance.max,
.reference = default_lum.reference, // TODO: make configurable
};
target_luminances = &target_luminances_value;
}
}
if (options->color_transform != NULL) {
assert(color_transform == NULL);
@ -2388,6 +2407,7 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
.timer = timer ? timer->render_timer : NULL,
.color_transform = color_transform,
.primaries = primaries,
.luminances = target_luminances,
.signal_timeline = scene_output->in_timeline,
.signal_point = scene_output->in_point,
});