[plasma/kwin] /: wayland: implement linux dmabuf version 6

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

wayland: implement linux dmabuf version 6

This ports the protocol to version 6, but there are no functional changes yet.

M  +1    -1    CMakeLists.txt
M  +1    -1    src/wayland-client/linuxdmabuf.cpp
M  +33   -20   src/wayland/linuxdmabufv1clientbuffer.cpp
M  +2    -0    src/wayland/linuxdmabufv1clientbuffer_p.h

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

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8788c3f14e4..6d77a57976e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -211,7 +211,7 @@ if (Wayland_VERSION VERSION_GREATER_EQUAL "1.25.91")
     add_compile_definitions(HAVE_ACK_GLOBAL_REMOVE=1)
 endif()
 
-find_package(WaylandProtocols 1.48)
+find_package(WaylandProtocols 1.49)
 set_package_properties(WaylandProtocols PROPERTIES
     TYPE REQUIRED
     PURPOSE "Collection of Wayland protocols that add functionality not available in the Wayland core protocol"
diff --git a/src/wayland-client/linuxdmabuf.cpp b/src/wayland-client/linuxdmabuf.cpp
index 17d3d4e4b68..5b323f68be0 100644
--- a/src/wayland-client/linuxdmabuf.cpp
+++ b/src/wayland-client/linuxdmabuf.cpp
@@ -135,7 +135,7 @@ void LinuxDmabufFeedbackV1::tranche_flags(void *data, zwp_linux_dmabuf_feedback_
 
 LinuxDmabufV1::LinuxDmabufV1(wl_registry *registry, uint32_t name, uint32_t version)
 {
-    m_dmabuf = static_cast<zwp_linux_dmabuf_v1 *>(wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, version));
+    m_dmabuf = static_cast<zwp_linux_dmabuf_v1 *>(wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, std::min(4u, version)));
 
     static const struct zwp_linux_dmabuf_v1_listener dmabufListener = {
         .format = format,
diff --git a/src/wayland/linuxdmabufv1clientbuffer.cpp b/src/wayland/linuxdmabufv1clientbuffer.cpp
index 8e5bab213f1..ae4935e8106 100644
--- a/src/wayland/linuxdmabufv1clientbuffer.cpp
+++ b/src/wayland/linuxdmabufv1clientbuffer.cpp
@@ -28,7 +28,7 @@
 namespace KWin
 {
 
-static const int s_version = 5;
+static const int s_version = 6;
 
 LinuxDmaBufV1ClientBufferIntegrationPrivate::LinuxDmaBufV1ClientBufferIntegrationPrivate(LinuxDmaBufV1ClientBufferIntegration *q, Display *display)
     : QtWaylandServer::zwp_linux_dmabuf_v1(*display, s_version)
@@ -103,7 +103,9 @@ LinuxDmaBufParamsV1::LinuxDmaBufParamsV1(LinuxDmaBufV1ClientBufferIntegration *i
     : QtWaylandServer::zwp_linux_buffer_params_v1(resource)
     , m_integration(integration)
 {
-    m_attrs.device = integration->mainDevice(wl_resource_get_client(resource));
+    if (wl_resource_get_version(resource) < ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION) {
+        m_targetDevice = integration->mainDevice(wl_resource_get_client(resource));
+    }
 }
 
 void LinuxDmaBufParamsV1::zwp_linux_buffer_params_v1_destroy_resource(Resource *resource)
@@ -174,6 +176,7 @@ void LinuxDmaBufParamsV1::zwp_linux_buffer_params_v1_create(Resource *resource,
     m_attrs.width = width;
     m_attrs.height = height;
     m_attrs.format = format;
+    m_attrs.device = m_targetDevice.value_or(m_integration->mainDevice(resource->client()));
 
     auto clientBuffer = new LinuxDmaBufV1ClientBuffer(std::move(m_attrs));
     if (!renderBackend->testImportBuffer(clientBuffer)) {
@@ -225,6 +228,7 @@ void LinuxDmaBufParamsV1::zwp_linux_buffer_params_v1_create_immed(Resource *reso
     m_attrs.width = width;
     m_attrs.height = height;
     m_attrs.format = format;
+    m_attrs.device = m_targetDevice.value_or(m_integration->mainDevice(resource->client()));
 
     auto clientBuffer = new LinuxDmaBufV1ClientBuffer(std::move(m_attrs));
     if (!renderBackend->testImportBuffer(clientBuffer)) {
@@ -243,6 +247,15 @@ void LinuxDmaBufParamsV1::zwp_linux_buffer_params_v1_create_immed(Resource *reso
     clientBuffer->initialize(bufferResource);
 }
 
+void LinuxDmaBufParamsV1::zwp_linux_buffer_params_v1_set_sampling_device(Resource *resource, wl_array *device)
+{
+    if (device->size < sizeof(dev_t)) {
+        wl_resource_post_error(resource->handle, error_invalid_dev_t_size, "Incomplete dev_t sent!");
+        return;
+    }
+    m_targetDevice = *reinterpret_cast<dev_t *>(device->data);
+}
+
 bool LinuxDmaBufParamsV1::test(Resource *resource, uint32_t width, uint32_t height)
 {
     if (Q_UNLIKELY(!m_attrs.planeCount)) {
@@ -461,17 +474,7 @@ QList<LinuxDmaBufV1Feedback::Tranche> LinuxDmaBufV1Feedback::createScanoutTranch
     if (!scanoutDevice) {
         return ret;
     }
-    RenderDevice *compatibleWithScanout = GpuManager::self()->compatibleRenderDevice(scanoutDevice);
     for (const auto &tranche : tranches) {
-        // for now, limit scanout tranches to the main device
-        // TODO relax this with dmabuf v6
-        if (tranche.device != mainDevice) {
-            continue;
-        }
-        if (compatibleWithScanout && tranche.device != compatibleWithScanout->deviceId()) {
-            // limit scanout tranches to devices we can also sample from
-            continue;
-        }
         LinuxDmaBufV1Feedback::Tranche scanoutTranche;
         for (auto it = tranche.formatTable.constBegin(); it != tranche.formatTable.constEnd(); it++) {
             const uint32_t format = it.key();
@@ -485,7 +488,7 @@ QList<LinuxDmaBufV1Feedback::Tranche> LinuxDmaBufV1Feedback::createScanoutTranch
         }
         if (!scanoutTranche.formatTable.isEmpty()) {
             scanoutTranche.device = scanoutDevice->deviceId();
-            scanoutTranche.flags = tranche.flags | LinuxDmaBufV1Feedback::TrancheFlag::Scanout;
+            scanoutTranche.flags = LinuxDmaBufV1Feedback::TrancheFlag::Scanout;
             ret.push_back(scanoutTranche);
         }
     }
@@ -507,10 +510,19 @@ void LinuxDmaBufV1FeedbackPrivate::send(Resource *resource)
 {
     const dev_t mainDevice = m_bufferintegration->q->mainDevice(resource->client());
     send_format_table(resource->handle, m_bufferintegration->table->file.fd(), m_bufferintegration->table->file.size());
-    QByteArray bytes;
-    bytes.append(reinterpret_cast<const char *>(&mainDevice), sizeof(dev_t));
-    send_main_device(resource->handle, bytes);
-    const auto sendTranche = [this, resource](const LinuxDmaBufV1Feedback::Tranche &tranche) {
+    if (resource->version() < ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION) {
+        QByteArray bytes;
+        bytes.append(reinterpret_cast<const char *>(&mainDevice), sizeof(dev_t));
+        send_main_device(resource->handle, bytes);
+    }
+    const auto sendTranche = [this, resource, mainDevice](const LinuxDmaBufV1Feedback::Tranche &tranche) {
+        const bool supportsSamplingFlag = resource->version() >= ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SAMPLING_SINCE_VERSION;
+        if (!supportsSamplingFlag
+            && tranche.flags == LinuxDmaBufV1Feedback::TrancheFlag::Sampling
+            && tranche.device != mainDevice) {
+            // dmabuf v5 only supports the main device for sampling
+            return;
+        }
         QByteArray targetDevice;
         targetDevice.append(reinterpret_cast<const char *>(&tranche.device), sizeof(dev_t));
         QByteArray indices;
@@ -527,6 +539,10 @@ void LinuxDmaBufV1FeedbackPrivate::send(Resource *resource)
         if (tranche.flags & LinuxDmaBufV1Feedback::TrancheFlag::Scanout) {
             flags |= tranche_flags_scanout;
         }
+        if (resource->version() >= ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION
+            && (tranche.flags & LinuxDmaBufV1Feedback::TrancheFlag::Sampling)) {
+            flags |= tranche_flags_sampling;
+        }
         send_tranche_flags(resource->handle, flags);
         send_tranche_done(resource->handle);
     };
@@ -534,9 +550,6 @@ void LinuxDmaBufV1FeedbackPrivate::send(Resource *resource)
         sendTranche(tranche);
     }
     for (const auto &tranche : std::as_const(m_bufferintegration->defaultTranches)) {
-        if (tranche.device != mainDevice) {
-            continue;
-        }
         sendTranche(tranche);
     }
     send_done(resource->handle);
diff --git a/src/wayland/linuxdmabufv1clientbuffer_p.h b/src/wayland/linuxdmabufv1clientbuffer_p.h
index 7fc4fcae955..c3efedfa2e2 100644
--- a/src/wayland/linuxdmabufv1clientbuffer_p.h
+++ b/src/wayland/linuxdmabufv1clientbuffer_p.h
@@ -70,6 +70,7 @@ protected:
     void zwp_linux_buffer_params_v1_create(Resource *resource, int32_t width, int32_t height, uint32_t format, uint32_t flags) override;
     void
     zwp_linux_buffer_params_v1_create_immed(Resource *resource, uint32_t buffer_id, int32_t width, int32_t height, uint32_t format, uint32_t flags) override;
+    void zwp_linux_buffer_params_v1_set_sampling_device(Resource *resource, wl_array *device) override;
 
 private:
     bool test(Resource *resource, uint32_t width, uint32_t height);
@@ -77,6 +78,7 @@ private:
     LinuxDmaBufV1ClientBufferIntegration *m_integration;
     DmaBufAttributes m_attrs;
     std::array<uint64_t, 4> m_modifiers;
+    std::optional<dev_t> m_targetDevice;
     bool m_isUsed = false;
 };
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.