Commit 7358daa9 authored by Xaver Hugl's avatar Xaver Hugl
Browse files

renderbackend: move render methods to OutputLayer

This is in preparation to using multiple outputlayers per output
parent 8e998a7c
Pipeline #162958 passed with stage
in 12 minutes and 2 seconds
......@@ -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();
......
......@@ -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
};
......
......@@ -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<QRegion> DrmOutputLayer::startRendering()
{
return {};
}
bool DrmOutputLayer::endRendering(const QRegion &damagedRegion)
{
Q_UNUSED(damagedRegion)
return false;
}
QRegion DrmOutputLayer::currentDamage() const
{
return {};
......
......@@ -7,6 +7,7 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "outputlayer.h"
#include <QObject>
#include <QRegion>
......@@ -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<QRegion> 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<GLTexture> texture() const;
virtual QRegion currentDamage() const;
};
......
......@@ -57,4 +57,14 @@ QSharedPointer<DrmBuffer> 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)
}
}
......@@ -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<DrmBuffer> testBuffer() override;
QSharedPointer<DrmBuffer> currentBuffer() const override;
......
......@@ -30,23 +30,23 @@ DrmQPainterLayer::DrmQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pip
});
}
std::optional<QRegion> DrmQPainterLayer::startRendering()
QRegion DrmQPainterLayer::beginFrame()
{
if (!doesSwapchainFit()) {
m_swapchain = QSharedPointer<DumbSwapchain>::create(m_pipeline->gpu(), m_pipeline->sourceSize(), DRM_FORMAT_XRGB8888);
}
QRegion needsRepaint;
if (!m_swapchain->acquireBuffer(&needsRepaint)) {
return std::optional<QRegion>();
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<DrmBuffer> DrmQPainterLayer::testBuffer()
......@@ -82,7 +82,7 @@ DrmVirtualQPainterLayer::DrmVirtualQPainterLayer(DrmVirtualOutput *output)
{
}
std::optional<QRegion> 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<QRegion> 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<DrmBuffer> 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)
}
}
......@@ -33,8 +33,8 @@ class DrmQPainterLayer : public DrmPipelineLayer, public QPainterLayer
public:
DrmQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline);
std::optional<QRegion> startRendering() override;
bool endRendering(const QRegion &damagedRegion) override;
QRegion beginFrame() override;
void endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override;
QSharedPointer<DrmBuffer> testBuffer() override;
QSharedPointer<DrmBuffer> currentBuffer() const override;
QRegion currentDamage() const override;
......@@ -52,8 +52,8 @@ class DrmVirtualQPainterLayer : public DrmOutputLayer, public QPainterLayer
public:
DrmVirtualQPainterLayer(DrmVirtualOutput *output);
std::optional<QRegion> 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<DrmBuffer> testBuffer() override;
QSharedPointer<DrmBuffer> currentBuffer() const override;
......
......@@ -216,11 +216,6 @@ bool EglGbmBackend::initBufferConfigs()
return false;
}
void EglGbmBackend::aboutToStartPainting(AbstractOutput *output, const QRegion &damagedRegion)
{
static_cast<DrmAbstractOutput *>(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<DrmAbstractOutput *>(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<DrmAbstractOutput *>(output);
drmOutput->outputLayer()->endRendering(damagedRegion);
}
void EglGbmBackend::present(AbstractOutput *output)
{
static_cast<DrmAbstractOutput *>(output)->present();
}
bool EglGbmBackend::scanout(AbstractOutput *output, SurfaceItem *surfaceItem)
OutputLayer *EglGbmBackend::primaryLayer(AbstractOutput *output)
{
const auto drmOutput = static_cast<DrmAbstractOutput *>(output);
if (drmOutput->outputLayer()->scanout(surfaceItem)) {
return true;
} else {
return false;
}
return static_cast<DrmAbstractOutput *>(output)->outputLayer();
}
QSharedPointer<GLTexture> EglGbmBackend::textureForOutput(AbstractOutput *output) const
......
......@@ -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<DrmPipelineLayer> createDrmPipelineLayer(DrmPipeline *pipeline) override;
QSharedPointer<DrmOutputLayer> 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();
......
......@@ -61,7 +61,7 @@ void EglGbmLayer::destroyResources()
m_oldGbmSurface.reset();
}
std::optional<QRegion> EglGbmLayer::startRendering()
QRegion EglGbmLayer::beginFrame()
{
m_scanoutBuffer.reset();
// dmabuf feedback
......@@ -81,14 +81,14 @@ std::optional<QRegion> EglGbmLayer::startRendering()
m_gbmSurface = m_oldGbmSurface;
} else {
if (!createGbmSurface()) {
return std::optional<QRegion>();
return QRegion();
}
// dmabuf might work with the new surface
m_importMode = MultiGpuImportMode::Dmabuf;
}
}
if (!m_gbmSurface->makeContextCurrent()) {
return std::optional<QRegion>();
return QRegion();
}
auto repaintRegion = m_gbmSurface->repaintRegion();
......@@ -103,7 +103,7 @@ std::optional<QRegion> EglGbmLayer::startRendering()
const auto format = m_eglBackend->gbmFormatForDrmFormat(m_gbmSurface->format());
m_shadowBuffer = QSharedPointer<ShadowBuffer>::create(m_pipeline->sourceSize(), format);
if (!m_shadowBuffer->isComplete()) {
return std::optional<QRegion>();
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<DrmBuffer> 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<uint64_t> &modifiers)
......
......@@ -36,9 +36,9 @@ public:
EglGbmLayer(EglGbmBackend *eglBackend, DrmPipeline *pipeline);
~EglGbmLayer();
std::optional<QRegion> 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<DrmBuffer> testBuffer() override;
QSharedPointer<DrmBuffer> currentBuffer() const override;
......
......@@ -39,22 +39,14 @@ QImage *DrmQPainterBackend::bufferForScreen(AbstractOutput *output)
return dynamic_cast<QPainterLayer *>(drmOutput->outputLayer())->image();
}
QRegion DrmQPainterBackend::beginFrame(AbstractOutput *output)
{
const auto drmOutput = static_cast<DrmAbstractOutput *>(output);
return drmOutput->outputLayer()->startRendering().value_or(QRegion());
}
void DrmQPainterBackend::endFrame(AbstractOutput *output, const QRegion &renderedRegion, const QRegion &damage)
void DrmQPainterBackend::present(AbstractOutput *output)
{
Q_UNUSED(renderedRegion)
const auto drmOutput = static_cast<DrmAbstractOutput *>(output);
drmOutput->outputLayer()->endRendering(damage);
static_cast<DrmAbstractOutput *>(output)->present();
}
void DrmQPainterBackend::present(AbstractOutput *output)
OutputLayer *DrmQPainterBackend::primaryLayer(AbstractOutput *output)
{
static_cast<DrmAbstractOutput *>(output)->present();
return static_cast<DrmAbstractOutput *>(output)->outputLayer();
}
QSharedPointer<DrmPipelineLayer> DrmQPainterBackend::createDrmPipelineLayer(DrmPipeline *pipeline)
......
......@@ -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<DrmPipelineLayer> createDrmPipelineLayer(DrmPipeline *pipeline) override;
QSharedPointer<DrmOutputLayer> createLayer(DrmVirtualOutput *output) override;
......
......@@ -61,7 +61,7 @@ void VirtualEglGbmLayer::aboutToStartPainting(const QRegion &damagedRegion)
}
}
std::optional<QRegion> VirtualEglGbmLayer::startRendering()
QRegion VirtualEglGbmLayer::beginFrame()
{
// gbm surface
if (doesGbmSurfaceFit(m_gbmSurface.data())) {
......@@ -71,18 +71,18 @@ std::optional<QRegion> VirtualEglGbmLayer::startRendering()
m_gbmSurface = m_oldGbmSurface;
} else {
if (!createGbmSurface()) {
return std::optional<QRegion>();
return QRegion();
}
}
}
if (!m_gbmSurface->makeContextCurrent()) {
return std::optional<QRegion>();
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
......
......@@ -36,8 +36,8 @@ public:
VirtualEglGbmLayer(EglGbmBackend *eglBackend, DrmVirtualOutput *output);
void aboutToStartPainting(const QRegion &damagedRegion) override;
std::optional<QRegion> 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;
......
......@@ -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)
......
......@@ -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<VirtualOutputLayer> m_layer;
};
} // namespace
......
......@@ -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();