diff --git a/src/drm.cpp b/src/drm.cpp index 19070d6..7ff7185 100644 --- a/src/drm.cpp +++ b/src/drm.cpp @@ -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 ) diff --git a/src/drm.hpp b/src/drm.hpp index 2c56b13..ff8f283 100644 --- a/src/drm.hpp +++ b/src/drm.hpp @@ -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 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 diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index cdbc4a0..86cdba8 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -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(); }