From a86a914f705af2d57dac72b9b338f460f2830def Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Wed, 10 Jul 2024 15:41:52 +0200 Subject: [PATCH] backends/drm: allow offloading more complex color pipelines to legacy modesetting This is done by combining multiple transfer functions and multipliers into one LUT. --- src/backends/drm/drm_pipeline_legacy.cpp | 32 +++++++++++++----------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/backends/drm/drm_pipeline_legacy.cpp b/src/backends/drm/drm_pipeline_legacy.cpp index 95e39c5485..5564cd854b 100644 --- a/src/backends/drm/drm_pipeline_legacy.cpp +++ b/src/backends/drm/drm_pipeline_legacy.cpp @@ -164,25 +164,27 @@ DrmPipeline::Error DrmPipeline::applyPendingChangesLegacy() DrmPipeline::Error DrmPipeline::setLegacyGamma() { - if (m_pending.crtcColorPipeline.ops.size() > 1) { - return DrmPipeline::Error::InvalidArguments; - } - QVector3D factors(1, 1, 1); - if (m_pending.crtcColorPipeline.ops.size() == 1) { - auto mult = std::get_if(&m_pending.crtcColorPipeline.ops.front().operation); - if (!mult) { - return DrmPipeline::Error::InvalidArguments; - } - factors = mult->factors; - } QList red(m_pending.crtc->gammaRampSize()); QList green(m_pending.crtc->gammaRampSize()); QList blue(m_pending.crtc->gammaRampSize()); for (int i = 0; i < m_pending.crtc->gammaRampSize(); i++) { - const double relative = i / double(m_pending.crtc->gammaRampSize() - 1) * std::numeric_limits::max(); - red[i] = std::round(relative * factors.x()); - green[i] = std::round(relative * factors.y()); - blue[i] = std::round(relative * factors.z()); + const double input = i / double(m_pending.crtc->gammaRampSize() - 1); + QVector3D output = QVector3D(input, input, input); + for (const auto &op : m_pending.crtcColorPipeline.ops) { + if (auto tf = std::get_if(&op.operation)) { + output = tf->tf.encodedToNits(output, tf->referenceLuminance); + } else if (auto tf = std::get_if(&op.operation)) { + output = tf->tf.nitsToEncoded(output, tf->referenceLuminance); + } else if (auto mult = std::get_if(&op.operation)) { + output *= mult->factors; + } else { + // not supported + return Error::InvalidArguments; + } + } + red[i] = std::clamp(output.x(), 0.0f, 1.0f) * std::numeric_limits::max(); + green[i] = std::clamp(output.y(), 0.0f, 1.0f) * std::numeric_limits::max(); + blue[i] = std::clamp(output.z(), 0.0f, 1.0f) * std::numeric_limits::max(); } if (drmModeCrtcSetGamma(gpu()->fd(), m_pending.crtc->id(), m_pending.crtc->gammaRampSize(), red.data(), green.data(), blue.data()) != 0) { qCWarning(KWIN_DRM) << "Setting gamma failed!" << strerror(errno);