From 120d14150128ffa6baf0bce1b275df3e4dd9153d Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Tue, 5 Dec 2023 19:23:50 +0100 Subject: [PATCH] backends/drm: use sync files for checking buffer readiness and use IN_FENCE_FD This shouldn't change anything in practice, but with some badly behaving drivers it can prevent oversynchronization. --- src/backends/drm/drm_buffer.cpp | 21 +++++++++++++++++++++ src/backends/drm/drm_buffer.h | 4 ++++ src/backends/drm/drm_commit.cpp | 3 +++ src/backends/drm/drm_plane.cpp | 2 ++ src/backends/drm/drm_plane.h | 1 + 5 files changed, 31 insertions(+) diff --git a/src/backends/drm/drm_buffer.cpp b/src/backends/drm/drm_buffer.cpp index d0a4d1b86c..4bdc2553e1 100644 --- a/src/backends/drm/drm_buffer.cpp +++ b/src/backends/drm/drm_buffer.cpp @@ -19,9 +19,13 @@ #include // drm #include +#include #include #include #include +#ifdef Q_OS_LINUX +#include +#endif #ifndef DRM_IOCTL_MODE_CLOSEFB #define DRM_IOCTL_MODE_CLOSEFB 0xD0 @@ -42,6 +46,16 @@ DrmFramebuffer::DrmFramebuffer(DrmGpu *gpu, uint32_t fbId, GraphicsBuffer *buffe // buffer readability checks cause frames to be wrongly delayed on some Intel laptops // See https://gitlab.freedesktop.org/drm/intel/-/issues/9415 m_readable = true; + } else { +#ifdef Q_OS_LINUX + dma_buf_export_sync_file req{ + .flags = DMA_BUF_SYNC_READ, + .fd = -1, + }; + if (drmIoctl(buffer->dmabufAttributes()->fd[0].get(), DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &req) == 0) { + m_syncFd = FileDescriptor{req.fd}; + } +#endif } } @@ -68,10 +82,17 @@ void DrmFramebuffer::releaseBuffer() m_bufferRef = nullptr; } +const FileDescriptor &DrmFramebuffer::syncFd() const +{ + return m_syncFd; +} + bool DrmFramebuffer::isReadable() { if (m_readable) { return true; + } else if (m_syncFd.isValid()) { + return m_readable = m_syncFd.isReadable(); } else { const auto &fds = m_bufferRef->dmabufAttributes()->fd; return m_readable = std::all_of(fds.begin(), fds.end(), [](const auto &fd) { diff --git a/src/backends/drm/drm_buffer.h b/src/backends/drm/drm_buffer.h index 4d5145c60d..3dd747e959 100644 --- a/src/backends/drm/drm_buffer.h +++ b/src/backends/drm/drm_buffer.h @@ -10,6 +10,7 @@ #pragma once #include "core/graphicsbuffer.h" +#include "utils/filedescriptor.h" namespace KWin { @@ -32,11 +33,14 @@ public: void releaseBuffer(); bool isReadable(); + const FileDescriptor &syncFd() const; + protected: const uint32_t m_framebufferId; DrmGpu *const m_gpu; GraphicsBufferRef m_bufferRef; bool m_readable = false; + FileDescriptor m_syncFd; }; } diff --git a/src/backends/drm/drm_commit.cpp b/src/backends/drm/drm_commit.cpp index 234a1de1da..6c474232f9 100644 --- a/src/backends/drm/drm_commit.cpp +++ b/src/backends/drm/drm_commit.cpp @@ -57,6 +57,9 @@ void DrmAtomicCommit::addBuffer(DrmPlane *plane, const std::shared_ptrfbId, buffer ? buffer->framebufferId() : 0); m_buffers[plane] = buffer; + if (plane->inFenceFd.isValid()) { + addProperty(plane->inFenceFd, buffer ? buffer->syncFd().get() : -1); + } m_planes.emplace(plane); } diff --git a/src/backends/drm/drm_plane.cpp b/src/backends/drm/drm_plane.cpp index f1b0561bc3..0532f629c9 100644 --- a/src/backends/drm/drm_plane.cpp +++ b/src/backends/drm/drm_plane.cpp @@ -65,6 +65,7 @@ DrmPlane::DrmPlane(DrmGpu *gpu, uint32_t planeId) }) , vmHotspotX(this, QByteArrayLiteral("HOTSPOT_X")) , vmHotspotY(this, QByteArrayLiteral("HOTSPOT_Y")) + , inFenceFd(this, QByteArrayLiteral("IN_FENCE_FD")) { } @@ -95,6 +96,7 @@ bool DrmPlane::updateProperties() colorRange.update(props); vmHotspotX.update(props); vmHotspotY.update(props); + inFenceFd.update(props); if (!type.isValid() || !srcX.isValid() || !srcY.isValid() || !srcW.isValid() || !srcH.isValid() || !crtcX.isValid() || !crtcY.isValid() || !crtcW.isValid() || !crtcH.isValid() || !fbId.isValid()) { diff --git a/src/backends/drm/drm_plane.h b/src/backends/drm/drm_plane.h index 8aeff067f2..441aa93018 100644 --- a/src/backends/drm/drm_plane.h +++ b/src/backends/drm/drm_plane.h @@ -90,6 +90,7 @@ public: DrmEnumProperty colorRange; DrmProperty vmHotspotX; DrmProperty vmHotspotY; + DrmProperty inFenceFd; static int32_t transformationToDegrees(Transformations transformation);