diff options
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> | 2022-07-07 12:03:21 +0200 |
---|---|---|
committer | Dudemanguy <random342@airmail.cc> | 2022-10-26 18:41:47 +0000 |
commit | 666cb91cf12a4f8b42087530104513b0fc4ba16d (patch) | |
tree | d4a0f88472c64a4c20fe77d2b0cff232e03df0db | |
parent | aeb4792cb6804a78974faa329a9c9f8a7bb5fa7b (diff) | |
download | mpv-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.c | 6 | ||||
-rw-r--r-- | video/out/wayland_common.c | 87 | ||||
-rw-r--r-- | video/out/wayland_common.h | 6 |
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); |