[plasma/kwin] src: core/gpumanager: add a RenderDevice backed by udmabuf
Xaver Hugl <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 85337818cffc4f1af75a569de7740cbcf717944c by Xaver Hugl.
Committed on 16/07/2026 at 19:21.
Pushed by zamundaaa into branch 'master'.
core/gpumanager: add a RenderDevice backed by udmabuf
This RenderDevice doesn't (need to) have a drm device, so it can be used even
without any drm nodes.
Right now this is mostly useful for the virtual backend, where a lack of drm
nodes is often expected, but later on it will be useful elsewhere, too.
For example, the drm backend will need to handle all GPUs being hotunplugged
(temporarily) when simpledrm gets "hotunplugged" for the real driver on system
startup, or for VFIO use cases.
M +2 -0 src/CMakeLists.txt
M +1 -1 src/compositor.cpp
M +3 -137 src/core/gbmgraphicsbufferallocator.cpp
M +15 -0 src/core/gpumanager.cpp
M +5 -0 src/core/gpumanager.h
M +39 -1 src/core/renderdevice.cpp
M +8 -0 src/core/renderdevice.h
A +173 -0 src/core/udmabufallocator.cpp [License: GPL(v2.0+)]
A +23 -0 src/core/udmabufallocator.h [License: GPL(v2.0+)]
M +1 -1 src/opengl/egldisplay.cpp
https://invent.kde.org/plasma/kwin/-/commit/85337818cffc4f1af75a569de7740cbcf717944c
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2cbe5923939..fd112413e57 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -76,6 +76,7 @@ target_sources(kwin PRIVATE
core/session_noop.cpp
core/shmgraphicsbufferallocator.cpp
core/syncobjtimeline.cpp
+ core/udmabufallocator.cpp
cursor.cpp
cursorsource.cpp
dbusinterface.cpp
@@ -584,6 +585,7 @@ install(FILES
core/session_logind.h
core/session_noop.h
core/shmgraphicsbufferallocator.h
+ core/udmabufallocator.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kwin/core COMPONENT Devel)
install(FILES
diff --git a/src/compositor.cpp b/src/compositor.cpp
index 861eb44276f..ba756030cc4 100644
--- a/src/compositor.cpp
+++ b/src/compositor.cpp
@@ -198,7 +198,7 @@ static RenderDevice *selectRenderDevice()
}
}
if (!s_drmDevicesEnv.isEmpty()) {
- return nullptr;
+ return GpuManager::self()->softwareDevice();
}
const auto &devices = GpuManager::self()->renderDevices();
diff --git a/src/core/gbmgraphicsbufferallocator.cpp b/src/core/gbmgraphicsbufferallocator.cpp
index d65f1f06b2f..27d76bf8e6c 100644
--- a/src/core/gbmgraphicsbufferallocator.cpp
+++ b/src/core/gbmgraphicsbufferallocator.cpp
@@ -11,6 +11,7 @@
#include "core/drmdevice.h"
#include "core/gpumanager.h"
#include "core/graphicsbuffer.h"
+#include "core/udmabufallocator.h"
#include "utils/common.h"
#include "utils/memorymap.h"
@@ -21,11 +22,6 @@
#include <unistd.h>
#include <xf86drm.h>
-#if defined(Q_OS_LINUX)
-#include <linux/dma-buf.h>
-#include <sys/ioctl.h>
-#endif
-
namespace KWin
{
@@ -216,90 +212,11 @@ static GraphicsBuffer *allocateDmaBuf(gbm_device *device, dev_t deviceId, const
return nullptr;
}
-#if defined(Q_OS_LINUX)
-class UdmabufGraphicsBuffer : public GraphicsBuffer
-{
- Q_OBJECT
-
-public:
- explicit UdmabufGraphicsBuffer(DmaBufAttributes &&attributes, MemoryMap &&map);
-
- Map map(MapFlags flags) override;
- void unmap() override;
-
- QSize size() const override;
- bool hasAlphaChannel() const override;
- const DmaBufAttributes *dmabufAttributes() const override;
-
-private:
- const DmaBufAttributes m_attributes;
- const bool m_hasAlphaChannel;
- MemoryMap m_map;
- uint32_t m_mapCount = 0;
-};
-
-static uint64_t align(uint64_t size, uint64_t minimum)
-{
- if (auto remainder = size % minimum) {
- return size + (minimum - remainder);
- } else {
- return size;
- }
-}
-#endif
-
-static GraphicsBuffer *allocateUdmabuf(uint32_t drmFormat, const QSize &size)
-{
-#if HAVE_MEMFD && defined(Q_OS_LINUX)
- if (!GpuManager::self()->udmabuf().isValid()) {
- return nullptr;
- }
- auto info = FormatInfo::get(drmFormat);
- if (!info) {
- return nullptr;
- }
- const int stride = align(size.width() * info->bitsPerPixel / 8, 256);
- const int bufferSize = align(size.height() * stride, getpagesize());
-
- FileDescriptor fd = FileDescriptor(memfd_create("udmabuf", MFD_CLOEXEC | MFD_ALLOW_SEALING));
- if (!fd.isValid()) {
- return nullptr;
- }
-
- if (ftruncate(fd.get(), bufferSize) < 0) {
- return nullptr;
- }
- if (fcntl(fd.get(), F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL) != 0) {
- return nullptr;
- }
-
- MemoryMap memoryMap(stride * size.height(), PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0);
- if (!memoryMap.isValid()) {
- return nullptr;
- }
-
- ShmAttributes attributes{
- .fd = std::move(fd),
- .stride = stride,
- .offset = 0,
- .size = size,
- .format = drmFormat,
- };
- auto dmabufAttributes = GpuManager::self()->createUdmabuf(&attributes);
- if (!dmabufAttributes) {
- return nullptr;
- }
- return new UdmabufGraphicsBuffer(std::move(*dmabufAttributes), std::move(memoryMap));
-#else
- return nullptr;
-#endif
-}
-
GraphicsBuffer *GbmGraphicsBufferAllocator::allocate(const GraphicsBufferOptions &options)
{
if (options.software) {
if (!options.scanout) {
- auto ret = allocateUdmabuf(options.format, options.size);
+ auto ret = UDmabufAllocator::allocate(options.format, options.size);
if (ret) {
return ret;
}
@@ -310,7 +227,7 @@ GraphicsBuffer *GbmGraphicsBufferAllocator::allocate(const GraphicsBufferOptions
if (!options.scanout && m_device->busType() == DRM_BUS_FAUX && options.modifiers.contains(DRM_FORMAT_MOD_LINEAR)) {
// With vgem, gbm attempts to allocate dumb buffers, which can't
// actually work on the render node, so use udmabuf instead
- return allocateUdmabuf(options.format, options.size);
+ return UDmabufAllocator::allocate(options.format, options.size);
}
return allocateDmaBuf(m_device->gbmDevice(), m_device->deviceId(), options);
}
@@ -438,57 +355,6 @@ void DumbGraphicsBuffer::unmap()
}
}
-#if defined(Q_OS_LINUX)
-UdmabufGraphicsBuffer::UdmabufGraphicsBuffer(DmaBufAttributes &&attributes, MemoryMap &&map)
- : m_attributes(std::move(attributes))
- , m_hasAlphaChannel(alphaChannelFromDrmFormat(m_attributes.format))
- , m_map(std::move(map))
-{
-}
-
-GraphicsBuffer::Map UdmabufGraphicsBuffer::map(MapFlags flags)
-{
- m_mapCount++;
- if (m_mapCount == 1) {
- struct dma_buf_sync sync = {
- .flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_READ,
- };
- ioctl(m_attributes.fd[0].get(), DMA_BUF_IOCTL_SYNC, &sync);
- }
- return Map{
- .data = m_map.data(),
- .stride = m_attributes.pitch[0],
- };
-}
-
-void UdmabufGraphicsBuffer::unmap()
-{
- Q_ASSERT(m_mapCount > 0);
- m_mapCount--;
- if (m_mapCount == 0) {
- struct dma_buf_sync sync = {
- .flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_READ,
- };
- ioctl(m_attributes.fd[0].get(), DMA_BUF_IOCTL_SYNC, &sync);
- }
-}
-
-QSize UdmabufGraphicsBuffer::size() const
-{
- return QSize(m_attributes.width, m_attributes.height);
-}
-
-bool UdmabufGraphicsBuffer::hasAlphaChannel() const
-{
- return m_hasAlphaChannel;
-}
-
-const DmaBufAttributes *UdmabufGraphicsBuffer::dmabufAttributes() const
-{
- return &m_attributes;
-}
-#endif
-
} // namespace KWin
#include "gbmgraphicsbufferallocator.moc"
diff --git a/src/core/gpumanager.cpp b/src/core/gpumanager.cpp
index 4c44e9143d6..0b194026c9d 100644
--- a/src/core/gpumanager.cpp
+++ b/src/core/gpumanager.cpp
@@ -79,6 +79,12 @@ GpuManager::GpuManager()
, m_udevNotifier(std::make_unique<QSocketNotifier>(m_udevMonitor->fd(), QSocketNotifier::Read))
, m_explicitRenderNodes(qEnvironmentVariableIsSet("KWIN_RENDER_NODES") ? splitPathList(qEnvironmentVariable("KWIN_RENDER_NODES")) : std::optional<QStringList>())
{
+ if (m_udmabuf.isValid()) {
+ if (auto device = RenderDevice::createSoftwareDevice(*m_udmabufDevId)) {
+ m_softwareDevice = device.get();
+ addDevice(std::move(device));
+ }
+ }
m_udevMonitor->filterSubsystemDevType("drm");
connect(m_udevNotifier.get(), &QSocketNotifier::activated, this, &GpuManager::handleUdevEvent);
m_udevMonitor->enable();
@@ -112,10 +118,19 @@ RenderDevice *GpuManager::findDevice(dev_t id) const
return it == m_renderDevices.end() ? nullptr : it->get();
}
+RenderDevice *GpuManager::softwareDevice() const
+{
+ return m_softwareDevice;
+}
+
void GpuManager::updateCompatibilityMap()
{
m_compatibleDeviceMap.clear();
+ if (m_udmabufDevId) {
+ m_compatibleDeviceMap[*m_udmabufDevId] = m_softwareDevice;
+ }
+
int numberOfDevices = drmGetDevices2(0, nullptr, 0);
if (numberOfDevices <= 0) {
return;
diff --git a/src/core/gpumanager.h b/src/core/gpumanager.h
index 05f0b08d24e..2146fd26a7e 100644
--- a/src/core/gpumanager.h
+++ b/src/core/gpumanager.h
@@ -39,6 +39,10 @@ public:
RenderDevice *compatibleRenderDevice(DrmDevice *dev) const;
RenderDevice *compatibleRenderDevice(dev_t id) const;
RenderDevice *findDevice(dev_t id) const;
+ /**
+ * @returns a software renderdevice backed by udmabuf (and no drm device)
+ */
+ RenderDevice *softwareDevice() const;
/**
* NOTE that the list is automatically updated through
@@ -74,6 +78,7 @@ private:
const std::unique_ptr<UdevMonitor> m_udevMonitor;
const std::unique_ptr<QSocketNotifier> m_udevNotifier;
const std::optional<QStringList> m_explicitRenderNodes;
+ RenderDevice *m_softwareDevice = nullptr;
std::vector<std::unique_ptr<RenderDevice>> m_renderDevices;
QHash<dev_t, RenderDevice *> m_compatibleDeviceMap;
};
diff --git a/src/core/renderdevice.cpp b/src/core/renderdevice.cpp
index 2d87fe63966..0d4d54b6b9a 100644
--- a/src/core/renderdevice.cpp
+++ b/src/core/renderdevice.cpp
@@ -9,9 +9,11 @@
#include "renderdevice.h"
#include "drmdevice.h"
+#include "gpumanager.h"
#include "graphicsbuffer.h"
#include "opengl/eglcontext.h"
#include "opengl/egldisplay.h"
+#include "udmabufallocator.h"
#include "utils/common.h"
#include "utils/envvar.h"
#include "vulkan/vulkan_device.h"
@@ -89,6 +91,17 @@ RenderDevice::RenderDevice(std::unique_ptr<DrmDevice> &&device, std::unique_ptr<
m_allImportableFormats = getImportFormats(m_display.get(), m_vulkanDevice.get());
}
+RenderDevice::RenderDevice(std::unique_ptr<UDmabufAllocator> &&allocator, std::unique_ptr<EglDisplay> &&display, dev_t deviceId)
+ : m_udmabufAllocator(std::move(allocator))
+ , m_display(std::move(display))
+ , m_vulkanInstance(createVulkanInstance(m_vulkanContext))
+ , m_path(QStringLiteral("/dev/udmabuf"))
+ , m_deviceId(deviceId)
+{
+ createVulkanDevice();
+ m_allImportableFormats = getImportFormats(m_display.get(), m_vulkanDevice.get());
+}
+
RenderDevice::~RenderDevice()
{
}
@@ -110,7 +123,7 @@ dev_t RenderDevice::deviceId() const
GraphicsBufferAllocator *RenderDevice::allocator() const
{
- return m_device->allocator();
+ return m_udmabufAllocator ? m_udmabufAllocator.get() : m_device->allocator();
}
EglDisplay *RenderDevice::eglDisplay() const
@@ -310,6 +323,31 @@ std::unique_ptr<RenderDevice> RenderDevice::open(const QString &path, int authen
return std::make_unique<RenderDevice>(std::move(drmDevice), std::move(eglDisplay));
}
+std::unique_ptr<RenderDevice> RenderDevice::createSoftwareDevice(dev_t deviceId)
+{
+ EGLint numDevices = 0;
+ if (eglQueryDevicesEXT(0, nullptr, &numDevices) != EGL_TRUE) {
+ return nullptr;
+ }
+ QList<EGLDeviceEXT> devices;
+ devices.resize(numDevices);
+ if (eglQueryDevicesEXT(numDevices, devices.data(), &numDevices) != EGL_TRUE) {
+ return nullptr;
+ }
+ devices.resize(numDevices);
+ const auto it = std::ranges::find_if(devices, [](EGLDeviceEXT device) {
+ return QByteArrayView(eglQueryDeviceStringEXT(device, EGL_EXTENSIONS)).contains("EGL_MESA_device_software");
+ });
+ if (it == devices.end()) {
+ return nullptr;
+ }
+ auto eglDisplay = EglDisplay::create(eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, *it, nullptr), nullptr);
+ if (!eglDisplay) {
+ return nullptr;
+ }
+ return std::make_unique<RenderDevice>(std::make_unique<UDmabufAllocator>(), std::move(eglDisplay), deviceId);
+}
+
bool RenderDevice::isSoftwareDevice() const
{
return m_display->isSoftwareRenderer() && (!m_vulkanDevice || m_vulkanDevice->isSoftwareRenderer());
diff --git a/src/core/renderdevice.h b/src/core/renderdevice.h
index 78901f02a46..81b44aab978 100644
--- a/src/core/renderdevice.h
+++ b/src/core/renderdevice.h
@@ -25,6 +25,7 @@ class EglContext;
class GraphicsBuffer;
class VulkanDevice;
class GraphicsBufferAllocator;
+class UDmabufAllocator;
class KWIN_EXPORT RenderDevice : public QObject
{
@@ -32,6 +33,7 @@ class KWIN_EXPORT RenderDevice : public QObject
public:
explicit RenderDevice(std::unique_ptr<DrmDevice> &&device, std::unique_ptr<EglDisplay> &&display);
+ explicit RenderDevice(std::unique_ptr<UDmabufAllocator> &&allocator, std::unique_ptr<EglDisplay> &&display, dev_t deviceId);
~RenderDevice();
/**
@@ -73,12 +75,18 @@ public:
bool isSoftwareDevice() const;
static std::unique_ptr<RenderDevice> open(const QString &path, int authenticatedFd = -1);
+ /**
+ * @returns a RenderDevice without a drm device, using udmabuf for allocations
+ * and a software renderer for OpenGL and Vulkan
+ */
+ static std::unique_ptr<RenderDevice> createSoftwareDevice(dev_t deviceId);
private:
void handleVulkanDeviceLoss();
void createVulkanDevice();
const std::unique_ptr<DrmDevice> m_device;
+ const std::unique_ptr<UDmabufAllocator> m_udmabufAllocator;
const std::unique_ptr<EglDisplay> m_display;
const vk::raii::Context m_vulkanContext;
const vk::raii::Instance m_vulkanInstance;
diff --git a/src/core/udmabufallocator.cpp b/src/core/udmabufallocator.cpp
new file mode 100644
index 00000000000..21ed9f3c79c
--- /dev/null
+++ b/src/core/udmabufallocator.cpp
@@ -0,0 +1,173 @@
+/*
+ SPDX-FileCopyrightText: 2026 Xaver Hugl <[email protected]>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+#include "udmabufallocator.h"
+#include "core/gpumanager.h"
+#include "core/graphicsbuffer.h"
+#include "utils/common.h"
+#include "utils/memorymap.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#if defined(Q_OS_LINUX)
+#include <linux/dma-buf.h>
+#include <sys/ioctl.h>
+#endif
+
+namespace KWin
+{
+
+class UdmabufGraphicsBuffer : public GraphicsBuffer
+{
+ Q_OBJECT
+
+public:
+ explicit UdmabufGraphicsBuffer(DmaBufAttributes &&attributes, MemoryMap &&map);
+
+ Map map(MapFlags flags) override;
+ void unmap() override;
+
+ QSize size() const override;
+ bool hasAlphaChannel() const override;
+ const DmaBufAttributes *dmabufAttributes() const override;
+
+private:
+ const DmaBufAttributes m_attributes;
+ const bool m_hasAlphaChannel;
+ MemoryMap m_memoryMap;
+ uint32_t m_mapCount = 0;
+};
+
+static uint64_t align(uint64_t size, uint64_t minimum)
+{
+ if (auto remainder = size % minimum) {
+ return size + (minimum - remainder);
+ } else {
+ return size;
+ }
+}
+
+UdmabufGraphicsBuffer::UdmabufGraphicsBuffer(DmaBufAttributes &&attributes, MemoryMap &&memoryMap)
+ : m_attributes(std::move(attributes))
+ , m_hasAlphaChannel(alphaChannelFromDrmFormat(attributes.format))
+ , m_memoryMap(std::move(memoryMap))
+{
+}
+
+GraphicsBuffer::Map UdmabufGraphicsBuffer::map(MapFlags flags)
+{
+#if defined(Q_OS_LINUX)
+ if (m_mapCount == 1) {
+ struct dma_buf_sync sync = {
+ .flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_READ,
+ };
+ ioctl(m_attributes.fd[0].get(), DMA_BUF_IOCTL_SYNC, &sync);
+ }
+#endif
+ return Map{
+ .data = m_memoryMap.data(),
+ .stride = uint32_t(m_attributes.pitch[0]),
+ };
+}
+
+void UdmabufGraphicsBuffer::unmap()
+{
+ Q_ASSERT(m_mapCount > 0);
+ m_mapCount--;
+ if (m_mapCount == 0) {
+#if defined(Q_OS_LINUX)
+ struct dma_buf_sync sync = {
+ .flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_READ,
+ };
+ ioctl(m_attributes.fd[0].get(), DMA_BUF_IOCTL_SYNC, &sync);
+#endif
+ }
+}
+
+QSize UdmabufGraphicsBuffer::size() const
+{
+ return QSize(m_attributes.width, m_attributes.height);
+}
+
+bool UdmabufGraphicsBuffer::hasAlphaChannel() const
+{
+ return m_hasAlphaChannel;
+}
+
+const DmaBufAttributes *UdmabufGraphicsBuffer::dmabufAttributes() const
+{
+ return &m_attributes;
+}
+
+UDmabufAllocator::UDmabufAllocator()
+{
+}
+
+GraphicsBuffer *UDmabufAllocator::allocate(const GraphicsBufferOptions &options)
+{
+ if (!options.modifiers.contains(DRM_FORMAT_MOD_LINEAR)) {
+ return nullptr;
+ }
+ return allocate(options.format, options.size);
+}
+
+GraphicsBuffer *UDmabufAllocator::allocate(uint32_t format, const QSize &size)
+{
+#if HAVE_MEMFD && defined(Q_OS_LINUX)
+ if (!GpuManager::self()->udmabuf().isValid()) {
+ return nullptr;
+ }
+ auto info = FormatInfo::get(format);
+ if (!info) {
+ return nullptr;
+ }
+ const int stride = align(size.width() * info->bitsPerPixel / 8, 256);
+ const int bufferSize = align(size.height() * stride, getpagesize());
+
+ FileDescriptor fd = FileDescriptor(memfd_create("udmabuf", MFD_CLOEXEC | MFD_ALLOW_SEALING));
+ if (!fd.isValid()) {
+ qCWarning(KWIN_CORE, "Creating memfd for udmabuf failed!");
+ return nullptr;
+ }
+
+ if (ftruncate(fd.get(), bufferSize) < 0) {
+ qCWarning(KWIN_CORE, "Resizing memfd for udmabuf failed!");
+ return nullptr;
+ }
+ if (fcntl(fd.get(), F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL) != 0) {
+ qCWarning(KWIN_CORE, "Sealing memfd for udmabuf failed!");
+ return nullptr;
+ }
+
+ MemoryMap memoryMap(stride * size.height(), PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0);
+ if (!memoryMap.isValid()) {
+ qCWarning(KWIN_CORE, "Mapping memfd for udmabuf failed!");
+ return nullptr;
+ }
+
+ ShmAttributes attributes{
+ .fd = std::move(fd),
+ .stride = stride,
+ .offset = 0,
+ .size = size,
+ .format = format,
+ };
+ auto dmabufAttributes = GpuManager::self()->createUdmabuf(&attributes);
+ if (!dmabufAttributes) {
+ return nullptr;
+ }
+ return new UdmabufGraphicsBuffer(std::move(*dmabufAttributes), std::move(memoryMap));
+#else
+ return nullptr;
+#endif
+}
+
+}
+#include "udmabufallocator.moc"
diff --git a/src/core/udmabufallocator.h b/src/core/udmabufallocator.h
new file mode 100644
index 00000000000..147fdd752b5
--- /dev/null
+++ b/src/core/udmabufallocator.h
@@ -0,0 +1,23 @@
+/*
+ SPDX-FileCopyrightText: 2026 Xaver Hugl <[email protected]>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+#pragma once
+#include "core/graphicsbufferallocator.h"
+#include "utils/filedescriptor.h"
+
+namespace KWin
+{
+
+class KWIN_EXPORT UDmabufAllocator : public GraphicsBufferAllocator
+{
+public:
+ explicit UDmabufAllocator();
+
+ GraphicsBuffer *allocate(const GraphicsBufferOptions &options) override;
+
+ static GraphicsBuffer *allocate(uint32_t format, const QSize &size);
+};
+
+}
diff --git a/src/opengl/egldisplay.cpp b/src/opengl/egldisplay.cpp
index 664ec786665..d543d5f64d6 100644
--- a/src/opengl/egldisplay.cpp
+++ b/src/opengl/egldisplay.cpp
@@ -385,7 +385,7 @@ EGLImageKHR EglDisplay::importBufferAsImage(GraphicsBuffer *buffer)
image = importDmaBufAsImage(*buffer->dmabufAttributes());
// On Nvidia, sampling from udmabuf just results in black,
// and on i915 there are glitches on some systems
- } else if (buffer->udmabufAttributes() && m_drmDevice && !s_disableUdmabuf.value_or(m_drmDevice->isNvidia() || m_drmDevice->isI915())) {
+ } else if (buffer->udmabufAttributes() && (!m_drmDevice || !s_disableUdmabuf.value_or(m_drmDevice->isNvidia() || m_drmDevice->isI915()))) {
image = importDmaBufAsImage(*buffer->udmabufAttributes());
}
m_importCache[key] = image;