backends/drm: port qpainter to layers

This commit is contained in:
Xaver Hugl 2022-02-05 14:24:42 +01:00
parent 153d5965f8
commit ddb6dadfc2
7 changed files with 173 additions and 37 deletions

View file

@ -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

View file

@ -0,0 +1,47 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <optional>
#include <QRegion>
#include <QSharedPointer>
namespace KWin
{
class SurfaceItem;
class DrmBuffer;
class DrmAbstractOutput;
class DrmLayer
{
public:
virtual ~DrmLayer() = default;
virtual std::optional<QRegion> 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<DrmBuffer> testBuffer() = 0;
virtual QSharedPointer<DrmBuffer> currentBuffer() const = 0;
virtual DrmAbstractOutput *output() const = 0;
};
}

View file

@ -0,0 +1,71 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
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 <drm_fourcc.h>
namespace KWin
{
DrmQPainterLayer::DrmQPainterLayer(DrmAbstractOutput *output)
: m_output(output)
{
}
std::optional<QRegion> DrmQPainterLayer::startRendering()
{
if (!doesSwapchainFit()) {
m_swapchain = QSharedPointer<DumbSwapchain>::create(m_output->gpu(), m_output->sourceSize(), DRM_FORMAT_XRGB8888);
}
QRegion needsRepaint;
if (!m_swapchain->acquireBuffer(m_output->geometry(), &needsRepaint)) {
return std::optional<QRegion>();
}
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<DrmBuffer> DrmQPainterLayer::testBuffer()
{
if (!doesSwapchainFit()) {
m_swapchain = QSharedPointer<DumbSwapchain>::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<DrmBuffer> DrmQPainterLayer::currentBuffer() const
{
return m_swapchain ? m_swapchain->currentBuffer() : nullptr;
}
DrmAbstractOutput *DrmQPainterLayer::output() const
{
return m_output;
}
}

View file

@ -0,0 +1,35 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
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<QRegion> startRendering() override;
bool endRendering(const QRegion &damagedRegion) override;
bool scanout(SurfaceItem *surfaceItem) override;
QSharedPointer<DrmBuffer> testBuffer() override;
QSharedPointer<DrmBuffer> currentBuffer() const override;
DrmAbstractOutput *output() const override;
private:
bool doesSwapchainFit() const;
QSharedPointer<DumbSwapchain> m_swapchain;
DrmAbstractOutput *const m_output;
};
}

View file

@ -7,6 +7,7 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "drm_layer.h"
#include <QSharedPointer>
#include <QPointer>
@ -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<QRegion> 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<DrmBuffer> testBuffer();
/**
* only temporarily here, should be migrated out!
*/
std::optional<QRegion> startRendering() override;
bool endRendering(const QRegion &damagedRegion) override;
bool scanout(SurfaceItem *surfaceItem) override;
QSharedPointer<DrmBuffer> testBuffer() override;
QSharedPointer<DrmBuffer> currentBuffer() const override;
QSharedPointer<GLTexture> texture() const;
QSharedPointer<DrmBuffer> currentBuffer() const;
DrmAbstractOutput *output() const;
DrmAbstractOutput *output() const override;
int bufferAge() const;
EGLSurface eglSurface() const;

View file

@ -12,6 +12,7 @@
#include "drm_gpu.h"
#include "drm_buffer.h"
#include "renderloop_p.h"
#include "drm_qpainter_layer.h"
#include <drm_fourcc.h>
@ -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<DrmQPainterLayer>::create(static_cast<DrmAbstractOutput*>(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<DrmDumbBuffer*>(m_swapchains[output]->currentBuffer().data())->image();
}
QRegion DrmQPainterBackend::beginFrame(AbstractOutput *output)
{
const auto drmOutput = static_cast<DrmAbstractOutput*>(output);
if (!m_swapchains[output] || m_swapchains[output]->size() != drmOutput->sourceSize()) {
m_swapchains[output] = QSharedPointer<DumbSwapchain>::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<DrmDumbBuffer> back = m_swapchains[output]->currentBuffer();
m_swapchains[output]->releaseBuffer(back, damage);
static_cast<DrmAbstractOutput*>(output)->present(back, output->geometry());
m_swapchains[output]->endRendering(damage);
static_cast<DrmAbstractOutput*>(output)->present(m_swapchains[output]->currentBuffer(), output->geometry());
}
}

View file

@ -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<AbstractOutput *, QSharedPointer<DumbSwapchain>> m_swapchains;
QMap<AbstractOutput *, QSharedPointer<DrmQPainterLayer>> m_swapchains;
DrmBackend *m_backend;
};
}