backends/drm: use the post-blending color pipeline for direct scanout
This makes direct scanout of SDR content on an HDR screen and vice versa possible, as well as direct scanout while night color is active or the brightness isn't 100%.
This commit is contained in:
parent
2799c270b4
commit
0704319235
6 changed files with 32 additions and 5 deletions
|
@ -55,6 +55,7 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayer::doBeginFrame()
|
|||
// as the hardware cursor is more important than an incorrectly blended cursor edge
|
||||
|
||||
m_scanoutBuffer.reset();
|
||||
m_colorPipeline = ColorPipeline{};
|
||||
return m_surface.startRendering(targetRect().size(), m_pipeline->output()->transform().combine(OutputTransform::FlipY), m_pipeline->formats(m_type), m_pipeline->colorDescription(), m_pipeline->output()->effectiveChannelFactors(), m_pipeline->iccProfile(), m_pipeline->output()->needsColormanagement());
|
||||
}
|
||||
|
||||
|
@ -105,9 +106,7 @@ bool EglGbmLayer::doAttemptScanout(GraphicsBuffer *buffer, const ColorDescriptio
|
|||
if (m_pipeline->output()->needsColormanagement()) {
|
||||
pipeline.addInverseTransferFunction(m_pipeline->colorDescription().transferFunction(), m_pipeline->colorDescription().referenceLuminance());
|
||||
}
|
||||
if (!pipeline.isIdentity()) {
|
||||
return false;
|
||||
}
|
||||
m_colorPipeline = pipeline;
|
||||
// kernel documentation says that
|
||||
// "Devices that don’t support subpixel plane coordinates can ignore the fractional part."
|
||||
// so we need to make sure that doesn't cause a difference vs the composited result
|
||||
|
@ -157,4 +156,9 @@ std::optional<QSize> EglGbmLayer::fixedSize() const
|
|||
{
|
||||
return m_type == DrmPlane::TypeIndex::Cursor ? std::make_optional(m_pipeline->gpu()->cursorSize()) : std::nullopt;
|
||||
}
|
||||
|
||||
const ColorPipeline &EglGbmLayer::colorPipeline() const
|
||||
{
|
||||
return m_colorPipeline;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,11 +37,13 @@ public:
|
|||
DrmDevice *scanoutDevice() const override;
|
||||
QHash<uint32_t, QList<uint64_t>> supportedDrmFormats() const override;
|
||||
std::optional<QSize> fixedSize() const override;
|
||||
const ColorPipeline &colorPipeline() const override;
|
||||
|
||||
private:
|
||||
bool doAttemptScanout(GraphicsBuffer *buffer, const ColorDescription &color, const std::shared_ptr<OutputFrame> &frame) override;
|
||||
|
||||
std::shared_ptr<DrmFramebuffer> m_scanoutBuffer;
|
||||
ColorPipeline m_colorPipeline;
|
||||
|
||||
EglGbmLayerSurface m_surface;
|
||||
};
|
||||
|
|
|
@ -36,4 +36,9 @@ DrmPipelineLayer::DrmPipelineLayer(DrmPipeline *pipeline, DrmPlane::TypeIndex ty
|
|||
, m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
const ColorPipeline &DrmPipelineLayer::colorPipeline() const
|
||||
{
|
||||
return m_colorPipeline;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#pragma once
|
||||
#include "core/colorpipeline.h"
|
||||
#include "core/outputlayer.h"
|
||||
#include "drm_plane.h"
|
||||
|
||||
|
@ -39,9 +40,11 @@ public:
|
|||
|
||||
virtual bool checkTestBuffer() = 0;
|
||||
virtual std::shared_ptr<DrmFramebuffer> currentBuffer() const = 0;
|
||||
virtual const ColorPipeline &colorPipeline() const;
|
||||
|
||||
protected:
|
||||
DrmPipeline *const m_pipeline;
|
||||
const DrmPlane::TypeIndex m_type;
|
||||
ColorPipeline m_colorPipeline;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -213,12 +213,20 @@ DrmPipeline::Error DrmPipeline::prepareAtomicPresentation(DrmAtomicCommit *commi
|
|||
commit->setVrr(m_pending.crtc, m_pending.presentationMode == PresentationMode::AdaptiveSync || m_pending.presentationMode == PresentationMode::AdaptiveAsync);
|
||||
}
|
||||
|
||||
if (m_cursorLayer->isEnabled() && m_primaryLayer->colorPipeline() != m_cursorLayer->colorPipeline()) {
|
||||
return DrmPipeline::Error::InvalidArguments;
|
||||
}
|
||||
if (!m_pending.crtcColorPipeline.isIdentity() && !m_primaryLayer->colorPipeline().isIdentity()) {
|
||||
// TODO merge the pipelines instead?
|
||||
return DrmPipeline::Error::InvalidArguments;
|
||||
}
|
||||
const auto &colorPipeline = m_pending.crtcColorPipeline.isIdentity() ? m_primaryLayer->colorPipeline() : m_pending.crtcColorPipeline;
|
||||
if (!m_pending.crtc->postBlendingPipeline) {
|
||||
if (!m_pending.crtcColorPipeline.isIdentity()) {
|
||||
if (!colorPipeline.isIdentity()) {
|
||||
return Error::InvalidArguments;
|
||||
}
|
||||
} else {
|
||||
if (!m_pending.crtc->postBlendingPipeline->matchPipeline(commit, m_pending.crtcColorPipeline)) {
|
||||
if (!m_pending.crtc->postBlendingPipeline->matchPipeline(commit, colorPipeline)) {
|
||||
return Error::InvalidArguments;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,6 +102,11 @@ DrmPipeline::Error DrmPipeline::applyPendingChangesLegacy()
|
|||
drmModeSetCursor(gpu()->fd(), m_pending.crtc->id(), 0, 0, 0);
|
||||
}
|
||||
if (activePending()) {
|
||||
if (!m_primaryLayer->colorPipeline().isIdentity() || !m_cursorLayer->colorPipeline().isIdentity()) {
|
||||
// while it's technically possible to set CRTC color management properties,
|
||||
// it may result in glitches
|
||||
return DrmPipeline::Error::InvalidArguments;
|
||||
}
|
||||
const bool shouldEnableVrr = m_pending.presentationMode == PresentationMode::AdaptiveSync || m_pending.presentationMode == PresentationMode::AdaptiveAsync;
|
||||
if (m_pending.crtc->vrrEnabled.isValid() && !m_pending.crtc->vrrEnabled.setPropertyLegacy(shouldEnableVrr)) {
|
||||
qCWarning(KWIN_DRM) << "Setting vrr failed!" << strerror(errno);
|
||||
|
|
Loading…
Reference in a new issue