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 <pekka.paalanen@collabora.com>
This commit is contained in:
Pekka Paalanen 2021-07-12 17:30:06 +03:00 committed by Pekka Paalanen
parent 6914064066
commit 1d17e4991f
6 changed files with 74 additions and 2 deletions

View file

@ -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
};

View file

@ -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);

View file

@ -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[] = {

View file

@ -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,

View file

@ -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;
}

View file

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