[plasma/kwin] /: wayland-client: use GpuManager for linux-dmabuf

Xaver Hugl <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit f5aa52f436adbbd0680097ece8fcc6158a7749d6 by Xaver Hugl.
Committed on 16/07/2026 at 18:38.
Pushed by zamundaaa into branch 'master'.

wayland-client: use GpuManager for linux-dmabuf

This simplifies the code and makes it possible to use the devices from each
tranche instead of only the main device.

M  +8    -3    autotests/integration/drm_test.cpp
M  +1    -4    src/backends/wayland/wayland_backend.cpp
M  +11   -40   src/wayland-client/linuxdmabuf.cpp
M  +3    -4    src/wayland-client/linuxdmabuf.h

https://invent.kde.org/plasma/kwin/-/commit/f5aa52f436adbbd0680097ece8fcc6158a7749d6

diff --git a/autotests/integration/drm_test.cpp b/autotests/integration/drm_test.cpp
index 3cd1b1ee19e..eef543a9be2 100644
--- a/autotests/integration/drm_test.cpp
+++ b/autotests/integration/drm_test.cpp
@@ -12,6 +12,7 @@
 #include "backends/drm/drm_pointer.h"
 #include "compositor.h"
 #include "core/drmdevice.h"
+#include "core/gpumanager.h"
 #include "core/graphicsbuffer.h"
 #include "core/outputbackend.h"
 #include "core/outputconfiguration.h"
@@ -227,7 +228,7 @@ public:
     explicit DmabufWindow(std::function<void(Test::XdgToplevel *toplevel)> setup = [](Test::XdgToplevel *toplevel) { })
         : m_surface(Test::createSurface())
         , m_shellSurface(Test::createXdgToplevelSurface(m_surface.get(), setup))
-        , m_device(DrmDevice::open(Test::linuxDmabuf()->mainDevice()))
+        , m_device(GpuManager::self()->compatibleRenderDevice(Test::linuxDmabuf()->mainDevice()))
         , m_surfaceFeedback(Test::linuxDmabuf()->getSurfaceFeedback(*m_surface))
     {
         connect(m_surfaceFeedback.get(), &WaylandClient::LinuxDmabufFeedbackV1::changed, this, &DmabufWindow::reactToDmabufFeedback);
@@ -261,7 +262,11 @@ public:
                 if (!tranche.formats.contains(m_buffer->dmabufAttributes()->format)) {
                     continue;
                 }
-                m_buffer = m_device->allocator()->allocate(GraphicsBufferOptions{
+                auto device = GpuManager::self()->compatibleRenderDevice(tranche.device);
+                if (!device) {
+                    continue;
+                }
+                m_buffer = device->allocator()->allocate(GraphicsBufferOptions{
                     .size = m_buffer->size(),
                     .format = m_buffer->dmabufAttributes()->format,
                     .modifiers = tranche.formats[m_buffer->dmabufAttributes()->format],
@@ -291,7 +296,7 @@ public:
 
     std::unique_ptr<KWayland::Client::Surface> m_surface;
     std::unique_ptr<Test::XdgToplevel> m_shellSurface;
-    std::unique_ptr<DrmDevice> m_device;
+    RenderDevice *m_device = nullptr;
     std::unique_ptr<WaylandClient::LinuxDmabufFeedbackV1> m_surfaceFeedback;
     GraphicsBufferRef m_buffer;
     bool m_needsRealloc = false;
diff --git a/src/backends/wayland/wayland_backend.cpp b/src/backends/wayland/wayland_backend.cpp
index f56e47ff30c..9f4bc4f599d 100644
--- a/src/backends/wayland/wayland_backend.cpp
+++ b/src/backends/wayland/wayland_backend.cpp
@@ -438,10 +438,7 @@ bool WaylandBackend::initialize()
     }
 
     if (WaylandClient::LinuxDmabufV1 *dmabuf = m_display->linuxDmabuf()) {
-        auto device = DrmDevice::open(dmabuf->mainDevice());
-        if (device) {
-            m_renderDevice = GpuManager::self()->compatibleRenderDevice(device.get());
-        }
+        m_renderDevice = GpuManager::self()->compatibleRenderDevice(dmabuf->mainDevice());
     }
 
     createOutputs();
diff --git a/src/wayland-client/linuxdmabuf.cpp b/src/wayland-client/linuxdmabuf.cpp
index 120f1972901..17d3d4e4b68 100644
--- a/src/wayland-client/linuxdmabuf.cpp
+++ b/src/wayland-client/linuxdmabuf.cpp
@@ -4,6 +4,7 @@
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 #include "linuxdmabuf.h"
+#include "core/gpumanager.h"
 #include "core/graphicsbuffer.h"
 #include "wayland-client/waylandclientlogging.h"
 
@@ -51,9 +52,9 @@ FormatModifierMap LinuxDmabufFeedbackV1::formats() const
     return m_formats;
 }
 
-QByteArray LinuxDmabufFeedbackV1::devicePath() const
+dev_t LinuxDmabufFeedbackV1::mainDevice() const
 {
-    return m_mainDevice;
+    return m_mainDeviceId;
 }
 
 QList<LinuxDmabufFeedbackV1::Tranche> LinuxDmabufFeedbackV1::tranches() const
@@ -80,31 +81,13 @@ void LinuxDmabufFeedbackV1::format_table(void *data, zwp_linux_dmabuf_feedback_v
 void LinuxDmabufFeedbackV1::main_device(void *data, zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, wl_array *deviceId)
 {
     LinuxDmabufFeedbackV1 *feedback = static_cast<LinuxDmabufFeedbackV1 *>(data);
-
     feedback->m_mainDeviceId = deserializeDeviceId(deviceId);
-
-    drmDevice *device = nullptr;
-    if (drmGetDeviceFromDevId(feedback->m_mainDeviceId, 0, &device) != 0) {
-        qCWarning(KWIN_WAYLAND_CLIENT) << "drmGetDeviceFromDevId() failed";
-        return;
-    }
-
-    if (device->available_nodes & (1 << DRM_NODE_RENDER)) {
-        feedback->m_mainDevice = QByteArray(device->nodes[DRM_NODE_RENDER]);
-    } else if (device->available_nodes & (1 << DRM_NODE_PRIMARY)) {
-        // We can't reliably find the render node from the primary node if the display and
-        // render devices are split, so just fallback to the primary node.
-        feedback->m_mainDevice = QByteArray(device->nodes[DRM_NODE_PRIMARY]);
-    }
-
-    drmFreeDevice(&device);
 }
 
 void LinuxDmabufFeedbackV1::tranche_done(void *data, zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1)
 {
     LinuxDmabufFeedbackV1 *feedback = static_cast<LinuxDmabufFeedbackV1 *>(data);
 
-    feedback->m_trancheDeviceId = 0;
     feedback->m_pendingTranches.push_back(feedback->m_pendingTranche);
     feedback->m_pendingTranche = {};
 }
@@ -113,7 +96,7 @@ void LinuxDmabufFeedbackV1::tranche_target_device(void *data, zwp_linux_dmabuf_f
 {
     LinuxDmabufFeedbackV1 *feedback = static_cast<LinuxDmabufFeedbackV1 *>(data);
 
-    feedback->m_trancheDeviceId = deserializeDeviceId(deviceId);
+    feedback->m_pendingTranche.device = deserializeDeviceId(deviceId);
 }
 
 void LinuxDmabufFeedbackV1::tranche_formats(void *data, zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, wl_array *indices)
@@ -124,22 +107,8 @@ void LinuxDmabufFeedbackV1::tranche_formats(void *data, zwp_linux_dmabuf_feedbac
         return;
     }
 
-    drmDevice *mainDevice = nullptr;
-    drmDevice *trancheDevice = nullptr;
-    const auto cleanup = qScopeGuard([&]() {
-        drmFreeDevice(&mainDevice);
-        drmFreeDevice(&trancheDevice);
-    });
-    if (drmGetDeviceFromDevId(feedback->m_mainDeviceId, 0, &mainDevice) != 0
-        || drmGetDeviceFromDevId(feedback->m_trancheDeviceId, 0, &trancheDevice) != 0) {
-        qCWarning(KWIN_WAYLAND_CLIENT, "drmGetDeviceFromDevId() failed");
-        return;
-    }
-    if (!drmDevicesEqual(mainDevice, trancheDevice)) {
-        // TODO take multi GPU handling into account as well
-        qCDebug(KWIN_WAYLAND_CLIENT, "Ignoring tranche from non-main device");
-        return;
-    }
+    auto main = GpuManager::self()->compatibleRenderDevice(feedback->m_mainDeviceId);
+    auto tranche = GpuManager::self()->compatibleRenderDevice(feedback->m_pendingTranche.device);
 
     struct linux_dmabuf_feedback_v1_table_entry
     {
@@ -151,7 +120,9 @@ void LinuxDmabufFeedbackV1::tranche_formats(void *data, zwp_linux_dmabuf_feedbac
     const auto entries = static_cast<linux_dmabuf_feedback_v1_table_entry *>(feedback->m_formatTable.data());
     for (const uint16_t &index : std::span(static_cast<uint16_t *>(indices->data), indices->size / sizeof(uint16_t))) {
         const linux_dmabuf_feedback_v1_table_entry &entry = entries[index];
-        feedback->m_formats[entry.format].insert(entry.modifier);
+        if (main == tranche) {
+            feedback->m_formats[entry.format].insert(entry.modifier);
+        }
         feedback->m_pendingTranche.formats[entry.format].insert(entry.modifier);
     }
 }
@@ -185,9 +156,9 @@ zwp_linux_dmabuf_v1 *LinuxDmabufV1::handle() const
     return m_dmabuf;
 }
 
-QByteArray LinuxDmabufV1::mainDevice() const
+dev_t LinuxDmabufV1::mainDevice() const
 {
-    return m_defaultFeedback->devicePath();
+    return m_defaultFeedback->mainDevice();
 }
 
 FormatModifierMap LinuxDmabufV1::formats() const
diff --git a/src/wayland-client/linuxdmabuf.h b/src/wayland-client/linuxdmabuf.h
index e0e6ba4a2e1..f1858407aa6 100644
--- a/src/wayland-client/linuxdmabuf.h
+++ b/src/wayland-client/linuxdmabuf.h
@@ -40,10 +40,11 @@ public:
     ~LinuxDmabufFeedbackV1();
 
     FormatModifierMap formats() const;
-    QByteArray devicePath() const;
+    dev_t mainDevice() const;
 
     struct Tranche
     {
+        dev_t device;
         FormatModifierMap formats;
         bool scanout = false;
     };
@@ -63,9 +64,7 @@ private:
     static void tranche_flags(void *data, zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, uint32_t flags);
 
     zwp_linux_dmabuf_feedback_v1 *const m_feedback;
-    QByteArray m_mainDevice;
     dev_t m_mainDeviceId = 0;
-    dev_t m_trancheDeviceId = 0;
     MemoryMap m_formatTable;
     FormatModifierMap m_formats;
     QList<Tranche> m_tranches;
@@ -80,7 +79,7 @@ public:
     ~LinuxDmabufV1();
 
     zwp_linux_dmabuf_v1 *handle() const;
-    QByteArray mainDevice() const;
+    dev_t mainDevice() const;
     FormatModifierMap formats() const;
     /**
      * NOTE that it's up to the calling client to take care of the
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.