From 62f0fd1568ef2a927c525b7b3a885795aaa7179c Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Tue, 30 Sep 2025 12:43:39 +0200 Subject: [PATCH 1/3] drop this: use git wayland-protocols --- src/egl/drivers/dri2/egl_dri2.c | 2 +- src/egl/drivers/dri2/platform_wayland.c | 2 +- src/egl/meson.build | 2 +- src/loader/meson.build | 2 +- .../device-select-layer/device_select_wayland.c | 2 +- src/vulkan/device-select-layer/meson.build | 2 +- src/vulkan/wsi/meson.build | 2 +- src/vulkan/wsi/wsi_common_wayland.c | 2 +- subprojects/wayland-protocols.wrap | 11 +++++++---- 9 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index bec8af9dbfa..3c205688fdf 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -48,7 +48,7 @@ #include "dri_screen.h" #ifdef HAVE_WAYLAND_PLATFORM -#include "linux-dmabuf-unstable-v1-client-protocol.h" +#include "linux-dmabuf-v1-client-protocol.h" #if HAVE_BIND_WL_DISPLAY #include "wayland-drm-client-protocol.h" #include "wayland-drm.h" diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index 2228b0e1580..af4fe2cd513 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -56,7 +56,7 @@ #include "dri_util.h" #include -#include "linux-dmabuf-unstable-v1-client-protocol.h" +#include "linux-dmabuf-v1-client-protocol.h" #ifdef HAVE_BIND_WL_DISPLAY #include "wayland-drm-client-protocol.h" #endif diff --git a/src/egl/meson.build b/src/egl/meson.build index f9b0e348ad4..2b5e595ddaf 100644 --- a/src/egl/meson.build +++ b/src/egl/meson.build @@ -122,7 +122,7 @@ if with_dri deps_for_egl += [dep_wayland_client, dep_wayland_server, dep_wayland_egl_headers] link_for_egl += libloader_wayland_helper files_egl += files('drivers/dri2/platform_wayland.c') - files_egl += wp_files['linux-dmabuf-unstable-v1'] + files_egl += wp_files['linux-dmabuf-v1'] files_egl += wp_files['presentation-time'] if with_wayland_bind_display files_egl += [wayland_drm_client_protocol_h] diff --git a/src/loader/meson.build b/src/loader/meson.build index a8603ad5767..876ad9fd229 100644 --- a/src/loader/meson.build +++ b/src/loader/meson.build @@ -7,7 +7,7 @@ if with_platform_wayland wp_protos = { 'fifo-v1': mod_wl.find_protocol('fifo', state : 'staging', version : 1), 'commit-timing-v1': mod_wl.find_protocol('commit-timing', state : 'staging', version : 1), - 'linux-dmabuf-unstable-v1': mod_wl.find_protocol('linux-dmabuf', state : 'unstable', version : 1), + 'linux-dmabuf-v1': mod_wl.find_protocol('linux-dmabuf', state : 'stable', version : 1), 'presentation-time': mod_wl.find_protocol('presentation-time'), 'tearing-control-v1': mod_wl.find_protocol('tearing-control', state : 'staging', version : 1), 'linux-drm-syncobj-v1': mod_wl.find_protocol('linux-drm-syncobj', state : 'staging', version : 1), diff --git a/src/vulkan/device-select-layer/device_select_wayland.c b/src/vulkan/device-select-layer/device_select_wayland.c index 5846d2aaa2c..a1d4c31c18b 100644 --- a/src/vulkan/device-select-layer/device_select_wayland.c +++ b/src/vulkan/device-select-layer/device_select_wayland.c @@ -31,7 +31,7 @@ #include #include #include "device_select.h" -#include "linux-dmabuf-unstable-v1-client-protocol.h" +#include "linux-dmabuf-v1-client-protocol.h" struct device_select_wayland_info { #ifdef HAVE_BIND_WL_DISPLAY diff --git a/src/vulkan/device-select-layer/meson.build b/src/vulkan/device-select-layer/meson.build index 331a9587ef2..97becbf6cd2 100644 --- a/src/vulkan/device-select-layer/meson.build +++ b/src/vulkan/device-select-layer/meson.build @@ -20,7 +20,7 @@ if with_platform_wayland vklayer_files += [ wayland_drm_client_protocol_h, wayland_drm_protocol_c ] vklayer_flags += [ '-DHAVE_BIND_WL_DISPLAY' ] endif - vklayer_files += wp_files['linux-dmabuf-unstable-v1'] + vklayer_files += wp_files['linux-dmabuf-v1'] vklayer_deps += dep_wayland_client endif diff --git a/src/vulkan/wsi/meson.build b/src/vulkan/wsi/meson.build index 38a83d08eab..a8a70a1d631 100644 --- a/src/vulkan/wsi/meson.build +++ b/src/vulkan/wsi/meson.build @@ -18,7 +18,7 @@ if with_platform_wayland files_vulkan_wsi += files('wsi_common_wayland.c') files_vulkan_wsi += wp_files['fifo-v1'] files_vulkan_wsi += wp_files['commit-timing-v1'] - files_vulkan_wsi += wp_files['linux-dmabuf-unstable-v1'] + files_vulkan_wsi += wp_files['linux-dmabuf-v1'] files_vulkan_wsi += wp_files['presentation-time'] files_vulkan_wsi += wp_files['tearing-control-v1'] links_vulkan_wsi += libloader_wayland_helper diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c index 083777f42ac..837724f4ed4 100644 --- a/src/vulkan/wsi/wsi_common_wayland.c +++ b/src/vulkan/wsi/wsi_common_wayland.c @@ -43,7 +43,7 @@ #include "wsi_common_private.h" #include "fifo-v1-client-protocol.h" #include "commit-timing-v1-client-protocol.h" -#include "linux-dmabuf-unstable-v1-client-protocol.h" +#include "linux-dmabuf-v1-client-protocol.h" #include "presentation-time-client-protocol.h" #include "linux-drm-syncobj-v1-client-protocol.h" #include "tearing-control-v1-client-protocol.h" diff --git a/subprojects/wayland-protocols.wrap b/subprojects/wayland-protocols.wrap index c6686b4ae4a..e25556ee420 100644 --- a/subprojects/wayland-protocols.wrap +++ b/subprojects/wayland-protocols.wrap @@ -1,8 +1,11 @@ -[wrap-file] +[wrap-git] directory = wayland-protocols-1.41 -source_url = https://gitlab.freedesktop.org/wayland/wayland-protocols/-/releases/1.41/downloads/wayland-protocols-1.41.tar.xz -source_filename = wayland-protocols-1.41.tar.xz -source_hash = 2786b6b1b79965e313f2c289c12075b9ed700d41844810c51afda10ee329576b +#source_url = https://gitlab.freedesktop.org/wayland/wayland-protocols/-/releases/1.41/downloads/wayland-protocols-1.41.tar.xz +#source_filename = wayland-protocols-1.41.tar.xz +#source_hash = 2786b6b1b79965e313f2c289c12075b9ed700d41844810c51afda10ee329576b +url = https://gitlab.freedesktop.org/Zamundaaa/wayland-protocols.git +revision = work/multi-gpu-dmabuf +depth = 1 [provide] wayland-protocols = wayland_protocols From 4266c8a449d1d6adf17ab6da1cf5f2b99d608dc8 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Sat, 28 Sep 2024 13:09:27 +0200 Subject: [PATCH 2/3] egl/wsi/wayland: Support wl-dmabuf v6 --- src/egl/drivers/dri2/egl_dri2.h | 3 +- src/egl/drivers/dri2/platform_wayland.c | 139 +++++++++++++++++++----- src/loader/loader.c | 78 +++++++++---- src/loader/loader.h | 12 ++ 4 files changed, 183 insertions(+), 49 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 04c9d4840db..bd84042214d 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -283,8 +283,9 @@ struct dri2_egl_display { struct wp_presentation *wp_presentation; struct dri2_wl_formats formats; struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback; - struct dmabuf_feedback_format_table format_table; + struct dmabuf_feedback dmabuf_feedback; char *device_name; + dev_t display_device_dev; bool is_render_node; clockid_t presentation_clock_id; #endif diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index af4fe2cd513..04aedc48414 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -37,6 +37,7 @@ #include #include #include "drm-uapi/drm_fourcc.h" +#include "util/u_dynarray.h" #include #include #include @@ -1205,8 +1206,8 @@ create_dri_image_from_dmabuf_feedback(struct dri2_egl_surface *dri2_surf, { uint32_t flags; - /* We don't have valid dma-buf feedback, so return */ - if (dri2_surf->dmabuf_feedback.main_device == 0) + /* We don't have any tranches for our surface dma-buf feedback, so return */ + if (util_dynarray_num_elements(&dri2_surf->dmabuf_feedback.tranches, struct dmabuf_feedback_tranche) == 0) return; /* Iterates through the dma-buf feedback to pick a new set of modifiers. The @@ -1697,6 +1698,16 @@ create_wl_buffer(struct dri2_egl_display *dri2_dpy, if (dri2_surf) wl_proxy_set_queue((struct wl_proxy *)params, dri2_surf->wl_queue); + if (wl_proxy_get_version((struct wl_proxy *)dri2_dpy->wl_dmabuf) >= + ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION) { + struct wl_array dev; + wl_array_init(&dev); + wl_array_add(&dev, sizeof(dev_t)); + memcpy(dev.data, &dri2_dpy->display_device_dev, sizeof(dev_t)); + zwp_linux_buffer_params_v1_set_sampling_device(params, &dev); + wl_array_release(&dev); + } + for (i = 0; i < num_planes; i++) { struct dri_image *p_image; int stride, offset; @@ -2145,26 +2156,24 @@ default_dmabuf_feedback_format_table( int32_t fd, uint32_t size) { struct dri2_egl_display *dri2_dpy = data; + struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback; - dri2_dpy->format_table.size = size; - dri2_dpy->format_table.data = + feedback->format_table.size = size; + feedback->format_table.data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); } static void -default_dmabuf_feedback_main_device( - void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, - struct wl_array *device) +dri2_wl_init_display_dev( + struct dri2_egl_display *dri2_dpy, + dev_t dev) { - struct dri2_egl_display *dri2_dpy = data; char *node; int fd; - dev_t dev; /* Given the device, look for a render node and try to open it. */ - memcpy(&dev, device->data, sizeof(dev)); node = loader_get_render_node(dev); if (!node) return; @@ -2174,6 +2183,7 @@ default_dmabuf_feedback_main_device( return; } + dri2_dpy->display_device_dev = dev; dri2_dpy->device_name = node; dri2_dpy->fd_render_gpu = fd; #ifdef HAVE_BIND_WL_DISPLAY @@ -2181,12 +2191,27 @@ default_dmabuf_feedback_main_device( #endif } +static void +default_dmabuf_feedback_main_device( + void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, + struct wl_array *device) +{ + struct dri2_egl_display *dri2_dpy = data; + struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback; + + memcpy(&feedback->main_device, device->data, sizeof(feedback->main_device)); + dri2_wl_init_display_dev(dri2_dpy, feedback->main_device); +} + 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 */ + struct dri2_egl_display *dri2_dpy = data; + struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback; + + memcpy(&feedback->pending_tranche.target_device, device->data, sizeof(feedback->pending_tranche.target_device)); } static void @@ -2194,7 +2219,10 @@ default_dmabuf_feedback_tranche_flags( void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, uint32_t flags) { - /* ignore this event */ + struct dri2_egl_display *dri2_dpy = data; + struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback; + + feedback->pending_tranche.flags = flags; } static void @@ -2203,18 +2231,19 @@ default_dmabuf_feedback_tranche_formats( struct wl_array *indices) { struct dri2_egl_display *dri2_dpy = data; + struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback; uint64_t *modifier_ptr, modifier; uint32_t format; uint16_t *index; int visual_idx; - if (dri2_dpy->format_table.data == MAP_FAILED) { + if (feedback->format_table.data == MAP_FAILED) { _eglLog(_EGL_WARNING, "wayland-egl: we could not map the format table " "so we won't be able to use this batch of dma-buf " "feedback events."); return; } - if (dri2_dpy->format_table.data == NULL) { + if (feedback->format_table.data == NULL) { _eglLog(_EGL_WARNING, "wayland-egl: compositor didn't advertise a format " "table, so we won't be able to use this batch of dma-buf " @@ -2223,8 +2252,8 @@ default_dmabuf_feedback_tranche_formats( } wl_array_for_each (index, indices) { - format = dri2_dpy->format_table.data[*index].format; - modifier = dri2_dpy->format_table.data[*index].modifier; + format = feedback->format_table.data[*index].format; + modifier = feedback->format_table.data[*index].modifier; /* skip formats that we don't support */ visual_idx = dri2_wl_visual_idx_from_fourcc(format); @@ -2242,15 +2271,20 @@ static void default_dmabuf_feedback_tranche_done( void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) { - /* ignore this event */ + struct dri2_egl_display *dri2_dpy = data; + struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback; + + /* Add tranche to array of tranches. */ + util_dynarray_append(&feedback->tranches, + feedback->pending_tranche); + + dmabuf_feedback_tranche_init(&feedback->pending_tranche); } 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 = { @@ -2292,7 +2326,7 @@ registry_handle_global_drm(void *data, struct wl_registry *registry, version >= 3) { dri2_dpy->wl_dmabuf = wl_registry_bind( registry, name, &zwp_linux_dmabuf_v1_interface, - MIN2(version, ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION)); + MIN2(version, ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION)); zwp_linux_dmabuf_v1_add_listener(dri2_dpy->wl_dmabuf, &dmabuf_listener, dri2_dpy); } else if (strcmp(interface, wp_presentation_interface.name) == 0) { @@ -2590,7 +2624,9 @@ dri2_initialize_wayland_drm_extensions(struct dri2_egl_display *dri2_dpy) if (dri2_dpy->wl_dmabuf && zwp_linux_dmabuf_v1_get_version(dri2_dpy->wl_dmabuf) >= ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION) { - dmabuf_feedback_format_table_init(&dri2_dpy->format_table); + if (dmabuf_feedback_init(&dri2_dpy->dmabuf_feedback) < 0) { + return false; + } dri2_dpy->wl_dmabuf_feedback = zwp_linux_dmabuf_v1_get_default_feedback(dri2_dpy->wl_dmabuf); zwp_linux_dmabuf_feedback_v1_add_listener( @@ -2600,11 +2636,20 @@ dri2_initialize_wayland_drm_extensions(struct dri2_egl_display *dri2_dpy) if (roundtrip(dri2_dpy) < 0) return false; - /* Destroy the default dma-buf feedback and the format table. */ + /* Destroy the default dma-buf feedback. */ if (dri2_dpy->wl_dmabuf_feedback) { zwp_linux_dmabuf_feedback_v1_destroy(dri2_dpy->wl_dmabuf_feedback); dri2_dpy->wl_dmabuf_feedback = NULL; - dmabuf_feedback_format_table_fini(&dri2_dpy->format_table); + + /* For dmabuf v6 we don't get a main device, use the first tranch suitable for sampling as default */ + if (dri2_dpy->fd_render_gpu == -1) { + util_dynarray_foreach(&dri2_dpy->dmabuf_feedback.tranches, struct dmabuf_feedback_tranche, tranche) { + if ((tranche->flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SAMPLING) != 0) { + dri2_wl_init_display_dev(dri2_dpy, tranche->target_device); + break; + } + } + } } #ifdef HAVE_BIND_WL_DISPLAY @@ -2633,6 +2678,8 @@ static EGLBoolean dri2_initialize_wayland_drm(_EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + dev_t preferred_dev_id = 0; + drmDevicePtr render_dev = NULL, preferred_dev = NULL, tranche_dev = NULL; if (dri2_wl_formats_init(&dri2_dpy->formats) < 0) goto cleanup; @@ -2669,8 +2716,43 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp) if (!dri2_initialize_wayland_drm_extensions(dri2_dpy)) goto cleanup; - loader_get_user_preferred_fd(&dri2_dpy->fd_render_gpu, - &dri2_dpy->fd_display_gpu); + if (drmGetDevice2(dri2_dpy->fd_render_gpu, 0, &render_dev) != 0) + goto cleanup; + + if (loader_get_user_preferred_device(render_dev, &preferred_dev_id)) + { + bool found_matching_tranche = false; + if (drmGetDeviceFromDevId(preferred_dev_id, 0, &preferred_dev) < 0) { + goto cleanup; + } + + /* check if the compositor can sample from the new device */ + util_dynarray_foreach(&dri2_dpy->dmabuf_feedback.tranches, struct dmabuf_feedback_tranche, tranche) { + if ((tranche->flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SAMPLING) != 0) { + if (drmGetDeviceFromDevId(tranche->target_device, 0, &tranche_dev) < 0) { + continue; + } + + if (!found_matching_tranche && loader_drm_devices_match(preferred_dev, tranche_dev)) { + close(dri2_dpy->fd_render_gpu); + dri2_wl_init_display_dev(dri2_dpy, tranche->target_device); + found_matching_tranche = true; + } + + drmFreeDevice(&tranche_dev); + } + } + + dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu; + if (!found_matching_tranche) { + // fallback to copying + dri2_dpy->fd_render_gpu = loader_open_device(preferred_dev->nodes[DRM_NODE_RENDER]); + } + drmFreeDevice(&preferred_dev); + } else { + dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu; + } + drmFreeDevice(&render_dev); if (dri2_dpy->fd_render_gpu != dri2_dpy->fd_display_gpu) { free(dri2_dpy->device_name); @@ -2753,6 +2835,9 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp) return EGL_TRUE; cleanup: + if (render_dev) drmFreeDevice(&render_dev); + if (preferred_dev) drmFreeDevice(&preferred_dev); + if (tranche_dev) drmFreeDevice(&tranche_dev); return EGL_FALSE; } @@ -3259,7 +3344,6 @@ dri2_initialize_wayland(_EGLDisplay *disp) void dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy) { - dri2_wl_formats_fini(&dri2_dpy->formats); if (dri2_dpy->wp_presentation) wp_presentation_destroy(dri2_dpy->wp_presentation); #ifdef HAVE_BIND_WL_DISPLAY @@ -3268,6 +3352,7 @@ dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy) #endif if (dri2_dpy->wl_dmabuf) zwp_linux_dmabuf_v1_destroy(dri2_dpy->wl_dmabuf); + dmabuf_feedback_fini(&dri2_dpy->dmabuf_feedback); if (dri2_dpy->wl_shm) wl_shm_destroy(dri2_dpy->wl_shm); if (dri2_dpy->wl_registry) diff --git a/src/loader/loader.c b/src/loader/loader.c index 0567beb3dee..5827fe0b2b2 100644 --- a/src/loader/loader.c +++ b/src/loader/loader.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #ifdef MAJOR_IN_MKDEV #include @@ -48,7 +49,6 @@ #include "mesa_interface.h" #include "loader.h" #include "util/drm_is_nouveau.h" -#include "util/libdrm.h" #include "util/os_file.h" #include "util/os_misc.h" #include "util/u_debug.h" @@ -448,13 +448,20 @@ static char *drm_get_id_path_tag_for_fd(int fd) return tag; } -bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd) +bool loader_drm_devices_match(drmDevicePtr dev1, drmDevicePtr dev2) +{ + char *tag = drm_construct_id_path_tag(dev1); + return drm_device_matches_tag(dev2, tag); +} + +bool loader_get_user_preferred_device(drmDevicePtr default_dev, dev_t *preferred_dev_id) { const char *dri_prime = os_get_option("DRI_PRIME"); bool debug = debug_get_bool_option("DRI_PRIME_DEBUG", false); char *default_tag = NULL; drmDevicePtr devices[MAX_DRM_DEVICES]; - int i, num_devices, fd = -1; + int i, num_devices = -1; + struct stat sbuf; struct { enum { PRIME_IS_INTEGER, @@ -500,7 +507,7 @@ bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd) } } - default_tag = drm_get_id_path_tag_for_fd(*fd_render_gpu); + default_tag = drm_construct_id_path_tag(default_dev); if (default_tag == NULL) goto err; @@ -605,20 +612,58 @@ bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd) log_(debug ? _LOADER_WARNING : _LOADER_INFO, "selected (%s)\n", devices[i]->nodes[DRM_NODE_RENDER]); - fd = loader_open_device(devices[i]->nodes[DRM_NODE_RENDER]); - if (fd < 0) { - log_(debug ? _LOADER_WARNING : _LOADER_INFO, - "DRI_PRIME: failed to open '%s'\n", - devices[i]->nodes[DRM_NODE_RENDER]); + char *preferred_node = devices[i]->nodes[DRM_NODE_RENDER]; + if (stat(preferred_node, &sbuf) != 0) { + goto err; } + *preferred_dev_id = sbuf.st_rdev; break; } drmFreeDevices(devices, num_devices); - if (i == num_devices || fd < 0) + if (i == num_devices) goto err; bool is_render_and_display_gpu_diff = !!strcmp(default_tag, prime.str); + + free(default_tag); + free(prime.str); + return is_render_and_display_gpu_diff; + err: + log_(debug ? _LOADER_WARNING : _LOADER_INFO, + "DRI_PRIME: error. Using the default GPU\n"); + free(default_tag); + free(prime.str); + no_prime_gpu_offloading: + return false; +} + +bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd) +{ + int fd = -1; + bool is_render_and_display_gpu_diff; + dev_t preferred_dev_id = 0; + drmDevicePtr render_dev, preferred_dev; + bool debug = debug_get_bool_option("DRI_PRIME_DEBUG", false); + + if (drmGetDevice2(*fd_render_gpu, 0, &render_dev) != 0) + return false; + is_render_and_display_gpu_diff = loader_get_user_preferred_device(render_dev, &preferred_dev_id); + if (drmGetDeviceFromDevId(preferred_dev_id, 0, &preferred_dev) != 0) { + drmFreeDevice(&render_dev); + return false; + }; + fd = loader_open_device(preferred_dev->nodes[DRM_NODE_RENDER]); + + if (fd < 0) { + log_(debug ? _LOADER_WARNING : _LOADER_INFO, + "DRI_PRIME: failed to open '%s'\n", + render_dev->nodes[DRM_NODE_RENDER]); + drmFreeDevice(&render_dev); + drmFreeDevice(&preferred_dev); + return false; + } + if (original_fd) { if (is_render_and_display_gpu_diff) { *original_fd = *fd_render_gpu; @@ -632,18 +677,9 @@ bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd) *fd_render_gpu = fd; } - free(default_tag); - free(prime.str); + drmFreeDevice(&render_dev); + drmFreeDevice(&preferred_dev); return is_render_and_display_gpu_diff; - err: - log_(debug ? _LOADER_WARNING : _LOADER_INFO, - "DRI_PRIME: error. Using the default GPU\n"); - free(default_tag); - free(prime.str); - no_prime_gpu_offloading: - if (original_fd) - *original_fd = *fd_render_gpu; - return false; } static bool diff --git a/src/loader/loader.h b/src/loader/loader.h index 6748cb5269d..81dc60d7d23 100644 --- a/src/loader/loader.h +++ b/src/loader/loader.h @@ -30,6 +30,7 @@ #include #include #include +#include #include "mesa_interface.h" #ifdef __cplusplus @@ -75,6 +76,9 @@ loader_open_driver_lib(const char *driver_name, char * loader_get_device_name_for_fd(int fd); +bool +loader_drm_devices_match(drmDevicePtr dev1, drmDevicePtr dev2); + /* For dri prime gpu offloading this function will take current render fd and possibly * update it with new prime gpu offloading fd. For dri prime gpu offloading optionally * this function can return the original fd. Also this function returns true/false based @@ -84,6 +88,14 @@ loader_get_device_name_for_fd(int fd); bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd); +/* For dri prime offloading this function will take a default device and possibly set + * the user preferred device for prime gpu offloading. This function returns true/false + * based on if the default device is different from the preferred one. + */ + +bool +loader_get_user_preferred_device(drmDevicePtr default_dev, dev_t *preferred_dev_id); + /* for logging.. keep this aligned with egllog.h so we can just use * _eglLog directly. */ From 378a5ef906dcd757b5ec173226dd3e20ece10211 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Sat, 28 Sep 2024 13:35:42 +0200 Subject: [PATCH 3/3] vulkan/wsi/wayland: Support wl-dmabuf v6 --- src/vulkan/wsi/wsi_common_wayland.c | 108 +++++++++++++++++++++------- 1 file changed, 81 insertions(+), 27 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c index 837724f4ed4..9f2a05ff50a 100644 --- a/src/vulkan/wsi/wsi_common_wayland.c +++ b/src/vulkan/wsi/wsi_common_wayland.c @@ -113,7 +113,7 @@ struct wsi_wl_display { struct wp_color_manager_v1 *color_manager; - struct dmabuf_feedback_format_table format_table; + struct dmabuf_feedback dmabuf_feedback; struct u_vector color_primaries; struct u_vector color_transfer_funcs; @@ -136,7 +136,7 @@ struct wsi_wl_display { bool sw; - dev_t main_device; + dev_t display_device_dev; bool same_gpu; clockid_t presentation_clock_id; @@ -813,9 +813,10 @@ default_dmabuf_feedback_format_table(void *data, int32_t fd, uint32_t size) { struct wsi_wl_display *display = data; + struct dmabuf_feedback *feedback = &display->dmabuf_feedback; - display->format_table.size = size; - display->format_table.data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + feedback->format_table.size = size; + feedback->format_table.data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); } @@ -826,9 +827,10 @@ default_dmabuf_feedback_main_device(void *data, struct wl_array *device) { struct wsi_wl_display *display = data; + struct dmabuf_feedback *feedback = &display->dmabuf_feedback; assert(device->size == sizeof(dev_t)); - memcpy(&display->main_device, device->data, device->size); + memcpy(&feedback->main_device, device->data, device->size); } static void @@ -836,7 +838,10 @@ default_dmabuf_feedback_tranche_target_device(void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, struct wl_array *device) { - /* ignore this event */ + struct wsi_wl_display *display = data; + struct dmabuf_feedback *feedback = &display->dmabuf_feedback; + + memcpy(&feedback->pending_tranche.target_device, device->data, sizeof(feedback->pending_tranche.target_device)); } static void @@ -844,7 +849,10 @@ default_dmabuf_feedback_tranche_flags(void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, uint32_t flags) { - /* ignore this event */ + struct wsi_wl_display *display = data; + struct dmabuf_feedback *feedback = &display->dmabuf_feedback; + + feedback->pending_tranche.flags = flags; } static void @@ -853,19 +861,20 @@ default_dmabuf_feedback_tranche_formats(void *data, struct wl_array *indices) { struct wsi_wl_display *display = data; + struct dmabuf_feedback *feedback = &display->dmabuf_feedback; uint32_t format; uint64_t modifier; uint16_t *index; /* We couldn't map the format table or the compositor didn't advertise it, * so we have to ignore the feedback. */ - if (display->format_table.data == MAP_FAILED || - display->format_table.data == NULL) + if (feedback->format_table.data == MAP_FAILED || + feedback->format_table.data == NULL) return; wl_array_for_each(index, indices) { - format = display->format_table.data[*index].format; - modifier = display->format_table.data[*index].modifier; + format = feedback->format_table.data[*index].format; + modifier = feedback->format_table.data[*index].modifier; wsi_wl_display_add_drm_format_modifier(display, &display->formats, format, modifier); } @@ -875,15 +884,20 @@ static void default_dmabuf_feedback_tranche_done(void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) { - /* ignore this event */ + struct wsi_wl_display *display = data; + struct dmabuf_feedback *feedback = &display->dmabuf_feedback; + + /* Add tranche to array of tranches. */ + util_dynarray_append(&feedback->tranches, + feedback->pending_tranche); + + dmabuf_feedback_tranche_init(&feedback->pending_tranche); } 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 = { @@ -1412,7 +1426,7 @@ registry_handle_global(void *data, struct wl_registry *registry, if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0 && version >= 3) { display->wl_dmabuf = wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, - MIN2(version, ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION)); + MIN2(version, ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION)); zwp_linux_dmabuf_v1_add_listener(display->wl_dmabuf, &dmabuf_listener, display); } else if (strcmp(interface, wp_linux_drm_syncobj_manager_v1_interface.name) == 0) { @@ -1559,7 +1573,7 @@ wsi_wl_display_init(struct wsi_wayland *wsi_wl, /* Get the default dma-buf feedback */ if (display->wl_dmabuf && zwp_linux_dmabuf_v1_get_version(display->wl_dmabuf) >= ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION) { - dmabuf_feedback_format_table_init(&display->format_table); + dmabuf_feedback_init(&display->dmabuf_feedback); display->wl_dmabuf_feedback = zwp_linux_dmabuf_v1_get_default_feedback(display->wl_dmabuf); zwp_linux_dmabuf_feedback_v1_add_listener(display->wl_dmabuf_feedback, @@ -1573,13 +1587,42 @@ wsi_wl_display_init(struct wsi_wayland *wsi_wl, /* Apparently some wayland compositor do not send the render * device node but the primary, so test against both. */ - display->same_gpu = - (wsi_wl->wsi->drm_info.hasRender && - major(display->main_device) == wsi_wl->wsi->drm_info.renderMajor && - minor(display->main_device) == wsi_wl->wsi->drm_info.renderMinor) || - (wsi_wl->wsi->drm_info.hasPrimary && - major(display->main_device) == wsi_wl->wsi->drm_info.primaryMajor && - minor(display->main_device) == wsi_wl->wsi->drm_info.primaryMinor); + if (wl_proxy_get_version((struct wl_proxy *)display->wl_dmabuf) >= + ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION) + { + /* + For dmabuf v6 we don't get a main device, so we use the first one the compositor can sample from + as default and then try to figure out, if we can use our gpu directly. + */ + util_dynarray_foreach(&display->dmabuf_feedback.tranches, struct dmabuf_feedback_tranche, tranche) { + if ((tranche->flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SAMPLING) != 0 && !display->display_device_dev) { + display->same_gpu = false; // if this actually is the same_gpu, we'll figure out in the next loop + display->display_device_dev = tranche->target_device; + } + + if ((tranche->flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SAMPLING) != 0 && + ((wsi_wl->wsi->drm_info.hasRender && + major(tranche->target_device) == wsi_wl->wsi->drm_info.renderMajor && + minor(tranche->target_device) == wsi_wl->wsi->drm_info.renderMinor) || + (wsi_wl->wsi->drm_info.hasPrimary && + major(tranche->target_device) == wsi_wl->wsi->drm_info.primaryMajor && + minor(tranche->target_device) == wsi_wl->wsi->drm_info.primaryMinor))) + { + display->display_device_dev = tranche->target_device; + display->same_gpu = true; + break; + } + } + } else { + display->same_gpu = + (wsi_wl->wsi->drm_info.hasRender && + major(display->dmabuf_feedback.main_device) == wsi_wl->wsi->drm_info.renderMajor && + minor(display->dmabuf_feedback.main_device) == wsi_wl->wsi->drm_info.renderMinor) || + (wsi_wl->wsi->drm_info.hasPrimary && + major(display->dmabuf_feedback.main_device) == wsi_wl->wsi->drm_info.primaryMajor && + minor(display->dmabuf_feedback.main_device) == wsi_wl->wsi->drm_info.primaryMinor); + display->display_device_dev = display->dmabuf_feedback.main_device; + } } } @@ -1613,7 +1656,7 @@ out: if (display->wl_dmabuf_feedback) { zwp_linux_dmabuf_feedback_v1_destroy(display->wl_dmabuf_feedback); display->wl_dmabuf_feedback = NULL; - dmabuf_feedback_format_table_fini(&display->format_table); + dmabuf_feedback_fini(&display->dmabuf_feedback); } return VK_SUCCESS; @@ -2107,8 +2150,8 @@ pick_format_from_surface_dmabuf_feedback(struct wsi_wl_surface *wsi_wl_surface, { struct wsi_wl_format *f = NULL; - /* If the main_device was not advertised, we don't have valid feedback */ - if (wsi_wl_surface->dmabuf_feedback.main_device == 0) + /* We don't have any tranches for our surface dma-buf feedback, so return */ + if (util_dynarray_num_elements(&wsi_wl_surface->dmabuf_feedback.tranches, struct dmabuf_feedback_tranche) == 0) return NULL; util_dynarray_foreach(&wsi_wl_surface->dmabuf_feedback.tranches, @@ -3279,6 +3322,17 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain, if (!params) goto fail_image; + if (wl_proxy_get_version((struct wl_proxy *)display->wl_dmabuf) >= + ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION) + { + struct wl_array dev; + wl_array_init(&dev); + wl_array_add(&dev, sizeof(dev_t)); + memcpy(dev.data, &display->display_device_dev, sizeof(dev_t)); + zwp_linux_buffer_params_v1_set_sampling_device(params, &dev); + wl_array_release(&dev); + } + for (int i = 0; i < image->base.num_planes; i++) { zwp_linux_buffer_params_v1_add(params, image->base.dma_buf_fd,