backends/drm: introduce DrmDisplayDevice

DrmDisplayDevice is a new parent class for both normal and lease outputs,
which makes it possible to simplify a few things
This commit is contained in:
Xaver Hugl 2022-02-10 04:48:11 +01:00
parent ddb6dadfc2
commit dd198461ea
12 changed files with 142 additions and 40 deletions

View file

@ -13,6 +13,7 @@ set(DRM_SOURCES
drm_gpu.cpp
dumb_swapchain.cpp
shadowbuffer.cpp
drm_display_device.cpp
drm_pipeline.cpp
drm_pipeline_legacy.cpp
drm_abstract_output.cpp

View file

@ -15,16 +15,11 @@ namespace KWin
DrmAbstractOutput::DrmAbstractOutput(DrmGpu *gpu)
: AbstractWaylandOutput(gpu->platform())
, DrmDisplayDevice(gpu)
, m_renderLoop(new RenderLoop(this))
, m_gpu(gpu)
{
}
DrmGpu *DrmAbstractOutput::gpu() const
{
return m_gpu;
}
RenderLoop *DrmAbstractOutput::renderLoop() const
{
return m_renderLoop;

View file

@ -9,41 +9,25 @@
#pragma once
#include "abstract_wayland_output.h"
#include "drm_display_device.h"
namespace KWin
{
class DrmBackend;
class DrmGpu;
class DrmBuffer;
class GbmBuffer;
class DrmAbstractOutput : public AbstractWaylandOutput
class DrmAbstractOutput : public AbstractWaylandOutput, public DrmDisplayDevice
{
Q_OBJECT
public:
virtual bool present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion) = 0;
DrmAbstractOutput(DrmGpu *gpu);
virtual bool needsSoftwareTransformation() const = 0;
virtual QSize bufferSize() const = 0;
virtual QSize sourceSize() const = 0;
virtual bool isFormatSupported(uint32_t drmFormat) const = 0;
virtual QVector<uint64_t> supportedModifiers(uint32_t drmFormat) const = 0;
/**
* returns the maximum bits per color channel that make sense to be used for this output
*/
virtual int maxBpc() const = 0;
DrmGpu *gpu() const;
RenderLoop *renderLoop() const override;
protected:
friend class DrmBackend;
friend class DrmGpu;
DrmAbstractOutput(DrmGpu *gpu);
RenderLoop *m_renderLoop;
DrmGpu *m_gpu;
};
}

View file

@ -0,0 +1,24 @@
/*
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

@ -0,0 +1,41 @@
/*
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 DrmDisplayDevice
{
public:
DrmDisplayDevice(DrmGpu *gpu);
virtual ~DrmDisplayDevice() = default;
DrmGpu *gpu() const;
virtual bool present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion) = 0;
virtual DrmPlane::Transformations softwareTransforms() const = 0;
virtual QSize bufferSize() const = 0;
virtual QSize sourceSize() const = 0;
virtual bool isFormatSupported(uint32_t drmFormat) const = 0;
virtual QVector<uint64_t> supportedModifiers(uint32_t drmFormat) const = 0;
virtual int maxBpc() const = 0;
protected:
DrmGpu *const m_gpu;
};
}

View file

@ -29,6 +29,7 @@ DrmLeaseOutput::DrmLeaseOutput(DrmPipeline *pipeline, KWaylandServer::DrmLeaseDe
pipeline->connector()->modelName(),
QStringLiteral("%1 %2").arg(pipeline->connector()->edid()->manufacturerString(), pipeline->connector()->modelName())
)
, DrmDisplayDevice(pipeline->gpu())
, m_pipeline(pipeline)
{
qCDebug(KWIN_DRM) << "offering connector" << m_pipeline->connector()->id() << "for lease";
@ -75,4 +76,45 @@ DrmPipeline *DrmLeaseOutput::pipeline() const
return m_pipeline;
}
bool DrmLeaseOutput::present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion)
{
Q_UNUSED(buffer)
Q_UNUSED(damagedRegion)
return false;
}
DrmPlane::Transformations DrmLeaseOutput::softwareTransforms() const
{
return DrmPlane::Transformation::Rotate0;
}
QSize DrmLeaseOutput::bufferSize() const
{
return m_pipeline->bufferSize();
}
QSize DrmLeaseOutput::sourceSize() const
{
return m_pipeline->sourceSize();
}
bool DrmLeaseOutput::isFormatSupported(uint32_t drmFormat) const
{
return m_pipeline->isFormatSupported(drmFormat);
}
QVector<uint64_t> DrmLeaseOutput::supportedModifiers(uint32_t drmFormat) const
{
return m_pipeline->supportedModifiers(drmFormat);
}
int DrmLeaseOutput::maxBpc() const
{
if (const auto prop = m_pipeline->connector()->getProp(DrmConnector::PropertyIndex::MaxBpc)) {
return prop->maxValue();
} else {
return 8;
}
}
}

View file

@ -13,6 +13,8 @@
#include <QVector>
#include <KWaylandServer/drmleasedevice_v1_interface.h>
#include "drm_display_device.h"
namespace KWin
{
@ -24,7 +26,7 @@ class DrmPipeline;
* that is not used directly by the compositor but is instead leased out to
* applications (usually VR compositors) that drive the output themselves
*/
class DrmLeaseOutput : public KWaylandServer::DrmLeaseConnectorV1Interface
class DrmLeaseOutput : public KWaylandServer::DrmLeaseConnectorV1Interface, public DrmDisplayDevice
{
Q_OBJECT
public:
@ -38,6 +40,14 @@ public:
KWaylandServer::DrmLeaseV1Interface *lease() const;
DrmPipeline *pipeline() const;
bool present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion) override;
DrmPlane::Transformations softwareTransforms() const override;
QSize bufferSize() const override;
QSize sourceSize() const override;
bool isFormatSupported(uint32_t drmFormat) const override;
QVector<uint64_t> supportedModifiers(uint32_t drmFormat) const override;
int maxBpc() const override;
private:
DrmPipeline *m_pipeline;
KWaylandServer::DrmLeaseV1Interface *m_lease = nullptr;

View file

@ -318,11 +318,6 @@ void DrmOutput::updateModes()
}
}
bool DrmOutput::needsSoftwareTransformation() const
{
return m_pipeline->pending.bufferTransformation != m_pipeline->pending.sourceTransformation;
}
bool DrmOutput::present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion)
{
if (!buffer || buffer->bufferId() == 0) {
@ -472,4 +467,14 @@ bool DrmOutput::usesSoftwareCursor() const
return !m_setCursorSuccessful || !m_moveCursorSuccessful;
}
DrmPlane::Transformations DrmOutput::softwareTransforms() const
{
if (m_pipeline->pending.bufferTransformation == m_pipeline->pending.sourceTransformation) {
return DrmPlane::Transformation::Rotate0;
} else {
// TODO handle sourceTransformation != Rotate0
return m_pipeline->pending.sourceTransformation;
}
}
}

View file

@ -52,7 +52,7 @@ public:
QSize sourceSize() const override;
bool isFormatSupported(uint32_t drmFormat) const override;
QVector<uint64_t> supportedModifiers(uint32_t drmFormat) const override;
bool needsSoftwareTransformation() const override;
DrmPlane::Transformations softwareTransforms() const override;
int maxBpc() const override;
bool queueChanges(const WaylandOutputConfig &config);

View file

@ -109,14 +109,14 @@ bool DrmVirtualOutput::setGammaRamp(const GammaRamp &gamma)
return true;
}
bool DrmVirtualOutput::needsSoftwareTransformation() const
{
return false;
}
int DrmVirtualOutput::maxBpc() const
{
return 8;
}
DrmPlane::Transformations DrmVirtualOutput::softwareTransforms() const
{
return DrmPlane::Transformation::Rotate0;
}
}

View file

@ -38,7 +38,7 @@ public:
int gammaRampSize() const override;
bool setGammaRamp(const GammaRamp &gamma) override;
bool needsSoftwareTransformation() const override;
DrmPlane::Transformations softwareTransforms() const override;
private:
void vblank(std::chrono::nanoseconds timestamp);

View file

@ -85,7 +85,7 @@ std::optional<QRegion> EglGbmLayer::startRendering()
if (doesShadowBufferFit(m_oldShadowBuffer.data())) {
m_shadowBuffer = m_oldShadowBuffer;
} else {
if (m_output->needsSoftwareTransformation()) {
if (m_output->softwareTransforms() != DrmPlane::Transformations(DrmPlane::Transformation::Rotate0)) {
const auto format = m_renderGpu->eglBackend()->gbmFormatForDrmFormat(m_gbmSurface->format());
m_shadowBuffer = QSharedPointer<ShadowBuffer>::create(m_output->sourceSize(), format);
if (!m_shadowBuffer->isComplete()) {
@ -200,7 +200,7 @@ bool EglGbmLayer::doesGbmSurfaceFit(GbmSurface *surf) const
bool EglGbmLayer::doesShadowBufferFit(ShadowBuffer *buffer) const
{
if (m_output->needsSoftwareTransformation()) {
if (m_output->softwareTransforms() != DrmPlane::Transformations(DrmPlane::Transformation::Rotate0)) {
return buffer && buffer->texture()->size() == m_output->sourceSize() && buffer->drmFormat() == m_gbmSurface->format();
} else {
return buffer == nullptr;