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 */