diff --git a/src/plugins/platforms/drm/drm_buffer.cpp b/src/plugins/platforms/drm/drm_buffer.cpp index 9508eca113..05c58901ef 100644 --- a/src/plugins/platforms/drm/drm_buffer.cpp +++ b/src/plugins/platforms/drm/drm_buffer.cpp @@ -9,6 +9,7 @@ #include "drm_buffer.h" #include "logging.h" +#include "drm_gpu.h" // system #include @@ -21,14 +22,14 @@ namespace KWin { -DrmBuffer:: DrmBuffer(int fd) - : m_fd(fd) +DrmBuffer:: DrmBuffer(DrmGpu *gpu) + : m_gpu(gpu) { } // DrmDumbBuffer -DrmDumbBuffer::DrmDumbBuffer(int fd, const QSize &size) - : DrmBuffer(fd) +DrmDumbBuffer::DrmDumbBuffer(DrmGpu *gpu, const QSize &size) + : DrmBuffer(gpu) { m_size = size; drm_mode_create_dumb createArgs; @@ -36,14 +37,14 @@ DrmDumbBuffer::DrmDumbBuffer(int fd, const QSize &size) createArgs.bpp = 32; createArgs.width = size.width(); createArgs.height = size.height(); - if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &createArgs) != 0) { + if (drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_CREATE_DUMB, &createArgs) != 0) { qCWarning(KWIN_DRM) << "DRM_IOCTL_MODE_CREATE_DUMB failed"; return; } m_handle = createArgs.handle; m_bufferSize = createArgs.size; m_stride = createArgs.pitch; - if (drmModeAddFB(fd, size.width(), size.height(), 24, 32, + if (drmModeAddFB(m_gpu->fd(), size.width(), size.height(), 24, 32, m_stride, createArgs.handle, &m_bufferId) != 0) { qCWarning(KWIN_DRM) << "drmModeAddFB failed with errno" << errno; } @@ -52,7 +53,7 @@ DrmDumbBuffer::DrmDumbBuffer(int fd, const QSize &size) DrmDumbBuffer::~DrmDumbBuffer() { if (m_bufferId) { - drmModeRmFB(fd(), m_bufferId); + drmModeRmFB(m_gpu->fd(), m_bufferId); } delete m_image; @@ -62,7 +63,7 @@ DrmDumbBuffer::~DrmDumbBuffer() if (m_handle) { drm_mode_destroy_dumb destroyArgs; destroyArgs.handle = m_handle; - drmIoctl(fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs); + drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs); } } @@ -82,10 +83,10 @@ bool DrmDumbBuffer::map(QImage::Format format) drm_mode_map_dumb mapArgs; memset(&mapArgs, 0, sizeof mapArgs); mapArgs.handle = m_handle; - if (drmIoctl(fd(), DRM_IOCTL_MODE_MAP_DUMB, &mapArgs) != 0) { + if (drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_MAP_DUMB, &mapArgs) != 0) { return false; } - void *address = mmap(nullptr, m_bufferSize, PROT_WRITE, MAP_SHARED, fd(), mapArgs.offset); + void *address = mmap(nullptr, m_bufferSize, PROT_WRITE, MAP_SHARED, m_gpu->fd(), mapArgs.offset); if (address == MAP_FAILED) { return false; } diff --git a/src/plugins/platforms/drm/drm_buffer.h b/src/plugins/platforms/drm/drm_buffer.h index c7f524d0ca..6c21028468 100644 --- a/src/plugins/platforms/drm/drm_buffer.h +++ b/src/plugins/platforms/drm/drm_buffer.h @@ -15,11 +15,13 @@ namespace KWin { +class DrmGpu; + class DrmBuffer : public QObject { Q_OBJECT public: - DrmBuffer(int fd); + DrmBuffer(DrmGpu *gpu); virtual ~DrmBuffer() = default; virtual bool needsModeChange(DrmBuffer *b) const {Q_UNUSED(b) return false;} @@ -34,20 +36,20 @@ public: virtual void releaseGbm() {} - int fd() const { - return m_fd; + DrmGpu *gpu() const { + return m_gpu; } protected: quint32 m_bufferId = 0; QSize m_size; - int m_fd; + DrmGpu *m_gpu; }; class DrmDumbBuffer : public DrmBuffer { public: - DrmDumbBuffer(int fd, const QSize &size); + DrmDumbBuffer(DrmGpu *gpu, const QSize &size); ~DrmDumbBuffer() override; bool needsModeChange(DrmBuffer *b) const override; diff --git a/src/plugins/platforms/drm/drm_buffer_gbm.cpp b/src/plugins/platforms/drm/drm_buffer_gbm.cpp index cecd9e6189..e19e5e9efb 100644 --- a/src/plugins/platforms/drm/drm_buffer_gbm.cpp +++ b/src/plugins/platforms/drm/drm_buffer_gbm.cpp @@ -11,6 +11,7 @@ #include "gbm_surface.h" #include "logging.h" +#include "drm_gpu.h" // system #include @@ -28,8 +29,8 @@ namespace KWin { // DrmSurfaceBuffer -DrmSurfaceBuffer::DrmSurfaceBuffer(int fd, const QSharedPointer &surface) - : DrmBuffer(fd) +DrmSurfaceBuffer::DrmSurfaceBuffer(DrmGpu *gpu, const QSharedPointer &surface) + : DrmBuffer(gpu) , m_surface(surface) { m_bo = m_surface->lockFrontBuffer(); @@ -40,8 +41,8 @@ DrmSurfaceBuffer::DrmSurfaceBuffer(int fd, const QSharedPointer &sur initialize(); } -DrmSurfaceBuffer::DrmSurfaceBuffer(int fd, gbm_bo *buffer, KWaylandServer::BufferInterface *bufferInterface) - : DrmBuffer(fd) +DrmSurfaceBuffer::DrmSurfaceBuffer(DrmGpu *gpu, gbm_bo *buffer, KWaylandServer::BufferInterface *bufferInterface) + : DrmBuffer(gpu) , m_bo(buffer) , m_bufferInterface(bufferInterface) { @@ -55,7 +56,7 @@ DrmSurfaceBuffer::DrmSurfaceBuffer(int fd, gbm_bo *buffer, KWaylandServer::Buffe DrmSurfaceBuffer::~DrmSurfaceBuffer() { if (m_bufferId) { - drmModeRmFB(fd(), m_bufferId); + drmModeRmFB(m_gpu->fd(), m_bufferId); } releaseGbm(); if (m_bufferInterface) { @@ -99,14 +100,14 @@ void DrmSurfaceBuffer::initialize() modifiers[0] = DRM_FORMAT_MOD_INVALID; } - if (modifiers[0] != DRM_FORMAT_MOD_INVALID) { - if (drmModeAddFB2WithModifiers(m_fd, m_size.width(), m_size.height(), gbm_bo_get_format(m_bo), handles, strides, offsets, modifiers, &m_bufferId, DRM_MODE_FB_MODIFIERS)) { + if (modifiers[0] != DRM_FORMAT_MOD_INVALID && m_gpu->addFB2ModifiersSupported()) { + if (drmModeAddFB2WithModifiers(m_gpu->fd(), m_size.width(), m_size.height(), gbm_bo_get_format(m_bo), handles, strides, offsets, modifiers, &m_bufferId, DRM_MODE_FB_MODIFIERS)) { qCWarning(KWIN_DRM) << "drmModeAddFB2WithModifiers failed!" << strerror(errno); } } else { - if (drmModeAddFB2(m_fd, m_size.width(), m_size.height(), gbm_bo_get_format(m_bo), handles, strides, offsets, &m_bufferId, 0)) { + if (drmModeAddFB2(m_gpu->fd(), m_size.width(), m_size.height(), gbm_bo_get_format(m_bo), handles, strides, offsets, &m_bufferId, 0)) { // fallback - if (drmModeAddFB(m_fd, m_size.width(), m_size.height(), 24, 32, strides[0], handles[0], &m_bufferId) != 0) { + if (drmModeAddFB(m_gpu->fd(), m_size.width(), m_size.height(), 24, 32, strides[0], handles[0], &m_bufferId) != 0) { qCWarning(KWIN_DRM) << "drmModeAddFB2 and drmModeAddFB both failed!" << strerror(errno); } } diff --git a/src/plugins/platforms/drm/drm_buffer_gbm.h b/src/plugins/platforms/drm/drm_buffer_gbm.h index e2970014e8..2958de7576 100644 --- a/src/plugins/platforms/drm/drm_buffer_gbm.h +++ b/src/plugins/platforms/drm/drm_buffer_gbm.h @@ -29,8 +29,8 @@ class GbmSurface; class DrmSurfaceBuffer : public DrmBuffer { public: - DrmSurfaceBuffer(int fd, const QSharedPointer &surface); - DrmSurfaceBuffer(int fd, gbm_bo *buffer, KWaylandServer::BufferInterface *bufferInterface); + DrmSurfaceBuffer(DrmGpu *gpu, const QSharedPointer &surface); + DrmSurfaceBuffer(DrmGpu *gpu, gbm_bo *buffer, KWaylandServer::BufferInterface *bufferInterface); ~DrmSurfaceBuffer() override; bool needsModeChange(DrmBuffer *b) const override { diff --git a/src/plugins/platforms/drm/drm_gpu.cpp b/src/plugins/platforms/drm/drm_gpu.cpp index c8ada81a47..d4ca98b30f 100644 --- a/src/plugins/platforms/drm/drm_gpu.cpp +++ b/src/plugins/platforms/drm/drm_gpu.cpp @@ -58,6 +58,11 @@ DrmGpu::DrmGpu(DrmBackend *backend, QByteArray devNode, int fd, int drmId) : m_b m_presentationClock = CLOCK_REALTIME; } + if (!qEnvironmentVariableIsSet("KWIN_DRM_NO_MODIFIERS")) { + m_addFB2ModifiersSupported = drmGetCap(fd, DRM_CAP_ADDFB2_MODIFIERS, &capability) && capability == 1; + qCDebug(KWIN_DRM) << "drmModeAddFB2WithModifiers is" << (m_addFB2ModifiersSupported ? "supported" : "not supported"); + } + // find out if this GPU is using the NVidia proprietary driver DrmScopedPointer version(drmGetVersion(fd)); m_useEglStreams = strstr(version->name, "nvidia-drm"); diff --git a/src/plugins/platforms/drm/drm_gpu.h b/src/plugins/platforms/drm/drm_gpu.h index 5ae90c8b7f..cd6eec2cae 100644 --- a/src/plugins/platforms/drm/drm_gpu.h +++ b/src/plugins/platforms/drm/drm_gpu.h @@ -92,6 +92,10 @@ public: */ clockid_t presentationClock() const; + bool addFB2ModifiersSupported() const { + return m_addFB2ModifiersSupported; + } + void waitIdle(); Q_SIGNALS: @@ -124,6 +128,7 @@ private: EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; clockid_t m_presentationClock; QSocketNotifier *m_socketNotifier = nullptr; + bool m_addFB2ModifiersSupported = false; // all planes: primarys, cursors and overlays QVector m_planes; diff --git a/src/plugins/platforms/drm/drm_object_crtc.cpp b/src/plugins/platforms/drm/drm_object_crtc.cpp index 7b480fbe31..4799a15d60 100644 --- a/src/plugins/platforms/drm/drm_object_crtc.cpp +++ b/src/plugins/platforms/drm/drm_object_crtc.cpp @@ -81,7 +81,7 @@ bool DrmCrtc::blank(DrmOutput *output) } if (!m_blackBuffer) { - DrmDumbBuffer *blackBuffer = new DrmDumbBuffer(m_gpu->fd(), output->pixelSize()); + DrmDumbBuffer *blackBuffer = new DrmDumbBuffer(m_gpu, output->pixelSize()); if (!blackBuffer->map()) { delete blackBuffer; return false; diff --git a/src/plugins/platforms/drm/drm_output.cpp b/src/plugins/platforms/drm/drm_output.cpp index 002ea81f4c..52ff5ac534 100644 --- a/src/plugins/platforms/drm/drm_output.cpp +++ b/src/plugins/platforms/drm/drm_output.cpp @@ -359,7 +359,7 @@ void DrmOutput::initEdid(drmModeConnector *connector) bool DrmOutput::initCursor(const QSize &cursorSize) { auto createCursor = [this, cursorSize] (int index) { - m_cursor[index].reset(new DrmDumbBuffer(m_gpu->fd(), cursorSize)); + m_cursor[index].reset(new DrmDumbBuffer(m_gpu, cursorSize)); if (!m_cursor[index]->map(QImage::Format_ARGB32_Premultiplied)) { return false; } diff --git a/src/plugins/platforms/drm/egl_gbm_backend.cpp b/src/plugins/platforms/drm/egl_gbm_backend.cpp index c6093f0122..63f63b3944 100644 --- a/src/plugins/platforms/drm/egl_gbm_backend.cpp +++ b/src/plugins/platforms/drm/egl_gbm_backend.cpp @@ -580,7 +580,7 @@ void EglGbmBackend::aboutToStartPainting(int screenId, const QRegion &damagedReg bool EglGbmBackend::presentOnOutput(Output &output, const QRegion &damagedRegion) { if (output.directScanoutBuffer) { - output.buffer = QSharedPointer::create(m_gpu->fd(), output.directScanoutBuffer, output.bufferInterface); + output.buffer = QSharedPointer::create(m_gpu, output.directScanoutBuffer, output.bufferInterface); } else if (isPrimary()) { if (supportsSwapBuffersWithDamage()) { QVector rects = regionToRects(output.damageHistory.constFirst(), output.output); @@ -595,7 +595,7 @@ bool EglGbmBackend::presentOnOutput(Output &output, const QRegion &damagedRegion return false; } } - output.buffer = QSharedPointer::create(m_gpu->fd(), output.gbmSurface); + output.buffer = QSharedPointer::create(m_gpu, output.gbmSurface); } else { qCDebug(KWIN_DRM) << "imported gbm_bo does not exist!"; return false; diff --git a/src/plugins/platforms/drm/egl_stream_backend.cpp b/src/plugins/platforms/drm/egl_stream_backend.cpp index adef29f55f..8d664b0b59 100644 --- a/src/plugins/platforms/drm/egl_stream_backend.cpp +++ b/src/plugins/platforms/drm/egl_stream_backend.cpp @@ -281,7 +281,7 @@ bool EglStreamBackend::resetOutput(Output &o, DrmOutput *drmOutput) { o.output = drmOutput; // dumb buffer used for modesetting - o.buffer = QSharedPointer::create(m_gpu->fd(), drmOutput->pixelSize()); + o.buffer = QSharedPointer::create(m_gpu, drmOutput->pixelSize()); EGLAttrib streamAttribs[] = { EGL_STREAM_FIFO_LENGTH_KHR, 0, // mailbox mode diff --git a/src/plugins/platforms/drm/scene_qpainter_drm_backend.cpp b/src/plugins/platforms/drm/scene_qpainter_drm_backend.cpp index 4507963e45..a4f702fbc3 100644 --- a/src/plugins/platforms/drm/scene_qpainter_drm_backend.cpp +++ b/src/plugins/platforms/drm/scene_qpainter_drm_backend.cpp @@ -45,7 +45,7 @@ void DrmQPainterBackend::initOutput(DrmOutput *output) { Output o; auto initBuffer = [&o, output, this] (int index) { - o.buffer[index] = QSharedPointer::create(m_gpu->fd(), output->pixelSize()); + o.buffer[index] = QSharedPointer::create(m_gpu, output->pixelSize()); if (o.buffer[index]->map()) { o.buffer[index]->image()->fill(Qt::black); } @@ -61,7 +61,7 @@ void DrmQPainterBackend::initOutput(DrmOutput *output) return; } auto initBuffer = [it, output, this] (int index) { - it->buffer[index] = QSharedPointer::create(m_gpu->fd(), output->pixelSize()); + it->buffer[index] = QSharedPointer::create(m_gpu, output->pixelSize()); if (it->buffer[index]->map()) { it->buffer[index]->image()->fill(Qt::black); }