summaryrefslogtreecommitdiffstats
path: root/video/out/wayland_common.c
diff options
context:
space:
mode:
authorAaron Boxer <boxerab@protonmail.com>2022-05-18 10:35:53 -0400
committerDudemanguy <random342@airmail.cc>2022-05-24 21:39:34 +0000
commitdefb02daa461200f4de972c57c4ac8dc108feb5f (patch)
tree0f6725f695b3d8be240c71bc1c5e35aacc3fdb8c /video/out/wayland_common.c
parent9022b1b51dc1204760f9d495e7b3b5550f501bf3 (diff)
downloadmpv-defb02daa461200f4de972c57c4ac8dc108feb5f.tar.bz2
mpv-defb02daa461200f4de972c57c4ac8dc108feb5f.tar.xz
vo: add new vaapi-wayland driver
This driver makes use of dmabuffer and viewporter interfaces to enable efficient display of vaapi surfaces, avoiding any unnecessary colour space conversion, and avoiding scaling or colour conversion using GPU shader resources.
Diffstat (limited to 'video/out/wayland_common.c')
-rw-r--r--video/out/wayland_common.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index cd97c77bf6..93a44fde7a 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -32,17 +32,21 @@
#include "osdep/timer.h"
#include "wayland_common.h"
#include "win_state.h"
+#include "drm_common.h"
// Generated from wayland-protocols
#include "generated/wayland/idle-inhibit-unstable-v1.h"
#include "generated/wayland/presentation-time.h"
#include "generated/wayland/xdg-decoration-unstable-v1.h"
#include "generated/wayland/xdg-shell.h"
+#include "generated/wayland/linux-dmabuf-unstable-v1.h"
+#include "generated/wayland/viewporter.h"
#if WAYLAND_VERSION_MAJOR > 1 || WAYLAND_VERSION_MINOR >= 20
#define HAVE_WAYLAND_1_20
#endif
+
static const struct mp_keymap keymap[] = {
/* Special keys */
{XKB_KEY_Pause, MP_KEY_PAUSE}, {XKB_KEY_Escape, MP_KEY_ESC},
@@ -1039,6 +1043,41 @@ static const struct wl_callback_listener frame_listener = {
frame_callback,
};
+static void dmabuf_format(void *data,
+ struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format) {
+ struct vo_wayland_state *wl = data;
+
+ if (wl->drm_format_ct == wl->drm_format_ct_max) {
+ wl->drm_format_ct_max *= 2;
+ wl->drm_formats = talloc_realloc(NULL,wl->drm_formats,uint, wl->drm_format_ct_max);
+ }
+ wl->drm_formats[wl->drm_format_ct++] = format;
+ MP_VERBOSE(wl, "%s available\n", drm_format_string(format));
+}
+
+bool vo_wayland_supported_format(struct vo *vo, uint drm_format) {
+ struct vo_wayland_state *wl = vo->wl;
+
+ for (uint i = 0; i < wl->drm_format_ct; ++i) {
+ if (drm_format == wl->drm_formats[i])
+ return true;
+ }
+
+ return false;
+}
+
+/* currently unused */
+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,
+ dmabuf_modifier
+};
+
static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id,
const char *interface, uint32_t ver)
{
@@ -1048,10 +1087,34 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id
if (!strcmp(interface, wl_compositor_interface.name) && (ver >= 4) && found++) {
wl->compositor = wl_registry_bind(reg, id, &wl_compositor_interface, 4);
wl->surface = wl_compositor_create_surface(wl->compositor);
+ wl->video_surface = wl_compositor_create_surface(wl->compositor);
+ /* never accept input events on the video surface */
+ struct wl_region *region = wl_compositor_create_region (wl->compositor);
+ wl_surface_set_input_region (wl->video_surface, region);
+ wl_region_destroy (region);
wl->cursor_surface = wl_compositor_create_surface(wl->compositor);
wl_surface_add_listener(wl->surface, &surface_listener, wl);
}
+ if (!strcmp(interface, wl_subcompositor_interface.name) && (ver >= 1) && found++) {
+ wl->subcompositor = wl_registry_bind(reg, id, &wl_subcompositor_interface, 1);
+ wl->video_subsurface = wl_subcompositor_get_subsurface(wl->subcompositor, wl->video_surface, wl->surface);
+ wl_subsurface_set_desync (wl->video_subsurface);
+ }
+
+ 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;
+ wl->drm_formats = talloc_array(NULL,uint,wl->drm_format_ct_max);
+ }
+
+ if (!strcmp (interface, wp_viewporter_interface.name) && (ver >= 1) && found++) {
+ wl->viewporter = wl_registry_bind (reg, id, &wp_viewporter_interface, 1);
+ wl->viewport = wp_viewporter_get_viewport (wl->viewporter, wl->surface);
+ wl->video_viewport = wp_viewporter_get_viewport (wl->viewporter,wl->video_surface);
+ }
+
if (!strcmp(interface, wl_data_device_manager_interface.name) && (ver >= 3) && found++) {
wl->dnd_devman = wl_registry_bind(reg, id, &wl_data_device_manager_interface, 3);
}
@@ -1938,6 +2001,9 @@ void vo_wayland_uninit(struct vo *vo)
if (wl->compositor)
wl_compositor_destroy(wl->compositor);
+ if (wl->subcompositor)
+ wl_subcompositor_destroy(wl->subcompositor);
+
if (wl->current_output && wl->current_output->output)
wl_output_destroy(wl->current_output->output);
@@ -1980,6 +2046,18 @@ void vo_wayland_uninit(struct vo *vo)
if (wl->registry)
wl_registry_destroy(wl->registry);
+ if (wl->viewporter)
+ wp_viewporter_destroy (wl->viewporter);
+
+ if (wl->viewport)
+ wp_viewport_destroy (wl->viewport);
+
+ if (wl->video_viewport)
+ wp_viewport_destroy (wl->video_viewport);
+
+ if (wl->dmabuf)
+ zwp_linux_dmabuf_v1_destroy (wl->dmabuf);
+
if (wl->seat)
wl_seat_destroy(wl->seat);
@@ -1989,6 +2067,12 @@ void vo_wayland_uninit(struct vo *vo)
if (wl->surface)
wl_surface_destroy(wl->surface);
+ if (wl->video_surface)
+ wl_surface_destroy(wl->video_surface);
+
+ if (wl->video_subsurface)
+ wl_subsurface_destroy(wl->video_subsurface);
+
if (wl->wm_base)
xdg_wm_base_destroy(wl->wm_base);
@@ -2022,6 +2106,8 @@ void vo_wayland_uninit(struct vo *vo)
wl_list_for_each_safe(output, tmp, &wl->output_list, link)
remove_output(output);
+ talloc_free(wl->drm_formats);
+
talloc_free(wl->dnd_mime_type);
for (int n = 0; n < 2; n++)