backends/drm: split out layers for lease outputs and remove DrmDisplayDevice

This commit is contained in:
Xaver Hugl 2022-02-19 04:25:11 +01:00
parent aac7f50d8b
commit 0cd453690b
26 changed files with 235 additions and 208 deletions

View file

@ -13,7 +13,6 @@ set(DRM_SOURCES
drm_gpu.cpp drm_gpu.cpp
dumb_swapchain.cpp dumb_swapchain.cpp
shadowbuffer.cpp shadowbuffer.cpp
drm_display_device.cpp
drm_layer.cpp drm_layer.cpp
drm_pipeline.cpp drm_pipeline.cpp
drm_pipeline_legacy.cpp drm_pipeline_legacy.cpp
@ -28,6 +27,7 @@ set(DRM_SOURCES
gbm_dmabuf.cpp gbm_dmabuf.cpp
placeholderinputeventfilter.cpp placeholderinputeventfilter.cpp
virtual_egl_gbm_layer.cpp virtual_egl_gbm_layer.cpp
drm_lease_egl_gbm_layer.cpp
) )
add_library(KWinWaylandDrmBackend MODULE ${DRM_SOURCES}) add_library(KWinWaylandDrmBackend MODULE ${DRM_SOURCES})

View file

@ -16,8 +16,8 @@ namespace KWin
DrmAbstractOutput::DrmAbstractOutput(DrmGpu *gpu) DrmAbstractOutput::DrmAbstractOutput(DrmGpu *gpu)
: AbstractWaylandOutput(gpu->platform()) : AbstractWaylandOutput(gpu->platform())
, DrmDisplayDevice(gpu)
, m_renderLoop(new RenderLoop(this)) , m_renderLoop(new RenderLoop(this))
, m_gpu(gpu)
{ {
} }
@ -26,11 +26,6 @@ RenderLoop *DrmAbstractOutput::renderLoop() const
return m_renderLoop; return m_renderLoop;
} }
QRect DrmAbstractOutput::renderGeometry() const
{
return geometry();
}
void DrmAbstractOutput::frameFailed() const void DrmAbstractOutput::frameFailed() const
{ {
RenderLoopPrivate::get(m_renderLoop)->notifyFrameFailed(); RenderLoopPrivate::get(m_renderLoop)->notifyFrameFailed();
@ -57,4 +52,9 @@ QVector<int32_t> DrmAbstractOutput::regionToRects(const QRegion &region) const
return rects; return rects;
} }
DrmGpu *DrmAbstractOutput::gpu() const
{
return m_gpu;
}
} }

View file

@ -9,29 +9,34 @@
#pragma once #pragma once
#include "abstract_wayland_output.h" #include "abstract_wayland_output.h"
#include "drm_display_device.h"
namespace KWin namespace KWin
{ {
class DrmBackend; class DrmBackend;
class DrmGpu;
class DrmOutputLayer;
class DrmAbstractOutput : public AbstractWaylandOutput, public DrmDisplayDevice class DrmAbstractOutput : public AbstractWaylandOutput
{ {
Q_OBJECT Q_OBJECT
public: public:
DrmAbstractOutput(DrmGpu *gpu); DrmAbstractOutput(DrmGpu *gpu);
RenderLoop *renderLoop() const override; RenderLoop *renderLoop() const override;
QRect renderGeometry() const override; void frameFailed() const;
void frameFailed() const override; void pageFlipped(std::chrono::nanoseconds timestamp) const;
void pageFlipped(std::chrono::nanoseconds timestamp) const override; QVector<int32_t> regionToRects(const QRegion &region) const;
QVector<int32_t> regionToRects(const QRegion &region) const override; DrmGpu *gpu() const;
virtual bool present() = 0;
virtual DrmOutputLayer *outputLayer() const = 0;
protected: protected:
friend class DrmGpu; friend class DrmGpu;
RenderLoop *m_renderLoop; RenderLoop *m_renderLoop;
DrmGpu *const m_gpu;
}; };
} }

View file

@ -1,24 +0,0 @@
/*
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_display_device.h"
namespace KWin
{
DrmDisplayDevice::DrmDisplayDevice(DrmGpu *gpu)
: m_gpu(gpu)
{
}
DrmGpu *DrmDisplayDevice::gpu() const
{
return m_gpu;
}
}

View file

@ -1,41 +0,0 @@
/*
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 <QRegion>
#include "drm_object_plane.h"
namespace KWin
{
class DrmBuffer;
class DrmGpu;
class DrmOutputLayer;
class DrmDisplayDevice
{
public:
DrmDisplayDevice(DrmGpu *gpu);
virtual ~DrmDisplayDevice() = default;
DrmGpu *gpu() const;
virtual bool present() = 0;
virtual void frameFailed() const = 0;
virtual void pageFlipped(std::chrono::nanoseconds timestamp) const = 0;
virtual QRect renderGeometry() const = 0;
virtual DrmOutputLayer *outputLayer() const = 0;
virtual QVector<int32_t> regionToRects(const QRegion &region) const = 0;
protected:
DrmGpu *const m_gpu;
};
}

View file

@ -309,9 +309,9 @@ bool DrmGpu::updateOutputs()
if (testPendingConfiguration()) { if (testPendingConfiguration()) {
for (const auto &pipeline : qAsConst(m_pipelines)) { for (const auto &pipeline : qAsConst(m_pipelines)) {
pipeline->applyPendingChanges(); pipeline->applyPendingChanges();
if (const auto drmOutput = dynamic_cast<DrmAbstractOutput*>(pipeline->displayDevice()); drmOutput && !pipeline->pending.crtc) { if (pipeline->output() && !pipeline->pending.crtc) {
pipeline->pending.enabled = false; pipeline->pending.enabled = false;
drmOutput->setEnabled(false); pipeline->output()->setEnabled(false);
} }
} }
} else { } else {
@ -740,7 +740,7 @@ bool DrmGpu::maybeModeset()
if (pipeline->modesetPresentPending()) { if (pipeline->modesetPresentPending()) {
pipeline->resetModesetPresentPending(); pipeline->resetModesetPresentPending();
if (!ok) { if (!ok) {
pipeline->displayDevice()->frameFailed(); pipeline->output()->frameFailed();
} }
} }
} }

View file

@ -8,7 +8,6 @@
*/ */
#include "drm_layer.h" #include "drm_layer.h"
#include "drm_pipeline.h" #include "drm_pipeline.h"
#include "drm_display_device.h"
#include <QMatrix4x4> #include <QMatrix4x4>
@ -22,11 +21,43 @@ void DrmOutputLayer::aboutToStartPainting(const QRegion &damagedRegion)
Q_UNUSED(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 {};
}
QSharedPointer<GLTexture> DrmOutputLayer::texture() const
{
return nullptr;
}
DrmPipelineLayer::DrmPipelineLayer(DrmPipeline *pipeline) DrmPipelineLayer::DrmPipelineLayer(DrmPipeline *pipeline)
: m_pipeline(pipeline) : m_pipeline(pipeline)
{ {
} }
bool DrmPipelineLayer::hasDirectScanoutBuffer() const
{
return false;
}
} }
#include "drm_layer.moc" #include "drm_layer.moc"

View file

@ -28,19 +28,19 @@ public:
virtual ~DrmOutputLayer(); virtual ~DrmOutputLayer();
virtual void aboutToStartPainting(const QRegion &damagedRegion); virtual void aboutToStartPainting(const QRegion &damagedRegion);
virtual std::optional<QRegion> startRendering() = 0; virtual std::optional<QRegion> startRendering();
virtual bool endRendering(const QRegion &damagedRegion) = 0; virtual bool endRendering(const QRegion &damagedRegion);
/** /**
* attempts to directly scan out the current buffer of the surfaceItem * attempts to directly scan out the current buffer of the surfaceItem
* @returns true if scanout was successful * @returns true if scanout was successful
* false if rendering is required * false if rendering is required
*/ */
virtual bool scanout(SurfaceItem *surfaceItem) = 0; virtual bool scanout(SurfaceItem *surfaceItem);
virtual QSharedPointer<GLTexture> texture() const = 0; virtual QSharedPointer<GLTexture> texture() const;
virtual QRegion currentDamage() const = 0; virtual QRegion currentDamage() const;
}; };
class DrmPipelineLayer : public DrmOutputLayer class DrmPipelineLayer : public DrmOutputLayer
@ -55,7 +55,7 @@ public:
virtual QSharedPointer<DrmBuffer> testBuffer() = 0; virtual QSharedPointer<DrmBuffer> testBuffer() = 0;
virtual QSharedPointer<DrmBuffer> currentBuffer() const = 0; virtual QSharedPointer<DrmBuffer> currentBuffer() const = 0;
virtual bool hasDirectScanoutBuffer() const = 0; virtual bool hasDirectScanoutBuffer() const;
protected: protected:
DrmPipeline *const m_pipeline; DrmPipeline *const m_pipeline;

View file

@ -0,0 +1,60 @@
/*
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_lease_egl_gbm_layer.h"
#include "drm_buffer_gbm.h"
#include "egl_gbm_backend.h"
#include "drm_pipeline.h"
#include "drm_gpu.h"
#include "logging.h"
#include <drm_fourcc.h>
#include <gbm.h>
namespace KWin
{
DrmLeaseEglGbmLayer::DrmLeaseEglGbmLayer(EglGbmBackend *backend, DrmPipeline *pipeline)
: DrmPipelineLayer(pipeline)
{
connect(backend, &EglGbmBackend::aboutToBeDestroyed, this, [this]() {
m_buffer.reset();
});
}
QSharedPointer<DrmBuffer> DrmLeaseEglGbmLayer::testBuffer()
{
const auto mods = m_pipeline->supportedModifiers(DRM_FORMAT_XRGB8888);
const auto size = m_pipeline->sourceSize();
if (!m_buffer || m_buffer->size() != size || !(mods.isEmpty() || mods.contains(m_buffer->modifier()))) {
gbm_bo *newBo;
if (mods.isEmpty()) {
newBo = gbm_bo_create(m_pipeline->gpu()->gbmDevice(), size.width(), size.height(), DRM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT);
} else {
QVector<uint64_t> modifiers;
modifiers.reserve(mods.count());
for (const auto &mod : mods) {
modifiers << mod;
}
newBo = gbm_bo_create_with_modifiers(m_pipeline->gpu()->gbmDevice(), size.width(), size.height(), DRM_FORMAT_XRGB8888, modifiers.constData(), mods.count());
}
if (newBo) {
m_buffer = QSharedPointer<DrmGbmBuffer>::create(m_pipeline->gpu(), nullptr, newBo);
} else {
qCWarning(KWIN_DRM) << "Failed to create gbm_bo for lease output";
}
}
return m_buffer;
}
QSharedPointer<DrmBuffer> DrmLeaseEglGbmLayer::currentBuffer() const
{
return m_buffer;
}
}

View file

@ -0,0 +1,31 @@
/*
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"
#include <QSharedPointer>
namespace KWin
{
class EglGbmBackend;
class DrmLeaseEglGbmLayer : public DrmPipelineLayer
{
public:
DrmLeaseEglGbmLayer(EglGbmBackend *backend, DrmPipeline *pipeline);
QSharedPointer<DrmBuffer> testBuffer() override;
QSharedPointer<DrmBuffer> currentBuffer() const override;
private:
QSharedPointer<DrmBuffer> m_buffer;
};
}

View file

@ -30,16 +30,13 @@ DrmLeaseOutput::DrmLeaseOutput(DrmPipeline *pipeline, KWaylandServer::DrmLeaseDe
pipeline->connector()->modelName(), pipeline->connector()->modelName(),
QStringLiteral("%1 %2").arg(pipeline->connector()->edid()->manufacturerString(), pipeline->connector()->modelName()) QStringLiteral("%1 %2").arg(pipeline->connector()->edid()->manufacturerString(), pipeline->connector()->modelName())
) )
, DrmDisplayDevice(pipeline->gpu())
, m_pipeline(pipeline) , m_pipeline(pipeline)
{ {
m_pipeline->setDisplayDevice(this);
qCDebug(KWIN_DRM) << "offering connector" << m_pipeline->connector()->id() << "for lease"; qCDebug(KWIN_DRM) << "offering connector" << m_pipeline->connector()->id() << "for lease";
} }
DrmLeaseOutput::~DrmLeaseOutput() DrmLeaseOutput::~DrmLeaseOutput()
{ {
m_pipeline->setDisplayDevice(nullptr);
qCDebug(KWIN_DRM) << "revoking lease offer for connector" << m_pipeline->connector()->id(); qCDebug(KWIN_DRM) << "revoking lease offer for connector" << m_pipeline->connector()->id();
} }
@ -79,34 +76,4 @@ DrmPipeline *DrmLeaseOutput::pipeline() const
return m_pipeline; return m_pipeline;
} }
bool DrmLeaseOutput::present()
{
return false;
}
QRect DrmLeaseOutput::renderGeometry() const
{
return QRect(QPoint(), m_pipeline->sourceSize());
}
DrmOutputLayer *DrmLeaseOutput::outputLayer() const
{
return m_pipeline->pending.layer.data();
}
void DrmLeaseOutput::frameFailed() const
{
}
void DrmLeaseOutput::pageFlipped(std::chrono::nanoseconds timestamp) const
{
Q_UNUSED(timestamp)
}
QVector<int32_t> DrmLeaseOutput::regionToRects(const QRegion &region) const
{
Q_UNUSED(region)
return {};
}
} }

View file

@ -13,8 +13,6 @@
#include <QVector> #include <QVector>
#include <KWaylandServer/drmleasedevice_v1_interface.h> #include <KWaylandServer/drmleasedevice_v1_interface.h>
#include "drm_display_device.h"
namespace KWin namespace KWin
{ {
@ -26,7 +24,7 @@ class DrmPipeline;
* that is not used directly by the compositor but is instead leased out to * that is not used directly by the compositor but is instead leased out to
* applications (usually VR compositors) that drive the output themselves * applications (usually VR compositors) that drive the output themselves
*/ */
class DrmLeaseOutput : public KWaylandServer::DrmLeaseConnectorV1Interface, public DrmDisplayDevice class DrmLeaseOutput : public KWaylandServer::DrmLeaseConnectorV1Interface
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -40,13 +38,6 @@ public:
KWaylandServer::DrmLeaseV1Interface *lease() const; KWaylandServer::DrmLeaseV1Interface *lease() const;
DrmPipeline *pipeline() const; DrmPipeline *pipeline() const;
bool present() override;
QRect renderGeometry() const override;
DrmOutputLayer *outputLayer() const override;
void frameFailed() const override;
void pageFlipped(std::chrono::nanoseconds timestamp) const override;
QVector<int32_t> regionToRects(const QRegion &region) const override;
private: private:
DrmPipeline *m_pipeline; DrmPipeline *m_pipeline;
KWaylandServer::DrmLeaseV1Interface *m_lease = nullptr; KWaylandServer::DrmLeaseV1Interface *m_lease = nullptr;

View file

@ -377,8 +377,8 @@ bool DrmConnector::updateProperties()
if (!m_pipeline->pending.mode) { if (!m_pipeline->pending.mode) {
m_pipeline->pending.mode = m_modes.constFirst(); m_pipeline->pending.mode = m_modes.constFirst();
} }
if (const auto output = dynamic_cast<DrmOutput*>(m_pipeline->displayDevice())) { if (m_pipeline->output()) {
output->updateModes(); m_pipeline->output()->updateModes();
} }
} }
} }

View file

@ -46,7 +46,7 @@ DrmOutput::DrmOutput(DrmPipeline *pipeline)
, m_pipeline(pipeline) , m_pipeline(pipeline)
, m_connector(pipeline->connector()) , m_connector(pipeline->connector())
{ {
m_pipeline->setDisplayDevice(this); m_pipeline->setOutput(this);
const auto conn = m_pipeline->connector(); const auto conn = m_pipeline->connector();
m_renderLoop->setRefreshRate(m_pipeline->pending.mode->refreshRate()); m_renderLoop->setRefreshRate(m_pipeline->pending.mode->refreshRate());
setSubPixelInternal(conn->subpixel()); setSubPixelInternal(conn->subpixel());
@ -79,7 +79,7 @@ DrmOutput::DrmOutput(DrmPipeline *pipeline)
DrmOutput::~DrmOutput() DrmOutput::~DrmOutput()
{ {
m_pipeline->setDisplayDevice(nullptr); m_pipeline->setOutput(nullptr);
} }
static bool isCursorSpriteCompatible(const QImage *buffer, const QImage *sprite) static bool isCursorSpriteCompatible(const QImage *buffer, const QImage *sprite)

View file

@ -32,8 +32,7 @@ namespace KWin
{ {
DrmPipeline::DrmPipeline(DrmConnector *conn) DrmPipeline::DrmPipeline(DrmConnector *conn)
: m_displayDevice(nullptr) : m_connector(conn)
, m_connector(conn)
{ {
} }
@ -309,8 +308,8 @@ bool DrmPipeline::setCursor(const QSharedPointer<DrmDumbBuffer> &buffer, const Q
} }
if (result) { if (result) {
m_next = pending; m_next = pending;
if (const auto drmOutput = dynamic_cast<DrmOutput*>(m_displayDevice); drmOutput && (visibleBefore || isCursorVisible())) { if (m_output && (visibleBefore || isCursorVisible())) {
drmOutput->renderLoop()->scheduleRepaint(); m_output->renderLoop()->scheduleRepaint();
} }
} else { } else {
pending = m_next; pending = m_next;
@ -334,8 +333,8 @@ bool DrmPipeline::moveCursor(QPoint pos)
} }
if (result) { if (result) {
m_next = pending; m_next = pending;
if (const auto drmOutput = dynamic_cast<DrmOutput*>(m_displayDevice); drmOutput && (visibleBefore || isCursorVisible())) { if (m_output && (visibleBefore || isCursorVisible())) {
drmOutput->renderLoop()->scheduleRepaint(); m_output->renderLoop()->scheduleRepaint();
} }
} else { } else {
pending = m_next; pending = m_next;
@ -395,12 +394,19 @@ void DrmPipeline::pageFlipped(std::chrono::nanoseconds timestamp)
m_current.crtc->cursorPlane()->flipBuffer(); m_current.crtc->cursorPlane()->flipBuffer();
} }
m_pageflipPending = false; m_pageflipPending = false;
m_displayDevice->pageFlipped(timestamp); if (m_output) {
m_output->pageFlipped(timestamp);
}
} }
void DrmPipeline::setDisplayDevice(DrmDisplayDevice *device) void DrmPipeline::setOutput(DrmOutput *output)
{ {
m_displayDevice = device; m_output = output;
}
DrmOutput *DrmPipeline::output() const
{
return m_output;
} }
static const QMap<uint32_t, QVector<uint64_t>> legacyFormats = { static const QMap<uint32_t, QVector<uint64_t>> legacyFormats = {
@ -483,11 +489,6 @@ DrmCrtc *DrmPipeline::currentCrtc() const
return m_current.crtc; return m_current.crtc;
} }
DrmDisplayDevice *DrmPipeline::displayDevice() const
{
return m_displayDevice;
}
DrmGammaRamp::DrmGammaRamp(DrmGpu *gpu, const GammaRamp &lut) DrmGammaRamp::DrmGammaRamp(DrmGpu *gpu, const GammaRamp &lut)
: m_gpu(gpu) : m_gpu(gpu)
, m_lut(lut) , m_lut(lut)

View file

@ -32,7 +32,6 @@ class DrmDumbBuffer;
class GammaRamp; class GammaRamp;
class DrmConnectorMode; class DrmConnectorMode;
class DrmPipelineLayer; class DrmPipelineLayer;
class DrmDisplayDevice;
class DrmGammaRamp class DrmGammaRamp
{ {
@ -94,8 +93,8 @@ public:
QVector<uint64_t> supportedModifiers(uint32_t drmFormat) const; QVector<uint64_t> supportedModifiers(uint32_t drmFormat) const;
QMap<uint32_t, QVector<uint64_t>> supportedFormats() const; QMap<uint32_t, QVector<uint64_t>> supportedFormats() const;
void setDisplayDevice(DrmDisplayDevice *device); void setOutput(DrmOutput *output);
DrmDisplayDevice *displayDevice() const; DrmOutput *output() const;
struct State { struct State {
DrmCrtc *crtc = nullptr; DrmCrtc *crtc = nullptr;
@ -154,7 +153,7 @@ private:
static void printFlags(uint32_t flags); static void printFlags(uint32_t flags);
static void printProps(DrmObject *object, PrintMode mode); static void printProps(DrmObject *object, PrintMode mode);
DrmDisplayDevice *m_displayDevice = nullptr; DrmOutput *m_output = nullptr;
DrmConnector *m_connector = nullptr; DrmConnector *m_connector = nullptr;
bool m_pageflipPending = false; bool m_pageflipPending = false;

View file

@ -15,16 +15,17 @@
#include "drm_backend.h" #include "drm_backend.h"
#include "drm_pipeline.h" #include "drm_pipeline.h"
#include "drm_virtual_output.h" #include "drm_virtual_output.h"
#include "drm_output.h"
#include <drm_fourcc.h> #include <drm_fourcc.h>
namespace KWin namespace KWin
{ {
DrmQPainterLayer::DrmQPainterLayer(DrmPipeline *pipeline) DrmQPainterLayer::DrmQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline)
: DrmPipelineLayer(pipeline) : DrmPipelineLayer(pipeline)
{ {
connect(static_cast<DrmQPainterBackend*>(pipeline->gpu()->platform()->renderBackend()), &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() { connect(backend, &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() {
m_swapchain.reset(); m_swapchain.reset();
}); });
} }
@ -35,7 +36,7 @@ std::optional<QRegion> DrmQPainterLayer::startRendering()
m_swapchain = QSharedPointer<DumbSwapchain>::create(m_pipeline->gpu(), m_pipeline->sourceSize(), DRM_FORMAT_XRGB8888); m_swapchain = QSharedPointer<DumbSwapchain>::create(m_pipeline->gpu(), m_pipeline->sourceSize(), DRM_FORMAT_XRGB8888);
} }
QRegion needsRepaint; QRegion needsRepaint;
if (!m_swapchain->acquireBuffer(m_pipeline->displayDevice()->renderGeometry(), &needsRepaint)) { if (!m_swapchain->acquireBuffer(m_pipeline->output()->geometry(), &needsRepaint)) {
return std::optional<QRegion>(); return std::optional<QRegion>();
} }
return needsRepaint; return needsRepaint;
@ -48,12 +49,6 @@ bool DrmQPainterLayer::endRendering(const QRegion &damagedRegion)
return true; return true;
} }
bool DrmQPainterLayer::scanout(SurfaceItem *surfaceItem)
{
Q_UNUSED(surfaceItem);
return false;
}
QSharedPointer<DrmBuffer> DrmQPainterLayer::testBuffer() QSharedPointer<DrmBuffer> DrmQPainterLayer::testBuffer()
{ {
if (!doesSwapchainFit()) { if (!doesSwapchainFit()) {
@ -77,16 +72,6 @@ QRegion DrmQPainterLayer::currentDamage() const
return m_currentDamage; return m_currentDamage;
} }
bool DrmQPainterLayer::hasDirectScanoutBuffer() const
{
return false;
}
QSharedPointer<GLTexture> DrmQPainterLayer::texture() const
{
return nullptr;
}
QImage *DrmQPainterLayer::image() QImage *DrmQPainterLayer::image()
{ {
return m_swapchain ? m_swapchain->currentBuffer()->image() : nullptr; return m_swapchain ? m_swapchain->currentBuffer()->image() : nullptr;
@ -112,17 +97,6 @@ bool DrmVirtualQPainterLayer::endRendering(const QRegion &damagedRegion)
return true; return true;
} }
bool DrmVirtualQPainterLayer::scanout(SurfaceItem *surfaceItem)
{
Q_UNUSED(surfaceItem);
return false;
}
QSharedPointer<GLTexture> DrmVirtualQPainterLayer::texture() const
{
return nullptr;
}
QRegion DrmVirtualQPainterLayer::currentDamage() const QRegion DrmVirtualQPainterLayer::currentDamage() const
{ {
return m_currentDamage; return m_currentDamage;
@ -133,4 +107,27 @@ QImage *DrmVirtualQPainterLayer::image()
return &m_image; return &m_image;
} }
DrmLeaseQPainterLayer::DrmLeaseQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline)
: DrmPipelineLayer(pipeline)
{
connect(backend, &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() {
m_buffer.reset();
});
}
QSharedPointer<DrmBuffer> DrmLeaseQPainterLayer::testBuffer()
{
const auto size = m_pipeline->sourceSize();
if (!m_buffer || m_buffer->size() != size) {
m_buffer = QSharedPointer<DrmDumbBuffer>::create(m_pipeline->gpu(), size, DRM_FORMAT_XRGB8888);
}
return m_buffer;
}
QSharedPointer<DrmBuffer> DrmLeaseQPainterLayer::currentBuffer() const
{
return m_buffer;
}
} }

View file

@ -17,6 +17,8 @@ namespace KWin
class DumbSwapchain; class DumbSwapchain;
class DrmPipeline; class DrmPipeline;
class DrmVirtualOutput; class DrmVirtualOutput;
class DrmQPainterBackend;
class DrmDumbBuffer;
class QPainterLayer class QPainterLayer
{ {
@ -26,19 +28,16 @@ public:
virtual QImage *image() = 0; virtual QImage *image() = 0;
}; };
class DrmQPainterLayer : public DrmPipelineLayer, QPainterLayer class DrmQPainterLayer : public DrmPipelineLayer, public QPainterLayer
{ {
public: public:
DrmQPainterLayer(DrmPipeline *pipeline); DrmQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline);
std::optional<QRegion> startRendering() override; std::optional<QRegion> startRendering() override;
bool endRendering(const QRegion &damagedRegion) override; bool endRendering(const QRegion &damagedRegion) override;
bool scanout(SurfaceItem *surfaceItem) override;
QSharedPointer<DrmBuffer> testBuffer() override; QSharedPointer<DrmBuffer> testBuffer() override;
QSharedPointer<GLTexture> texture() const override;
QSharedPointer<DrmBuffer> currentBuffer() const override; QSharedPointer<DrmBuffer> currentBuffer() const override;
QRegion currentDamage() const override; QRegion currentDamage() const override;
bool hasDirectScanoutBuffer() const override;
QImage *image() override; QImage *image() override;
private: private:
@ -48,16 +47,14 @@ private:
QRegion m_currentDamage; QRegion m_currentDamage;
}; };
class DrmVirtualQPainterLayer : public DrmOutputLayer, QPainterLayer class DrmVirtualQPainterLayer : public DrmOutputLayer, public QPainterLayer
{ {
public: public:
DrmVirtualQPainterLayer(DrmVirtualOutput *output); DrmVirtualQPainterLayer(DrmVirtualOutput *output);
std::optional<QRegion> startRendering() override; std::optional<QRegion> startRendering() override;
bool endRendering(const QRegion &damagedRegion) override; bool endRendering(const QRegion &damagedRegion) override;
bool scanout(SurfaceItem *surfaceItem) override;
QSharedPointer<GLTexture> texture() const override;
QRegion currentDamage() const override; QRegion currentDamage() const override;
QImage *image() override; QImage *image() override;
@ -67,4 +64,16 @@ private:
DrmVirtualOutput *const m_output; DrmVirtualOutput *const m_output;
}; };
class DrmLeaseQPainterLayer : public DrmPipelineLayer
{
public:
DrmLeaseQPainterLayer(DrmQPainterBackend *backend, DrmPipeline *pipeline);
QSharedPointer<DrmBuffer> testBuffer() override;
QSharedPointer<DrmBuffer> currentBuffer() const override;
private:
QSharedPointer<DrmDumbBuffer> m_buffer;
};
} }

View file

@ -14,7 +14,6 @@ namespace KWin
{ {
class DrmPipelineLayer; class DrmPipelineLayer;
class DrmDisplayDevice;
class DrmVirtualOutput; class DrmVirtualOutput;
class DrmPipeline; class DrmPipeline;
class DrmOutputLayer; class DrmOutputLayer;

View file

@ -74,7 +74,7 @@ void DrmVirtualOutput::setDpmsMode(DpmsMode mode)
void DrmVirtualOutput::updateEnablement(bool enable) void DrmVirtualOutput::updateEnablement(bool enable)
{ {
gpu()->platform()->enableOutput(this, enable); m_gpu->platform()->enableOutput(this, enable);
} }
int DrmVirtualOutput::gammaRampSize() const int DrmVirtualOutput::gammaRampSize() const

View file

@ -30,6 +30,7 @@
#include "egl_dmabuf.h" #include "egl_dmabuf.h"
#include "egl_gbm_layer.h" #include "egl_gbm_layer.h"
#include "virtual_egl_gbm_layer.h" #include "virtual_egl_gbm_layer.h"
#include "drm_lease_egl_gbm_layer.h"
// kwin libs // kwin libs
#include <kwinglplatform.h> #include <kwinglplatform.h>
#include <kwineglimagetexture.h> #include <kwineglimagetexture.h>
@ -289,7 +290,11 @@ EGLConfig EglGbmBackend::config(uint32_t format) const
QSharedPointer<DrmPipelineLayer> EglGbmBackend::createDrmPipelineLayer(DrmPipeline *pipeline) QSharedPointer<DrmPipelineLayer> EglGbmBackend::createDrmPipelineLayer(DrmPipeline *pipeline)
{ {
return QSharedPointer<EglGbmLayer>::create(this, pipeline); if (pipeline->output()) {
return QSharedPointer<EglGbmLayer>::create(this, pipeline);
} else {
return QSharedPointer<DrmLeaseEglGbmLayer>::create(this, pipeline);
}
} }
QSharedPointer<DrmOutputLayer> EglGbmBackend::createLayer(DrmVirtualOutput *output) QSharedPointer<DrmOutputLayer> EglGbmBackend::createLayer(DrmVirtualOutput *output)

View file

@ -38,7 +38,6 @@ class ShadowBuffer;
class DrmBackend; class DrmBackend;
class DrmGpu; class DrmGpu;
class EglGbmLayer; class EglGbmLayer;
class DrmDisplayDevice;
class DrmOutputLayer; class DrmOutputLayer;
class DrmPipeline; class DrmPipeline;

View file

@ -90,7 +90,7 @@ std::optional<QRegion> EglGbmLayer::startRendering()
if (!m_gbmSurface->makeContextCurrent()) { if (!m_gbmSurface->makeContextCurrent()) {
return std::optional<QRegion>(); return std::optional<QRegion>();
} }
auto repaintRegion = m_gbmSurface->repaintRegion(m_pipeline->displayDevice()->renderGeometry()); auto repaintRegion = m_gbmSurface->repaintRegion(m_pipeline->output()->geometry());
// shadow buffer // shadow buffer
if (doesShadowBufferFit(m_shadowBuffer.data())) { if (doesShadowBufferFit(m_shadowBuffer.data())) {
@ -124,7 +124,7 @@ std::optional<QRegion> EglGbmLayer::startRendering()
void EglGbmLayer::aboutToStartPainting(const QRegion &damagedRegion) void EglGbmLayer::aboutToStartPainting(const QRegion &damagedRegion)
{ {
if (m_gbmSurface->bufferAge() > 0 && !damagedRegion.isEmpty() && m_eglBackend->supportsPartialUpdate()) { if (m_gbmSurface->bufferAge() > 0 && !damagedRegion.isEmpty() && m_eglBackend->supportsPartialUpdate()) {
QVector<EGLint> rects = m_pipeline->displayDevice()->regionToRects(damagedRegion); QVector<EGLint> rects = m_pipeline->output()->regionToRects(damagedRegion);
const bool correct = eglSetDamageRegionKHR(m_eglBackend->eglDisplay(), m_gbmSurface->eglSurface(), rects.data(), rects.count() / 4); const bool correct = eglSetDamageRegionKHR(m_eglBackend->eglDisplay(), m_gbmSurface->eglSurface(), rects.data(), rects.count() / 4);
if (!correct) { if (!correct) {
qCWarning(KWIN_DRM) << "eglSetDamageRegionKHR failed:" << getEglErrorString(); qCWarning(KWIN_DRM) << "eglSetDamageRegionKHR failed:" << getEglErrorString();
@ -178,7 +178,7 @@ bool EglGbmLayer::renderTestBuffer()
return false; return false;
} }
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
if (!endRendering(m_pipeline->displayDevice()->renderGeometry())) { if (!endRendering(m_pipeline->output()->geometry())) {
return false; return false;
} }
return true; return true;
@ -438,11 +438,11 @@ bool EglGbmLayer::scanout(SurfaceItem *surfaceItem)
surfaceItem->resetDamage(); surfaceItem->resetDamage();
for (const auto &rect : trackedDamage) { for (const auto &rect : trackedDamage) {
auto damageRect = QRect(rect); auto damageRect = QRect(rect);
damageRect.translate(m_pipeline->displayDevice()->renderGeometry().topLeft()); damageRect.translate(m_pipeline->output()->geometry().topLeft());
damage |= damageRect; damage |= damageRect;
} }
} else { } else {
damage = m_pipeline->displayDevice()->renderGeometry(); damage = m_pipeline->output()->geometry();
} }
if (m_pipeline->testScanout()) { if (m_pipeline->testScanout()) {
m_currentBuffer = m_scanoutBuffer; m_currentBuffer = m_scanoutBuffer;

View file

@ -28,12 +28,7 @@ namespace KWin
class GbmSurface; class GbmSurface;
class DumbSwapchain; class DumbSwapchain;
class ShadowBuffer; class ShadowBuffer;
class DrmBuffer;
class DrmGpu;
class SurfaceItem;
class GLTexture;
class EglGbmBackend; class EglGbmBackend;
class DrmPipeline;
class EglGbmLayer : public DrmPipelineLayer class EglGbmLayer : public DrmPipelineLayer
{ {

View file

@ -14,6 +14,7 @@
#include "renderloop_p.h" #include "renderloop_p.h"
#include "drm_qpainter_layer.h" #include "drm_qpainter_layer.h"
#include "drm_virtual_output.h" #include "drm_virtual_output.h"
#include "drm_pipeline.h"
#include <drm_fourcc.h> #include <drm_fourcc.h>
@ -54,7 +55,11 @@ void DrmQPainterBackend::endFrame(AbstractOutput *output, const QRegion &rendere
QSharedPointer<DrmPipelineLayer> DrmQPainterBackend::createDrmPipelineLayer(DrmPipeline *pipeline) QSharedPointer<DrmPipelineLayer> DrmQPainterBackend::createDrmPipelineLayer(DrmPipeline *pipeline)
{ {
return QSharedPointer<DrmQPainterLayer>::create(pipeline); if (pipeline->output()) {
return QSharedPointer<DrmQPainterLayer>::create(this, pipeline);
} else {
return QSharedPointer<DrmLeaseQPainterLayer>::create(this, pipeline);
}
} }
QSharedPointer<DrmOutputLayer> DrmQPainterBackend::createLayer(DrmVirtualOutput *output) QSharedPointer<DrmOutputLayer> DrmQPainterBackend::createLayer(DrmVirtualOutput *output)

View file

@ -17,8 +17,6 @@
namespace KWin namespace KWin
{ {
class DrmDisplayDevice;
class ShadowBuffer class ShadowBuffer
{ {
public: public: