From ddb6dadfc2554a978c3573e816f4a11b3f963af8 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Sat, 5 Feb 2022 14:24:42 +0100 Subject: [PATCH] backends/drm: port qpainter to layers --- src/backends/drm/CMakeLists.txt | 1 + src/backends/drm/drm_layer.h | 47 ++++++++++++ src/backends/drm/drm_qpainter_layer.cpp | 71 +++++++++++++++++++ src/backends/drm/drm_qpainter_layer.h | 35 +++++++++ src/backends/drm/egl_gbm_layer.h | 32 +++------ .../drm/scene_qpainter_drm_backend.cpp | 19 +++-- src/backends/drm/scene_qpainter_drm_backend.h | 5 +- 7 files changed, 173 insertions(+), 37 deletions(-) create mode 100644 src/backends/drm/drm_layer.h create mode 100644 src/backends/drm/drm_qpainter_layer.cpp create mode 100644 src/backends/drm/drm_qpainter_layer.h diff --git a/src/backends/drm/CMakeLists.txt b/src/backends/drm/CMakeLists.txt index 53096f00e5..77538589df 100644 --- a/src/backends/drm/CMakeLists.txt +++ b/src/backends/drm/CMakeLists.txt @@ -18,6 +18,7 @@ set(DRM_SOURCES drm_abstract_output.cpp drm_virtual_output.cpp drm_lease_output.cpp + drm_qpainter_layer.cpp egl_gbm_backend.cpp egl_gbm_layer.cpp drm_buffer_gbm.cpp diff --git a/src/backends/drm/drm_layer.h b/src/backends/drm/drm_layer.h new file mode 100644 index 0000000000..f49cdbf105 --- /dev/null +++ b/src/backends/drm/drm_layer.h @@ -0,0 +1,47 @@ +/* + 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 +#include + +namespace KWin +{ + +class SurfaceItem; +class DrmBuffer; +class DrmAbstractOutput; + +class DrmLayer +{ +public: + virtual ~DrmLayer() = default; + + virtual std::optional startRendering() = 0; + virtual bool endRendering(const QRegion &damagedRegion) = 0; + + /** + * 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; + + /** + * @returns a buffer for atomic test commits + * If no fitting buffer is available, a new current buffer is created + */ + virtual QSharedPointer testBuffer() = 0; + + virtual QSharedPointer currentBuffer() const = 0; + virtual DrmAbstractOutput *output() const = 0; +}; + +} diff --git a/src/backends/drm/drm_qpainter_layer.cpp b/src/backends/drm/drm_qpainter_layer.cpp new file mode 100644 index 0000000000..cd76bf900b --- /dev/null +++ b/src/backends/drm/drm_qpainter_layer.cpp @@ -0,0 +1,71 @@ +/* + 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_qpainter_layer.h" +#include "dumb_swapchain.h" +#include "drm_abstract_output.h" +#include "drm_buffer.h" + +#include + +namespace KWin +{ + +DrmQPainterLayer::DrmQPainterLayer(DrmAbstractOutput *output) + : m_output(output) +{ +} + +std::optional DrmQPainterLayer::startRendering() +{ + if (!doesSwapchainFit()) { + m_swapchain = QSharedPointer::create(m_output->gpu(), m_output->sourceSize(), DRM_FORMAT_XRGB8888); + } + QRegion needsRepaint; + if (!m_swapchain->acquireBuffer(m_output->geometry(), &needsRepaint)) { + return std::optional(); + } + return needsRepaint; +} + +bool DrmQPainterLayer::endRendering(const QRegion &damagedRegion) +{ + m_swapchain->releaseBuffer(m_swapchain->currentBuffer(), damagedRegion); + return true; +} + +bool DrmQPainterLayer::scanout(SurfaceItem *surfaceItem) +{ + Q_UNUSED(surfaceItem); + return false; +} + +QSharedPointer DrmQPainterLayer::testBuffer() +{ + if (!doesSwapchainFit()) { + m_swapchain = QSharedPointer::create(m_output->gpu(), m_output->sourceSize(), DRM_FORMAT_XRGB8888); + } + return m_swapchain->currentBuffer(); +} + +bool DrmQPainterLayer::doesSwapchainFit() const +{ + return m_swapchain && m_swapchain->size() == m_output->sourceSize(); +} + +QSharedPointer DrmQPainterLayer::currentBuffer() const +{ + return m_swapchain ? m_swapchain->currentBuffer() : nullptr; +} + +DrmAbstractOutput *DrmQPainterLayer::output() const +{ + return m_output; +} + +} diff --git a/src/backends/drm/drm_qpainter_layer.h b/src/backends/drm/drm_qpainter_layer.h new file mode 100644 index 0000000000..75c0ed2443 --- /dev/null +++ b/src/backends/drm/drm_qpainter_layer.h @@ -0,0 +1,35 @@ +/* + 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" + +namespace KWin +{ + +class DumbSwapchain; + +class DrmQPainterLayer : public DrmLayer { +public: + DrmQPainterLayer(DrmAbstractOutput *output); + + std::optional startRendering() override; + bool endRendering(const QRegion &damagedRegion) override; + bool scanout(SurfaceItem *surfaceItem) override; + QSharedPointer testBuffer() override; + QSharedPointer currentBuffer() const override; + DrmAbstractOutput *output() const override; + +private: + bool doesSwapchainFit() const; + + QSharedPointer m_swapchain; + DrmAbstractOutput *const m_output; +}; + +} diff --git a/src/backends/drm/egl_gbm_layer.h b/src/backends/drm/egl_gbm_layer.h index 8c03c722e4..cc10a14823 100644 --- a/src/backends/drm/egl_gbm_layer.h +++ b/src/backends/drm/egl_gbm_layer.h @@ -7,6 +7,7 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once +#include "drm_layer.h" #include #include @@ -33,35 +34,20 @@ class DrmGpu; class SurfaceItem; class GLTexture; -class EglGbmLayer { +class EglGbmLayer : public DrmLayer +{ public: EglGbmLayer(DrmGpu *renderGpu, DrmAbstractOutput *output); ~EglGbmLayer(); - std::optional startRendering(); - 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 - */ - bool scanout(SurfaceItem *surfaceItem); - - /** - * @returns a buffer for atomic test commits - * If no fitting buffer is available, one is created - */ - QSharedPointer testBuffer(); - - /** - * only temporarily here, should be migrated out! - */ + std::optional startRendering() override; + bool endRendering(const QRegion &damagedRegion) override; + bool scanout(SurfaceItem *surfaceItem) override; + QSharedPointer testBuffer() override; + QSharedPointer currentBuffer() const override; QSharedPointer texture() const; - QSharedPointer currentBuffer() const; - - DrmAbstractOutput *output() const; + DrmAbstractOutput *output() const override; int bufferAge() const; EGLSurface eglSurface() const; diff --git a/src/backends/drm/scene_qpainter_drm_backend.cpp b/src/backends/drm/scene_qpainter_drm_backend.cpp index 7ba2d01088..f645f822ed 100644 --- a/src/backends/drm/scene_qpainter_drm_backend.cpp +++ b/src/backends/drm/scene_qpainter_drm_backend.cpp @@ -12,6 +12,7 @@ #include "drm_gpu.h" #include "drm_buffer.h" #include "renderloop_p.h" +#include "drm_qpainter_layer.h" #include @@ -22,6 +23,9 @@ DrmQPainterBackend::DrmQPainterBackend(DrmBackend *backend) : QPainterBackend() , m_backend(backend) { + connect(m_backend, &DrmBackend::outputEnabled, this, [this] (const auto output) { + m_swapchains[output] = QSharedPointer::create(static_cast(output)); + }); connect(m_backend, &DrmBackend::outputDisabled, this, [this] (const auto output) { m_swapchains.remove(output); }); @@ -29,26 +33,19 @@ DrmQPainterBackend::DrmQPainterBackend(DrmBackend *backend) QImage *DrmQPainterBackend::bufferForScreen(AbstractOutput *output) { - return m_swapchains[output]->currentBuffer()->image(); + return static_cast(m_swapchains[output]->currentBuffer().data())->image(); } QRegion DrmQPainterBackend::beginFrame(AbstractOutput *output) { - const auto drmOutput = static_cast(output); - if (!m_swapchains[output] || m_swapchains[output]->size() != drmOutput->sourceSize()) { - m_swapchains[output] = QSharedPointer::create(drmOutput->gpu(), drmOutput->sourceSize(), DRM_FORMAT_XRGB8888); - } - QRegion needsRepainting; - m_swapchains[output]->acquireBuffer(output->geometry(), &needsRepainting); - return needsRepainting; + return m_swapchains[output]->startRendering().value_or(QRegion()); } void DrmQPainterBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damage) { Q_UNUSED(renderedRegion) - QSharedPointer back = m_swapchains[output]->currentBuffer(); - m_swapchains[output]->releaseBuffer(back, damage); - static_cast(output)->present(back, output->geometry()); + m_swapchains[output]->endRendering(damage); + static_cast(output)->present(m_swapchains[output]->currentBuffer(), output->geometry()); } } diff --git a/src/backends/drm/scene_qpainter_drm_backend.h b/src/backends/drm/scene_qpainter_drm_backend.h index 5141588408..71c6b6b34d 100644 --- a/src/backends/drm/scene_qpainter_drm_backend.h +++ b/src/backends/drm/scene_qpainter_drm_backend.h @@ -20,9 +20,8 @@ namespace KWin { class DrmBackend; -class DrmDumbBuffer; class DrmAbstractOutput; -class DrmGpu; +class DrmQPainterLayer; class DrmQPainterBackend : public QPainterBackend { @@ -35,7 +34,7 @@ public: void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; private: - QMap> m_swapchains; + QMap> m_swapchains; DrmBackend *m_backend; }; }