From 0cd453690be88550cdc915be181fb3004f64d0f1 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Sat, 19 Feb 2022 04:25:11 +0100 Subject: [PATCH] backends/drm: split out layers for lease outputs and remove DrmDisplayDevice --- src/backends/drm/CMakeLists.txt | 2 +- src/backends/drm/drm_abstract_output.cpp | 12 ++-- src/backends/drm/drm_abstract_output.h | 17 ++++-- src/backends/drm/drm_display_device.cpp | 24 -------- src/backends/drm/drm_display_device.h | 41 ------------- src/backends/drm/drm_gpu.cpp | 6 +- src/backends/drm/drm_layer.cpp | 33 +++++++++- src/backends/drm/drm_layer.h | 12 ++-- src/backends/drm/drm_lease_egl_gbm_layer.cpp | 60 +++++++++++++++++++ src/backends/drm/drm_lease_egl_gbm_layer.h | 31 ++++++++++ src/backends/drm/drm_lease_output.cpp | 33 ---------- src/backends/drm/drm_lease_output.h | 11 +--- src/backends/drm/drm_object_connector.cpp | 4 +- src/backends/drm/drm_output.cpp | 4 +- src/backends/drm/drm_pipeline.cpp | 29 ++++----- src/backends/drm/drm_pipeline.h | 7 +-- src/backends/drm/drm_qpainter_layer.cpp | 57 +++++++++--------- src/backends/drm/drm_qpainter_layer.h | 25 +++++--- src/backends/drm/drm_render_backend.h | 1 - src/backends/drm/drm_virtual_output.cpp | 2 +- src/backends/drm/egl_gbm_backend.cpp | 7 ++- src/backends/drm/egl_gbm_backend.h | 1 - src/backends/drm/egl_gbm_layer.cpp | 10 ++-- src/backends/drm/egl_gbm_layer.h | 5 -- .../drm/scene_qpainter_drm_backend.cpp | 7 ++- src/backends/drm/shadowbuffer.h | 2 - 26 files changed, 235 insertions(+), 208 deletions(-) delete mode 100644 src/backends/drm/drm_display_device.cpp delete mode 100644 src/backends/drm/drm_display_device.h create mode 100644 src/backends/drm/drm_lease_egl_gbm_layer.cpp create mode 100644 src/backends/drm/drm_lease_egl_gbm_layer.h diff --git a/src/backends/drm/CMakeLists.txt b/src/backends/drm/CMakeLists.txt index 94d8160f61..f67e29019b 100644 --- a/src/backends/drm/CMakeLists.txt +++ b/src/backends/drm/CMakeLists.txt @@ -13,7 +13,6 @@ set(DRM_SOURCES drm_gpu.cpp dumb_swapchain.cpp shadowbuffer.cpp - drm_display_device.cpp drm_layer.cpp drm_pipeline.cpp drm_pipeline_legacy.cpp @@ -28,6 +27,7 @@ set(DRM_SOURCES gbm_dmabuf.cpp placeholderinputeventfilter.cpp virtual_egl_gbm_layer.cpp + drm_lease_egl_gbm_layer.cpp ) add_library(KWinWaylandDrmBackend MODULE ${DRM_SOURCES}) diff --git a/src/backends/drm/drm_abstract_output.cpp b/src/backends/drm/drm_abstract_output.cpp index 5a9048a6fe..3e2d2de0c2 100644 --- a/src/backends/drm/drm_abstract_output.cpp +++ b/src/backends/drm/drm_abstract_output.cpp @@ -16,8 +16,8 @@ namespace KWin DrmAbstractOutput::DrmAbstractOutput(DrmGpu *gpu) : AbstractWaylandOutput(gpu->platform()) - , DrmDisplayDevice(gpu) , m_renderLoop(new RenderLoop(this)) + , m_gpu(gpu) { } @@ -26,11 +26,6 @@ RenderLoop *DrmAbstractOutput::renderLoop() const return m_renderLoop; } -QRect DrmAbstractOutput::renderGeometry() const -{ - return geometry(); -} - void DrmAbstractOutput::frameFailed() const { RenderLoopPrivate::get(m_renderLoop)->notifyFrameFailed(); @@ -57,4 +52,9 @@ QVector DrmAbstractOutput::regionToRects(const QRegion ®ion) const return rects; } +DrmGpu *DrmAbstractOutput::gpu() const +{ + return m_gpu; +} + } diff --git a/src/backends/drm/drm_abstract_output.h b/src/backends/drm/drm_abstract_output.h index e3f1f00348..783bea77e6 100644 --- a/src/backends/drm/drm_abstract_output.h +++ b/src/backends/drm/drm_abstract_output.h @@ -9,29 +9,34 @@ #pragma once #include "abstract_wayland_output.h" -#include "drm_display_device.h" namespace KWin { class DrmBackend; +class DrmGpu; +class DrmOutputLayer; -class DrmAbstractOutput : public AbstractWaylandOutput, public DrmDisplayDevice +class DrmAbstractOutput : public AbstractWaylandOutput { Q_OBJECT public: DrmAbstractOutput(DrmGpu *gpu); RenderLoop *renderLoop() const override; - QRect renderGeometry() const override; - void frameFailed() const override; - void pageFlipped(std::chrono::nanoseconds timestamp) const override; - QVector regionToRects(const QRegion ®ion) const override; + void frameFailed() const; + void pageFlipped(std::chrono::nanoseconds timestamp) const; + QVector regionToRects(const QRegion ®ion) const; + DrmGpu *gpu() const; + + virtual bool present() = 0; + virtual DrmOutputLayer *outputLayer() const = 0; protected: friend class DrmGpu; RenderLoop *m_renderLoop; + DrmGpu *const m_gpu; }; } diff --git a/src/backends/drm/drm_display_device.cpp b/src/backends/drm/drm_display_device.cpp deleted file mode 100644 index aafefb4c9a..0000000000 --- a/src/backends/drm/drm_display_device.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2022 Xaver Hugl - - SPDX-License-Identifier: GPL-2.0-or-later -*/ -#include "drm_display_device.h" - -namespace KWin -{ - -DrmDisplayDevice::DrmDisplayDevice(DrmGpu *gpu) - : m_gpu(gpu) -{ -} - -DrmGpu *DrmDisplayDevice::gpu() const -{ - return m_gpu; -} - -} diff --git a/src/backends/drm/drm_display_device.h b/src/backends/drm/drm_display_device.h deleted file mode 100644 index ca73b9a892..0000000000 --- a/src/backends/drm/drm_display_device.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2022 Xaver Hugl - - SPDX-License-Identifier: GPL-2.0-or-later -*/ -#pragma once - -#include - -#include "drm_object_plane.h" - -namespace KWin -{ - -class DrmBuffer; -class DrmGpu; -class DrmOutputLayer; - -class DrmDisplayDevice -{ -public: - DrmDisplayDevice(DrmGpu *gpu); - virtual ~DrmDisplayDevice() = default; - - DrmGpu *gpu() const; - - virtual bool present() = 0; - virtual void frameFailed() const = 0; - virtual void pageFlipped(std::chrono::nanoseconds timestamp) const = 0; - virtual QRect renderGeometry() const = 0; - virtual DrmOutputLayer *outputLayer() const = 0; - virtual QVector regionToRects(const QRegion ®ion) const = 0; - -protected: - DrmGpu *const m_gpu; -}; - -} diff --git a/src/backends/drm/drm_gpu.cpp b/src/backends/drm/drm_gpu.cpp index 7dbf51a02d..51b8719f57 100644 --- a/src/backends/drm/drm_gpu.cpp +++ b/src/backends/drm/drm_gpu.cpp @@ -309,9 +309,9 @@ bool DrmGpu::updateOutputs() if (testPendingConfiguration()) { for (const auto &pipeline : qAsConst(m_pipelines)) { pipeline->applyPendingChanges(); - if (const auto drmOutput = dynamic_cast(pipeline->displayDevice()); drmOutput && !pipeline->pending.crtc) { + if (pipeline->output() && !pipeline->pending.crtc) { pipeline->pending.enabled = false; - drmOutput->setEnabled(false); + pipeline->output()->setEnabled(false); } } } else { @@ -740,7 +740,7 @@ bool DrmGpu::maybeModeset() if (pipeline->modesetPresentPending()) { pipeline->resetModesetPresentPending(); if (!ok) { - pipeline->displayDevice()->frameFailed(); + pipeline->output()->frameFailed(); } } } diff --git a/src/backends/drm/drm_layer.cpp b/src/backends/drm/drm_layer.cpp index 2d34e2963d..b8813d9de6 100644 --- a/src/backends/drm/drm_layer.cpp +++ b/src/backends/drm/drm_layer.cpp @@ -8,7 +8,6 @@ */ #include "drm_layer.h" #include "drm_pipeline.h" -#include "drm_display_device.h" #include @@ -22,11 +21,43 @@ void DrmOutputLayer::aboutToStartPainting(const QRegion &damagedRegion) Q_UNUSED(damagedRegion) } +bool DrmOutputLayer::scanout(SurfaceItem *surfaceItem) +{ + Q_UNUSED(surfaceItem) + return false; +} + +std::optional DrmOutputLayer::startRendering() +{ + return {}; +} + +bool DrmOutputLayer::endRendering(const QRegion &damagedRegion) +{ + Q_UNUSED(damagedRegion) + return false; +} + +QRegion DrmOutputLayer::currentDamage() const +{ + return {}; +} + +QSharedPointer DrmOutputLayer::texture() const +{ + return nullptr; +} + DrmPipelineLayer::DrmPipelineLayer(DrmPipeline *pipeline) : m_pipeline(pipeline) { } +bool DrmPipelineLayer::hasDirectScanoutBuffer() const +{ + return false; +} + } #include "drm_layer.moc" diff --git a/src/backends/drm/drm_layer.h b/src/backends/drm/drm_layer.h index d844c89326..a042027c8b 100644 --- a/src/backends/drm/drm_layer.h +++ b/src/backends/drm/drm_layer.h @@ -28,19 +28,19 @@ public: virtual ~DrmOutputLayer(); virtual void aboutToStartPainting(const QRegion &damagedRegion); - virtual std::optional startRendering() = 0; - virtual bool endRendering(const QRegion &damagedRegion) = 0; + virtual std::optional startRendering(); + virtual bool endRendering(const QRegion &damagedRegion); /** * attempts to directly scan out the current buffer of the surfaceItem * @returns true if scanout was successful * false if rendering is required */ - virtual bool scanout(SurfaceItem *surfaceItem) = 0; + virtual bool scanout(SurfaceItem *surfaceItem); - virtual QSharedPointer texture() const = 0; + virtual QSharedPointer texture() const; - virtual QRegion currentDamage() const = 0; + virtual QRegion currentDamage() const; }; class DrmPipelineLayer : public DrmOutputLayer @@ -55,7 +55,7 @@ public: virtual QSharedPointer testBuffer() = 0; virtual QSharedPointer currentBuffer() const = 0; - virtual bool hasDirectScanoutBuffer() const = 0; + virtual bool hasDirectScanoutBuffer() const; protected: DrmPipeline *const m_pipeline; diff --git a/src/backends/drm/drm_lease_egl_gbm_layer.cpp b/src/backends/drm/drm_lease_egl_gbm_layer.cpp new file mode 100644 index 0000000000..115d6fd696 --- /dev/null +++ b/src/backends/drm/drm_lease_egl_gbm_layer.cpp @@ -0,0 +1,60 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2022 Xaver Hugl + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#include "drm_lease_egl_gbm_layer.h" +#include "drm_buffer_gbm.h" +#include "egl_gbm_backend.h" +#include "drm_pipeline.h" +#include "drm_gpu.h" +#include "logging.h" + +#include +#include + +namespace KWin +{ + +DrmLeaseEglGbmLayer::DrmLeaseEglGbmLayer(EglGbmBackend *backend, DrmPipeline *pipeline) + : DrmPipelineLayer(pipeline) +{ + connect(backend, &EglGbmBackend::aboutToBeDestroyed, this, [this]() { + m_buffer.reset(); + }); +} + +QSharedPointer DrmLeaseEglGbmLayer::testBuffer() +{ + const auto mods = m_pipeline->supportedModifiers(DRM_FORMAT_XRGB8888); + const auto size = m_pipeline->sourceSize(); + if (!m_buffer || m_buffer->size() != size || !(mods.isEmpty() || mods.contains(m_buffer->modifier()))) { + gbm_bo *newBo; + if (mods.isEmpty()) { + newBo = gbm_bo_create(m_pipeline->gpu()->gbmDevice(), size.width(), size.height(), DRM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT); + } else { + QVector modifiers; + modifiers.reserve(mods.count()); + for (const auto &mod : mods) { + modifiers << mod; + } + newBo = gbm_bo_create_with_modifiers(m_pipeline->gpu()->gbmDevice(), size.width(), size.height(), DRM_FORMAT_XRGB8888, modifiers.constData(), mods.count()); + } + if (newBo) { + m_buffer = QSharedPointer::create(m_pipeline->gpu(), nullptr, newBo); + } else { + qCWarning(KWIN_DRM) << "Failed to create gbm_bo for lease output"; + } + } + return m_buffer; +} + +QSharedPointer DrmLeaseEglGbmLayer::currentBuffer() const +{ + return m_buffer; +} + +} diff --git a/src/backends/drm/drm_lease_egl_gbm_layer.h b/src/backends/drm/drm_lease_egl_gbm_layer.h new file mode 100644 index 0000000000..52b2f445e7 --- /dev/null +++ b/src/backends/drm/drm_lease_egl_gbm_layer.h @@ -0,0 +1,31 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2022 Xaver Hugl + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#pragma once +#include "drm_layer.h" + +#include + +namespace KWin +{ + +class EglGbmBackend; + +class DrmLeaseEglGbmLayer : public DrmPipelineLayer +{ +public: + DrmLeaseEglGbmLayer(EglGbmBackend *backend, DrmPipeline *pipeline); + + QSharedPointer testBuffer() override; + QSharedPointer currentBuffer() const override; + +private: + QSharedPointer m_buffer; +}; + +} diff --git a/src/backends/drm/drm_lease_output.cpp b/src/backends/drm/drm_lease_output.cpp index dc357f8e51..37a2545137 100644 --- a/src/backends/drm/drm_lease_output.cpp +++ b/src/backends/drm/drm_lease_output.cpp @@ -30,16 +30,13 @@ DrmLeaseOutput::DrmLeaseOutput(DrmPipeline *pipeline, KWaylandServer::DrmLeaseDe pipeline->connector()->modelName(), QStringLiteral("%1 %2").arg(pipeline->connector()->edid()->manufacturerString(), pipeline->connector()->modelName()) ) - , DrmDisplayDevice(pipeline->gpu()) , m_pipeline(pipeline) { - m_pipeline->setDisplayDevice(this); qCDebug(KWIN_DRM) << "offering connector" << m_pipeline->connector()->id() << "for lease"; } DrmLeaseOutput::~DrmLeaseOutput() { - m_pipeline->setDisplayDevice(nullptr); qCDebug(KWIN_DRM) << "revoking lease offer for connector" << m_pipeline->connector()->id(); } @@ -79,34 +76,4 @@ DrmPipeline *DrmLeaseOutput::pipeline() const return m_pipeline; } -bool DrmLeaseOutput::present() -{ - return false; -} - -QRect DrmLeaseOutput::renderGeometry() const -{ - return QRect(QPoint(), m_pipeline->sourceSize()); -} - -DrmOutputLayer *DrmLeaseOutput::outputLayer() const -{ - return m_pipeline->pending.layer.data(); -} - -void DrmLeaseOutput::frameFailed() const -{ -} - -void DrmLeaseOutput::pageFlipped(std::chrono::nanoseconds timestamp) const -{ - Q_UNUSED(timestamp) -} - -QVector DrmLeaseOutput::regionToRects(const QRegion ®ion) const -{ - Q_UNUSED(region) - return {}; -} - } diff --git a/src/backends/drm/drm_lease_output.h b/src/backends/drm/drm_lease_output.h index f4e5c897ed..ae8db03128 100644 --- a/src/backends/drm/drm_lease_output.h +++ b/src/backends/drm/drm_lease_output.h @@ -13,8 +13,6 @@ #include #include -#include "drm_display_device.h" - namespace KWin { @@ -26,7 +24,7 @@ class DrmPipeline; * that is not used directly by the compositor but is instead leased out to * applications (usually VR compositors) that drive the output themselves */ -class DrmLeaseOutput : public KWaylandServer::DrmLeaseConnectorV1Interface, public DrmDisplayDevice +class DrmLeaseOutput : public KWaylandServer::DrmLeaseConnectorV1Interface { Q_OBJECT public: @@ -40,13 +38,6 @@ public: KWaylandServer::DrmLeaseV1Interface *lease() const; DrmPipeline *pipeline() const; - bool present() override; - QRect renderGeometry() const override; - DrmOutputLayer *outputLayer() const override; - void frameFailed() const override; - void pageFlipped(std::chrono::nanoseconds timestamp) const override; - QVector regionToRects(const QRegion ®ion) const override; - private: DrmPipeline *m_pipeline; KWaylandServer::DrmLeaseV1Interface *m_lease = nullptr; diff --git a/src/backends/drm/drm_object_connector.cpp b/src/backends/drm/drm_object_connector.cpp index 42dd5448c8..2a9f1d6ad5 100644 --- a/src/backends/drm/drm_object_connector.cpp +++ b/src/backends/drm/drm_object_connector.cpp @@ -377,8 +377,8 @@ bool DrmConnector::updateProperties() if (!m_pipeline->pending.mode) { m_pipeline->pending.mode = m_modes.constFirst(); } - if (const auto output = dynamic_cast(m_pipeline->displayDevice())) { - output->updateModes(); + if (m_pipeline->output()) { + m_pipeline->output()->updateModes(); } } } diff --git a/src/backends/drm/drm_output.cpp b/src/backends/drm/drm_output.cpp index dc4563918c..d7b4bbd954 100644 --- a/src/backends/drm/drm_output.cpp +++ b/src/backends/drm/drm_output.cpp @@ -46,7 +46,7 @@ DrmOutput::DrmOutput(DrmPipeline *pipeline) , m_pipeline(pipeline) , m_connector(pipeline->connector()) { - m_pipeline->setDisplayDevice(this); + m_pipeline->setOutput(this); const auto conn = m_pipeline->connector(); m_renderLoop->setRefreshRate(m_pipeline->pending.mode->refreshRate()); setSubPixelInternal(conn->subpixel()); @@ -79,7 +79,7 @@ DrmOutput::DrmOutput(DrmPipeline *pipeline) DrmOutput::~DrmOutput() { - m_pipeline->setDisplayDevice(nullptr); + m_pipeline->setOutput(nullptr); } static bool isCursorSpriteCompatible(const QImage *buffer, const QImage *sprite) diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp index 2264f5a549..ce8473d7a9 100644 --- a/src/backends/drm/drm_pipeline.cpp +++ b/src/backends/drm/drm_pipeline.cpp @@ -32,8 +32,7 @@ namespace KWin { DrmPipeline::DrmPipeline(DrmConnector *conn) - : m_displayDevice(nullptr) - , m_connector(conn) + : m_connector(conn) { } @@ -309,8 +308,8 @@ bool DrmPipeline::setCursor(const QSharedPointer &buffer, const Q } if (result) { m_next = pending; - if (const auto drmOutput = dynamic_cast(m_displayDevice); drmOutput && (visibleBefore || isCursorVisible())) { - drmOutput->renderLoop()->scheduleRepaint(); + if (m_output && (visibleBefore || isCursorVisible())) { + m_output->renderLoop()->scheduleRepaint(); } } else { pending = m_next; @@ -334,8 +333,8 @@ bool DrmPipeline::moveCursor(QPoint pos) } if (result) { m_next = pending; - if (const auto drmOutput = dynamic_cast(m_displayDevice); drmOutput && (visibleBefore || isCursorVisible())) { - drmOutput->renderLoop()->scheduleRepaint(); + if (m_output && (visibleBefore || isCursorVisible())) { + m_output->renderLoop()->scheduleRepaint(); } } else { pending = m_next; @@ -395,12 +394,19 @@ void DrmPipeline::pageFlipped(std::chrono::nanoseconds timestamp) m_current.crtc->cursorPlane()->flipBuffer(); } m_pageflipPending = false; - m_displayDevice->pageFlipped(timestamp); + if (m_output) { + m_output->pageFlipped(timestamp); + } } -void DrmPipeline::setDisplayDevice(DrmDisplayDevice *device) +void DrmPipeline::setOutput(DrmOutput *output) { - m_displayDevice = device; + m_output = output; +} + +DrmOutput *DrmPipeline::output() const +{ + return m_output; } static const QMap> legacyFormats = { @@ -483,11 +489,6 @@ DrmCrtc *DrmPipeline::currentCrtc() const return m_current.crtc; } -DrmDisplayDevice *DrmPipeline::displayDevice() const -{ - return m_displayDevice; -} - DrmGammaRamp::DrmGammaRamp(DrmGpu *gpu, const GammaRamp &lut) : m_gpu(gpu) , m_lut(lut) diff --git a/src/backends/drm/drm_pipeline.h b/src/backends/drm/drm_pipeline.h index 0be97cd778..60cb5a61f6 100644 --- a/src/backends/drm/drm_pipeline.h +++ b/src/backends/drm/drm_pipeline.h @@ -32,7 +32,6 @@ class DrmDumbBuffer; class GammaRamp; class DrmConnectorMode; class DrmPipelineLayer; -class DrmDisplayDevice; class DrmGammaRamp { @@ -94,8 +93,8 @@ public: QVector supportedModifiers(uint32_t drmFormat) const; QMap> supportedFormats() const; - void setDisplayDevice(DrmDisplayDevice *device); - DrmDisplayDevice *displayDevice() const; + void setOutput(DrmOutput *output); + DrmOutput *output() const; struct State { DrmCrtc *crtc = nullptr; @@ -154,7 +153,7 @@ private: static void printFlags(uint32_t flags); static void printProps(DrmObject *object, PrintMode mode); - DrmDisplayDevice *m_displayDevice = nullptr; + DrmOutput *m_output = nullptr; DrmConnector *m_connector = nullptr; bool m_pageflipPending = false; diff --git a/src/backends/drm/drm_qpainter_layer.cpp b/src/backends/drm/drm_qpainter_layer.cpp index b3a97b5d4d..044c43ac30 100644 --- a/src/backends/drm/drm_qpainter_layer.cpp +++ b/src/backends/drm/drm_qpainter_layer.cpp @@ -15,16 +15,17 @@ #include "drm_backend.h" #include "drm_pipeline.h" #include "drm_virtual_output.h" +#include "drm_output.h" #include namespace KWin { -DrmQPainterLayer::DrmQPainterLayer(DrmPipeline *pipeline) +DrmQPainterLayer::DrmQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline) : DrmPipelineLayer(pipeline) { - connect(static_cast(pipeline->gpu()->platform()->renderBackend()), &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() { + connect(backend, &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() { m_swapchain.reset(); }); } @@ -35,7 +36,7 @@ std::optional DrmQPainterLayer::startRendering() m_swapchain = QSharedPointer::create(m_pipeline->gpu(), m_pipeline->sourceSize(), DRM_FORMAT_XRGB8888); } QRegion needsRepaint; - if (!m_swapchain->acquireBuffer(m_pipeline->displayDevice()->renderGeometry(), &needsRepaint)) { + if (!m_swapchain->acquireBuffer(m_pipeline->output()->geometry(), &needsRepaint)) { return std::optional(); } return needsRepaint; @@ -48,12 +49,6 @@ bool DrmQPainterLayer::endRendering(const QRegion &damagedRegion) return true; } -bool DrmQPainterLayer::scanout(SurfaceItem *surfaceItem) -{ - Q_UNUSED(surfaceItem); - return false; -} - QSharedPointer DrmQPainterLayer::testBuffer() { if (!doesSwapchainFit()) { @@ -77,16 +72,6 @@ QRegion DrmQPainterLayer::currentDamage() const return m_currentDamage; } -bool DrmQPainterLayer::hasDirectScanoutBuffer() const -{ - return false; -} - -QSharedPointer DrmQPainterLayer::texture() const -{ - return nullptr; -} - QImage *DrmQPainterLayer::image() { return m_swapchain ? m_swapchain->currentBuffer()->image() : nullptr; @@ -112,17 +97,6 @@ bool DrmVirtualQPainterLayer::endRendering(const QRegion &damagedRegion) return true; } -bool DrmVirtualQPainterLayer::scanout(SurfaceItem *surfaceItem) -{ - Q_UNUSED(surfaceItem); - return false; -} - -QSharedPointer DrmVirtualQPainterLayer::texture() const -{ - return nullptr; -} - QRegion DrmVirtualQPainterLayer::currentDamage() const { return m_currentDamage; @@ -133,4 +107,27 @@ QImage *DrmVirtualQPainterLayer::image() return &m_image; } + +DrmLeaseQPainterLayer::DrmLeaseQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline) + : DrmPipelineLayer(pipeline) +{ + connect(backend, &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() { + m_buffer.reset(); + }); +} + +QSharedPointer DrmLeaseQPainterLayer::testBuffer() +{ + const auto size = m_pipeline->sourceSize(); + if (!m_buffer || m_buffer->size() != size) { + m_buffer = QSharedPointer::create(m_pipeline->gpu(), size, DRM_FORMAT_XRGB8888); + } + return m_buffer; +} + +QSharedPointer DrmLeaseQPainterLayer::currentBuffer() const +{ + return m_buffer; +} + } diff --git a/src/backends/drm/drm_qpainter_layer.h b/src/backends/drm/drm_qpainter_layer.h index 49960dbd1d..ca31fc39c6 100644 --- a/src/backends/drm/drm_qpainter_layer.h +++ b/src/backends/drm/drm_qpainter_layer.h @@ -17,6 +17,8 @@ namespace KWin class DumbSwapchain; class DrmPipeline; class DrmVirtualOutput; +class DrmQPainterBackend; +class DrmDumbBuffer; class QPainterLayer { @@ -26,19 +28,16 @@ public: virtual QImage *image() = 0; }; -class DrmQPainterLayer : public DrmPipelineLayer, QPainterLayer +class DrmQPainterLayer : public DrmPipelineLayer, public QPainterLayer { public: - DrmQPainterLayer(DrmPipeline *pipeline); + DrmQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline); std::optional startRendering() override; bool endRendering(const QRegion &damagedRegion) override; - bool scanout(SurfaceItem *surfaceItem) override; QSharedPointer testBuffer() override; - QSharedPointer texture() const override; QSharedPointer currentBuffer() const override; QRegion currentDamage() const override; - bool hasDirectScanoutBuffer() const override; QImage *image() override; private: @@ -48,16 +47,14 @@ private: QRegion m_currentDamage; }; -class DrmVirtualQPainterLayer : public DrmOutputLayer, QPainterLayer +class DrmVirtualQPainterLayer : public DrmOutputLayer, public QPainterLayer { public: DrmVirtualQPainterLayer(DrmVirtualOutput *output); std::optional startRendering() override; bool endRendering(const QRegion &damagedRegion) override; - bool scanout(SurfaceItem *surfaceItem) override; - QSharedPointer texture() const override; QRegion currentDamage() const override; QImage *image() override; @@ -67,4 +64,16 @@ private: DrmVirtualOutput *const m_output; }; +class DrmLeaseQPainterLayer : public DrmPipelineLayer +{ +public: + DrmLeaseQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline); + + QSharedPointer testBuffer() override; + QSharedPointer currentBuffer() const override; + +private: + QSharedPointer m_buffer; +}; + } diff --git a/src/backends/drm/drm_render_backend.h b/src/backends/drm/drm_render_backend.h index 36067d9fbb..5834bc5467 100644 --- a/src/backends/drm/drm_render_backend.h +++ b/src/backends/drm/drm_render_backend.h @@ -14,7 +14,6 @@ namespace KWin { class DrmPipelineLayer; -class DrmDisplayDevice; class DrmVirtualOutput; class DrmPipeline; class DrmOutputLayer; diff --git a/src/backends/drm/drm_virtual_output.cpp b/src/backends/drm/drm_virtual_output.cpp index ca5126a348..fb39c79023 100644 --- a/src/backends/drm/drm_virtual_output.cpp +++ b/src/backends/drm/drm_virtual_output.cpp @@ -74,7 +74,7 @@ void DrmVirtualOutput::setDpmsMode(DpmsMode mode) void DrmVirtualOutput::updateEnablement(bool enable) { - gpu()->platform()->enableOutput(this, enable); + m_gpu->platform()->enableOutput(this, enable); } int DrmVirtualOutput::gammaRampSize() const diff --git a/src/backends/drm/egl_gbm_backend.cpp b/src/backends/drm/egl_gbm_backend.cpp index 19bf1a08a2..b0211f67d0 100644 --- a/src/backends/drm/egl_gbm_backend.cpp +++ b/src/backends/drm/egl_gbm_backend.cpp @@ -30,6 +30,7 @@ #include "egl_dmabuf.h" #include "egl_gbm_layer.h" #include "virtual_egl_gbm_layer.h" +#include "drm_lease_egl_gbm_layer.h" // kwin libs #include #include @@ -289,7 +290,11 @@ EGLConfig EglGbmBackend::config(uint32_t format) const QSharedPointer EglGbmBackend::createDrmPipelineLayer(DrmPipeline *pipeline) { - return QSharedPointer::create(this, pipeline); + if (pipeline->output()) { + return QSharedPointer::create(this, pipeline); + } else { + return QSharedPointer::create(this, pipeline); + } } QSharedPointer EglGbmBackend::createLayer(DrmVirtualOutput *output) diff --git a/src/backends/drm/egl_gbm_backend.h b/src/backends/drm/egl_gbm_backend.h index 0c7b4ea50f..55ed9bde98 100644 --- a/src/backends/drm/egl_gbm_backend.h +++ b/src/backends/drm/egl_gbm_backend.h @@ -38,7 +38,6 @@ class ShadowBuffer; class DrmBackend; class DrmGpu; class EglGbmLayer; -class DrmDisplayDevice; class DrmOutputLayer; class DrmPipeline; diff --git a/src/backends/drm/egl_gbm_layer.cpp b/src/backends/drm/egl_gbm_layer.cpp index 421f110eae..0f4875cee2 100644 --- a/src/backends/drm/egl_gbm_layer.cpp +++ b/src/backends/drm/egl_gbm_layer.cpp @@ -90,7 +90,7 @@ std::optional EglGbmLayer::startRendering() if (!m_gbmSurface->makeContextCurrent()) { return std::optional(); } - auto repaintRegion = m_gbmSurface->repaintRegion(m_pipeline->displayDevice()->renderGeometry()); + auto repaintRegion = m_gbmSurface->repaintRegion(m_pipeline->output()->geometry()); // shadow buffer if (doesShadowBufferFit(m_shadowBuffer.data())) { @@ -124,7 +124,7 @@ std::optional EglGbmLayer::startRendering() void EglGbmLayer::aboutToStartPainting(const QRegion &damagedRegion) { if (m_gbmSurface->bufferAge() > 0 && !damagedRegion.isEmpty() && m_eglBackend->supportsPartialUpdate()) { - QVector rects = m_pipeline->displayDevice()->regionToRects(damagedRegion); + QVector rects = m_pipeline->output()->regionToRects(damagedRegion); const bool correct = eglSetDamageRegionKHR(m_eglBackend->eglDisplay(), m_gbmSurface->eglSurface(), rects.data(), rects.count() / 4); if (!correct) { qCWarning(KWIN_DRM) << "eglSetDamageRegionKHR failed:" << getEglErrorString(); @@ -178,7 +178,7 @@ bool EglGbmLayer::renderTestBuffer() return false; } glClear(GL_COLOR_BUFFER_BIT); - if (!endRendering(m_pipeline->displayDevice()->renderGeometry())) { + if (!endRendering(m_pipeline->output()->geometry())) { return false; } return true; @@ -438,11 +438,11 @@ bool EglGbmLayer::scanout(SurfaceItem *surfaceItem) surfaceItem->resetDamage(); for (const auto &rect : trackedDamage) { auto damageRect = QRect(rect); - damageRect.translate(m_pipeline->displayDevice()->renderGeometry().topLeft()); + damageRect.translate(m_pipeline->output()->geometry().topLeft()); damage |= damageRect; } } else { - damage = m_pipeline->displayDevice()->renderGeometry(); + damage = m_pipeline->output()->geometry(); } if (m_pipeline->testScanout()) { m_currentBuffer = m_scanoutBuffer; diff --git a/src/backends/drm/egl_gbm_layer.h b/src/backends/drm/egl_gbm_layer.h index d4c9643667..1160718e16 100644 --- a/src/backends/drm/egl_gbm_layer.h +++ b/src/backends/drm/egl_gbm_layer.h @@ -28,12 +28,7 @@ namespace KWin class GbmSurface; class DumbSwapchain; class ShadowBuffer; -class DrmBuffer; -class DrmGpu; -class SurfaceItem; -class GLTexture; class EglGbmBackend; -class DrmPipeline; class EglGbmLayer : public DrmPipelineLayer { diff --git a/src/backends/drm/scene_qpainter_drm_backend.cpp b/src/backends/drm/scene_qpainter_drm_backend.cpp index 229781e213..4013e9cfea 100644 --- a/src/backends/drm/scene_qpainter_drm_backend.cpp +++ b/src/backends/drm/scene_qpainter_drm_backend.cpp @@ -14,6 +14,7 @@ #include "renderloop_p.h" #include "drm_qpainter_layer.h" #include "drm_virtual_output.h" +#include "drm_pipeline.h" #include @@ -54,7 +55,11 @@ void DrmQPainterBackend::endFrame(AbstractOutput *output, const QRegion &rendere QSharedPointer DrmQPainterBackend::createDrmPipelineLayer(DrmPipeline *pipeline) { - return QSharedPointer::create(pipeline); + if (pipeline->output()) { + return QSharedPointer::create(this, pipeline); + } else { + return QSharedPointer::create(this, pipeline); + } } QSharedPointer DrmQPainterBackend::createLayer(DrmVirtualOutput *output) diff --git a/src/backends/drm/shadowbuffer.h b/src/backends/drm/shadowbuffer.h index 2f70813e2e..5b3d5f7bc0 100644 --- a/src/backends/drm/shadowbuffer.h +++ b/src/backends/drm/shadowbuffer.h @@ -17,8 +17,6 @@ namespace KWin { -class DrmDisplayDevice; - class ShadowBuffer { public: