summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Gil Peyrot <linkmauve@linkmauve.fr>2022-07-07 12:03:21 +0200
committerDudemanguy <random342@airmail.cc>2022-10-26 18:41:47 +0000
commit666cb91cf12a4f8b42087530104513b0fc4ba16d (patch)
treed4a0f88472c64a4c20fe77d2b0cff232e03df0db
parentaeb4792cb6804a78974faa329a9c9f8a7bb5fa7b (diff)
downloadmpv-666cb91cf12a4f8b42087530104513b0fc4ba16d.tar.bz2
mpv-666cb91cf12a4f8b42087530104513b0fc4ba16d.tar.xz
wayland: bump dmabuf protocol to version 4
Pulled from https://github.com/mpv-player/mpv/pull/10382 The zwp_linux_dmabuf_v1 protocol version 4 provides a file descriptor containing both formats and modifiers, which makes it possible for the compositor to import the buffers onto planes using explicit modifiers. This is an extremely important efficiency improvement, as the 3D hardware can be left powered off altogether, the vaapi buffer being sent directly from the video hardware to the display controller. It could be possible to support zwp_linux_dmabuf_v1 version 3 as well, but there is no reason beyond compatibility with old stacks. I would recommend to ditch version 2 as well, as modifier-less formats aren’t very useful nowadays.
-rw-r--r--video/out/vo_dmabuf_wayland.c6
-rw-r--r--video/out/wayland_common.c87
-rw-r--r--video/out/wayland_common.h6
3 files changed, 88 insertions, 11 deletions
diff --git a/video/out/vo_dmabuf_wayland.c b/video/out/vo_dmabuf_wayland.c
index f3c1fe36f9..17ead0066d 100644
--- a/video/out/vo_dmabuf_wayland.c
+++ b/video/out/vo_dmabuf_wayland.c
@@ -75,11 +75,11 @@ static bool vaapi_dmabuf_importer(struct mp_image *src, struct wlbuf_pool_entry*
int layer_no = 0;
VAStatus status = vaExportSurfaceHandle(p->display, entry->key, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
VA_EXPORT_SURFACE_COMPOSED_LAYERS | VA_EXPORT_SURFACE_READ_ONLY, &desc);
-
if (status == VA_STATUS_ERROR_INVALID_SURFACE) {
MP_VERBOSE(entry->vo, "VA export to composed layers not supported.\n");
- } else if (!vo_wayland_supported_format(entry->vo, desc.layers[layer_no].drm_format)) {
- MP_VERBOSE(entry->vo, "%s is not supported.\n", mp_tag_str(desc.layers[layer_no].drm_format));
+ } else if (!vo_wayland_supported_format(entry->vo, desc.layers[0].drm_format, desc.objects[0].drm_format_modifier)) {
+ MP_VERBOSE(entry->vo, "%s(%016lx) is not supported.\n",
+ mp_tag_str(desc.layers[0].drm_format), desc.objects[0].drm_format_modifier);
} else if (CHECK_VA_STATUS(entry->vo, "vaExportSurfaceHandle()")) {
entry->drm_format = desc.layers[layer_no].drm_format;
for (int plane_no = 0; plane_no < desc.layers[layer_no].num_planes; ++plane_no) {
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index ba2fba7f78..9c8dd1a6a1 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -1071,14 +1071,68 @@ static void dmabuf_format(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmab
MP_VERBOSE(wl, "%s is supported by the compositor.\n", mp_tag_str(format));
}
-static void dmabuf_modifier(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
- uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo)
+static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
+ dmabuf_format
+};
+
+static void done(void *data,
+ struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1)
{
}
-static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
- dmabuf_format,
- dmabuf_modifier
+static void format_table(void *data,
+ struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
+ int32_t fd,
+ uint32_t size)
+{
+ struct vo_wayland_state *wl = data;
+
+ void *map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ close(fd);
+
+ if (map != MAP_FAILED) {
+ wl->format_map = map;
+ wl->format_size = size;
+ }
+}
+
+static void main_device(void *data,
+ struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
+ struct wl_array *device)
+{
+}
+
+static void tranche_done(void *data,
+ struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1)
+{
+}
+
+static void tranche_target_device(void *data,
+ struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
+ struct wl_array *device)
+{
+}
+
+static void tranche_formats(void *data,
+ struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
+ struct wl_array *indices)
+{
+}
+
+static void tranche_flags(void *data,
+ struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
+ uint32_t flags)
+{
+}
+
+static const struct zwp_linux_dmabuf_feedback_v1_listener dmabuf_feedback_listener = {
+ done,
+ format_table,
+ main_device,
+ tranche_done,
+ tranche_target_device,
+ tranche_formats,
+ tranche_flags,
};
static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id,
@@ -1103,7 +1157,12 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id
wl->subcompositor = wl_registry_bind(reg, id, &wl_subcompositor_interface, 1);
}
- if (!strcmp (interface, zwp_linux_dmabuf_v1_interface.name) && (ver >= 2) && found++) {
+ if (!strcmp (interface, zwp_linux_dmabuf_v1_interface.name) && (ver >= 4) && found++) {
+ wl->dmabuf = wl_registry_bind(reg, id, &zwp_linux_dmabuf_v1_interface, 4);
+ wl->dmabuf_feedback = zwp_linux_dmabuf_v1_get_default_feedback(wl->dmabuf);
+ zwp_linux_dmabuf_feedback_v1_add_listener(wl->dmabuf_feedback, &dmabuf_feedback_listener, wl);
+ }
+ else if (!strcmp (interface, zwp_linux_dmabuf_v1_interface.name) && (ver >= 2) && found++) {
wl->dmabuf = wl_registry_bind(reg, id, &zwp_linux_dmabuf_v1_interface, 2);
zwp_linux_dmabuf_v1_add_listener(wl->dmabuf, &dmabuf_listener, wl);
wl->drm_format_ct_max = 64;
@@ -1964,10 +2023,22 @@ void vo_wayland_set_opaque_region(struct vo_wayland_state *wl, int alpha)
}
}
-bool vo_wayland_supported_format(struct vo *vo, uint32_t drm_format)
+bool vo_wayland_supported_format(struct vo *vo, uint32_t drm_format, uint64_t modifier)
{
struct vo_wayland_state *wl = vo->wl;
+ const struct {
+ uint32_t format;
+ uint32_t padding;
+ uint64_t modifier;
+ } *formats = wl->format_map;
+
+ for (int i = 0; i < wl->format_size / 16; ++i) {
+ if (drm_format == formats[i].format && modifier == formats[i].modifier)
+ return true;
+ }
+
+ /* TODO: remove these once zwp_linux_dmabuf_v1 version 2 support is removed. */
for (int i = 0; i < wl->drm_format_ct; ++i) {
if (drm_format == wl->drm_formats[i])
return true;
@@ -2088,6 +2159,8 @@ void vo_wayland_uninit(struct vo *vo)
wl_display_disconnect(wl->display);
}
+ munmap(wl->format_map, wl->format_size);
+
struct vo_wayland_output *output, *tmp;
wl_list_for_each_safe(output, tmp, &wl->output_list, link)
remove_output(output);
diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h
index 77699a3dd6..fdb745c5d3 100644
--- a/video/out/wayland_common.h
+++ b/video/out/wayland_common.h
@@ -83,6 +83,10 @@ struct vo_wayland_state {
/* linux-dmabuf */
struct zwp_linux_dmabuf_v1 *dmabuf;
+ struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback;
+ void *format_map;
+ uint32_t format_size;
+ /* TODO: remove these once zwp_linux_dmabuf_v1 version 2 support is removed. */
int *drm_formats;
int drm_format_ct;
int drm_format_ct_max;
@@ -138,7 +142,7 @@ struct vo_wayland_state {
};
bool vo_wayland_check_visible(struct vo *vo);
-bool vo_wayland_supported_format(struct vo *vo, uint32_t format);
+bool vo_wayland_supported_format(struct vo *vo, uint32_t format, uint64_t modifier);
int vo_wayland_allocate_memfd(struct vo *vo, size_t size);
int vo_wayland_control(struct vo *vo, int *events, int request, void *arg);