drm: Hook up Colorspace and HDR_OUTPUT_METADATA

This commit is contained in:
Joshua Ashton 2022-12-18 10:03:42 +00:00 committed by Joshie
parent b5bb169889
commit 70b74e73be
3 changed files with 106 additions and 15 deletions

View file

@ -350,23 +350,25 @@ drm_hdr_parse_edid(drm_t *drm, struct connector *connector, drmModePropertyBlobR
}
}
struct hdr_metadata_infoframe *infoframe = &metadata->defaultHdrMetadata.hdmi_metadata_type1;
if (chroma) {
metadata->defaultHdrMetadata.display_primaries[0].x = color_xy_to_u16(chroma->red_x);
metadata->defaultHdrMetadata.display_primaries[0].y = color_xy_to_u16(chroma->red_y);
metadata->defaultHdrMetadata.display_primaries[1].x = color_xy_to_u16(chroma->green_x);
metadata->defaultHdrMetadata.display_primaries[1].y = color_xy_to_u16(chroma->green_y);
metadata->defaultHdrMetadata.display_primaries[2].x = color_xy_to_u16(chroma->blue_x);
metadata->defaultHdrMetadata.display_primaries[2].y = color_xy_to_u16(chroma->blue_y);
metadata->defaultHdrMetadata.white_point.x = color_xy_to_u16(chroma->white_x);
metadata->defaultHdrMetadata.white_point.y = color_xy_to_u16(chroma->white_y);
infoframe->display_primaries[0].x = color_xy_to_u16(chroma->red_x);
infoframe->display_primaries[0].y = color_xy_to_u16(chroma->red_y);
infoframe->display_primaries[1].x = color_xy_to_u16(chroma->green_x);
infoframe->display_primaries[1].y = color_xy_to_u16(chroma->green_y);
infoframe->display_primaries[2].x = color_xy_to_u16(chroma->blue_x);
infoframe->display_primaries[2].y = color_xy_to_u16(chroma->blue_y);
infoframe->white_point.x = color_xy_to_u16(chroma->white_x);
infoframe->white_point.y = color_xy_to_u16(chroma->white_y);
}
if (hdr_static_metadata) {
metadata->defaultHdrMetadata.max_display_mastering_luminance = nits_to_u16(hdr_static_metadata->desired_content_max_luminance);
metadata->defaultHdrMetadata.min_display_mastering_luminance = nits_to_u16_dark(hdr_static_metadata->desired_content_min_luminance);
infoframe->max_display_mastering_luminance = nits_to_u16(hdr_static_metadata->desired_content_max_luminance);
infoframe->min_display_mastering_luminance = nits_to_u16_dark(hdr_static_metadata->desired_content_min_luminance);
/* To be filled in by the app based on the scene, default to desired_content_max_luminance. */
metadata->defaultHdrMetadata.max_cll = nits_to_u16(hdr_static_metadata->desired_content_max_luminance);
metadata->defaultHdrMetadata.max_fall = nits_to_u16(hdr_static_metadata->desired_content_max_frame_avg_luminance);
infoframe->max_cll = nits_to_u16(hdr_static_metadata->desired_content_max_luminance);
infoframe->max_fall = nits_to_u16(hdr_static_metadata->desired_content_max_frame_avg_luminance);
}
metadata->supportsST2084 =
@ -374,6 +376,22 @@ drm_hdr_parse_edid(drm_t *drm, struct connector *connector, drmModePropertyBlobR
colorimetry && colorimetry->bt2020_rgb &&
hdr_static_metadata && hdr_static_metadata->eotfs && hdr_static_metadata->eotfs->pq;
if (metadata->supportsST2084) {
metadata->defaultHdrMetadata.metadata_type = 0;
infoframe->metadata_type = 0;
infoframe->eotf = HDMI_EOTF_ST2084;
int ret = drmModeCreatePropertyBlob(drm->fd,
&metadata->defaultHdrMetadata,
sizeof(metadata->defaultHdrMetadata),
&metadata->hdr10_metadata_blob);
if (ret != 0) {
fprintf(stderr, "Failed to create blob for HDR_OUTPUT_METADATA. (%s) Falling back to null blob.\n", strerror(-ret));
metadata->hdr10_metadata_blob = 0;
}
}
di_info_destroy(info);
}
@ -486,6 +504,8 @@ static bool refresh_state( drm_t *drm )
free(conn->name);
conn->name = nullptr;
drmModeDestroyPropertyBlob(drm->fd, conn->metadata.hdr10_metadata_blob);
conn->metadata.hdr10_metadata_blob = 0;
drmModeFreeConnector(conn->connector);
it = drm->connectors.erase(it);
} else {
@ -498,8 +518,11 @@ static bool refresh_state( drm_t *drm )
// Re-probe connectors props and status
for (auto &kv : drm->connectors) {
struct connector *conn = &kv.second;
if (conn->connector != nullptr)
if (conn->connector != nullptr) {
drmModeDestroyPropertyBlob(drm->fd, conn->metadata.hdr10_metadata_blob);
conn->metadata.hdr10_metadata_blob = 0;
drmModeFreeConnector(conn->connector);
}
conn->connector = drmModeGetConnector(drm->fd, conn->id);
if (conn->connector == nullptr) {
@ -533,6 +556,8 @@ static bool refresh_state( drm_t *drm )
drm_log.errorf_errno("drmModeConnectorGetPossibleCrtcs failed");
conn->current.crtc_id = conn->initial_prop_values["CRTC_ID"];
conn->current.colorspace = conn->initial_prop_values["Colorspace"];
conn->current.hdr_output_metadata = conn->initial_prop_values["HDR_OUTPUT_METADATA"];
conn->target_refresh = 0;
@ -1012,6 +1037,8 @@ void finish_drm(struct drm_t *drm)
for ( auto &kv : drm->connectors ) {
struct connector *conn = &kv.second;
add_connector_property(req, conn, "CRTC_ID", 0);
add_connector_property(req, conn, "Colorspace", 0);
add_connector_property(req, conn, "HDR_OUTPUT_METADATA", 0);
}
for ( size_t i = 0; i < drm->crtcs.size(); i++ ) {
add_crtc_property(req, &drm->crtcs[i], "MODE_ID", 0);
@ -1752,6 +1779,14 @@ int drm_prepare( struct drm_t *drm, bool async, const struct FrameInfo_t *frameI
int ret = add_connector_property( drm->req, conn, "CRTC_ID", 0 );
if (ret < 0)
return ret;
ret = add_connector_property( drm->req, conn, "Colorspace", 0 );
if (ret < 0)
return ret;
ret = add_connector_property( drm->req, conn, "HDR_OUTPUT_METADATA", 0 );
if (ret < 0)
return ret;
}
for ( size_t i = 0; i < drm->crtcs.size(); i++ ) {
struct crtc *crtc = &drm->crtcs[i];
@ -1805,6 +1840,16 @@ int drm_prepare( struct drm_t *drm, bool async, const struct FrameInfo_t *frameI
if (ret < 0)
return ret;
drm->connector->pending.colorspace = g_bOutputHDREnabled ? DRM_MODE_COLORIMETRY_BT2020_RGB : DRM_MODE_COLORIMETRY_DEFAULT;
ret = add_connector_property(drm->req, drm->connector, "Colorspace", drm->connector->pending.colorspace);
if (ret < 0)
return ret;
drm->connector->pending.hdr_output_metadata = g_bOutputHDREnabled ? drm->connector->metadata.hdr10_metadata_blob : 0;
ret = add_connector_property(drm->req, drm->connector, "HDR_OUTPUT_METADATA", drm->connector->pending.hdr_output_metadata);
if (ret < 0)
return ret;
ret = add_crtc_property(drm->req, drm->crtc, "MODE_ID", drm->pending.mode_id);
if (ret < 0)
return ret;
@ -2487,6 +2532,13 @@ bool drm_supports_st2084(struct drm_t *drm)
return false;
}
void drm_set_hdr_state(struct drm_t *drm, bool enabled) {
if (drm->enable_hdr != enabled) {
drm->needs_modeset = true;
drm->enable_hdr = enabled;
}
}
const char *drm_get_connector_name(struct drm_t *drm)
{
if ( !drm->connector )

View file

@ -78,8 +78,9 @@ struct crtc {
};
struct connector_metadata_t {
struct hdr_metadata_infoframe defaultHdrMetadata;
bool supportsST2084;
struct hdr_output_metadata defaultHdrMetadata = {};
uint32_t hdr10_metadata_blob = 0;
bool supportsST2084 = false;
};
struct connector {
@ -101,6 +102,8 @@ struct connector {
struct {
uint32_t crtc_id;
uint32_t colorspace;
uint32_t hdr_output_metadata;
} current, pending;
};
@ -201,6 +204,7 @@ struct drm_t {
std::unordered_map< std::string, int > connector_priorities;
bool force_internal = false;
bool enable_hdr = false;
char *device_name = nullptr;
};
@ -271,5 +275,35 @@ const char *drm_get_connector_name(struct drm_t *drm);
const char *drm_get_device_name(struct drm_t *drm);
std::pair<uint32_t, uint32_t> drm_get_connector_identifier(struct drm_t *drm);
void drm_set_hdr_state(struct drm_t *drm, bool enabled);
extern bool g_bSupportsAsyncFlips;
/* from CTA-861-G */
#define HDMI_EOTF_SDR 0
#define HDMI_EOTF_TRADITIONAL_HDR 1
#define HDMI_EOTF_ST2084 2
#define HDMI_EOTF_HLG 3
/* For Default case, driver will set the colorspace */
#define DRM_MODE_COLORIMETRY_DEFAULT 0
/* CEA 861 Normal Colorimetry options */
#define DRM_MODE_COLORIMETRY_NO_DATA 0
#define DRM_MODE_COLORIMETRY_SMPTE_170M_YCC 1
#define DRM_MODE_COLORIMETRY_BT709_YCC 2
/* CEA 861 Extended Colorimetry Options */
#define DRM_MODE_COLORIMETRY_XVYCC_601 3
#define DRM_MODE_COLORIMETRY_XVYCC_709 4
#define DRM_MODE_COLORIMETRY_SYCC_601 5
#define DRM_MODE_COLORIMETRY_OPYCC_601 6
#define DRM_MODE_COLORIMETRY_OPRGB 7
#define DRM_MODE_COLORIMETRY_BT2020_CYCC 8
#define DRM_MODE_COLORIMETRY_BT2020_RGB 9
#define DRM_MODE_COLORIMETRY_BT2020_YCC 10
/* Additional Colorimetry extension added as part of CTA 861.G */
#define DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65 11
#define DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER 12
/* Additional Colorimetry Options added for DP 1.4a VSC Colorimetry Format */
#define DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED 13
#define DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT 14
#define DRM_MODE_COLORIMETRY_BT601_YCC 15

View file

@ -5797,6 +5797,11 @@ steamcompmgr_main(int argc, char **argv)
wlserver_unlock();
}
if (g_bOutputHDREnabled != currentHDROutput)
{
drm_set_hdr_state(&g_DRM, g_bOutputHDREnabled);
}
vulkan_remake_output_images();
}