vulkan/wsi/wayland: add default dma-buf feedback support
This bumps the supported dma-buf version up to 4 and adds default dma-buf feedback support. It follows the changes in the dma-buf protocol extension to include dma-buf feedback. From version 4 onwards, the dma-buf modifier events are not sent by the compositor anymore, so we use the default feedback to pick the set of formats/modifiers supported by the compositor. In the next commit we add support for per-surface feedback. Reviewed-by: Simon Ser <contact@emersion.fr> Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12226>
This commit is contained in:

committed by
Marge Bot

parent
947a465cee
commit
edd3c00d5d
@@ -46,6 +46,7 @@
|
||||
#include <util/hash_table.h>
|
||||
#include <util/timespec.h>
|
||||
#include <util/u_vector.h>
|
||||
#include <util/u_dynarray.h>
|
||||
#include <util/anon_file.h>
|
||||
|
||||
struct wsi_wayland;
|
||||
@@ -56,6 +57,28 @@ struct wsi_wl_format {
|
||||
struct u_vector modifiers;
|
||||
};
|
||||
|
||||
struct dmabuf_feedback_format_table {
|
||||
unsigned int size;
|
||||
struct {
|
||||
uint32_t format;
|
||||
uint32_t padding; /* unused */
|
||||
uint64_t modifier;
|
||||
} *data;
|
||||
};
|
||||
|
||||
struct dmabuf_feedback_tranche {
|
||||
dev_t target_device;
|
||||
uint32_t flags;
|
||||
struct u_vector formats;
|
||||
};
|
||||
|
||||
struct dmabuf_feedback {
|
||||
dev_t main_device;
|
||||
struct dmabuf_feedback_format_table format_table;
|
||||
struct util_dynarray tranches;
|
||||
struct dmabuf_feedback_tranche pending_tranche;
|
||||
};
|
||||
|
||||
struct wsi_wl_display {
|
||||
/* The real wl_display */
|
||||
struct wl_display *wl_display;
|
||||
@@ -65,6 +88,9 @@ struct wsi_wl_display {
|
||||
|
||||
struct wl_shm *wl_shm;
|
||||
struct zwp_linux_dmabuf_v1 *wl_dmabuf;
|
||||
struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback;
|
||||
|
||||
struct dmabuf_feedback_format_table format_table;
|
||||
|
||||
struct wsi_wayland *wsi_wl;
|
||||
|
||||
@@ -504,6 +530,12 @@ dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
|
||||
struct wsi_wl_display *display = data;
|
||||
uint64_t modifier;
|
||||
|
||||
/* Ignore this if the compositor advertised dma-buf feedback. From version 4
|
||||
* onwards (when dma-buf feedback was introduced), the compositor should not
|
||||
* advertise this event anymore, but let's keep this for safety. */
|
||||
if (display->wl_dmabuf_feedback)
|
||||
return;
|
||||
|
||||
modifier = ((uint64_t) modifier_hi << 32) | modifier_lo;
|
||||
wsi_wl_display_add_drm_format_modifier(display, &display->formats,
|
||||
format, modifier);
|
||||
@@ -514,6 +546,155 @@ static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
|
||||
dmabuf_handle_modifier,
|
||||
};
|
||||
|
||||
static void
|
||||
dmabuf_feedback_format_table_fini(struct dmabuf_feedback_format_table *format_table)
|
||||
{
|
||||
if (format_table->data && format_table->data != MAP_FAILED)
|
||||
munmap(format_table->data, format_table->size);
|
||||
}
|
||||
|
||||
static void
|
||||
dmabuf_feedback_format_table_init(struct dmabuf_feedback_format_table *format_table)
|
||||
{
|
||||
memset(format_table, 0, sizeof(*format_table));
|
||||
}
|
||||
|
||||
static void
|
||||
dmabuf_feedback_tranche_fini(struct dmabuf_feedback_tranche *tranche)
|
||||
{
|
||||
struct wsi_wl_format *format;
|
||||
|
||||
u_vector_foreach(format, &tranche->formats)
|
||||
u_vector_finish(&format->modifiers);
|
||||
|
||||
u_vector_finish(&tranche->formats);
|
||||
}
|
||||
|
||||
static int
|
||||
dmabuf_feedback_tranche_init(struct dmabuf_feedback_tranche *tranche)
|
||||
{
|
||||
memset(tranche, 0, sizeof(*tranche));
|
||||
|
||||
if (!u_vector_init(&tranche->formats, 8, sizeof(struct wsi_wl_format)))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dmabuf_feedback_fini(struct dmabuf_feedback *dmabuf_feedback)
|
||||
{
|
||||
dmabuf_feedback_tranche_fini(&dmabuf_feedback->pending_tranche);
|
||||
|
||||
util_dynarray_foreach(&dmabuf_feedback->tranches,
|
||||
struct dmabuf_feedback_tranche, tranche)
|
||||
dmabuf_feedback_tranche_fini(tranche);
|
||||
util_dynarray_fini(&dmabuf_feedback->tranches);
|
||||
|
||||
dmabuf_feedback_format_table_fini(&dmabuf_feedback->format_table);
|
||||
}
|
||||
|
||||
static int
|
||||
dmabuf_feedback_init(struct dmabuf_feedback *dmabuf_feedback)
|
||||
{
|
||||
memset(dmabuf_feedback, 0, sizeof(*dmabuf_feedback));
|
||||
|
||||
if (dmabuf_feedback_tranche_init(&dmabuf_feedback->pending_tranche) < 0)
|
||||
return -1;
|
||||
|
||||
util_dynarray_init(&dmabuf_feedback->tranches, NULL);
|
||||
|
||||
dmabuf_feedback_format_table_init(&dmabuf_feedback->format_table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct wsi_wl_display *display = data;
|
||||
|
||||
display->format_table.size = size;
|
||||
display->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)
|
||||
{
|
||||
/* ignore this event */
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct wsi_wl_display *display = data;
|
||||
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)
|
||||
return;
|
||||
|
||||
wl_array_for_each(index, indices) {
|
||||
format = display->format_table.data[*index].format;
|
||||
modifier = display->format_table.data[*index].modifier;
|
||||
wsi_wl_display_add_drm_format_modifier(display, &display->formats,
|
||||
format, modifier);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
shm_handle_format(void *data, struct wl_shm *shm, uint32_t format)
|
||||
{
|
||||
@@ -542,7 +723,8 @@ 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, 3);
|
||||
wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface,
|
||||
MIN2(version, ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION));
|
||||
zwp_linux_dmabuf_v1_add_listener(display->wl_dmabuf,
|
||||
&dmabuf_listener, display);
|
||||
}
|
||||
@@ -626,6 +808,16 @@ wsi_wl_display_init(struct wsi_wayland *wsi_wl,
|
||||
if (!get_format_list)
|
||||
goto out;
|
||||
|
||||
/* 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);
|
||||
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,
|
||||
&dmabuf_feedback_listener, display);
|
||||
}
|
||||
|
||||
/* Round-trip again to get formats and modifiers */
|
||||
wl_display_roundtrip_queue(display->wl_display, display->queue);
|
||||
|
||||
@@ -647,6 +839,13 @@ out:
|
||||
/* We don't need this anymore */
|
||||
wl_registry_destroy(registry);
|
||||
|
||||
/* Destroy default dma-buf feedback object and format table */
|
||||
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);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail_registry:
|
||||
|
Reference in New Issue
Block a user