backends/drm: support cropping with direct scanout
This commit is contained in:
parent
4448e23363
commit
d9ee6d98ae
8 changed files with 49 additions and 15 deletions
|
@ -94,6 +94,13 @@ bool EglGbmLayer::scanout(SurfaceItem *surfaceItem)
|
|||
return false;
|
||||
}
|
||||
const auto surface = item->surface();
|
||||
// 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
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue