vulkan/wsi/wayland: Support wl-dmabuf v6

This commit is contained in:
Victoria Brekenfeld 2024-09-28 13:35:42 +02:00
parent 4266c8a449
commit 378a5ef906

View file

@ -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,