From c217453c85aaba7a8cde7cb3ddbd8eba59d1fba9 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Thu, 22 Jul 2021 16:33:51 +0300 Subject: [PATCH] backend-drm: forward HDR metadata Forward the HDR Static Metadata Type 1 to the video sink. This makes the sink aware of our video content parameters and may be able to produce a better picture. This type of metadata is used only with the ST 2084 HDR mode a.k.a PQ. Signed-off-by: Pekka Paalanen --- libweston/backend-drm/kms-color.c | 78 ++++++++++++++++++++++++++++++- libweston/backend-drm/meson.build | 1 + 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/libweston/backend-drm/kms-color.c b/libweston/backend-drm/kms-color.c index ae479754..8219c94c 100644 --- a/libweston/backend-drm/kms-color.c +++ b/libweston/backend-drm/kms-color.c @@ -29,13 +29,86 @@ #include #include #include +#include #include "drm-internal.h" #include "libdrm-updates.h" +static inline uint16_t +color_xy_to_u16(float v) +{ + assert(v >= 0.0f); + assert(v <= 1.0f); + /* + * CTA-861-G + * 6.9.1 Static Metadata Type 1 + * chromaticity coordinate encoding + */ + return (uint16_t)round(v * 50000.0); +} + +static inline uint16_t +nits_to_u16(float nits) +{ + assert(nits >= 1.0f); + assert(nits <= 65535.0f); + /* + * CTA-861-G + * 6.9.1 Static Metadata Type 1 + * max display mastering luminance, max content light level, + * max frame-average light level + */ + return (uint16_t)round(nits); +} + +static inline uint16_t +nits_to_u16_dark(float nits) +{ + assert(nits >= 0.0001f); + assert(nits <= 6.5535f); + /* + * CTA-861-G + * 6.9.1 Static Metadata Type 1 + * min display mastering luminance + */ + return (uint16_t)round(nits * 10000.0); +} + +static void +weston_hdr_metadata_type1_to_kms(struct hdr_metadata_infoframe *dst, + const struct weston_hdr_metadata_type1 *src) +{ + if (src->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_PRIMARIES) { + unsigned i; + + for (i = 0; i < 3; i++) { + dst->display_primaries[i].x = color_xy_to_u16(src->primary[i].x); + dst->display_primaries[i].y = color_xy_to_u16(src->primary[i].y); + } + } + + if (src->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_WHITE) { + dst->white_point.x = color_xy_to_u16(src->white.x); + dst->white_point.y = color_xy_to_u16(src->white.y); + } + + if (src->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MAXDML) + dst->max_display_mastering_luminance = nits_to_u16(src->maxDML); + + if (src->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MINDML) + dst->min_display_mastering_luminance = nits_to_u16_dark(src->minDML); + + if (src->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MAXCLL) + dst->max_cll = nits_to_u16(src->maxCLL); + + if (src->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MAXFALL) + dst->max_fall = nits_to_u16(src->maxFALL); +} + int drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output) { + const struct weston_hdr_metadata_type1 *src; struct hdr_output_metadata meta; uint32_t blob_id = 0; int ret; @@ -43,6 +116,8 @@ drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output) if (output->hdr_output_metadata_blob_id) return 0; + src = weston_output_get_hdr_metadata_type1(&output->base); + /* * Set up the data for Dynamic Range and Mastering InfoFrame, * CTA-861-G, a.k.a the static HDR metadata. @@ -72,6 +147,7 @@ drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output) break; case WESTON_EOTF_MODE_ST2084: meta.hdmi_metadata_type1.eotf = 2; /* from CTA-861-G */ + weston_hdr_metadata_type1_to_kms(&meta.hdmi_metadata_type1, src); break; case WESTON_EOTF_MODE_HLG: meta.hdmi_metadata_type1.eotf = 3; /* from CTA-861-G */ @@ -83,8 +159,6 @@ drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output) return -1; } - /* The other fields are intentionally left as zeroes. */ - ret = drmModeCreatePropertyBlob(output->backend->drm.fd, &meta, sizeof meta, &blob_id); if (ret != 0) { diff --git a/libweston/backend-drm/meson.build b/libweston/backend-drm/meson.build index e913f4b9..cb2ebda0 100644 --- a/libweston/backend-drm/meson.build +++ b/libweston/backend-drm/meson.build @@ -38,6 +38,7 @@ srcs_drm = [ ] deps_drm = [ + dep_libm, dep_libdl, dep_libweston_private, dep_session_helper,