From d24edc78901bf69edd346d46446b67e1ea8f2223 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Wed, 8 Nov 2023 15:52:10 +0100 Subject: [PATCH] backends/drm: ensure correct colors with direct scanout of NV12 buffers If another compositor changes the color encoding and color range properties, the resulting colors will be wrong. This commit ensures they're always set to BT.709 limited range to prevent that --- src/backends/drm/drm_pipeline.cpp | 11 ++++++++++- src/backends/drm/drm_plane.cpp | 11 +++++++++++ src/backends/drm/drm_plane.h | 11 +++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp index f6b27b99a5..7ac0407357 100644 --- a/src/backends/drm/drm_pipeline.cpp +++ b/src/backends/drm/drm_pipeline.cpp @@ -249,8 +249,17 @@ DrmPipeline::Error DrmPipeline::prepareAtomicPresentation(DrmAtomicCommit *commi if (!fb) { return Error::InvalidArguments; } - m_pending.crtc->primaryPlane()->set(commit, QPoint(0, 0), fb->buffer()->size(), centerBuffer(fb->buffer()->size(), m_pending.mode->size())); + const auto primary = m_pending.crtc->primaryPlane(); + primary->set(commit, QPoint(0, 0), fb->buffer()->size(), centerBuffer(fb->buffer()->size(), m_pending.mode->size())); commit->addBuffer(m_pending.crtc->primaryPlane(), fb); + if (fb->buffer()->dmabufAttributes()->format == DRM_FORMAT_NV12) { + if (!primary->colorEncoding.isValid() || !primary->colorRange.isValid()) { + // don't allow NV12 direct scanout if we don't know what the driver will do + return Error::InvalidArguments; + } + commit->addEnum(primary->colorEncoding, DrmPlane::ColorEncoding::BT701_YCbCr); + commit->addEnum(primary->colorRange, DrmPlane::ColorRange::Limited_YCbCr); + } return Error::None; } diff --git a/src/backends/drm/drm_plane.cpp b/src/backends/drm/drm_plane.cpp index 1610121bca..6cc31c4ce8 100644 --- a/src/backends/drm/drm_plane.cpp +++ b/src/backends/drm/drm_plane.cpp @@ -54,6 +54,15 @@ DrmPlane::DrmPlane(DrmGpu *gpu, uint32_t planeId) QByteArrayLiteral("Pre-multiplied"), QByteArrayLiteral("Coverage"), }) + , colorEncoding(this, QByteArrayLiteral("COLOR_ENCODING"), { + QByteArrayLiteral("ITU-R BT.601 YCbCr"), + QByteArrayLiteral("ITU-R BT.709 YCbCr"), + QByteArrayLiteral("ITU-R BT.2020 YCbCr"), + }) + , colorRange(this, QByteArrayLiteral("COLOR_RANGE"), { + QByteArrayLiteral("YCbCr limited range"), + QByteArrayLiteral("YCbCr full range"), + }) { } @@ -80,6 +89,8 @@ bool DrmPlane::updateProperties() inFormats.update(props); alpha.update(props); pixelBlendMode.update(props); + colorEncoding.update(props); + colorRange.update(props); if (!type.isValid() || !srcX.isValid() || !srcY.isValid() || !srcW.isValid() || !srcH.isValid() || !crtcX.isValid() || !crtcY.isValid() || !crtcW.isValid() || !crtcH.isValid() || !fbId.isValid()) { diff --git a/src/backends/drm/drm_plane.h b/src/backends/drm/drm_plane.h index 975358d70f..f6829fa161 100644 --- a/src/backends/drm/drm_plane.h +++ b/src/backends/drm/drm_plane.h @@ -61,6 +61,15 @@ public: PreMultiplied, Coverage }; + enum class ColorEncoding : uint64_t { + BT601_YCbCr, + BT701_YCbCr, + BT2020_YCbCr + }; + enum class ColorRange : uint64_t { + Limited_YCbCr, + Full_YCbCr + }; DrmEnumProperty type; DrmProperty srcX; @@ -77,6 +86,8 @@ public: DrmProperty inFormats; DrmProperty alpha; DrmEnumProperty pixelBlendMode; + DrmEnumProperty colorEncoding; + DrmEnumProperty colorRange; static int32_t transformationToDegrees(Transformations transformation);