Files
RedBear-OS/local/recipes/kde/kwin/src/backends/drm/drm_buffer.cpp
T

126 lines
3.1 KiB
C++

/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "drm_buffer.h"
#include "core/graphicsbuffer.h"
#include "drm_gpu.h"
// system
#include <sys/mman.h>
#if defined(Q_OS_LINUX)
#include <linux/dma-buf.h>
#include <linux/sync_file.h>
#endif
// 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
namespace KWin
{
static bool s_envIsSet = false;
static bool s_disableBufferWait = qEnvironmentVariableIntValue("KWIN_DRM_DISABLE_BUFFER_READABILITY_CHECKS", &s_envIsSet) && s_envIsSet;
DrmFramebuffer::DrmFramebuffer(DrmGpu *gpu, uint32_t fbId, GraphicsBuffer *buffer, FileDescriptor &&readFence)
: m_framebufferId(fbId)
, m_gpu(gpu)
, m_bufferRef(buffer)
{
if (s_disableBufferWait || ((m_gpu->isVmwgfx()) && !s_envIsSet)) {
// buffer readability checks cause frames to be wrongly delayed on Virtual Machines running vmwgfx
m_readable = true;
}
m_syncFd = std::move(readFence);
#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
if (!m_syncFd.isValid()) {
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
}
DrmFramebuffer::~DrmFramebuffer()
{
uint32_t nonConstFb = m_framebufferId;
#ifdef DRM_IOCTL_MODE_CLOSEFB
struct drm_mode_closefb closeArgs{
.fb_id = m_framebufferId,
.pad = 0,
};
if (drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_CLOSEFB, &closeArgs) != 0) {
drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_RMFB, &nonConstFb);
}
#else
drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_RMFB, &nonConstFb);
#endif
}
uint32_t DrmFramebuffer::framebufferId() const
{
return m_framebufferId;
}
GraphicsBuffer *DrmFramebuffer::buffer() const
{
return *m_bufferRef;
}
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;
m_readable = std::ranges::all_of(fds, [](const auto &fd) {
return !fd.isValid() || fd.isReadable();
});
return m_readable;
}
}
void DrmFramebuffer::setDeadline(std::chrono::steady_clock::time_point deadline)
{
#ifdef SYNC_IOC_SET_DEADLINE
if (!m_syncFd.isValid()) {
return;
}
sync_set_deadline args{
.deadline_ns = uint64_t(deadline.time_since_epoch().count()),
.pad = 0,
};
drmIoctl(m_syncFd.get(), SYNC_IOC_SET_DEADLINE, &args);
#endif
}
}