diff --git a/src/abstract_output.cpp b/src/abstract_output.cpp index 4595e9a159..9ac27409e4 100644 --- a/src/abstract_output.cpp +++ b/src/abstract_output.cpp @@ -79,7 +79,6 @@ QDebug operator<<(QDebug debug, const AbstractOutput *output) AbstractOutput::AbstractOutput(QObject *parent) : QObject(parent) - , m_layer(new OutputLayer(this)) { } @@ -87,11 +86,6 @@ AbstractOutput::~AbstractOutput() { } -OutputLayer *AbstractOutput::layer() const -{ - return m_layer; -} - QUuid AbstractOutput::uuid() const { return QUuid(); diff --git a/src/abstract_output.h b/src/abstract_output.h index 718d508b74..4bf09f1594 100644 --- a/src/abstract_output.h +++ b/src/abstract_output.h @@ -26,7 +26,6 @@ class OutputChangeSetV2; namespace KWin { class EffectScreenImpl; -class OutputLayer; class RenderLoop; class KWIN_EXPORT GammaRamp @@ -99,15 +98,6 @@ public: */ QRect mapFromGlobal(const QRect &rect) const; - /** - * Returns a dummy OutputLayer corresponding to the primary plane. - * - * TODO: remove this. The Compositor should allocate and deallocate hardware planes - * after the pre paint pass. Planes must be allocated based on the bounding rect, transform, - * and visibility (for the cursor plane). - */ - OutputLayer *layer() const; - /** * Returns a short identifiable name of this output. */ @@ -285,7 +275,6 @@ Q_SIGNALS: private: Q_DISABLE_COPY(AbstractOutput) EffectScreenImpl *m_effectScreen = nullptr; - OutputLayer *m_layer; int m_directScanoutCount = 0; friend class EffectScreenImpl; // to access m_effectScreen }; diff --git a/src/backends/drm/drm_layer.cpp b/src/backends/drm/drm_layer.cpp index b8813d9de6..ec2687f75b 100644 --- a/src/backends/drm/drm_layer.cpp +++ b/src/backends/drm/drm_layer.cpp @@ -16,28 +16,6 @@ namespace KWin DrmOutputLayer::~DrmOutputLayer() = default; -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 {}; diff --git a/src/backends/drm/drm_layer.h b/src/backends/drm/drm_layer.h index 58799370ef..285889266e 100644 --- a/src/backends/drm/drm_layer.h +++ b/src/backends/drm/drm_layer.h @@ -7,6 +7,7 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once +#include "outputlayer.h" #include #include @@ -21,25 +22,12 @@ class DrmBuffer; class GLTexture; class DrmPipeline; -class DrmOutputLayer : public QObject +class DrmOutputLayer : public OutputLayer { - Q_OBJECT public: virtual ~DrmOutputLayer(); - virtual void aboutToStartPainting(const QRegion &damagedRegion); - 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); - virtual QSharedPointer texture() const; - virtual QRegion currentDamage() const; }; diff --git a/src/backends/drm/drm_lease_egl_gbm_layer.cpp b/src/backends/drm/drm_lease_egl_gbm_layer.cpp index 7f8e40338e..223c7abd90 100644 --- a/src/backends/drm/drm_lease_egl_gbm_layer.cpp +++ b/src/backends/drm/drm_lease_egl_gbm_layer.cpp @@ -57,4 +57,14 @@ QSharedPointer DrmLeaseEglGbmLayer::currentBuffer() const return m_buffer; } +QRegion DrmLeaseEglGbmLayer::beginFrame() +{ + return QRegion(); +} + +void DrmLeaseEglGbmLayer::endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) +{ + Q_UNUSED(damagedRegion) + Q_UNUSED(renderedRegion) +} } diff --git a/src/backends/drm/drm_lease_egl_gbm_layer.h b/src/backends/drm/drm_lease_egl_gbm_layer.h index 52b2f445e7..a00b14debf 100644 --- a/src/backends/drm/drm_lease_egl_gbm_layer.h +++ b/src/backends/drm/drm_lease_egl_gbm_layer.h @@ -21,6 +21,9 @@ class DrmLeaseEglGbmLayer : public DrmPipelineLayer public: DrmLeaseEglGbmLayer(EglGbmBackend *backend, DrmPipeline *pipeline); + QRegion beginFrame() override; + void endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override; + QSharedPointer testBuffer() override; QSharedPointer currentBuffer() const override; diff --git a/src/backends/drm/drm_qpainter_layer.cpp b/src/backends/drm/drm_qpainter_layer.cpp index 0289ee315a..2a1b7c23b3 100644 --- a/src/backends/drm/drm_qpainter_layer.cpp +++ b/src/backends/drm/drm_qpainter_layer.cpp @@ -30,23 +30,23 @@ DrmQPainterLayer::DrmQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pip }); } -std::optional DrmQPainterLayer::startRendering() +QRegion DrmQPainterLayer::beginFrame() { if (!doesSwapchainFit()) { m_swapchain = QSharedPointer::create(m_pipeline->gpu(), m_pipeline->sourceSize(), DRM_FORMAT_XRGB8888); } QRegion needsRepaint; if (!m_swapchain->acquireBuffer(&needsRepaint)) { - return std::optional(); + return QRegion(); } return needsRepaint; } -bool DrmQPainterLayer::endRendering(const QRegion &damagedRegion) +void DrmQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) { + Q_UNUSED(renderedRegion) m_currentDamage = damagedRegion; m_swapchain->releaseBuffer(m_swapchain->currentBuffer(), damagedRegion); - return true; } QSharedPointer DrmQPainterLayer::testBuffer() @@ -82,7 +82,7 @@ DrmVirtualQPainterLayer::DrmVirtualQPainterLayer(DrmVirtualOutput *output) { } -std::optional DrmVirtualQPainterLayer::startRendering() +QRegion DrmVirtualQPainterLayer::beginFrame() { if (m_image.isNull() || m_image.size() != m_output->pixelSize()) { m_image = QImage(m_output->pixelSize(), QImage::Format_RGB32); @@ -90,10 +90,10 @@ std::optional DrmVirtualQPainterLayer::startRendering() return QRegion(); } -bool DrmVirtualQPainterLayer::endRendering(const QRegion &damagedRegion) +void DrmVirtualQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) { + Q_UNUSED(renderedRegion) m_currentDamage = damagedRegion; - return true; } QRegion DrmVirtualQPainterLayer::currentDamage() const @@ -128,4 +128,14 @@ QSharedPointer DrmLeaseQPainterLayer::currentBuffer() const return m_buffer; } +QRegion DrmLeaseQPainterLayer::beginFrame() +{ + return QRegion(); +} + +void DrmLeaseQPainterLayer::endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) +{ + Q_UNUSED(damagedRegion) + Q_UNUSED(renderedRegion) +} } diff --git a/src/backends/drm/drm_qpainter_layer.h b/src/backends/drm/drm_qpainter_layer.h index ca31fc39c6..c7efa63420 100644 --- a/src/backends/drm/drm_qpainter_layer.h +++ b/src/backends/drm/drm_qpainter_layer.h @@ -33,8 +33,8 @@ class DrmQPainterLayer : public DrmPipelineLayer, public QPainterLayer public: DrmQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline); - std::optional startRendering() override; - bool endRendering(const QRegion &damagedRegion) override; + QRegion beginFrame() override; + void endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override; QSharedPointer testBuffer() override; QSharedPointer currentBuffer() const override; QRegion currentDamage() const override; @@ -52,8 +52,8 @@ class DrmVirtualQPainterLayer : public DrmOutputLayer, public QPainterLayer public: DrmVirtualQPainterLayer(DrmVirtualOutput *output); - std::optional startRendering() override; - bool endRendering(const QRegion &damagedRegion) override; + QRegion beginFrame() override; + void endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override; QRegion currentDamage() const override; QImage *image() override; @@ -69,6 +69,9 @@ class DrmLeaseQPainterLayer : public DrmPipelineLayer public: DrmLeaseQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline); + QRegion beginFrame() override; + void endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override; + QSharedPointer testBuffer() override; QSharedPointer currentBuffer() const override; diff --git a/src/backends/drm/egl_gbm_backend.cpp b/src/backends/drm/egl_gbm_backend.cpp index 2f7ae45a07..b80bd33d55 100644 --- a/src/backends/drm/egl_gbm_backend.cpp +++ b/src/backends/drm/egl_gbm_backend.cpp @@ -216,11 +216,6 @@ bool EglGbmBackend::initBufferConfigs() return false; } -void EglGbmBackend::aboutToStartPainting(AbstractOutput *output, const QRegion &damagedRegion) -{ - static_cast(output)->outputLayer()->aboutToStartPainting(damagedRegion); -} - SurfaceTexture *EglGbmBackend::createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) { return new BasicEGLSurfaceTextureInternal(this, pixmap); @@ -231,33 +226,14 @@ SurfaceTexture *EglGbmBackend::createSurfaceTextureWayland(SurfacePixmapWayland return new BasicEGLSurfaceTextureWayland(this, pixmap); } -QRegion EglGbmBackend::beginFrame(AbstractOutput *output) -{ - return static_cast(output)->outputLayer()->startRendering().value_or(QRegion()); -} - -void EglGbmBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, - const QRegion &damagedRegion) -{ - Q_UNUSED(renderedRegion) - - const auto drmOutput = static_cast(output); - drmOutput->outputLayer()->endRendering(damagedRegion); -} - void EglGbmBackend::present(AbstractOutput *output) { static_cast(output)->present(); } -bool EglGbmBackend::scanout(AbstractOutput *output, SurfaceItem *surfaceItem) +OutputLayer *EglGbmBackend::primaryLayer(AbstractOutput *output) { - const auto drmOutput = static_cast(output); - if (drmOutput->outputLayer()->scanout(surfaceItem)) { - return true; - } else { - return false; - } + return static_cast(output)->outputLayer(); } QSharedPointer EglGbmBackend::textureForOutput(AbstractOutput *output) const diff --git a/src/backends/drm/egl_gbm_backend.h b/src/backends/drm/egl_gbm_backend.h index 4ea099b10f..83a2a326c3 100644 --- a/src/backends/drm/egl_gbm_backend.h +++ b/src/backends/drm/egl_gbm_backend.h @@ -64,12 +64,10 @@ public: SurfaceTexture *createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override; SurfaceTexture *createSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override; - QRegion beginFrame(AbstractOutput *output) override; - void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; void present(AbstractOutput *output) override; + OutputLayer *primaryLayer(AbstractOutput *output) override; void init() override; - bool scanout(AbstractOutput *output, SurfaceItem *surfaceItem) override; bool prefer10bpc() const override; QSharedPointer createDrmPipelineLayer(DrmPipeline *pipeline) override; QSharedPointer createLayer(DrmVirtualOutput *output) override; @@ -84,9 +82,6 @@ public: Q_SIGNALS: void aboutToBeDestroyed(); -protected: - void aboutToStartPainting(AbstractOutput *output, const QRegion &damage) override; - private: bool initializeEgl(); bool initBufferConfigs(); diff --git a/src/backends/drm/egl_gbm_layer.cpp b/src/backends/drm/egl_gbm_layer.cpp index d68a3c3dc5..c19a31332c 100644 --- a/src/backends/drm/egl_gbm_layer.cpp +++ b/src/backends/drm/egl_gbm_layer.cpp @@ -61,7 +61,7 @@ void EglGbmLayer::destroyResources() m_oldGbmSurface.reset(); } -std::optional EglGbmLayer::startRendering() +QRegion EglGbmLayer::beginFrame() { m_scanoutBuffer.reset(); // dmabuf feedback @@ -81,14 +81,14 @@ std::optional EglGbmLayer::startRendering() m_gbmSurface = m_oldGbmSurface; } else { if (!createGbmSurface()) { - return std::optional(); + return QRegion(); } // dmabuf might work with the new surface m_importMode = MultiGpuImportMode::Dmabuf; } } if (!m_gbmSurface->makeContextCurrent()) { - return std::optional(); + return QRegion(); } auto repaintRegion = m_gbmSurface->repaintRegion(); @@ -103,7 +103,7 @@ std::optional EglGbmLayer::startRendering() const auto format = m_eglBackend->gbmFormatForDrmFormat(m_gbmSurface->format()); m_shadowBuffer = QSharedPointer::create(m_pipeline->sourceSize(), format); if (!m_shadowBuffer->isComplete()) { - return std::optional(); + return QRegion(); } } else { m_shadowBuffer.reset(); @@ -132,8 +132,9 @@ void EglGbmLayer::aboutToStartPainting(const QRegion &damagedRegion) } } -bool EglGbmLayer::endRendering(const QRegion &damagedRegion) +void EglGbmLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) { + Q_UNUSED(renderedRegion) if (m_shadowBuffer) { GLRenderTarget::popRenderTarget(); // TODO handle m_pipeline->pending.bufferTransformation != Rotate0 @@ -152,7 +153,6 @@ bool EglGbmLayer::endRendering(const QRegion &damagedRegion) m_currentBuffer = buffer; m_currentDamage = damagedRegion; } - return !buffer.isNull(); } QRegion EglGbmLayer::currentDamage() const @@ -181,14 +181,11 @@ QSharedPointer EglGbmLayer::testBuffer() bool EglGbmLayer::renderTestBuffer() { - if (!startRendering()) { - return false; - } + const auto oldBuffer = m_currentBuffer; + beginFrame(); glClear(GL_COLOR_BUFFER_BIT); - if (!endRendering(infiniteRegion())) { - return false; - } - return true; + endFrame(QRegion(), infiniteRegion()); + return m_currentBuffer != oldBuffer; } bool EglGbmLayer::createGbmSurface(uint32_t format, const QVector &modifiers) diff --git a/src/backends/drm/egl_gbm_layer.h b/src/backends/drm/egl_gbm_layer.h index 9b22b28bc9..aeba7db6a2 100644 --- a/src/backends/drm/egl_gbm_layer.h +++ b/src/backends/drm/egl_gbm_layer.h @@ -36,9 +36,9 @@ public: EglGbmLayer(EglGbmBackend *eglBackend, DrmPipeline *pipeline); ~EglGbmLayer(); - std::optional startRendering() override; + QRegion beginFrame() override; void aboutToStartPainting(const QRegion &damagedRegion) override; - bool endRendering(const QRegion &damagedRegion) override; + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override; bool scanout(SurfaceItem *surfaceItem) override; QSharedPointer testBuffer() override; QSharedPointer currentBuffer() const override; diff --git a/src/backends/drm/scene_qpainter_drm_backend.cpp b/src/backends/drm/scene_qpainter_drm_backend.cpp index 882d3252e4..64e0579828 100644 --- a/src/backends/drm/scene_qpainter_drm_backend.cpp +++ b/src/backends/drm/scene_qpainter_drm_backend.cpp @@ -39,24 +39,16 @@ QImage *DrmQPainterBackend::bufferForScreen(AbstractOutput *output) return dynamic_cast(drmOutput->outputLayer())->image(); } -QRegion DrmQPainterBackend::beginFrame(AbstractOutput *output) -{ - const auto drmOutput = static_cast(output); - return drmOutput->outputLayer()->startRendering().value_or(QRegion()); -} - -void DrmQPainterBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damage) -{ - Q_UNUSED(renderedRegion) - const auto drmOutput = static_cast(output); - drmOutput->outputLayer()->endRendering(damage); -} - void DrmQPainterBackend::present(AbstractOutput *output) { static_cast(output)->present(); } +OutputLayer *DrmQPainterBackend::primaryLayer(AbstractOutput *output) +{ + return static_cast(output)->outputLayer(); +} + QSharedPointer DrmQPainterBackend::createDrmPipelineLayer(DrmPipeline *pipeline) { if (pipeline->output()) { diff --git a/src/backends/drm/scene_qpainter_drm_backend.h b/src/backends/drm/scene_qpainter_drm_backend.h index 51c132e57a..4bf0f44f02 100644 --- a/src/backends/drm/scene_qpainter_drm_backend.h +++ b/src/backends/drm/scene_qpainter_drm_backend.h @@ -31,9 +31,8 @@ public: ~DrmQPainterBackend(); QImage *bufferForScreen(AbstractOutput *output) override; - QRegion beginFrame(AbstractOutput *output) override; - void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; void present(AbstractOutput *output) override; + OutputLayer *primaryLayer(AbstractOutput *output) override; QSharedPointer createDrmPipelineLayer(DrmPipeline *pipeline) override; QSharedPointer createLayer(DrmVirtualOutput *output) override; diff --git a/src/backends/drm/virtual_egl_gbm_layer.cpp b/src/backends/drm/virtual_egl_gbm_layer.cpp index 4618a4a96f..e90dce015b 100644 --- a/src/backends/drm/virtual_egl_gbm_layer.cpp +++ b/src/backends/drm/virtual_egl_gbm_layer.cpp @@ -61,7 +61,7 @@ void VirtualEglGbmLayer::aboutToStartPainting(const QRegion &damagedRegion) } } -std::optional VirtualEglGbmLayer::startRendering() +QRegion VirtualEglGbmLayer::beginFrame() { // gbm surface if (doesGbmSurfaceFit(m_gbmSurface.data())) { @@ -71,18 +71,18 @@ std::optional VirtualEglGbmLayer::startRendering() m_gbmSurface = m_oldGbmSurface; } else { if (!createGbmSurface()) { - return std::optional(); + return QRegion(); } } } if (!m_gbmSurface->makeContextCurrent()) { - return std::optional(); + return QRegion(); } GLRenderTarget::pushRenderTarget(m_gbmSurface->renderTarget()); return m_gbmSurface->repaintRegion(); } -bool VirtualEglGbmLayer::endRendering(const QRegion &damagedRegion) +void VirtualEglGbmLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) { GLRenderTarget::popRenderTarget(); const auto buffer = m_gbmSurface->swapBuffers(damagedRegion.intersected(m_output->geometry())); @@ -90,7 +90,6 @@ bool VirtualEglGbmLayer::endRendering(const QRegion &damagedRegion) m_currentBuffer = buffer; m_currentDamage = damagedRegion; } - return !buffer.isNull(); } QRegion VirtualEglGbmLayer::currentDamage() const diff --git a/src/backends/drm/virtual_egl_gbm_layer.h b/src/backends/drm/virtual_egl_gbm_layer.h index 4f3b202418..af0f493636 100644 --- a/src/backends/drm/virtual_egl_gbm_layer.h +++ b/src/backends/drm/virtual_egl_gbm_layer.h @@ -36,8 +36,8 @@ public: VirtualEglGbmLayer(EglGbmBackend *eglBackend, DrmVirtualOutput *output); void aboutToStartPainting(const QRegion &damagedRegion) override; - std::optional startRendering() override; - bool endRendering(const QRegion &damagedRegion) override; + QRegion beginFrame() override; + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override; bool scanout(SurfaceItem *surfaceItem) override; QRegion currentDamage() const override; diff --git a/src/backends/virtual/egl_gbm_backend.cpp b/src/backends/virtual/egl_gbm_backend.cpp index 72f298e132..5406171ea5 100644 --- a/src/backends/virtual/egl_gbm_backend.cpp +++ b/src/backends/virtual/egl_gbm_backend.cpp @@ -30,9 +30,26 @@ namespace KWin { +VirtualOutputLayer::VirtualOutputLayer(EglGbmBackend *backend) + : m_backend(backend) +{ +} + +QRegion VirtualOutputLayer::beginFrame() +{ + return m_backend->beginFrame(); +} + +void VirtualOutputLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) +{ + Q_UNUSED(renderedRegion) + Q_UNUSED(damagedRegion) +} + EglGbmBackend::EglGbmBackend(VirtualBackend *b) : AbstractEglBackend() , m_backend(b) + , m_layer(new VirtualOutputLayer(this)) { // Egl is always direct rendering setIsDirectRendering(true); @@ -158,9 +175,8 @@ SurfaceTexture *EglGbmBackend::createSurfaceTextureWayland(SurfacePixmapWayland return new BasicEGLSurfaceTextureWayland(this, pixmap); } -QRegion EglGbmBackend::beginFrame(AbstractOutput *output) +QRegion EglGbmBackend::beginFrame() { - Q_UNUSED(output) if (!GLRenderTarget::currentRenderTarget()) { GLRenderTarget::pushRenderTarget(m_fbo); } @@ -197,11 +213,10 @@ static void convertFromGLImage(QImage &img, int w, int h) img = img.mirrored(); } -void EglGbmBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) +OutputLayer *EglGbmBackend::primaryLayer(AbstractOutput *output) { Q_UNUSED(output) - Q_UNUSED(renderedRegion) - Q_UNUSED(damagedRegion) + return m_layer.get(); } void EglGbmBackend::present(AbstractOutput *output) diff --git a/src/backends/virtual/egl_gbm_backend.h b/src/backends/virtual/egl_gbm_backend.h index 9a65c271be..b2c6f162c7 100644 --- a/src/backends/virtual/egl_gbm_backend.h +++ b/src/backends/virtual/egl_gbm_backend.h @@ -9,12 +9,26 @@ #ifndef KWIN_EGL_GBM_BACKEND_H #define KWIN_EGL_GBM_BACKEND_H #include "abstract_egl_backend.h" +#include "outputlayer.h" namespace KWin { class VirtualBackend; class GLTexture; class GLRenderTarget; +class EglGbmBackend; + +class VirtualOutputLayer : public OutputLayer +{ +public: + VirtualOutputLayer(EglGbmBackend *backend); + + QRegion beginFrame() override; + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override; + +private: + EglGbmBackend *const m_backend; +}; /** * @brief OpenGL Backend using Egl on a GBM surface. @@ -28,11 +42,12 @@ public: ~EglGbmBackend() override; SurfaceTexture *createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override; SurfaceTexture *createSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override; - QRegion beginFrame(AbstractOutput *output) override; - void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; + OutputLayer *primaryLayer(AbstractOutput *output) override; void present(AbstractOutput *output) override; void init() override; + QRegion beginFrame(); + private: bool initializeEgl(); bool initBufferConfigs(); @@ -41,6 +56,7 @@ private: GLTexture *m_backBuffer = nullptr; GLRenderTarget *m_fbo = nullptr; int m_frameCounter = 0; + QScopedPointer m_layer; }; } // namespace diff --git a/src/backends/virtual/scene_qpainter_virtual_backend.cpp b/src/backends/virtual/scene_qpainter_virtual_backend.cpp index beb7bfc530..bd5e5d741f 100644 --- a/src/backends/virtual/scene_qpainter_virtual_backend.cpp +++ b/src/backends/virtual/scene_qpainter_virtual_backend.cpp @@ -17,6 +17,30 @@ namespace KWin { + +VirtualQPainterLayer::VirtualQPainterLayer(AbstractOutput *output) + : m_output(output) + , m_image(output->pixelSize(), QImage::Format_RGB32) +{ + m_image.fill(Qt::black); +} + +QRegion VirtualQPainterLayer::beginFrame() +{ + return m_output->geometry(); +} + +void VirtualQPainterLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) +{ + Q_UNUSED(renderedRegion) + Q_UNUSED(damagedRegion) +} + +QImage *VirtualQPainterLayer::image() +{ + return &m_image; +} + VirtualQPainterBackend::VirtualQPainterBackend(VirtualBackend *backend) : QPainterBackend() , m_backend(backend) @@ -29,38 +53,29 @@ VirtualQPainterBackend::~VirtualQPainterBackend() = default; QImage *VirtualQPainterBackend::bufferForScreen(AbstractOutput *output) { - return &m_backBuffers[output]; -} - -QRegion VirtualQPainterBackend::beginFrame(AbstractOutput *output) -{ - return output->geometry(); + return m_outputs[output]->image(); } void VirtualQPainterBackend::createOutputs() { - m_backBuffers.clear(); + m_outputs.clear(); const auto outputs = m_backend->enabledOutputs(); for (const auto &output : outputs) { - QImage buffer(output->pixelSize(), QImage::Format_RGB32); - buffer.fill(Qt::black); - m_backBuffers.insert(output, buffer); + m_outputs.insert(output, QSharedPointer::create(output)); } } -void VirtualQPainterBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) -{ - Q_UNUSED(output) - Q_UNUSED(renderedRegion) - Q_UNUSED(damagedRegion) -} - void VirtualQPainterBackend::present(AbstractOutput *output) { static_cast(output)->vsyncMonitor()->arm(); if (m_backend->saveFrames()) { - m_backBuffers[output].save(QStringLiteral("%1/%s-%3.png").arg(m_backend->screenshotDirPath(), output->name(), QString::number(m_frameCounter++))); + m_outputs[output]->image()->save(QStringLiteral("%1/%s-%3.png").arg(m_backend->screenshotDirPath(), output->name(), QString::number(m_frameCounter++))); } } + +OutputLayer *VirtualQPainterBackend::primaryLayer(AbstractOutput *output) +{ + return m_outputs[output].get(); +} } diff --git a/src/backends/virtual/scene_qpainter_virtual_backend.h b/src/backends/virtual/scene_qpainter_virtual_backend.h index fe58c324ab..52f548ecd8 100644 --- a/src/backends/virtual/scene_qpainter_virtual_backend.h +++ b/src/backends/virtual/scene_qpainter_virtual_backend.h @@ -9,6 +9,7 @@ #ifndef KWIN_SCENE_QPAINTER_VIRTUAL_BACKEND_H #define KWIN_SCENE_QPAINTER_VIRTUAL_BACKEND_H +#include "outputlayer.h" #include "qpainterbackend.h" #include @@ -20,6 +21,20 @@ namespace KWin class VirtualBackend; +class VirtualQPainterLayer : public OutputLayer +{ +public: + VirtualQPainterLayer(AbstractOutput *output); + + QRegion beginFrame() override; + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override; + QImage *image(); + +private: + AbstractOutput *const m_output; + QImage m_image; +}; + class VirtualQPainterBackend : public QPainterBackend { Q_OBJECT @@ -28,14 +43,13 @@ public: ~VirtualQPainterBackend() override; QImage *bufferForScreen(AbstractOutput *output) override; - QRegion beginFrame(AbstractOutput *output) override; - void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; void present(AbstractOutput *output) override; + OutputLayer *primaryLayer(AbstractOutput *output) override; private: void createOutputs(); - QMap m_backBuffers; + QMap> m_outputs; VirtualBackend *m_backend; int m_frameCounter = 0; }; diff --git a/src/backends/wayland/egl_wayland_backend.cpp b/src/backends/wayland/egl_wayland_backend.cpp index 5343d0a8fa..dbb4a899e1 100644 --- a/src/backends/wayland/egl_wayland_backend.cpp +++ b/src/backends/wayland/egl_wayland_backend.cpp @@ -44,13 +44,33 @@ namespace KWin namespace Wayland { -EglWaylandOutput::EglWaylandOutput(WaylandOutput *output, QObject *parent) - : QObject(parent) - , m_waylandOutput(output) +static QVector regionToRects(const QRegion ®ion, AbstractWaylandOutput *output) +{ + const int height = output->modeSize().height(); + const QMatrix4x4 matrix = WaylandOutput::logicalToNativeMatrix(output->rect(), + output->scale(), + output->transform()); + + QVector rects; + rects.reserve(region.rectCount() * 4); + for (const QRect &_rect : region) { + const QRect rect = matrix.mapRect(_rect); + + rects << rect.left(); + rects << height - (rect.y() + rect.height()); + rects << rect.width(); + rects << rect.height(); + } + return rects; +} + +EglWaylandOutput::EglWaylandOutput(WaylandOutput *output, EglWaylandBackend *backend) + : m_waylandOutput(output) + , m_backend(backend) { } -bool EglWaylandOutput::init(EglWaylandBackend *backend) +bool EglWaylandOutput::init() { auto surface = m_waylandOutput->surface(); const QSize nativeSize = m_waylandOutput->geometry().size() * m_waylandOutput->scale(); @@ -63,10 +83,10 @@ bool EglWaylandOutput::init(EglWaylandBackend *backend) m_renderTarget.reset(new GLRenderTarget(0, nativeSize)); EGLSurface eglSurface = EGL_NO_SURFACE; - if (backend->havePlatformBase()) { - eglSurface = eglCreatePlatformWindowSurfaceEXT(backend->eglDisplay(), backend->config(), (void *)overlay, nullptr); + if (m_backend->havePlatformBase()) { + eglSurface = eglCreatePlatformWindowSurfaceEXT(m_backend->eglDisplay(), m_backend->config(), (void *)overlay, nullptr); } else { - eglSurface = eglCreateWindowSurface(backend->eglDisplay(), backend->config(), overlay, nullptr); + eglSurface = eglCreateWindowSurface(m_backend->eglDisplay(), m_backend->config(), overlay, nullptr); } if (eglSurface == EGL_NO_SURFACE) { qCCritical(KWIN_WAYLAND_BACKEND) << "Create Window Surface failed"; @@ -83,6 +103,7 @@ bool EglWaylandOutput::init(EglWaylandBackend *backend) EglWaylandOutput::~EglWaylandOutput() { + wl_egl_window_destroy(m_overlay); } GLRenderTarget *EglWaylandOutput::renderTarget() const @@ -104,6 +125,76 @@ void EglWaylandOutput::resetBufferAge() m_bufferAge = 0; } +bool EglWaylandOutput::makeContextCurrent() const +{ + if (m_eglSurface == EGL_NO_SURFACE) { + return false; + } + if (eglMakeCurrent(m_backend->eglDisplay(), m_eglSurface, m_eglSurface, m_backend->context()) == EGL_FALSE) { + qCCritical(KWIN_WAYLAND_BACKEND) << "Make Context Current failed"; + return false; + } + EGLint error = eglGetError(); + if (error != EGL_SUCCESS) { + qCWarning(KWIN_WAYLAND_BACKEND) << "Error occurred while creating context " << error; + return false; + } + return true; +} + +QRegion EglWaylandOutput::beginFrame() +{ + eglWaitNative(EGL_CORE_NATIVE_ENGINE); + makeContextCurrent(); + GLRenderTarget::pushRenderTarget(m_renderTarget.get()); + if (m_backend->supportsBufferAge()) { + return m_damageJournal.accumulate(m_bufferAge, infiniteRegion()); + } + return QRegion(); +} + +void EglWaylandOutput::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) +{ + Q_UNUSED(renderedRegion) + m_damageJournal.add(damagedRegion); + GLRenderTarget::popRenderTarget(); +} + +void EglWaylandOutput::aboutToStartPainting(const QRegion &damage) +{ + if (m_bufferAge > 0 && !damage.isEmpty() && m_backend->supportsPartialUpdate()) { + QVector rects = regionToRects(damage, m_waylandOutput); + const bool correct = eglSetDamageRegionKHR(m_backend->eglDisplay(), m_eglSurface, + rects.data(), rects.count() / 4); + if (!correct) { + qCWarning(KWIN_WAYLAND_BACKEND) << "failed eglSetDamageRegionKHR" << eglGetError(); + } + } +} + +void EglWaylandOutput::present() +{ + m_waylandOutput->surface()->setupFrameCallback(); + m_waylandOutput->surface()->setScale(std::ceil(m_waylandOutput->scale())); + Q_EMIT m_waylandOutput->outputChange(m_damageJournal.lastDamage()); + + if (m_backend->supportsSwapBuffersWithDamage()) { + QVector rects = regionToRects(m_damageJournal.lastDamage(), m_waylandOutput); + if (!eglSwapBuffersWithDamageEXT(m_backend->eglDisplay(), m_eglSurface, + rects.data(), rects.count() / 4)) { + qCCritical(KWIN_WAYLAND_BACKEND, "eglSwapBuffersWithDamage() failed: %x", eglGetError()); + } + } else { + if (!eglSwapBuffers(m_backend->eglDisplay(), m_eglSurface)) { + qCCritical(KWIN_WAYLAND_BACKEND, "eglSwapBuffers() failed: %x", eglGetError()); + } + } + + if (m_backend->supportsBufferAge()) { + eglQuerySurface(m_backend->eglDisplay(), m_eglSurface, EGL_BUFFER_AGE_EXT, &m_bufferAge); + } +} + EglWaylandBackend::EglWaylandBackend(WaylandBackend *b) : AbstractEglBackend() , m_backend(b) @@ -123,13 +214,12 @@ EglWaylandBackend::EglWaylandBackend(WaylandBackend *b) connect(m_backend, &WaylandBackend::outputAdded, this, &EglWaylandBackend::createEglWaylandOutput); connect(m_backend, &WaylandBackend::outputRemoved, this, [this](AbstractOutput *output) { - auto it = std::find_if(m_outputs.begin(), m_outputs.end(), [output](const EglWaylandOutput *o) { + auto it = std::find_if(m_outputs.begin(), m_outputs.end(), [output](const auto &o) { return o->m_waylandOutput == output; }); if (it == m_outputs.end()) { return; } - cleanupOutput(*it); m_outputs.erase(it); }); } @@ -141,28 +231,19 @@ EglWaylandBackend::~EglWaylandBackend() void EglWaylandBackend::cleanupSurfaces() { - for (auto o : qAsConst(m_outputs)) { - cleanupOutput(o); - } m_outputs.clear(); } bool EglWaylandBackend::createEglWaylandOutput(AbstractOutput *waylandOutput) { - const auto &output = new EglWaylandOutput(static_cast(waylandOutput), this); - if (!output->init(this)) { - delete output; + const auto output = QSharedPointer::create(static_cast(waylandOutput), this); + if (!output->init()) { return false; } m_outputs.insert(waylandOutput, output); return true; } -void EglWaylandBackend::cleanupOutput(EglWaylandOutput *output) -{ - wl_egl_window_destroy(output->m_overlay); -} - bool EglWaylandBackend::initializeEgl() { initClientExtensions(); @@ -233,30 +314,10 @@ bool EglWaylandBackend::initRenderingContext() return false; } - auto *firstOutput = m_outputs.first(); + const auto &firstOutput = m_outputs.first(); // set our first surface as the one for the abstract backend, just to make it happy setSurface(firstOutput->m_eglSurface); - return makeContextCurrent(firstOutput); -} - -bool EglWaylandBackend::makeContextCurrent(EglWaylandOutput *output) -{ - const EGLSurface eglSurface = output->m_eglSurface; - if (eglSurface == EGL_NO_SURFACE) { - return false; - } - if (eglMakeCurrent(eglDisplay(), eglSurface, eglSurface, context()) == EGL_FALSE) { - qCCritical(KWIN_WAYLAND_BACKEND) << "Make Context Current failed"; - return false; - } - - EGLint error = eglGetError(); - if (error != EGL_SUCCESS) { - qCWarning(KWIN_WAYLAND_BACKEND) << "Error occurred while creating context " << error; - return false; - } - - return true; + return firstOutput->makeContextCurrent(); } bool EglWaylandBackend::initBufferConfigs() @@ -294,26 +355,6 @@ bool EglWaylandBackend::initBufferConfigs() return true; } -static QVector regionToRects(const QRegion ®ion, AbstractWaylandOutput *output) -{ - const int height = output->modeSize().height(); - const QMatrix4x4 matrix = WaylandOutput::logicalToNativeMatrix(output->rect(), - output->scale(), - output->transform()); - - QVector rects; - rects.reserve(region.rectCount() * 4); - for (const QRect &_rect : region) { - const QRect rect = matrix.mapRect(_rect); - - rects << rect.left(); - rects << height - (rect.y() + rect.height()); - rects << rect.width(); - rects << rect.height(); - } - return rects; -} - QSharedPointer EglWaylandBackend::textureForOutput(KWin::AbstractOutput *output) const { QSharedPointer texture(new GLTexture(GL_RGBA8, output->pixelSize())); @@ -324,46 +365,6 @@ QSharedPointer EglWaylandBackend::textureForOutput(KWin::Abstra return texture; } -void EglWaylandBackend::aboutToStartPainting(AbstractOutput *output, const QRegion &damagedRegion) -{ - Q_ASSERT_X(output, "aboutToStartPainting", "not using per screen rendering"); - Q_ASSERT(m_outputs.contains(output)); - const auto &eglOutput = m_outputs[output]; - if (eglOutput->m_bufferAge > 0 && !damagedRegion.isEmpty() && supportsPartialUpdate()) { - QVector rects = regionToRects(damagedRegion, eglOutput->m_waylandOutput); - const bool correct = eglSetDamageRegionKHR(eglDisplay(), eglOutput->m_eglSurface, - rects.data(), rects.count() / 4); - if (!correct) { - qCWarning(KWIN_WAYLAND_BACKEND) << "failed eglSetDamageRegionKHR" << eglGetError(); - } - } -} - -void EglWaylandBackend::presentOnSurface(EglWaylandOutput *output, const QRegion &damage) -{ - WaylandOutput *waylandOutput = output->m_waylandOutput; - - waylandOutput->surface()->setupFrameCallback(); - waylandOutput->surface()->setScale(std::ceil(waylandOutput->scale())); - Q_EMIT waylandOutput->outputChange(damage); - - if (supportsSwapBuffersWithDamage()) { - QVector rects = regionToRects(damage, waylandOutput); - if (!eglSwapBuffersWithDamageEXT(eglDisplay(), output->m_eglSurface, - rects.data(), rects.count() / 4)) { - qCCritical(KWIN_WAYLAND_BACKEND, "eglSwapBuffersWithDamage() failed: %x", eglGetError()); - } - } else { - if (!eglSwapBuffers(eglDisplay(), output->m_eglSurface)) { - qCCritical(KWIN_WAYLAND_BACKEND, "eglSwapBuffers() failed: %x", eglGetError()); - } - } - - if (supportsBufferAge()) { - eglQuerySurface(eglDisplay(), output->m_eglSurface, EGL_BUFFER_AGE_EXT, &output->m_bufferAge); - } -} - SurfaceTexture *EglWaylandBackend::createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) { return new BasicEGLSurfaceTextureInternal(this, pixmap); @@ -374,40 +375,14 @@ SurfaceTexture *EglWaylandBackend::createSurfaceTextureWayland(SurfacePixmapWayl return new BasicEGLSurfaceTextureWayland(this, pixmap); } -QRegion EglWaylandBackend::beginFrame(AbstractOutput *output) -{ - Q_ASSERT(m_outputs.contains(output)); - eglWaitNative(EGL_CORE_NATIVE_ENGINE); - - const auto &eglOutput = m_outputs[output]; - makeContextCurrent(eglOutput); - - GLRenderTarget::pushRenderTarget(eglOutput->renderTarget()); - - if (supportsBufferAge()) { - return eglOutput->m_damageJournal.accumulate(eglOutput->m_bufferAge, infiniteRegion()); - } - - return QRegion(); -} - -void EglWaylandBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) -{ - Q_ASSERT(m_outputs.contains(output)); - Q_UNUSED(renderedRegion); - - m_lastDamagedRegion = damagedRegion; - GLRenderTarget::popRenderTarget(); -} - void EglWaylandBackend::present(AbstractOutput *output) { - const auto &eglOutput = m_outputs[output]; - presentOnSurface(eglOutput, m_lastDamagedRegion); + m_outputs[output]->present(); +} - if (supportsBufferAge()) { - eglOutput->m_damageJournal.add(m_lastDamagedRegion); - } +OutputLayer *EglWaylandBackend::primaryLayer(AbstractOutput *output) +{ + return m_outputs[output].get(); } } } diff --git a/src/backends/wayland/egl_wayland_backend.h b/src/backends/wayland/egl_wayland_backend.h index b8975a3997..40350423a6 100644 --- a/src/backends/wayland/egl_wayland_backend.h +++ b/src/backends/wayland/egl_wayland_backend.h @@ -10,6 +10,7 @@ #ifndef KWIN_EGL_WAYLAND_BACKEND_H #define KWIN_EGL_WAYLAND_BACKEND_H #include "abstract_egl_backend.h" +#include "outputlayer.h" #include "utils/damagejournal.h" // wayland #include @@ -28,17 +29,22 @@ class WaylandBackend; class WaylandOutput; class EglWaylandBackend; -class EglWaylandOutput : public QObject +class EglWaylandOutput : public OutputLayer { - Q_OBJECT public: - EglWaylandOutput(WaylandOutput *output, QObject *parent = nullptr); + EglWaylandOutput(WaylandOutput *output, EglWaylandBackend *backend); ~EglWaylandOutput() override; - bool init(EglWaylandBackend *backend); + bool init(); void updateSize(); GLRenderTarget *renderTarget() const; + bool makeContextCurrent() const; + void present(); + + QRegion beginFrame() override; + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override; + void aboutToStartPainting(const QRegion &damage) override; private: void resetBufferAge(); @@ -49,6 +55,7 @@ private: int m_bufferAge = 0; DamageJournal m_damageJournal; QScopedPointer m_renderTarget; + EglWaylandBackend *const m_backend; friend class EglWaylandBackend; }; @@ -75,10 +82,9 @@ public: SurfaceTexture *createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override; SurfaceTexture *createSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override; - QRegion beginFrame(AbstractOutput *output) override; - void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; - void present(AbstractOutput *output) override; void init() override; + void present(AbstractOutput *output) override; + OutputLayer *primaryLayer(AbstractOutput *output) override; bool havePlatformBase() const { @@ -86,7 +92,6 @@ public: } QSharedPointer textureForOutput(KWin::AbstractOutput *output) const override; - void aboutToStartPainting(AbstractOutput *output, const QRegion &damage) override; private: bool initializeEgl(); @@ -96,14 +101,11 @@ private: bool createEglWaylandOutput(AbstractOutput *output); void cleanupSurfaces() override; - void cleanupOutput(EglWaylandOutput *output); - bool makeContextCurrent(EglWaylandOutput *output); void presentOnSurface(EglWaylandOutput *output, const QRegion &damagedRegion); WaylandBackend *m_backend; - QMap m_outputs; - QRegion m_lastDamagedRegion; + QMap> m_outputs; bool m_havePlatformBase; friend class EglWaylandTexture; }; diff --git a/src/backends/wayland/scene_qpainter_wayland_backend.cpp b/src/backends/wayland/scene_qpainter_wayland_backend.cpp index 4bbee5aba0..fce143d052 100644 --- a/src/backends/wayland/scene_qpainter_wayland_backend.cpp +++ b/src/backends/wayland/scene_qpainter_wayland_backend.cpp @@ -38,9 +38,8 @@ WaylandQPainterBufferSlot::~WaylandQPainterBufferSlot() buffer->setUsed(false); } -WaylandQPainterOutput::WaylandQPainterOutput(WaylandOutput *output, QObject *parent) - : QObject(parent) - , m_waylandOutput(output) +WaylandQPainterOutput::WaylandQPainterOutput(WaylandOutput *output) + : m_waylandOutput(output) { } @@ -78,7 +77,7 @@ void WaylandQPainterOutput::updateSize(const QSize &size) m_slots.clear(); } -void WaylandQPainterOutput::present(const QRegion &damage) +void WaylandQPainterOutput::present() { for (WaylandQPainterBufferSlot *slot : qAsConst(m_slots)) { if (slot == m_back) { @@ -90,11 +89,9 @@ void WaylandQPainterOutput::present(const QRegion &damage) auto s = m_waylandOutput->surface(); s->attachBuffer(m_back->buffer); - s->damage(damage); + s->damage(m_damageJournal.lastDamage()); s->setScale(std::ceil(m_waylandOutput->scale())); s->commit(); - - m_damageJournal.add(damage); } WaylandQPainterBufferSlot *WaylandQPainterOutput::back() const @@ -131,6 +128,19 @@ QRegion WaylandQPainterOutput::accumulateDamage(int bufferAge) const return m_damageJournal.accumulate(bufferAge, infiniteRegion()); } +QRegion WaylandQPainterOutput::beginFrame() +{ + WaylandQPainterBufferSlot *slot = acquire(); + return accumulateDamage(slot->age); +} + +void WaylandQPainterOutput::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) +{ + Q_UNUSED(renderedRegion) + + m_damageJournal.add(damagedRegion); +} + WaylandQPainterBackend::WaylandQPainterBackend(Wayland::WaylandBackend *b) : QPainterBackend() , m_backend(b) @@ -142,13 +152,12 @@ WaylandQPainterBackend::WaylandQPainterBackend(Wayland::WaylandBackend *b) } connect(m_backend, &WaylandBackend::outputAdded, this, &WaylandQPainterBackend::createOutput); connect(m_backend, &WaylandBackend::outputRemoved, this, [this](AbstractOutput *waylandOutput) { - auto it = std::find_if(m_outputs.begin(), m_outputs.end(), [waylandOutput](WaylandQPainterOutput *output) { + auto it = std::find_if(m_outputs.begin(), m_outputs.end(), [waylandOutput](const auto &output) { return output->m_waylandOutput == waylandOutput; }); if (it == m_outputs.end()) { return; } - delete *it; m_outputs.erase(it); }); } @@ -159,36 +168,24 @@ WaylandQPainterBackend::~WaylandQPainterBackend() void WaylandQPainterBackend::createOutput(AbstractOutput *waylandOutput) { - auto *output = new WaylandQPainterOutput(static_cast(waylandOutput), this); + const auto output = QSharedPointer::create(static_cast(waylandOutput)); output->init(m_backend->shmPool()); m_outputs.insert(waylandOutput, output); } -void WaylandQPainterBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) -{ - Q_UNUSED(output) - Q_UNUSED(renderedRegion) - - m_lastDamagedRegion = damagedRegion; -} - QImage *WaylandQPainterBackend::bufferForScreen(AbstractOutput *output) { return &m_outputs[output]->back()->image; } -QRegion WaylandQPainterBackend::beginFrame(AbstractOutput *output) -{ - WaylandQPainterOutput *rendererOutput = m_outputs[output]; - Q_ASSERT(rendererOutput); - - WaylandQPainterBufferSlot *slot = rendererOutput->acquire(); - return rendererOutput->accumulateDamage(slot->age); -} - void WaylandQPainterBackend::present(AbstractOutput *output) { - m_outputs[output]->present(m_lastDamagedRegion); + m_outputs[output]->present(); +} + +OutputLayer *WaylandQPainterBackend::primaryLayer(AbstractOutput *output) +{ + return m_outputs[output].get(); } } } diff --git a/src/backends/wayland/scene_qpainter_wayland_backend.h b/src/backends/wayland/scene_qpainter_wayland_backend.h index db8e171f70..a7b07915fd 100644 --- a/src/backends/wayland/scene_qpainter_wayland_backend.h +++ b/src/backends/wayland/scene_qpainter_wayland_backend.h @@ -10,6 +10,7 @@ #ifndef KWIN_SCENE_QPAINTER_WAYLAND_BACKEND_H #define KWIN_SCENE_QPAINTER_WAYLAND_BACKEND_H +#include "outputlayer.h" #include "qpainterbackend.h" #include "utils/damagejournal.h" @@ -46,13 +47,15 @@ public: int age = 0; }; -class WaylandQPainterOutput : public QObject +class WaylandQPainterOutput : public OutputLayer { - Q_OBJECT public: - WaylandQPainterOutput(WaylandOutput *output, QObject *parent = nullptr); + WaylandQPainterOutput(WaylandOutput *output); ~WaylandQPainterOutput() override; + QRegion beginFrame() override; + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override; + bool init(KWayland::Client::ShmPool *pool); void updateSize(const QSize &size); void remapBuffer(); @@ -60,7 +63,7 @@ public: WaylandQPainterBufferSlot *back() const; WaylandQPainterBufferSlot *acquire(); - void present(const QRegion &damage); + void present(); QRegion accumulateDamage(int bufferAge) const; @@ -84,17 +87,15 @@ public: QImage *bufferForScreen(AbstractOutput *output) override; - QRegion beginFrame(AbstractOutput *output) override; - void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; void present(AbstractOutput *output) override; + OutputLayer *primaryLayer(AbstractOutput *output) override; private: void createOutput(AbstractOutput *waylandOutput); void frameRendered(); WaylandBackend *m_backend; - QRegion m_lastDamagedRegion; - QMap m_outputs; + QMap> m_outputs; }; } diff --git a/src/backends/x11/standalone/eglbackend.cpp b/src/backends/x11/standalone/eglbackend.cpp index 31f505f9a0..316a4b1721 100644 --- a/src/backends/x11/standalone/eglbackend.cpp +++ b/src/backends/x11/standalone/eglbackend.cpp @@ -26,9 +26,25 @@ namespace KWin { +EglLayer::EglLayer(EglBackend *backend) + : m_backend(backend) +{ +} + +QRegion EglLayer::beginFrame() +{ + return m_backend->beginFrame(); +} + +void EglLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) +{ + m_backend->endFrame(renderedRegion, damagedRegion); +} + EglBackend::EglBackend(Display *display, X11StandalonePlatform *backend) : EglOnXBackend(display) , m_backend(backend) + , m_layer(new EglLayer(this)) { // There is no any way to determine when a buffer swap completes with EGL. Fallback // to software vblank events. Could we use the Present extension to get notified when @@ -105,9 +121,8 @@ void EglBackend::screenGeometryChanged() m_renderTarget.reset(new GLRenderTarget(0, screens()->size())); } -QRegion EglBackend::beginFrame(AbstractOutput *output) +QRegion EglBackend::beginFrame() { - Q_UNUSED(output) makeCurrent(); QRegion repaint; @@ -122,10 +137,8 @@ QRegion EglBackend::beginFrame(AbstractOutput *output) return repaint; } -void EglBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) +void EglBackend::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) { - Q_UNUSED(output) - // Save the damaged region to history if (supportsBufferAge()) { m_damageJournal.add(damagedRegion); @@ -179,6 +192,12 @@ void EglBackend::presentSurface(EGLSurface surface, const QRegion &damage, const } } +OutputLayer *EglBackend::primaryLayer(AbstractOutput *output) +{ + Q_UNUSED(output) + return m_layer.get(); +} + void EglBackend::vblank(std::chrono::nanoseconds timestamp) { RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(m_backend->renderLoop()); diff --git a/src/backends/x11/standalone/eglbackend.h b/src/backends/x11/standalone/eglbackend.h index dbbfd88e36..6b243c0778 100644 --- a/src/backends/x11/standalone/eglbackend.h +++ b/src/backends/x11/standalone/eglbackend.h @@ -8,6 +8,7 @@ #include "eglonxbackend.h" #include "openglsurfacetexture_x11.h" +#include "outputlayer.h" #include "utils/damagejournal.h" #include @@ -19,6 +20,19 @@ namespace KWin class EglPixmapTexturePrivate; class SoftwareVsyncMonitor; class X11StandalonePlatform; +class EglBackend; + +class EglLayer : public OutputLayer +{ +public: + EglLayer(EglBackend *backend); + + QRegion beginFrame() override; + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override; + +private: + EglBackend *const m_backend; +}; class EglBackend : public EglOnXBackend { @@ -31,9 +45,10 @@ public: void init() override; SurfaceTexture *createSurfaceTextureX11(SurfacePixmapX11 *texture) override; - QRegion beginFrame(AbstractOutput *output) override; - void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; + QRegion beginFrame(); + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion); void present(AbstractOutput *output) override; + OutputLayer *primaryLayer(AbstractOutput *output) override; private: void screenGeometryChanged(); @@ -46,6 +61,7 @@ private: QScopedPointer m_renderTarget; int m_bufferAge = 0; QRegion m_lastRenderedRegion; + QScopedPointer m_layer; }; class EglPixmapTexture : public GLTexture diff --git a/src/backends/x11/standalone/glxbackend.cpp b/src/backends/x11/standalone/glxbackend.cpp index 638db37ddf..2b242b6e03 100644 --- a/src/backends/x11/standalone/glxbackend.cpp +++ b/src/backends/x11/standalone/glxbackend.cpp @@ -103,6 +103,21 @@ bool SwapEventFilter::event(xcb_generic_event_t *event) return true; } +GlxLayer::GlxLayer(GlxBackend *backend) + : m_backend(backend) +{ +} + +QRegion GlxLayer::beginFrame() +{ + return m_backend->beginFrame(); +} + +void GlxLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) +{ + m_backend->endFrame(renderedRegion, damagedRegion); +} + GlxBackend::GlxBackend(Display *display, X11StandalonePlatform *backend) : OpenGLBackend() , m_overlayWindow(kwinApp()->platform()->createOverlayWindow()) @@ -113,6 +128,7 @@ GlxBackend::GlxBackend(Display *display, X11StandalonePlatform *backend) , m_bufferAge(0) , m_x11Display(display) , m_backend(backend) + , m_layer(new GlxLayer(this)) { // Force initialization of GLX integration in the Qt's xcb backend // to make it call XESetWireToEvent callbacks, which is required @@ -763,10 +779,8 @@ SurfaceTexture *GlxBackend::createSurfaceTextureX11(SurfacePixmapX11 *pixmap) return new GlxSurfaceTextureX11(this, pixmap); } -QRegion GlxBackend::beginFrame(AbstractOutput *output) +QRegion GlxBackend::beginFrame() { - Q_UNUSED(output) - QRegion repaint; makeCurrent(); @@ -780,10 +794,8 @@ QRegion GlxBackend::beginFrame(AbstractOutput *output) return repaint; } -void GlxBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) +void GlxBackend::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) { - Q_UNUSED(output) - // Save the damaged region to history if (supportsBufferAge()) { m_damageJournal.add(damagedRegion); @@ -846,6 +858,12 @@ OverlayWindow *GlxBackend::overlayWindow() const return m_overlayWindow; } +OutputLayer *GlxBackend::primaryLayer(AbstractOutput *output) +{ + Q_UNUSED(output) + return m_layer.get(); +} + GlxSurfaceTextureX11::GlxSurfaceTextureX11(GlxBackend *backend, SurfacePixmapX11 *texture) : OpenGLSurfaceTextureX11(backend, texture) { diff --git a/src/backends/x11/standalone/glxbackend.h b/src/backends/x11/standalone/glxbackend.h index fd4f6070c9..df183197ed 100644 --- a/src/backends/x11/standalone/glxbackend.h +++ b/src/backends/x11/standalone/glxbackend.h @@ -10,6 +10,7 @@ #define KWIN_GLX_BACKEND_H #include "openglbackend.h" #include "openglsurfacetexture_x11.h" +#include "outputlayer.h" #include "utils/damagejournal.h" #include "x11eventfilter.h" @@ -30,6 +31,7 @@ namespace KWin class GlxPixmapTexturePrivate; class VsyncMonitor; class X11StandalonePlatform; +class GlxBackend; // GLX_MESA_swap_interval using glXSwapIntervalMESA_func = int (*)(unsigned int interval); @@ -58,6 +60,18 @@ private: xcb_glx_drawable_t m_glxDrawable; }; +class GlxLayer : public OutputLayer +{ +public: + GlxLayer(GlxBackend *backend); + + QRegion beginFrame() override; + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override; + +private: + GlxBackend *const m_backend; +}; + /** * @brief OpenGL Backend using GLX over an X overlay window. */ @@ -69,13 +83,14 @@ public: GlxBackend(Display *display, X11StandalonePlatform *backend); ~GlxBackend() override; SurfaceTexture *createSurfaceTextureX11(SurfacePixmapX11 *pixmap) override; - QRegion beginFrame(AbstractOutput *output) override; - void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; + QRegion beginFrame(); + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion); void present(AbstractOutput *output) override; bool makeCurrent() override; void doneCurrent() override; OverlayWindow *overlayWindow() const override; void init() override; + OutputLayer *primaryLayer(AbstractOutput *output) override; Display *display() const { @@ -119,6 +134,7 @@ private: Display *m_x11Display; X11StandalonePlatform *m_backend; VsyncMonitor *m_vsyncMonitor = nullptr; + QScopedPointer m_layer; friend class GlxPixmapTexturePrivate; }; diff --git a/src/backends/x11/windowed/egl_x11_backend.cpp b/src/backends/x11/windowed/egl_x11_backend.cpp index a322bcb99b..6c158c43f2 100644 --- a/src/backends/x11/windowed/egl_x11_backend.cpp +++ b/src/backends/x11/windowed/egl_x11_backend.cpp @@ -21,6 +21,42 @@ namespace KWin { +EglX11Output::EglX11Output(EglX11Backend *backend, AbstractOutput *output, EGLSurface surface) + : m_eglSurface(surface) + , m_renderTarget(new GLRenderTarget(0, output->pixelSize())) + , m_output(output) + , m_backend(backend) +{ +} + +EglX11Output::~EglX11Output() +{ + eglDestroySurface(m_backend->eglDisplay(), m_eglSurface); +} + +QRegion EglX11Output::beginFrame() +{ + eglMakeCurrent(m_backend->eglDisplay(), m_eglSurface, m_eglSurface, m_backend->context()); + GLRenderTarget::pushRenderTarget(m_renderTarget.data()); + return m_output->rect(); +} + +void EglX11Output::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) +{ + Q_UNUSED(renderedRegion) + m_lastDamage = damagedRegion; +} + +EGLSurface EglX11Output::surface() const +{ + return m_eglSurface; +} + +QRegion EglX11Output::lastDamage() const +{ + return m_lastDamage; +} + EglX11Backend::EglX11Backend(X11WindowedBackend *backend) : EglOnXBackend(backend->connection(), backend->display(), backend->rootWindow(), backend->screenNumer(), XCB_WINDOW_NONE) , m_backend(backend) @@ -40,10 +76,7 @@ void EglX11Backend::init() void EglX11Backend::cleanupSurfaces() { - for (auto it = m_outputs.begin(); it != m_outputs.end(); ++it) { - eglDestroySurface(eglDisplay(), (*it)->m_eglSurface); - } - qDeleteAll(m_outputs); + m_outputs.clear(); } bool EglX11Backend::createSurfaces() @@ -54,38 +87,19 @@ bool EglX11Backend::createSurfaces() if (s == EGL_NO_SURFACE) { return false; } - EglX11Output *rendererOutput = new EglX11Output; - rendererOutput->m_eglSurface = s; - rendererOutput->m_renderTarget.reset(new GLRenderTarget(0, output->pixelSize())); - m_outputs[output] = rendererOutput; + m_outputs[output] = QSharedPointer::create(this, output, s); } if (m_outputs.isEmpty()) { return false; } - setSurface(m_outputs.first()->m_eglSurface); + setSurface(m_outputs.first()->surface()); return true; } -QRegion EglX11Backend::beginFrame(AbstractOutput *output) -{ - const EglX11Output *rendererOutput = m_outputs[output]; - makeContextCurrent(rendererOutput->m_eglSurface); - GLRenderTarget::pushRenderTarget(rendererOutput->m_renderTarget.data()); - return output->rect(); -} - -void EglX11Backend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) -{ - Q_UNUSED(damagedRegion) - - static_cast(output)->vsyncMonitor()->arm(); - GLRenderTarget::popRenderTarget(); - m_lastRenderedRegion = renderedRegion; -} - void EglX11Backend::present(AbstractOutput *output) { - presentSurface(m_outputs[output]->m_eglSurface, m_lastRenderedRegion, output->geometry()); + const auto &renderOutput = m_outputs[output]; + presentSurface(renderOutput->surface(), renderOutput->lastDamage(), output->geometry()); } void EglX11Backend::presentSurface(EGLSurface surface, const QRegion &damage, const QRect &screenGeometry) @@ -106,6 +120,11 @@ void EglX11Backend::presentSurface(EGLSurface surface, const QRegion &damage, co } } +OutputLayer *EglX11Backend::primaryLayer(AbstractOutput *output) +{ + return m_outputs[output].get(); +} + SurfaceTexture *EglX11Backend::createSurfaceTextureWayland(SurfacePixmapWayland *pixmap) { return new BasicEGLSurfaceTextureWayland(this, pixmap); diff --git a/src/backends/x11/windowed/egl_x11_backend.h b/src/backends/x11/windowed/egl_x11_backend.h index 44680f06ad..c2c072eee5 100644 --- a/src/backends/x11/windowed/egl_x11_backend.h +++ b/src/backends/x11/windowed/egl_x11_backend.h @@ -10,6 +10,7 @@ #define KWIN_EGL_X11_BACKEND_H #include "eglonxbackend.h" #include "kwinglutils.h" +#include "outputlayer.h" #include @@ -17,12 +18,26 @@ namespace KWin { class X11WindowedBackend; +class EglX11Backend; -class EglX11Output +class EglX11Output : public OutputLayer { public: + EglX11Output(EglX11Backend *backend, AbstractOutput *output, EGLSurface surface); + ~EglX11Output(); + + QRegion beginFrame() override; + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override; + EGLSurface surface() const; + QRegion lastDamage() const; + +private: EGLSurface m_eglSurface; QScopedPointer m_renderTarget; + QRegion m_lastDamage; + + AbstractOutput *const m_output; + EglX11Backend *const m_backend; }; /** @@ -39,9 +54,9 @@ public: SurfaceTexture *createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override; SurfaceTexture *createSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override; void init() override; - QRegion beginFrame(AbstractOutput *output) override; - void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; + void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion); void present(AbstractOutput *output) override; + OutputLayer *primaryLayer(AbstractOutput *output) override; protected: void cleanupSurfaces() override; @@ -50,8 +65,7 @@ protected: private: void presentSurface(EGLSurface surface, const QRegion &damage, const QRect &screenGeometry); - QMap m_outputs; - QRegion m_lastRenderedRegion; + QMap> m_outputs; X11WindowedBackend *m_backend; }; diff --git a/src/backends/x11/windowed/scene_qpainter_x11_backend.cpp b/src/backends/x11/windowed/scene_qpainter_x11_backend.cpp index 846b3bd430..e5ce934471 100644 --- a/src/backends/x11/windowed/scene_qpainter_x11_backend.cpp +++ b/src/backends/x11/windowed/scene_qpainter_x11_backend.cpp @@ -15,6 +15,26 @@ namespace KWin { + +X11WindowedQPainterOutput::X11WindowedQPainterOutput(AbstractOutput *output, xcb_window_t window) + : window(window) + , buffer(output->pixelSize() * output->scale(), QImage::Format_RGB32) + , m_output(output) +{ + buffer.fill(Qt::black); +} + +QRegion X11WindowedQPainterOutput::beginFrame() +{ + return m_output->rect(); +} + +void X11WindowedQPainterOutput::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) +{ + Q_UNUSED(renderedRegion) + Q_UNUSED(damagedRegion) +} + X11WindowedQPainterBackend::X11WindowedQPainterBackend(X11WindowedBackend *backend) : QPainterBackend() , m_backend(backend) @@ -25,7 +45,7 @@ X11WindowedQPainterBackend::X11WindowedQPainterBackend(X11WindowedBackend *backe X11WindowedQPainterBackend::~X11WindowedQPainterBackend() { - qDeleteAll(m_outputs); + m_outputs.clear(); if (m_gc) { xcb_free_gc(m_backend->connection(), m_gc); } @@ -33,15 +53,10 @@ X11WindowedQPainterBackend::~X11WindowedQPainterBackend() void X11WindowedQPainterBackend::createOutputs() { - qDeleteAll(m_outputs); m_outputs.clear(); const auto &outputs = m_backend->outputs(); for (const auto &x11Output : outputs) { - Output *output = new Output; - output->window = m_backend->windowForScreen(x11Output); - output->buffer = QImage(x11Output->pixelSize() * x11Output->scale(), QImage::Format_RGB32); - output->buffer.fill(Qt::black); - m_outputs.insert(x11Output, output); + m_outputs[x11Output] = QSharedPointer::create(x11Output, m_backend->windowForScreen(x11Output)); } } @@ -50,18 +65,6 @@ QImage *X11WindowedQPainterBackend::bufferForScreen(AbstractOutput *output) return &m_outputs[output]->buffer; } -QRegion X11WindowedQPainterBackend::beginFrame(AbstractOutput *output) -{ - return output->rect(); -} - -void X11WindowedQPainterBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) -{ - Q_UNUSED(output) - Q_UNUSED(renderedRegion) - Q_UNUSED(damagedRegion) -} - void X11WindowedQPainterBackend::present(AbstractOutput *output) { static_cast(output)->vsyncMonitor()->arm(); @@ -73,7 +76,7 @@ void X11WindowedQPainterBackend::present(AbstractOutput *output) xcb_create_gc(c, m_gc, window, 0, nullptr); } - Output *rendererOutput = m_outputs[output]; + const auto &rendererOutput = m_outputs[output]; Q_ASSERT(rendererOutput); // TODO: only update changes? @@ -82,4 +85,9 @@ void X11WindowedQPainterBackend::present(AbstractOutput *output) m_gc, buffer.width(), buffer.height(), 0, 0, 0, 24, buffer.sizeInBytes(), buffer.constBits()); } + +OutputLayer *X11WindowedQPainterBackend::primaryLayer(AbstractOutput *output) +{ + return m_outputs[output].get(); +} } diff --git a/src/backends/x11/windowed/scene_qpainter_x11_backend.h b/src/backends/x11/windowed/scene_qpainter_x11_backend.h index c04f43f4da..68baf1dbe9 100644 --- a/src/backends/x11/windowed/scene_qpainter_x11_backend.h +++ b/src/backends/x11/windowed/scene_qpainter_x11_backend.h @@ -9,6 +9,7 @@ #ifndef KWIN_SCENE_QPAINTER_X11_BACKEND_H #define KWIN_SCENE_QPAINTER_X11_BACKEND_H +#include "outputlayer.h" #include "qpainterbackend.h" #include @@ -23,6 +24,19 @@ namespace KWin class X11WindowedBackend; +class X11WindowedQPainterOutput : public OutputLayer +{ +public: + X11WindowedQPainterOutput(AbstractOutput *output, xcb_window_t window); + + QRegion beginFrame() override; + void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override; + + xcb_window_t window; + QImage buffer; + AbstractOutput *const m_output; +}; + class X11WindowedQPainterBackend : public QPainterBackend { Q_OBJECT @@ -31,20 +45,14 @@ public: ~X11WindowedQPainterBackend() override; QImage *bufferForScreen(AbstractOutput *output) override; - QRegion beginFrame(AbstractOutput *output) override; - void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) override; void present(AbstractOutput *output) override; + OutputLayer *primaryLayer(AbstractOutput *output) override; private: void createOutputs(); xcb_gcontext_t m_gc = XCB_NONE; X11WindowedBackend *m_backend; - struct Output - { - xcb_window_t window; - QImage buffer; - }; - QMap m_outputs; + QMap> m_outputs; }; } diff --git a/src/composite.cpp b/src/composite.cpp index c6070467ce..5997a6de7f 100644 --- a/src/composite.cpp +++ b/src/composite.cpp @@ -652,7 +652,7 @@ void Compositor::composite(RenderLoop *renderLoop) } AbstractOutput *output = findOutput(renderLoop); - OutputLayer *outputLayer = output->layer(); + OutputLayer *outputLayer = m_backend->primaryLayer(output); fTraceDuration("Paint (", output->name(), ")"); RenderLayer *superLayer = m_superlayers[renderLoop]; @@ -670,7 +670,7 @@ void Compositor::composite(RenderLoop *renderLoop) return sublayer->isVisible(); }); if (scanoutPossible && !output->directScanoutInhibited()) { - directScanout = m_backend->scanout(output, scanoutCandidate); + directScanout = outputLayer->scanout(scanoutCandidate); } } @@ -679,12 +679,12 @@ void Compositor::composite(RenderLoop *renderLoop) outputLayer->resetRepaints(); preparePaintPass(superLayer, &surfaceDamage); - const QRegion repair = m_backend->beginFrame(output); + const QRegion repair = outputLayer->beginFrame(); const QRegion bufferDamage = surfaceDamage.united(repair).intersected(superLayer->rect()); - m_backend->aboutToStartPainting(output, bufferDamage); + outputLayer->aboutToStartPainting(bufferDamage); paintPass(superLayer, bufferDamage); - m_backend->endFrame(output, bufferDamage, surfaceDamage); + outputLayer->endFrame(bufferDamage, surfaceDamage); } renderLoop->endFrame(); diff --git a/src/outputlayer.cpp b/src/outputlayer.cpp index 4123c4fc79..bedb193c31 100644 --- a/src/outputlayer.cpp +++ b/src/outputlayer.cpp @@ -29,4 +29,15 @@ void OutputLayer::resetRepaints() m_repaints = QRegion(); } +void OutputLayer::aboutToStartPainting(const QRegion &damage) +{ + Q_UNUSED(damage) +} + +bool OutputLayer::scanout(SurfaceItem *surfaceItem) +{ + Q_UNUSED(surfaceItem) + return false; +} + } // namespace KWin diff --git a/src/outputlayer.h b/src/outputlayer.h index 8259f2e810..4576785622 100644 --- a/src/outputlayer.h +++ b/src/outputlayer.h @@ -14,10 +14,11 @@ namespace KWin { +class SurfaceItem; + class KWIN_EXPORT OutputLayer : public QObject { Q_OBJECT - public: explicit OutputLayer(QObject *parent = nullptr); @@ -25,6 +26,22 @@ public: void resetRepaints(); void addRepaint(const QRegion ®ion); + /** + * Notifies about starting to paint. + * + * @p damage contains the reported damage as suggested by windows and effects on prepaint calls. + */ + virtual void aboutToStartPainting(const QRegion &damage); + + virtual QRegion beginFrame() = 0; + virtual void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) = 0; + + /** + * Tries to import the newest buffer of the surface for direct scanout + * Returns @c true if scanout succeeds, @c false if rendering is necessary + */ + virtual bool scanout(SurfaceItem *surfaceItem); + private: QRegion m_repaints; }; diff --git a/src/renderbackend.cpp b/src/renderbackend.cpp index 6067616942..54c0ceb8bd 100644 --- a/src/renderbackend.cpp +++ b/src/renderbackend.cpp @@ -24,17 +24,4 @@ bool RenderBackend::checkGraphicsReset() return false; } -void RenderBackend::aboutToStartPainting(AbstractOutput *output, const QRegion &damage) -{ - Q_UNUSED(output) - Q_UNUSED(damage) -} - -bool RenderBackend::scanout(AbstractOutput *output, SurfaceItem *surfaceItem) -{ - Q_UNUSED(output) - Q_UNUSED(surfaceItem) - return false; -} - } // namespace KWin diff --git a/src/renderbackend.h b/src/renderbackend.h index 1682752615..da8288381f 100644 --- a/src/renderbackend.h +++ b/src/renderbackend.h @@ -15,7 +15,7 @@ namespace KWin class AbstractOutput; class OverlayWindow; -class SurfaceItem; +class OutputLayer; /** * The RenderBackend class is the base class for all rendering backends. @@ -32,22 +32,8 @@ public: virtual bool checkGraphicsReset(); - /** - * Notifies about starting to paint. - * - * @p damage contains the reported damage as suggested by windows and effects on prepaint calls. - */ - virtual void aboutToStartPainting(AbstractOutput *output, const QRegion &damage); - - virtual QRegion beginFrame(AbstractOutput *output) = 0; - virtual void endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damagedRegion) = 0; + virtual OutputLayer *primaryLayer(AbstractOutput *output) = 0; virtual void present(AbstractOutput *output) = 0; - - /** - * Tries to directly scan out a surface to the screen - * Returns @c true if scanout succeeds, @c false if rendering is necessary - */ - virtual bool scanout(AbstractOutput *output, SurfaceItem *surfaceItem); }; } // namespace KWin diff --git a/src/utils/damagejournal.h b/src/utils/damagejournal.h index 79e420a5d7..6d761794d9 100644 --- a/src/utils/damagejournal.h +++ b/src/utils/damagejournal.h @@ -76,6 +76,11 @@ public: return region; } + QRegion lastDamage() const + { + return m_log.first(); + } + private: QList m_log; int m_capacity = 10;