From 1d17e4991f37feb67e63fbde67b5e02a44058f16 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Mon, 12 Jul 2021 17:30:06 +0300 Subject: [PATCH] backend-drm: check for HDR_OUTPUT_METADATA Check whether HDR_OUTPUT_METADATA property exists on a KMS connector. If yes, pretend that EDID claims support for all EOTF modes and update the head supported EOTFs mask accordingly. If not, then only SDR is possible. Parsing EDID to take monitor capabilities into account is left for later. HDR mode cannot be set without HDR_OUTPUT_METADATA. Signed-off-by: Pekka Paalanen --- libweston/backend-drm/drm-internal.h | 1 + libweston/backend-drm/drm.c | 9 +++++++ libweston/backend-drm/kms.c | 3 +++ libweston/backend-drm/modes.c | 25 ++++++++++++++++++-- libweston/color.c | 35 ++++++++++++++++++++++++++++ libweston/color.h | 3 +++ 6 files changed, 74 insertions(+), 2 deletions(-) diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h index f9d21e3b..6471357f 100644 --- a/libweston/backend-drm/drm-internal.h +++ b/libweston/backend-drm/drm-internal.h @@ -186,6 +186,7 @@ enum wdrm_connector_property { WDRM_CONNECTOR_CONTENT_PROTECTION, WDRM_CONNECTOR_HDCP_CONTENT_TYPE, WDRM_CONNECTOR_PANEL_ORIENTATION, + WDRM_CONNECTOR_HDR_OUTPUT_METADATA, WDRM_CONNECTOR__COUNT }; diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index 225d47e2..d7e91e35 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -2053,12 +2053,21 @@ drm_connector_fini(struct drm_connector *connector) static void drm_head_log_info(struct drm_head *head, const char *msg) { + char *eotf_list; + if (head->base.connected) { weston_log("DRM: head '%s' %s, connector %d is connected, " "EDID make '%s', model '%s', serial '%s'\n", head->base.name, msg, head->connector.connector_id, head->base.make, head->base.model, head->base.serial_number ?: ""); + eotf_list = weston_eotf_mask_to_str(head->base.supported_eotf_mask); + if (eotf_list) { + weston_log_continue(STAMP_SPACE + "Supported EOTF modes: %s\n", + eotf_list); + } + free(eotf_list); } else { weston_log("DRM: head '%s' %s, connector %d is disconnected.\n", head->base.name, msg, head->connector.connector_id); diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c index 780d0070..7ec274a2 100644 --- a/libweston/backend-drm/kms.c +++ b/libweston/backend-drm/kms.c @@ -143,6 +143,9 @@ const struct drm_property_info connector_props[] = { .enum_values = panel_orientation_enums, .num_enum_values = WDRM_PANEL_ORIENTATION__COUNT, }, + [WDRM_CONNECTOR_HDR_OUTPUT_METADATA] = { + .name = "HDR_OUTPUT_METADATA", + }, }; const struct drm_property_info crtc_props[] = { diff --git a/libweston/backend-drm/modes.c b/libweston/backend-drm/modes.c index a071375b..1c9d1068 100644 --- a/libweston/backend-drm/modes.c +++ b/libweston/backend-drm/modes.c @@ -304,6 +304,8 @@ edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length) * \param[out] make The monitor make (PNP ID). * \param[out] model The monitor model (name). * \param[out] serial_number The monitor serial number. + * \param[out] eotf_mask The monitor supported EOTF modes, combination of + * enum weston_eotf_mode bits. * * Each of \c *make, \c *model and \c *serial_number are set only if the * information is found in the EDID. The pointers they are set to must not @@ -315,7 +317,8 @@ find_and_parse_output_edid(struct drm_head *head, drmModeObjectPropertiesPtr props, const char **make, const char **model, - const char **serial_number) + const char **serial_number, + uint32_t *eotf_mask) { drmModePropertyBlobPtr edid_blob = NULL; uint32_t blob_id; @@ -344,6 +347,21 @@ find_and_parse_output_edid(struct drm_head *head, *serial_number = head->edid.serial_number; } drmModeFreePropertyBlob(edid_blob); + + /* TODO: parse this from EDID */ + *eotf_mask = WESTON_EOTF_MODE_ALL_MASK; +} + +static void +prune_eotf_modes_by_kms_support(struct drm_head *head, uint32_t *eotf_mask) +{ + const struct drm_property_info *info; + + /* Without the KMS property, cannot do anything but SDR. */ + + info = &head->connector.props[WDRM_CONNECTOR_HDR_OUTPUT_METADATA]; + if (info->prop_id == 0) + *eotf_mask = WESTON_EOTF_MODE_SDR; } static uint32_t @@ -515,9 +533,12 @@ update_head_from_connector(struct drm_head *head) const char *make = "unknown"; const char *model = "unknown"; const char *serial_number = "unknown"; + uint32_t eotf_mask = WESTON_EOTF_MODE_SDR; - find_and_parse_output_edid(head, props, &make, &model, &serial_number); + find_and_parse_output_edid(head, props, &make, &model, &serial_number, &eotf_mask); weston_head_set_monitor_strings(&head->base, make, model, serial_number); + prune_eotf_modes_by_kms_support(head, &eotf_mask); + weston_head_set_supported_eotf_mask(&head->base, eotf_mask); weston_head_set_non_desktop(&head->base, check_non_desktop(connector, props)); weston_head_set_subpixel(&head->base, diff --git a/libweston/color.c b/libweston/color.c index c2605fd7..27991901 100644 --- a/libweston/color.c +++ b/libweston/color.c @@ -314,3 +314,38 @@ weston_eotf_mode_to_str(enum weston_eotf_mode e) } return "???"; } + +/** A list of EOTF modes as a string + * + * \param eotf_mask Bitwise-or'd enum weston_eotf_mode values. + * \return Comma separated names of the listed EOTF modes. Must be free()'d by + * the caller. + */ +WL_EXPORT char * +weston_eotf_mask_to_str(uint32_t eotf_mask) +{ + FILE *fp; + char *str = NULL; + size_t size = 0; + unsigned i; + const char *sep = ""; + + fp = open_memstream(&str, &size); + if (!fp) + return NULL; + + for (i = 0; eotf_mask; i++) { + uint32_t bitmask = 1u << i; + + if (eotf_mask & bitmask) { + fprintf(fp, "%s%s", sep, + weston_eotf_mode_to_str(bitmask)); + sep = ", "; + } + + eotf_mask &= ~bitmask; + } + fclose(fp); + + return str; +} diff --git a/libweston/color.h b/libweston/color.h index 4db42e71..7c1335fa 100644 --- a/libweston/color.h +++ b/libweston/color.h @@ -382,4 +382,7 @@ weston_color_manager_create(struct weston_compositor *compositor); const char * weston_eotf_mode_to_str(enum weston_eotf_mode e); +char * +weston_eotf_mask_to_str(uint32_t eotf_mask); + #endif /* WESTON_COLOR_H */