Commit aac7f50d authored by Xaver Hugl's avatar Xaver Hugl
Browse files

backends/drm: remove some unnecessary redirection

parent 0ba5916f
......@@ -27,6 +27,7 @@ set(DRM_SOURCES
gbm_surface.cpp
gbm_dmabuf.cpp
placeholderinputeventfilter.cpp
virtual_egl_gbm_layer.cpp
)
add_library(KWinWaylandDrmBackend MODULE ${DRM_SOURCES})
......
......@@ -41,4 +41,20 @@ void DrmAbstractOutput::pageFlipped(std::chrono::nanoseconds timestamp) const
RenderLoopPrivate::get(m_renderLoop)->notifyFrameCompleted(timestamp);
}
QVector<int32_t> DrmAbstractOutput::regionToRects(const QRegion &region) const
{
const int height = pixelSize().height();
const QMatrix4x4 matrix = AbstractWaylandOutput::logicalToNativeMatrix(geometry(), scale(), transform());
QVector<EGLint> rects;
rects.reserve(region.rectCount() * 4);
for (const QRect &_rect : region) {
const QRect rect = matrix.mapRect(_rect);
rects << rect.left();
rects << height - (rect.y() + rect.height());
rects << rect.width();
rects << rect.height();
}
return rects;
}
}
......@@ -26,6 +26,7 @@ public:
QRect renderGeometry() const override;
void frameFailed() const override;
void pageFlipped(std::chrono::nanoseconds timestamp) const override;
QVector<int32_t> regionToRects(const QRegion &region) const override;
protected:
friend class DrmGpu;
......
......@@ -21,9 +21,10 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <gbm.h>
#include <drm_fourcc.h>
// KWaylandServer
#include "KWaylandServer/clientbuffer.h"
#include <drm_fourcc.h>
#include "KWaylandServer/linuxdmabufv1clientbuffer.h"
namespace KWin
{
......@@ -31,17 +32,42 @@ namespace KWin
GbmBuffer::GbmBuffer(GbmSurface *surface, gbm_bo *bo)
: m_surface(surface)
, m_bo(bo)
, m_stride(gbm_bo_get_stride(m_bo))
{
m_stride = gbm_bo_get_stride(m_bo);
}
GbmBuffer::GbmBuffer(gbm_bo *buffer, KWaylandServer::ClientBuffer *clientBuffer)
: m_bo(buffer)
, m_clientBuffer(clientBuffer)
, m_stride(gbm_bo_get_stride(m_bo))
GbmBuffer::GbmBuffer(DrmGpu *gpu, KWaylandServer::LinuxDmaBufV1ClientBuffer *clientBuffer)
: m_clientBuffer(clientBuffer)
{
if (m_clientBuffer) {
m_clientBuffer->ref();
clientBuffer->ref();
const auto planes = clientBuffer->planes();
if (planes.first().modifier != DRM_FORMAT_MOD_INVALID || planes.first().offset > 0 || planes.count() > 1) {
gbm_import_fd_modifier_data data = {};
data.format = clientBuffer->format();
data.width = (uint32_t) clientBuffer->size().width();
data.height = (uint32_t) clientBuffer->size().height();
data.num_fds = planes.count();
data.modifier = planes.first().modifier;
for (int i = 0; i < planes.count(); i++) {
data.fds[i] = planes[i].fd;
data.offsets[i] = planes[i].offset;
data.strides[i] = planes[i].stride;
}
m_bo = gbm_bo_import(gpu->gbmDevice(), GBM_BO_IMPORT_FD_MODIFIER, &data, GBM_BO_USE_SCANOUT);
} else {
const auto &plane = planes.first();
gbm_import_fd_data data = {};
data.fd = plane.fd;
data.width = (uint32_t) clientBuffer->size().width();
data.height = (uint32_t) clientBuffer->size().height();
data.stride = plane.stride;
data.format = clientBuffer->format();
m_bo = gbm_bo_import(gpu->gbmDevice(), GBM_BO_IMPORT_FD, &data, GBM_BO_USE_SCANOUT);
}
if (m_bo) {
m_stride = gbm_bo_get_stride(m_bo);
} else if (errno != EINVAL) {
qCWarning(KWIN_DRM) << "Importing buffer for direct scanout failed:" << strerror(errno);
}
}
......@@ -105,13 +131,15 @@ uint32_t GbmBuffer::stride() const
DrmGbmBuffer::DrmGbmBuffer(DrmGpu *gpu, GbmSurface *surface, gbm_bo *bo)
: DrmBuffer(gpu, gbm_bo_get_format(bo), gbm_bo_get_modifier(bo)), GbmBuffer(surface, bo)
: DrmBuffer(gpu, gbm_bo_get_format(bo), gbm_bo_get_modifier(bo))
, GbmBuffer(surface, bo)
{
initialize();
}
DrmGbmBuffer::DrmGbmBuffer(DrmGpu *gpu, gbm_bo *buffer, KWaylandServer::ClientBuffer *clientBuffer)
: DrmBuffer(gpu, gbm_bo_get_format(buffer), gbm_bo_get_modifier(buffer)), GbmBuffer(buffer, clientBuffer)
DrmGbmBuffer::DrmGbmBuffer(DrmGpu *gpu, KWaylandServer::LinuxDmaBufV1ClientBuffer *clientBuffer)
: DrmBuffer(gpu, clientBuffer->format(), clientBuffer->planes().constFirst().modifier)
, GbmBuffer(gpu, clientBuffer)
{
initialize();
}
......@@ -127,6 +155,9 @@ DrmGbmBuffer::~DrmGbmBuffer()
void DrmGbmBuffer::initialize()
{
if (!m_bo) {
return;
}
m_size = QSize(gbm_bo_get_width(m_bo), gbm_bo_get_height(m_bo));
uint32_t handles[4] = { };
uint32_t strides[4] = { };
......
......@@ -19,6 +19,7 @@ struct gbm_bo;
namespace KWaylandServer
{
class ClientBuffer;
class LinuxDmaBufV1ClientBuffer;
}
namespace KWin
......@@ -31,7 +32,7 @@ class GbmBuffer : public QObject
Q_OBJECT
public:
GbmBuffer(GbmSurface *surface, gbm_bo *bo);
GbmBuffer(gbm_bo *buffer, KWaylandServer::ClientBuffer *clientBuffer);
GbmBuffer(DrmGpu *gpu, KWaylandServer::LinuxDmaBufV1ClientBuffer *clientBuffer);
virtual ~GbmBuffer();
void releaseBuffer();
......@@ -56,7 +57,7 @@ class DrmGbmBuffer : public DrmBuffer, public GbmBuffer
{
public:
DrmGbmBuffer(DrmGpu *gpu, GbmSurface *surface, gbm_bo *bo);
DrmGbmBuffer(DrmGpu *gpu, gbm_bo *buffer, KWaylandServer::ClientBuffer *clientBuffer);
DrmGbmBuffer(DrmGpu *gpu, KWaylandServer::LinuxDmaBufV1ClientBuffer *clientBuffer);
~DrmGbmBuffer() override;
bool needsModeChange(DrmBuffer *b) const override;
......
......@@ -17,7 +17,7 @@ namespace KWin
class DrmBuffer;
class DrmGpu;
class DrmLayer;
class DrmOutputLayer;
class DrmDisplayDevice
{
......@@ -28,18 +28,11 @@ public:
DrmGpu *gpu() const;
virtual bool present() = 0;
virtual bool testScanout() = 0;
virtual void frameFailed() const = 0;
virtual void pageFlipped(std::chrono::nanoseconds timestamp) const = 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;
virtual QRect renderGeometry() const = 0;
virtual DrmLayer *outputLayer() const = 0;
virtual DrmOutputLayer *outputLayer() const = 0;
virtual QVector<int32_t> regionToRects(const QRegion &region) const = 0;
protected:
DrmGpu *const m_gpu;
......
......@@ -422,7 +422,7 @@ bool DrmGpu::testPipelines()
QVector<DrmPipeline*> inactivePipelines;
for (const auto &pipeline : qAsConst(m_pipelines)) {
if (!pipeline->pending.layer) {
pipeline->pending.layer = m_platform->renderBackend()->createLayer(pipeline->displayDevice());
pipeline->pending.layer = m_platform->renderBackend()->createDrmPipelineLayer(pipeline);
}
if (!pipeline->pending.active) {
pipeline->pending.active = true;
......@@ -772,7 +772,7 @@ QSize DrmGpu::cursorSize() const
void DrmGpu::recreateSurfaces()
{
for (const auto &pipeline : qAsConst(m_pipelines)) {
pipeline->pending.layer = m_platform->renderBackend()->createLayer(pipeline->displayDevice());
pipeline->pending.layer = m_platform->renderBackend()->createDrmPipelineLayer(pipeline);
}
for (const auto &output : qAsConst(m_outputs)) {
if (const auto virtualOutput = qobject_cast<DrmVirtualOutput*>(output)) {
......
......@@ -7,20 +7,24 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "drm_layer.h"
#include "drm_pipeline.h"
#include "drm_display_device.h"
#include <QMatrix4x4>
namespace KWin
{
DrmLayer::DrmLayer(KWin::DrmDisplayDevice* device)
: m_displayDevice(device)
DrmOutputLayer::~DrmOutputLayer() = default;
void DrmOutputLayer::aboutToStartPainting(const QRegion &damagedRegion)
{
Q_UNUSED(damagedRegion)
}
DrmLayer::~DrmLayer() = default;
DrmDisplayDevice *DrmLayer::displayDevice() const
DrmPipelineLayer::DrmPipelineLayer(DrmPipeline *pipeline)
: m_pipeline(pipeline)
{
return m_displayDevice;
}
}
......
......@@ -18,15 +18,16 @@ namespace KWin
class SurfaceItem;
class DrmBuffer;
class DrmDisplayDevice;
class GLTexture;
class DrmPipeline;
class DrmLayer : public QObject
class DrmOutputLayer : public QObject
{
Q_OBJECT
public:
DrmLayer(DrmDisplayDevice *device);
virtual ~DrmLayer();
virtual ~DrmOutputLayer();
virtual void aboutToStartPainting(const QRegion &damagedRegion);
virtual std::optional<QRegion> startRendering() = 0;
virtual bool endRendering(const QRegion &damagedRegion) = 0;
......@@ -37,6 +38,16 @@ public:
*/
virtual bool scanout(SurfaceItem *surfaceItem) = 0;
virtual QSharedPointer<GLTexture> texture() const = 0;
virtual QRegion currentDamage() const = 0;
};
class DrmPipelineLayer : public DrmOutputLayer
{
public:
DrmPipelineLayer(DrmPipeline *pipeline);
/**
* @returns a buffer for atomic test commits
* If no fitting buffer is available, a new current buffer is created
......@@ -44,13 +55,10 @@ public:
virtual QSharedPointer<DrmBuffer> testBuffer() = 0;
virtual QSharedPointer<DrmBuffer> currentBuffer() const = 0;
virtual QRegion currentDamage() const = 0;
virtual bool hasDirectScanoutBuffer() const = 0;
DrmDisplayDevice *displayDevice() const;
protected:
DrmDisplayDevice *const m_displayDevice;
DrmPipeline *const m_pipeline;
};
}
......@@ -14,6 +14,7 @@
#include "drm_object_crtc.h"
#include "drm_object_plane.h"
#include "drm_pipeline.h"
#include "drm_layer.h"
#include "logging.h"
......@@ -83,51 +84,12 @@ bool DrmLeaseOutput::present()
return false;
}
bool DrmLeaseOutput::testScanout()
{
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;
}
}
QRect DrmLeaseOutput::renderGeometry() const
{
return QRect(QPoint(), m_pipeline->sourceSize());
}
DrmLayer *DrmLeaseOutput::outputLayer() const
DrmOutputLayer *DrmLeaseOutput::outputLayer() const
{
return m_pipeline->pending.layer.data();
}
......@@ -141,4 +103,10 @@ void DrmLeaseOutput::pageFlipped(std::chrono::nanoseconds timestamp) const
Q_UNUSED(timestamp)
}
QVector<int32_t> DrmLeaseOutput::regionToRects(const QRegion &region) const
{
Q_UNUSED(region)
return {};
}
}
......@@ -41,17 +41,11 @@ public:
DrmPipeline *pipeline() const;
bool present() 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;
QRect renderGeometry() const override;
DrmLayer *outputLayer() const override;
bool testScanout() 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:
DrmPipeline *m_pipeline;
......
......@@ -340,11 +340,6 @@ bool DrmOutput::present()
}
}
bool DrmOutput::testScanout()
{
return m_pipeline->testScanout();
}
int DrmOutput::gammaRampSize() const
{
return m_pipeline->pending.crtc ? m_pipeline->pending.crtc->gammaRampSize() : 256;
......@@ -373,26 +368,6 @@ DrmPipeline *DrmOutput::pipeline() const
return m_pipeline;
}
QSize DrmOutput::bufferSize() const
{
return m_pipeline->bufferSize();
}
QSize DrmOutput::sourceSize() const
{
return m_pipeline->sourceSize();
}
bool DrmOutput::isFormatSupported(uint32_t drmFormat) const
{
return m_pipeline->isFormatSupported(drmFormat);
}
QVector<uint64_t> DrmOutput::supportedModifiers(uint32_t drmFormat) const
{
return m_pipeline->supportedModifiers(drmFormat);
}
bool DrmOutput::queueChanges(const WaylandOutputConfig &config)
{
static bool valid;
......@@ -449,28 +424,12 @@ void DrmOutput::revertQueuedChanges()
m_pipeline->revertPendingChanges();
}
int DrmOutput::maxBpc() const
{
auto prop = m_connector->getProp(DrmConnector::PropertyIndex::MaxBpc);
return prop ? prop->maxValue() : 8;
}
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;
}
}
DrmLayer *DrmOutput::outputLayer() const
DrmOutputLayer *DrmOutput::outputLayer() const
{
return m_pipeline->pending.layer.data();
}
......
......@@ -47,14 +47,7 @@ public:
DrmPipeline *pipeline() const;
bool present() override;
bool testScanout() 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;
DrmPlane::Transformations softwareTransforms() const override;
int maxBpc() const override;
DrmLayer *outputLayer() const override;
DrmOutputLayer *outputLayer() const override;
bool queueChanges(const WaylandOutputConfig &config);
void applyQueuedChanges(const WaylandOutputConfig &config);
......
......@@ -31,7 +31,7 @@ class DrmBuffer;
class DrmDumbBuffer;
class GammaRamp;
class DrmConnectorMode;
class DrmLayer;
class DrmPipelineLayer;
class DrmDisplayDevice;
class DrmGammaRamp
......@@ -107,7 +107,7 @@ public:
RenderLoopPrivate::SyncMode syncMode = RenderLoopPrivate::SyncMode::Fixed;
QSharedPointer<DrmGammaRamp> gamma;
QSharedPointer<DrmLayer> layer;
QSharedPointer<DrmPipelineLayer> layer;
QPoint cursorPos;
QPoint cursorHotspot;
......
......@@ -13,16 +13,18 @@
#include "scene_qpainter_drm_backend.h"
#include "drm_gpu.h"
#include "drm_backend.h"
#include "drm_pipeline.h"
#include "drm_virtual_output.h"
#include <drm_fourcc.h>
namespace KWin
{
DrmQPainterLayer::DrmQPainterLayer(DrmDisplayDevice *displayDevice)
: DrmLayer(displayDevice)
DrmQPainterLayer::DrmQPainterLayer(DrmPipeline *pipeline)
: DrmPipelineLayer(pipeline)
{
connect(static_cast<DrmQPainterBackend*>(displayDevice->gpu()->platform()->renderBackend()), &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() {
connect(static_cast<DrmQPainterBackend*>(pipeline->gpu()->platform()->renderBackend()), &DrmQPainterBackend::aboutToBeDestroyed, this, [this]() {
m_swapchain.reset();
});
}
......@@ -30,10 +32,10 @@ DrmQPainterLayer::DrmQPainterLayer(DrmDisplayDevice *displayDevice)
std::optional<QRegion> DrmQPainterLayer::startRendering()
{
if (!doesSwapchainFit()) {
m_swapchain = QSharedPointer<DumbSwapchain>::create(m_displayDevice->gpu(), m_displayDevice->sourceSize(), DRM_FORMAT_XRGB8888);
m_swapchain = QSharedPointer<DumbSwapchain>::create(m_pipeline->gpu(), m_pipeline->sourceSize(), DRM_FORMAT_XRGB8888);
}
QRegion needsRepaint;
if (!m_swapchain->acquireBuffer(m_displayDevice->renderGeometry(), &needsRepaint)) {
if (!m_swapchain->acquireBuffer(m_pipeline->displayDevice()->renderGeometry(), &needsRepaint)) {
return std::optional<QRegion>();
}
return needsRepaint;
......@@ -55,14 +57,14 @@ bool DrmQPainterLayer::scanout(SurfaceItem *surfaceItem)
QSharedPointer<DrmBuffer> DrmQPainterLayer::testBuffer()
{
if (!doesSwapchainFit()) {
m_swapchain = QSharedPointer<DumbSwapchain>::create(m_displayDevice->gpu(), m_displayDevice->sourceSize(), DRM_FORMAT_XRGB8888);
m_swapchain = QSharedPointer<DumbSwapchain>::create(m_pipeline->gpu(), m_pipeline->sourceSize(), DRM_FORMAT_XRGB8888);
}
return m_swapchain->currentBuffer();
}
bool DrmQPainterLayer::doesSwapchainFit() const
{
return m_swapchain && m_swapchain->size() == m_displayDevice->sourceSize();
return m_swapchain && m_swapchain->size() == m_pipeline->sourceSize();
}
QSharedPointer<DrmBuffer> DrmQPainterLayer::currentBuffer() const
......@@ -80,4 +82,55 @@ bool DrmQPainterLayer::hasDirectScanoutBuffer() const
return false;
}
QSharedPointer<GLTexture> DrmQPainterLayer::texture() const
{
return nullptr;
}
QImage *DrmQPainterLayer::image()
{
return m_swapchain ? m_swapchain->currentBuffer()->image() : nullptr;
}
DrmVirtualQPainterLayer::DrmVirtualQPainterLayer(DrmVirtualOutput *output)
: m_output(output)
{
}
std::optional<QRegion> DrmVirtualQPainterLayer::startRendering()
{
if (m_image.isNull() || m_image.size() != m_output->pixelSize()) {
m_image = QImage(m_output->pixelSize(), QImage::Format_RGB32);
}
return QRegion();
}
bool DrmVirtualQPainterLayer::endRendering(const QRegion &damagedRegion)
{
m_currentDamage = damagedRegion;
return true;
}
bool DrmVirtualQPainterLayer::scanout(SurfaceItem *surfaceItem)
{
Q_UNUSED(surfaceItem);
return false;
}
QSharedPointer<GLTexture> DrmVirtualQPainterLayer::texture() const
{
return nullptr;
}
QRegion DrmVirtualQPainterLayer::currentDamage() const
{
return m_currentDamage;
}
QImage *DrmVirtualQPainterLayer::image()
{
return &m_image;
}
}
......@@ -9,23 +9,37 @@
#pragma once
#include "drm_layer.h"
#include <QImage>
namespace KWin
{
class DumbSwapchain;
class DrmPipeline;
class DrmVirtualOutput;
class QPainterLayer
{