From 81905dbfaa75a4d616655064fc1952caab517350 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Wed, 1 Dec 2021 12:10:02 +0100 Subject: [PATCH] backends/drm: properly handle pending transformations AbstractWaylandOutput::pixelSize returns the size with already set transformation applied but the render backends need the pending transformation --- src/backends/drm/drm_abstract_output.h | 1 + src/backends/drm/drm_gpu.cpp | 4 +-- src/backends/drm/drm_output.cpp | 12 +++++-- src/backends/drm/drm_output.h | 1 + src/backends/drm/drm_pipeline.cpp | 31 ++++++++++++------- src/backends/drm/drm_pipeline.h | 13 +++++++- src/backends/drm/drm_virtual_output.cpp | 5 +++ src/backends/drm/drm_virtual_output.h | 1 + src/backends/drm/egl_gbm_backend.cpp | 12 +++---- .../drm/scene_qpainter_drm_backend.cpp | 4 +-- 10 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/backends/drm/drm_abstract_output.h b/src/backends/drm/drm_abstract_output.h index 11f6f1e524..604b24d1e6 100644 --- a/src/backends/drm/drm_abstract_output.h +++ b/src/backends/drm/drm_abstract_output.h @@ -25,6 +25,7 @@ public: virtual bool present(const QSharedPointer &buffer, QRegion damagedRegion) = 0; virtual bool needsSoftwareTransformation() const = 0; + virtual QSize bufferSize() const = 0; virtual QSize sourceSize() const = 0; virtual bool isFormatSupported(uint32_t drmFormat) const = 0; virtual QVector supportedModifiers(uint32_t drmFormat) const = 0; diff --git a/src/backends/drm/drm_gpu.cpp b/src/backends/drm/drm_gpu.cpp index 6e5a5afdf6..0f07b5efe1 100644 --- a/src/backends/drm/drm_gpu.cpp +++ b/src/backends/drm/drm_gpu.cpp @@ -406,8 +406,8 @@ bool DrmGpu::testPendingConfiguration(TestMode mode) // try again without hw rotation bool hwRotationUsed = false; for (const auto &pipeline : qAsConst(m_pipelines)) { - hwRotationUsed |= (pipeline->pending.transformation != DrmPlane::Transformations(DrmPlane::Transformation::Rotate0)); - pipeline->pending.transformation = DrmPlane::Transformation::Rotate0; + hwRotationUsed |= (pipeline->pending.bufferTransformation != DrmPlane::Transformations(DrmPlane::Transformation::Rotate0)); + pipeline->pending.bufferTransformation = DrmPlane::Transformation::Rotate0; } return hwRotationUsed ? test() : false; } diff --git a/src/backends/drm/drm_output.cpp b/src/backends/drm/drm_output.cpp index 2758e05a48..e89b9a7f1c 100644 --- a/src/backends/drm/drm_output.cpp +++ b/src/backends/drm/drm_output.cpp @@ -323,7 +323,7 @@ void DrmOutput::updateModes() bool DrmOutput::needsSoftwareTransformation() const { - return m_pipeline->pending.transformation != outputToPlaneTransform(transform()); + return m_pipeline->pending.bufferTransformation != m_pipeline->pending.sourceTransformation; } bool DrmOutput::present(const QSharedPointer &buffer, QRegion damagedRegion) @@ -378,6 +378,11 @@ DrmPipeline *DrmOutput::pipeline() const return m_pipeline; } +QSize DrmOutput::bufferSize() const +{ + return m_pipeline->bufferSize(); +} + QSize DrmOutput::sourceSize() const { return m_pipeline->sourceSize(); @@ -414,8 +419,9 @@ bool DrmOutput::queueChanges(const WaylandOutputConfig &config) m_pipeline->pending.modeIndex = index; m_pipeline->pending.overscan = props->overscan; m_pipeline->pending.rgbRange = props->rgbRange; - if (!envOnlySoftwareRotations) { - m_pipeline->pending.transformation = outputToPlaneTransform(props->transform); + m_pipeline->pending.sourceTransformation = outputToPlaneTransform(props->transform); + if (!envOnlySoftwareRotations && m_gpu->atomicModeSetting()) { + m_pipeline->pending.bufferTransformation = m_pipeline->pending.sourceTransformation; } m_pipeline->pending.enabled = props->enabled; return true; diff --git a/src/backends/drm/drm_output.h b/src/backends/drm/drm_output.h index c3ff61d853..f9e41a278d 100644 --- a/src/backends/drm/drm_output.h +++ b/src/backends/drm/drm_output.h @@ -48,6 +48,7 @@ public: DrmConnector *connector() const; DrmPipeline *pipeline() const; + QSize bufferSize() const override; QSize sourceSize() const override; bool isFormatSupported(uint32_t drmFormat) const override; QVector supportedModifiers(uint32_t drmFormat) const override; diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp index c9695c9ffd..fafb2910cd 100644 --- a/src/backends/drm/drm_pipeline.cpp +++ b/src/backends/drm/drm_pipeline.cpp @@ -192,7 +192,7 @@ bool DrmPipeline::populateAtomicValues(drmModeAtomicReq *req, uint32_t &flags) pending.crtc->setPending(DrmCrtc::PropertyIndex::VrrEnabled, pending.syncMode == RenderLoopPrivate::SyncMode::Adaptive); pending.crtc->setPending(DrmCrtc::PropertyIndex::Gamma_LUT, pending.gamma ? pending.gamma->blobId() : 0); auto modeSize = m_connector->modes()[pending.modeIndex]->size(); - pending.crtc->primaryPlane()->set(QPoint(0, 0), m_primaryBuffer ? m_primaryBuffer->size() : modeSize, QPoint(0, 0), modeSize); + pending.crtc->primaryPlane()->set(QPoint(0, 0), m_primaryBuffer ? m_primaryBuffer->size() : bufferSize(), QPoint(0, 0), modeSize); pending.crtc->primaryPlane()->setBuffer(activePending() ? m_primaryBuffer.get() : nullptr); if (pending.crtc->cursorPlane()) { @@ -235,7 +235,7 @@ void DrmPipeline::prepareAtomicModeset() pending.crtc->setPending(DrmCrtc::PropertyIndex::ModeId, activePending() ? mode->blobId() : 0); pending.crtc->primaryPlane()->setPending(DrmPlane::PropertyIndex::CrtcId, activePending() ? pending.crtc->id() : 0); - pending.crtc->primaryPlane()->setTransformation(pending.transformation); + pending.crtc->primaryPlane()->setTransformation(pending.bufferTransformation); if (pending.crtc->cursorPlane()) { pending.crtc->cursorPlane()->setTransformation(DrmPlane::Transformation::Rotate0); } @@ -291,7 +291,7 @@ void DrmPipeline::atomicCommitSuccessful(CommitMode mode) bool DrmPipeline::checkTestBuffer() { - if (!pending.crtc || (m_primaryBuffer && m_primaryBuffer->size() == sourceSize())) { + if (!pending.crtc || (m_primaryBuffer && m_primaryBuffer->size() == bufferSize())) { return true; } auto backend = gpu()->eglBackend(); @@ -301,7 +301,7 @@ bool DrmPipeline::checkTestBuffer() const auto &mods = supportedModifiers(buf->format()); if (backend && buf->format() == backend->drmFormat(m_output) && (mods.isEmpty() || mods.contains(buf->modifier())) - && buf->size() == sourceSize()) { + && buf->size() == bufferSize()) { buffer = buf; } }; @@ -319,13 +319,13 @@ bool DrmPipeline::checkTestBuffer() if (backend && m_output) { buffer = backend->renderTestFrame(m_output); } else if (backend && gpu()->gbmDevice()) { - gbm_bo *bo = gbm_bo_create(gpu()->gbmDevice(), sourceSize().width(), sourceSize().height(), DRM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + gbm_bo *bo = gbm_bo_create(gpu()->gbmDevice(), bufferSize().width(), bufferSize().height(), DRM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); if (!bo) { return false; } buffer = QSharedPointer::create(gpu(), bo, nullptr); } else { - buffer = QSharedPointer::create(gpu(), sourceSize(), DRM_FORMAT_XRGB8888); + buffer = QSharedPointer::create(gpu(), bufferSize(), DRM_FORMAT_XRGB8888); } } if (buffer && buffer->bufferId()) { @@ -395,13 +395,22 @@ void DrmPipeline::applyPendingChanges() m_next = pending; } +QSize DrmPipeline::bufferSize() const +{ + const auto modeSize = m_connector->modes()[pending.modeIndex]->size(); + if (pending.bufferTransformation & (DrmPlane::Transformation::Rotate90 | DrmPlane::Transformation::Rotate270)) { + return modeSize.transposed(); + } + return modeSize; +} + QSize DrmPipeline::sourceSize() const { - auto mode = m_connector->modes()[pending.modeIndex]; - if (pending.transformation & (DrmPlane::Transformation::Rotate90 | DrmPlane::Transformation::Rotate270)) { - return mode->size().transposed(); + const auto modeSize = m_connector->modes()[pending.modeIndex]->size(); + if (pending.sourceTransformation & (DrmPlane::Transformation::Rotate90 | DrmPlane::Transformation::Rotate270)) { + return modeSize.transposed(); } - return mode->size(); + return modeSize; } bool DrmPipeline::isCursorVisible() const @@ -491,7 +500,7 @@ bool DrmPipeline::needsModeset() const || pending.active != m_current.active || pending.modeIndex != m_current.modeIndex || pending.rgbRange != m_current.rgbRange - || pending.transformation != m_current.transformation + || pending.bufferTransformation != m_current.bufferTransformation || m_modesetPresentPending; } diff --git a/src/backends/drm/drm_pipeline.h b/src/backends/drm/drm_pipeline.h index 98fe19da5b..5dc68015b7 100644 --- a/src/backends/drm/drm_pipeline.h +++ b/src/backends/drm/drm_pipeline.h @@ -77,7 +77,14 @@ public: bool modesetPresentPending() const; void resetModesetPresentPending(); void printDebugInfo() const; + /** + * which size buffers for rendering should have + */ QSize sourceSize() const; + /** + * what size buffers submitted to this pipeline should have + */ + QSize bufferSize() const; bool isFormatSupported(uint32_t drmFormat) const; QVector supportedModifiers(uint32_t drmFormat) const; @@ -95,11 +102,15 @@ public: AbstractWaylandOutput::RgbRange rgbRange = AbstractWaylandOutput::RgbRange::Automatic; RenderLoopPrivate::SyncMode syncMode = RenderLoopPrivate::SyncMode::Fixed; QSharedPointer gamma; - DrmPlane::Transformations transformation = DrmPlane::Transformation::Rotate0; QPoint cursorPos; QPoint cursorHotspot; QSharedPointer cursorBo; + + // the transformation that this pipeline will apply to submitted buffers + DrmPlane::Transformations bufferTransformation = DrmPlane::Transformation::Rotate0; + // the transformation that buffers submitted to the pipeline should have + DrmPlane::Transformations sourceTransformation = DrmPlane::Transformation::Rotate0; }; State pending; diff --git a/src/backends/drm/drm_virtual_output.cpp b/src/backends/drm/drm_virtual_output.cpp index 0c31571e15..56f99a4719 100644 --- a/src/backends/drm/drm_virtual_output.cpp +++ b/src/backends/drm/drm_virtual_output.cpp @@ -75,6 +75,11 @@ void DrmVirtualOutput::updateEnablement(bool enable) gpu()->platform()->enableOutput(this, enable); } +QSize DrmVirtualOutput::bufferSize() const +{ + return pixelSize(); +} + QSize DrmVirtualOutput::sourceSize() const { return pixelSize(); diff --git a/src/backends/drm/drm_virtual_output.h b/src/backends/drm/drm_virtual_output.h index 18faaff70a..dd836bb64e 100644 --- a/src/backends/drm/drm_virtual_output.h +++ b/src/backends/drm/drm_virtual_output.h @@ -29,6 +29,7 @@ public: ~DrmVirtualOutput() override; bool present(const QSharedPointer &buffer, QRegion damagedRegion) override; + QSize bufferSize() const override; QSize sourceSize() const override; bool isFormatSupported(uint32_t drmFormat) const override; diff --git a/src/backends/drm/egl_gbm_backend.cpp b/src/backends/drm/egl_gbm_backend.cpp index 868c042947..831e09f66f 100644 --- a/src/backends/drm/egl_gbm_backend.cpp +++ b/src/backends/drm/egl_gbm_backend.cpp @@ -157,8 +157,8 @@ bool EglGbmBackend::resetOutput(Output &output) } output.current.format = gbmFormat.value(); uint32_t format = gbmFormat.value().drmFormat; - const QSize size = output.output->sourceSize(); QVector modifiers = output.output->supportedModifiers(format); + const QSize size = output.output->bufferSize(); QSharedPointer gbmSurface; bool modifiersEnvSet = false; @@ -199,7 +199,7 @@ bool EglGbmBackend::resetOutput(Output &output) output.current.shadowBuffer = nullptr; } else { makeContextCurrent(output.current); - output.current.shadowBuffer = QSharedPointer::create(output.output->pixelSize(), output.current.format); + output.current.shadowBuffer = QSharedPointer::create(output.output->sourceSize(), output.current.format); if (!output.current.shadowBuffer->isComplete()) { return false; } @@ -517,7 +517,7 @@ SurfaceTexture *EglGbmBackend::createSurfaceTextureWayland(SurfacePixmapWayland void EglGbmBackend::setViewport(const Output &output) const { - const QSize size = output.output->pixelSize(); + const QSize size = output.output->sourceSize(); glViewport(0, 0, size.width(), size.height()); } @@ -547,13 +547,13 @@ bool EglGbmBackend::doesRenderFit(DrmAbstractOutput *output, const Output::Rende if (!render.gbmSurface) { return false; } - QSize surfaceSize = output->sourceSize(); + QSize surfaceSize = output->bufferSize(); if (surfaceSize != render.gbmSurface->size()) { return false; } bool needsTexture = output->needsSoftwareTransformation(); if (needsTexture) { - return render.shadowBuffer && render.shadowBuffer->textureSize() == output->pixelSize(); + return render.shadowBuffer && render.shadowBuffer->textureSize() == output->sourceSize(); } else { return render.shadowBuffer == nullptr; } @@ -771,7 +771,7 @@ QSharedPointer EglGbmBackend::textureForOutput(AbstractOutput *output Q_ASSERT(m_outputs.contains(output)); auto &renderOutput = m_outputs[output]; if (renderOutput.current.shadowBuffer) { - const auto glTexture = QSharedPointer::create(renderOutput.current.shadowBuffer->texture(), GL_RGBA8, output->pixelSize()); + const auto glTexture = QSharedPointer::create(renderOutput.current.shadowBuffer->texture(), GL_RGBA8, renderOutput.output->sourceSize()); glTexture->setYInverted(true); return glTexture; } diff --git a/src/backends/drm/scene_qpainter_drm_backend.cpp b/src/backends/drm/scene_qpainter_drm_backend.cpp index 2f49f845b2..94896cc173 100644 --- a/src/backends/drm/scene_qpainter_drm_backend.cpp +++ b/src/backends/drm/scene_qpainter_drm_backend.cpp @@ -46,13 +46,13 @@ DrmQPainterBackend::DrmQPainterBackend(DrmBackend *backend, DrmGpu *gpu) void DrmQPainterBackend::initOutput(DrmAbstractOutput *output) { Output o; - o.swapchain = QSharedPointer::create(m_gpu, output->pixelSize(), DRM_FORMAT_XRGB8888); + o.swapchain = QSharedPointer::create(m_gpu, output->sourceSize(), DRM_FORMAT_XRGB8888); o.output = output; m_outputs.insert(output, o); connect(output, &DrmOutput::currentModeChanged, this, [output, this] { auto &o = m_outputs[output]; - o.swapchain = QSharedPointer::create(m_gpu, output->pixelSize(), DRM_FORMAT_XRGB8888); + o.swapchain = QSharedPointer::create(m_gpu, output->sourceSize(), DRM_FORMAT_XRGB8888); o.damageJournal.setCapacity(o.swapchain->slotCount()); } );