From cd4820d6acf284125d59a3d6711ab14925c53b16 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Wed, 26 Mar 2025 16:43:42 +0100 Subject: [PATCH] device-select: Support linux-dmabuf feedback device-select-layer needs to obtain the display server's preferred display device, and has so far relied on wl_drm for this. wl_drm is superseded by linux-dmabuf with some Wayland servers having dropped support for wl_drm entirely. Implement linux-dmabuf as preferred mechanism for obtaining the main device, with wl_drm support retained as a fallback for now. Signed-off-by: Kenny Levinsen Part-of: --- .../device_select_wayland.c | 163 ++++++++++++++---- src/vulkan/device-select-layer/meson.build | 1 + 2 files changed, 133 insertions(+), 31 deletions(-) diff --git a/src/vulkan/device-select-layer/device_select_wayland.c b/src/vulkan/device-select-layer/device_select_wayland.c index a744cdbfb75..b9a1bed2ef5 100644 --- a/src/vulkan/device-select-layer/device_select_wayland.c +++ b/src/vulkan/device-select-layer/device_select_wayland.c @@ -23,16 +23,21 @@ #include "util/macros.h" #include #include "wayland-drm-client-protocol.h" +#include "linux-dmabuf-unstable-v1-client-protocol.h" #include "device_select.h" #include #include #include #include #include + struct device_select_wayland_info { struct wl_drm *wl_drm; - drmDevicePtr dev_info; - bool info_is_set; + drmDevicePtr drm_dev_info; + + struct zwp_linux_dmabuf_v1 *wl_dmabuf; + struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback; + drmDevicePtr dmabuf_dev_info; }; static void @@ -44,30 +49,27 @@ device_select_drm_handle_device(void *data, struct wl_drm *drm, const char *devi if (fd == -1) return; - int ret = drmGetDevice2(fd, 0, &info->dev_info); - if (ret >= 0) - info->info_is_set = true; + drmGetDevice2(fd, 0, &info->drm_dev_info); close(fd); - return; } static void device_select_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format) { - + /* ignore this event */ } static void device_select_drm_handle_authenticated(void *data, struct wl_drm *drm) { - + /* ignore this event */ } static void device_select_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value) { - + /* ignore this event */ } @@ -78,6 +80,80 @@ static const struct wl_drm_listener ds_drm_listener = { .capabilities = device_select_drm_handle_capabilities }; +static void +default_dmabuf_feedback_format_table(void *data, + struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, + int32_t fd, uint32_t size) +{ + + /* ignore this event */ + close(fd); +} + +static void +default_dmabuf_feedback_main_device(void *data, + struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, + struct wl_array *device) +{ + + struct device_select_wayland_info *info = data; + + dev_t dev_id; + assert(device->size == sizeof(dev_id)); + memcpy(&dev_id, device->data, device->size); + + drmGetDeviceFromDevId(dev_id, 0, &info->dmabuf_dev_info); + return; +} + +static void +default_dmabuf_feedback_tranche_target_device(void *data, + struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, + struct wl_array *device) +{ + /* ignore this event */ +} + +static void +default_dmabuf_feedback_tranche_flags(void *data, + struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, + uint32_t flags) +{ + /* ignore this event */ +} + +static void +default_dmabuf_feedback_tranche_formats(void *data, + struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, + struct wl_array *indices) +{ + /* ignore this event */ +} + +static void +default_dmabuf_feedback_tranche_done(void *data, + struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) +{ + /* ignore this event */ +} + +static void +default_dmabuf_feedback_done(void *data, + struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) +{ + /* ignore this event */ +} + +static const struct zwp_linux_dmabuf_feedback_v1_listener dmabuf_feedback_listener = { + .format_table = default_dmabuf_feedback_format_table, + .main_device = default_dmabuf_feedback_main_device, + .tranche_target_device = default_dmabuf_feedback_tranche_target_device, + .tranche_flags = default_dmabuf_feedback_tranche_flags, + .tranche_formats = default_dmabuf_feedback_tranche_formats, + .tranche_done = default_dmabuf_feedback_tranche_done, + .done = default_dmabuf_feedback_done, +}; + static void device_select_registry_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) @@ -86,6 +162,15 @@ device_select_registry_global(void *data, struct wl_registry *registry, uint32_t if (strcmp(interface, wl_drm_interface.name) == 0) { info->wl_drm = wl_registry_bind(registry, name, &wl_drm_interface, MIN2(version, 2)); wl_drm_add_listener(info->wl_drm, &ds_drm_listener, data); + } else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0 && + version >= ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION) { + info->wl_dmabuf = + wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, + ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION); + info->wl_dmabuf_feedback = + zwp_linux_dmabuf_v1_get_default_feedback(info->wl_dmabuf); + zwp_linux_dmabuf_feedback_v1_add_listener(info->wl_dmabuf_feedback, + &dmabuf_feedback_listener, data); } } @@ -105,12 +190,12 @@ int device_select_find_wayland_pci_default(struct device_pci_info *devices, uint display = wl_display_connect(NULL); if (!display) - goto out; + return -1; registry = wl_display_get_registry(display); if (!registry) { wl_display_disconnect(display); - goto out; + return -1; } static const struct wl_registry_listener registry_listener = @@ -120,31 +205,47 @@ int device_select_find_wayland_pci_default(struct device_pci_info *devices, uint wl_display_dispatch(display); wl_display_roundtrip(display); - - if (info.info_is_set) { - for (unsigned i = 0; i < device_count; i++) { - if (devices[i].has_bus_info) { - if (info.dev_info->businfo.pci->domain == devices[i].bus_info.domain && - info.dev_info->businfo.pci->bus == devices[i].bus_info.bus && - info.dev_info->businfo.pci->dev == devices[i].bus_info.dev && - info.dev_info->businfo.pci->func == devices[i].bus_info.func) - default_idx = i; - } else { - if (info.dev_info->deviceinfo.pci->vendor_id == devices[i].dev_info.vendor_id && - info.dev_info->deviceinfo.pci->device_id == devices[i].dev_info.device_id) - default_idx = i; - } - if (default_idx != -1) - break; - } - - drmFreeDevice(&info.dev_info); + drmDevicePtr target; + if (info.dmabuf_dev_info != NULL) { + target = info.dmabuf_dev_info; + } else if (info.drm_dev_info != NULL) { + target = info.drm_dev_info; + } else { + goto done; } + for (unsigned i = 0; i < device_count; i++) { + if (devices[i].has_bus_info) { + if (target->businfo.pci->domain == devices[i].bus_info.domain && + target->businfo.pci->bus == devices[i].bus_info.bus && + target->businfo.pci->dev == devices[i].bus_info.dev && + target->businfo.pci->func == devices[i].bus_info.func) { + default_idx = i; + break; + } + } else { + if (target->deviceinfo.pci->vendor_id == devices[i].dev_info.vendor_id && + target->deviceinfo.pci->device_id == devices[i].dev_info.device_id) { + default_idx = i; + break; + } + } + } + + done: + if (info.dmabuf_dev_info != NULL) + drmFreeDevice(&info.dmabuf_dev_info); + if (info.drm_dev_info != NULL) + drmFreeDevice(&info.drm_dev_info); + + if (info.wl_dmabuf_feedback) + zwp_linux_dmabuf_feedback_v1_destroy(info.wl_dmabuf_feedback); + if (info.wl_dmabuf) + zwp_linux_dmabuf_v1_destroy(info.wl_dmabuf); if (info.wl_drm) wl_drm_destroy(info.wl_drm); + wl_registry_destroy(registry); wl_display_disconnect(display); - out: return default_idx; } diff --git a/src/vulkan/device-select-layer/meson.build b/src/vulkan/device-select-layer/meson.build index ef00ab3105c..03c731fbcf6 100644 --- a/src/vulkan/device-select-layer/meson.build +++ b/src/vulkan/device-select-layer/meson.build @@ -16,6 +16,7 @@ endif if with_platform_wayland vklayer_files += files('device_select_wayland.c') vklayer_files += [ wayland_drm_client_protocol_h, wayland_drm_protocol_c ] + vklayer_files += wp_files['linux-dmabuf-unstable-v1'] vklayer_deps += dep_wayland_client endif