backends/drm: support cropping with direct scanout

This commit is contained in:
Xaver Hugl 2024-04-03 00:13:42 +02:00
parent 4448e23363
commit d9ee6d98ae
8 changed files with 49 additions and 15 deletions

View file

@ -94,6 +94,13 @@ bool EglGbmLayer::scanout(SurfaceItem *surfaceItem)
return false;
}
const auto surface = item->surface();
// kernel documentation says that
// "Devices that dont 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
m_bufferSourceBox = surface->bufferSourceBox().toRect();
if (surface->bufferSourceBox() != m_bufferSourceBox) {
return false;
}
const auto neededTransform = surface->bufferTransform().combine(m_pipeline->output()->transform().inverted());
const auto plane = m_pipeline->crtc()->primaryPlane();
if (neededTransform != OutputTransform::Kind::Normal && (!plane || !plane->supportsTransformation(neededTransform))) {
@ -160,4 +167,9 @@ OutputTransform EglGbmLayer::hardwareTransform() const
{
return m_scanoutBuffer ? m_scanoutTransform : OutputTransform::Normal;
}
QRect EglGbmLayer::bufferSourceBox() const
{
return m_scanoutBuffer ? m_bufferSourceBox : QRect(QPoint(0, 0), m_surface.currentBuffer()->buffer()->size());
}
}

View file

@ -39,6 +39,7 @@ public:
void releaseBuffers() override;
std::chrono::nanoseconds queryRenderTime() const override;
OutputTransform hardwareTransform() const override;
QRect bufferSourceBox() const override;
private:
std::shared_ptr<DrmFramebuffer> m_scanoutBuffer;
@ -46,6 +47,7 @@ private:
OutputTransform m_scanoutTransform = OutputTransform::Kind::Normal;
// the output transform the buffer is made for
OutputTransform m_scanoutBufferTransform = OutputTransform::Kind::Normal;
QRect m_bufferSourceBox;
QRegion m_currentDamage;
EglGbmLayerSurface m_surface;

View file

@ -7,6 +7,8 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "drm_layer.h"
#include "core/graphicsbuffer.h"
#include "drm_buffer.h"
#include "drm_pipeline.h"
#include <QMatrix4x4>
@ -36,4 +38,10 @@ OutputTransform DrmPipelineLayer::hardwareTransform() const
{
return OutputTransform::Kind::Normal;
}
QRect DrmPipelineLayer::bufferSourceBox() const
{
const auto buffer = currentBuffer();
return buffer ? QRect(QPoint(0, 0), currentBuffer()->buffer()->size()) : QRect();
}
}

View file

@ -39,6 +39,7 @@ public:
virtual bool checkTestBuffer() = 0;
virtual std::shared_ptr<DrmFramebuffer> currentBuffer() const = 0;
virtual OutputTransform hardwareTransform() const;
virtual QRect bufferSourceBox() const;
protected:
DrmPipeline *const m_pipeline;

View file

@ -266,7 +266,7 @@ DrmPipeline::Error DrmPipeline::prepareAtomicPresentation(DrmAtomicCommit *commi
} else if (planeTransform != DrmPlane::Transformation::Rotate0) {
return Error::InvalidArguments;
}
primary->set(commit, QPoint(0, 0), fb->buffer()->size(), centerBuffer(transform.map(fb->buffer()->size()), m_pending.mode->size()));
primary->set(commit, m_primaryLayer->bufferSourceBox(), centerBuffer(transform.map(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()) {
@ -283,13 +283,18 @@ void DrmPipeline::prepareAtomicCursor(DrmAtomicCommit *commit)
{
auto plane = m_pending.crtc->cursorPlane();
const auto layer = cursorLayer();
plane->set(commit, QPoint(0, 0), gpu()->cursorSize(), QRect(layer->position().toPoint(), gpu()->cursorSize()));
commit->addProperty(plane->crtcId, layer->isEnabled() ? m_pending.crtc->id() : 0);
commit->addBuffer(plane, layer->isEnabled() ? layer->currentBuffer() : nullptr);
if (layer->isEnabled()) {
plane->set(commit, layer->bufferSourceBox(), QRect(layer->position().toPoint(), gpu()->cursorSize()));
commit->addProperty(plane->crtcId, m_pending.crtc->id());
commit->addBuffer(plane, layer->currentBuffer());
if (plane->vmHotspotX.isValid() && plane->vmHotspotY.isValid()) {
commit->addProperty(plane->vmHotspotX, std::round(layer->hotspot().x()));
commit->addProperty(plane->vmHotspotY, std::round(layer->hotspot().y()));
}
} else {
commit->addProperty(plane->crtcId, 0);
commit->addBuffer(plane, nullptr);
}
}
void DrmPipeline::prepareAtomicDisable(DrmAtomicCommit *commit)

View file

@ -30,6 +30,9 @@ DrmPipeline::Error DrmPipeline::presentLegacy()
return err;
}
const auto buffer = m_primaryLayer->currentBuffer();
if (m_primaryLayer->bufferSourceBox() != QRect(QPoint(0, 0), buffer->buffer()->size())) {
return Error::InvalidArguments;
}
auto commit = std::make_unique<DrmLegacyCommit>(this, buffer);
if (!commit->doPageflip(m_pending.presentationMode)) {
qCWarning(KWIN_DRM) << "Page flip failed:" << strerror(errno);
@ -50,7 +53,11 @@ DrmPipeline::Error DrmPipeline::legacyModeset()
if (!m_primaryLayer->checkTestBuffer()) {
return Error::TestBufferFailed;
}
auto commit = std::make_unique<DrmLegacyCommit>(this, m_primaryLayer->currentBuffer());
const auto buffer = m_primaryLayer->currentBuffer();
if (m_primaryLayer->bufferSourceBox() != QRect(QPoint(0, 0), buffer->buffer()->size())) {
return Error::InvalidArguments;
}
auto commit = std::make_unique<DrmLegacyCommit>(this, buffer);
if (!commit->doModeset(m_connector, m_pending.mode.get())) {
qCWarning(KWIN_DRM) << "Modeset failed!" << strerror(errno);
return errnoToError();

View file

@ -126,14 +126,13 @@ bool DrmPlane::updateProperties()
return true;
}
void DrmPlane::set(DrmAtomicCommit *commit, const QPoint &srcPos, const QSize &srcSize, const QRect &dst)
void DrmPlane::set(DrmAtomicCommit *commit, const QRect &src, const QRect &dst)
{
// Src* are in 16.16 fixed point format
commit->addProperty(srcX, srcPos.x() << 16);
commit->addProperty(srcX, srcPos.x() << 16);
commit->addProperty(srcY, srcPos.y() << 16);
commit->addProperty(srcW, srcSize.width() << 16);
commit->addProperty(srcH, srcSize.height() << 16);
commit->addProperty(srcX, src.x() << 16);
commit->addProperty(srcY, src.y() << 16);
commit->addProperty(srcW, src.width() << 16);
commit->addProperty(srcH, src.height() << 16);
commit->addProperty(crtcX, dst.x());
commit->addProperty(crtcY, dst.y());
commit->addProperty(crtcW, dst.width());

View file

@ -41,7 +41,7 @@ public:
void setCurrentBuffer(const std::shared_ptr<DrmFramebuffer> &b);
void releaseCurrentBuffer();
void set(DrmAtomicCommit *commit, const QPoint &srcPos, const QSize &srcSize, const QRect &dst);
void set(DrmAtomicCommit *commit, const QRect &src, const QRect &dst);
enum class TypeIndex : uint64_t {
Overlay = 0,