From 8556059785de127945b7902ace67a96f4dd808f9 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Wed, 20 Sep 2023 13:11:30 +0300 Subject: [PATCH] backend-drm: set connector property "Colorspace" Based on what is configured in weston_output, check and set the colorimetry mode into KMS connector property "Colorspace". This changes how video sinks interpret the pixels, and should allow driving e.g. WCG monitors in BT.2020 mode. This does not alter the pixel values themselves. That is the color manager responsibility, and ultimately the responsibility of the frontend and the end user to match the monitor driving mode with the output color profile they chose. Signed-off-by: Pekka Paalanen --- libweston/backend-drm/drm-internal.h | 4 ++++ libweston/backend-drm/drm.c | 4 ++++ libweston/backend-drm/kms-color.c | 17 +++++++++++++++++ libweston/backend-drm/kms.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h index 7cc55487..38e678db 100644 --- a/libweston/backend-drm/drm-internal.h +++ b/libweston/backend-drm/drm-internal.h @@ -548,6 +548,7 @@ struct drm_output { uint64_t ackd_color_outcome_serial; unsigned max_bpc; + enum wdrm_colorspace connector_colorspace; bool deprecated_gamma_is_set; bool legacy_gamma_not_supported; @@ -767,6 +768,9 @@ drm_output_set_cursor_view(struct drm_output *output, struct weston_view *ev); int drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output); +enum wdrm_colorspace +wdrm_colorspace_from_output(struct weston_output *output); + #ifdef BUILD_DRM_GBM extern struct drm_fb * drm_fb_get_from_paint_node(struct drm_output_state *state, diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index f8be3734..62f73d00 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -2259,6 +2259,10 @@ drm_output_enable(struct weston_output *base) output->format = b->format; } + output->connector_colorspace = wdrm_colorspace_from_output(&output->base); + if (output->connector_colorspace == WDRM_COLORSPACE__COUNT) + return -1; + ret = drm_output_attach_crtc(output); if (ret < 0) return -1; diff --git a/libweston/backend-drm/kms-color.c b/libweston/backend-drm/kms-color.c index 610b2442..fde6e3e9 100644 --- a/libweston/backend-drm/kms-color.c +++ b/libweston/backend-drm/kms-color.c @@ -176,3 +176,20 @@ drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output) return 0; } + +enum wdrm_colorspace +wdrm_colorspace_from_output(struct weston_output *output) +{ + enum weston_colorimetry_mode cmode = output->colorimetry_mode; + const struct weston_colorimetry_mode_info *cm; + + cm = weston_colorimetry_mode_info_get(cmode); + if (!(weston_output_get_supported_colorimetry_modes(output) & cmode) || + !cm || cm->wdrm == WDRM_COLORSPACE__COUNT) { + weston_log("Error: DRM output '%s' does not support colorimetry mode %s.", + output->name, weston_colorimetry_mode_to_str(cmode)); + return WDRM_COLORSPACE__COUNT; + } + + return cm->wdrm; +} diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c index 2a27cd6c..ccbfd4d9 100644 --- a/libweston/backend-drm/kms.c +++ b/libweston/backend-drm/kms.c @@ -1167,6 +1167,32 @@ drm_connector_set_content_type(struct drm_connector *connector, WDRM_CONNECTOR_CONTENT_TYPE, prop_val); } +static int +drm_connector_set_colorspace(struct drm_connector *connector, + enum wdrm_colorspace colorspace, + drmModeAtomicReq *req) +{ + const struct drm_property_info *info; + const struct drm_property_enum_info *enum_info; + + assert(colorspace >= 0); + assert(colorspace < WDRM_COLORSPACE__COUNT); + + if (!drm_connector_has_prop(connector, WDRM_CONNECTOR_COLORSPACE)) { + if (colorspace == WDRM_COLORSPACE_DEFAULT) + return 0; + + return -1; + } + + info = &connector->props[WDRM_CONNECTOR_COLORSPACE]; + enum_info = &info->enum_values[colorspace]; + assert(enum_info->valid); + + return connector_add_prop(req, connector, + WDRM_CONNECTOR_COLORSPACE, enum_info->value); +} + static int drm_output_apply_state_atomic(struct drm_output_state *state, drmModeAtomicReq *req, @@ -1276,6 +1302,8 @@ drm_output_apply_state_atomic(struct drm_output_state *state, } ret |= drm_connector_set_max_bpc(&head->connector, output, req); + ret |= drm_connector_set_colorspace(&head->connector, + output->connector_colorspace, req); } if (ret != 0) {