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.
wilder/Plasma/6.2
Xaver Hugl 2 years ago
parent b8caf31861
commit 120d141501
  1. 21
      src/backends/drm/drm_buffer.cpp
  2. 4
      src/backends/drm/drm_buffer.h
  3. 3
      src/backends/drm/drm_commit.cpp
  4. 2
      src/backends/drm/drm_plane.cpp
  5. 1
      src/backends/drm/drm_plane.h

@ -19,9 +19,13 @@
#include <cerrno>
// drm
#include <drm_fourcc.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#ifdef Q_OS_LINUX
#include <linux/dma-buf.h>
#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) {

@ -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;
};
}

@ -57,6 +57,9 @@ void DrmAtomicCommit::addBuffer(DrmPlane *plane, const std::shared_ptr<DrmFrameb
{
addProperty(plane->fbId, buffer ? buffer->framebufferId() : 0);
m_buffers[plane] = buffer;
if (plane->inFenceFd.isValid()) {
addProperty(plane->inFenceFd, buffer ? buffer->syncFd().get() : -1);
}
m_planes.emplace(plane);
}

@ -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()) {

@ -90,6 +90,7 @@ public:
DrmEnumProperty<ColorRange> colorRange;
DrmProperty vmHotspotX;
DrmProperty vmHotspotY;
DrmProperty inFenceFd;
static int32_t transformationToDegrees(Transformations transformation);

Loading…
Cancel
Save