diff --git a/src/backends/drm/CMakeLists.txt b/src/backends/drm/CMakeLists.txt index 77538589df..b28f23192e 100644 --- a/src/backends/drm/CMakeLists.txt +++ b/src/backends/drm/CMakeLists.txt @@ -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 diff --git a/src/backends/drm/drm_abstract_output.cpp b/src/backends/drm/drm_abstract_output.cpp index 04f5685d74..1c28444b8f 100644 --- a/src/backends/drm/drm_abstract_output.cpp +++ b/src/backends/drm/drm_abstract_output.cpp @@ -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; diff --git a/src/backends/drm/drm_abstract_output.h b/src/backends/drm/drm_abstract_output.h index 604b24d1e6..d1e4e522dc 100644 --- a/src/backends/drm/drm_abstract_output.h +++ b/src/backends/drm/drm_abstract_output.h @@ -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 &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 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; }; } diff --git a/src/backends/drm/drm_display_device.cpp b/src/backends/drm/drm_display_device.cpp new file mode 100644 index 0000000000..aafefb4c9a --- /dev/null +++ b/src/backends/drm/drm_display_device.cpp @@ -0,0 +1,24 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2022 Xaver Hugl + + 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; +} + +} diff --git a/src/backends/drm/drm_display_device.h b/src/backends/drm/drm_display_device.h new file mode 100644 index 0000000000..7021274950 --- /dev/null +++ b/src/backends/drm/drm_display_device.h @@ -0,0 +1,41 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2022 Xaver Hugl + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#pragma once + +#include + +#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 &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 supportedModifiers(uint32_t drmFormat) const = 0; + virtual int maxBpc() const = 0; + +protected: + DrmGpu *const m_gpu; +}; + +} diff --git a/src/backends/drm/drm_lease_output.cpp b/src/backends/drm/drm_lease_output.cpp index a2858824bf..80d6748355 100644 --- a/src/backends/drm/drm_lease_output.cpp +++ b/src/backends/drm/drm_lease_output.cpp @@ -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 &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 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; + } +} + } diff --git a/src/backends/drm/drm_lease_output.h b/src/backends/drm/drm_lease_output.h index ae8db03128..dc4be7f91a 100644 --- a/src/backends/drm/drm_lease_output.h +++ b/src/backends/drm/drm_lease_output.h @@ -13,6 +13,8 @@ #include #include +#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 &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 supportedModifiers(uint32_t drmFormat) const override; + int maxBpc() const override; + private: DrmPipeline *m_pipeline; KWaylandServer::DrmLeaseV1Interface *m_lease = nullptr; diff --git a/src/backends/drm/drm_output.cpp b/src/backends/drm/drm_output.cpp index 78432f588f..e8b9458b41 100644 --- a/src/backends/drm/drm_output.cpp +++ b/src/backends/drm/drm_output.cpp @@ -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 &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; + } +} + } diff --git a/src/backends/drm/drm_output.h b/src/backends/drm/drm_output.h index f9e41a278d..cf30ec2afd 100644 --- a/src/backends/drm/drm_output.h +++ b/src/backends/drm/drm_output.h @@ -52,7 +52,7 @@ public: QSize sourceSize() const override; bool isFormatSupported(uint32_t drmFormat) const override; QVector supportedModifiers(uint32_t drmFormat) const override; - bool needsSoftwareTransformation() const override; + DrmPlane::Transformations softwareTransforms() const override; int maxBpc() const override; bool queueChanges(const WaylandOutputConfig &config); diff --git a/src/backends/drm/drm_virtual_output.cpp b/src/backends/drm/drm_virtual_output.cpp index 56f99a4719..87ee88dadd 100644 --- a/src/backends/drm/drm_virtual_output.cpp +++ b/src/backends/drm/drm_virtual_output.cpp @@ -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; +} + } diff --git a/src/backends/drm/drm_virtual_output.h b/src/backends/drm/drm_virtual_output.h index dd836bb64e..68cdd57ba6 100644 --- a/src/backends/drm/drm_virtual_output.h +++ b/src/backends/drm/drm_virtual_output.h @@ -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); diff --git a/src/backends/drm/egl_gbm_layer.cpp b/src/backends/drm/egl_gbm_layer.cpp index adb5b883ba..43ffaa558a 100644 --- a/src/backends/drm/egl_gbm_layer.cpp +++ b/src/backends/drm/egl_gbm_layer.cpp @@ -85,7 +85,7 @@ std::optional 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::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;