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:
parent
6914064066
commit
1d17e4991f
@ -186,6 +186,7 @@ enum wdrm_connector_property {
|
|||||||
WDRM_CONNECTOR_CONTENT_PROTECTION,
|
WDRM_CONNECTOR_CONTENT_PROTECTION,
|
||||||
WDRM_CONNECTOR_HDCP_CONTENT_TYPE,
|
WDRM_CONNECTOR_HDCP_CONTENT_TYPE,
|
||||||
WDRM_CONNECTOR_PANEL_ORIENTATION,
|
WDRM_CONNECTOR_PANEL_ORIENTATION,
|
||||||
|
WDRM_CONNECTOR_HDR_OUTPUT_METADATA,
|
||||||
WDRM_CONNECTOR__COUNT
|
WDRM_CONNECTOR__COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2053,12 +2053,21 @@ drm_connector_fini(struct drm_connector *connector)
|
|||||||
static void
|
static void
|
||||||
drm_head_log_info(struct drm_head *head, const char *msg)
|
drm_head_log_info(struct drm_head *head, const char *msg)
|
||||||
{
|
{
|
||||||
|
char *eotf_list;
|
||||||
|
|
||||||
if (head->base.connected) {
|
if (head->base.connected) {
|
||||||
weston_log("DRM: head '%s' %s, connector %d is connected, "
|
weston_log("DRM: head '%s' %s, connector %d is connected, "
|
||||||
"EDID make '%s', model '%s', serial '%s'\n",
|
"EDID make '%s', model '%s', serial '%s'\n",
|
||||||
head->base.name, msg, head->connector.connector_id,
|
head->base.name, msg, head->connector.connector_id,
|
||||||
head->base.make, head->base.model,
|
head->base.make, head->base.model,
|
||||||
head->base.serial_number ?: "");
|
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 {
|
} else {
|
||||||
weston_log("DRM: head '%s' %s, connector %d is disconnected.\n",
|
weston_log("DRM: head '%s' %s, connector %d is disconnected.\n",
|
||||||
head->base.name, msg, head->connector.connector_id);
|
head->base.name, msg, head->connector.connector_id);
|
||||||
|
@ -143,6 +143,9 @@ const struct drm_property_info connector_props[] = {
|
|||||||
.enum_values = panel_orientation_enums,
|
.enum_values = panel_orientation_enums,
|
||||||
.num_enum_values = WDRM_PANEL_ORIENTATION__COUNT,
|
.num_enum_values = WDRM_PANEL_ORIENTATION__COUNT,
|
||||||
},
|
},
|
||||||
|
[WDRM_CONNECTOR_HDR_OUTPUT_METADATA] = {
|
||||||
|
.name = "HDR_OUTPUT_METADATA",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct drm_property_info crtc_props[] = {
|
const struct drm_property_info crtc_props[] = {
|
||||||
|
@ -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] make The monitor make (PNP ID).
|
||||||
* \param[out] model The monitor model (name).
|
* \param[out] model The monitor model (name).
|
||||||
* \param[out] serial_number The monitor serial number.
|
* \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
|
* 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
|
* 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,
|
drmModeObjectPropertiesPtr props,
|
||||||
const char **make,
|
const char **make,
|
||||||
const char **model,
|
const char **model,
|
||||||
const char **serial_number)
|
const char **serial_number,
|
||||||
|
uint32_t *eotf_mask)
|
||||||
{
|
{
|
||||||
drmModePropertyBlobPtr edid_blob = NULL;
|
drmModePropertyBlobPtr edid_blob = NULL;
|
||||||
uint32_t blob_id;
|
uint32_t blob_id;
|
||||||
@ -344,6 +347,21 @@ find_and_parse_output_edid(struct drm_head *head,
|
|||||||
*serial_number = head->edid.serial_number;
|
*serial_number = head->edid.serial_number;
|
||||||
}
|
}
|
||||||
drmModeFreePropertyBlob(edid_blob);
|
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
|
static uint32_t
|
||||||
@ -515,9 +533,12 @@ update_head_from_connector(struct drm_head *head)
|
|||||||
const char *make = "unknown";
|
const char *make = "unknown";
|
||||||
const char *model = "unknown";
|
const char *model = "unknown";
|
||||||
const char *serial_number = "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);
|
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,
|
weston_head_set_non_desktop(&head->base,
|
||||||
check_non_desktop(connector, props));
|
check_non_desktop(connector, props));
|
||||||
weston_head_set_subpixel(&head->base,
|
weston_head_set_subpixel(&head->base,
|
||||||
|
@ -314,3 +314,38 @@ weston_eotf_mode_to_str(enum weston_eotf_mode e)
|
|||||||
}
|
}
|
||||||
return "???";
|
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;
|
||||||
|
}
|
||||||
|
@ -382,4 +382,7 @@ weston_color_manager_create(struct weston_compositor *compositor);
|
|||||||
const char *
|
const char *
|
||||||
weston_eotf_mode_to_str(enum weston_eotf_mode e);
|
weston_eotf_mode_to_str(enum weston_eotf_mode e);
|
||||||
|
|
||||||
|
char *
|
||||||
|
weston_eotf_mask_to_str(uint32_t eotf_mask);
|
||||||
|
|
||||||
#endif /* WESTON_COLOR_H */
|
#endif /* WESTON_COLOR_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user