diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index 83a8a17873..13757e8bc1 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -28,6 +28,7 @@ Interface changes --- mpv 0.36.0 --- - add `--force-render` + - add `--wayland-content-type` --- mpv 0.35.0 --- - add the `--vo=gpu-next` video output driver, as well as the options `--allow-delayed-peak-detect`, `--builtin-scalers`, diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 3680cd0297..ed4505fb00 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -5587,6 +5587,12 @@ them. it first renders. This option will take precedence over any ``autofit`` or ``geometry`` type settings if the configure bounds are used. +``--wayland-content-type=`` + If supported by the compositor, mpv will send a hint using the content-type + protocol telling the compositor what type of content is being displayed. ``auto`` + (default) will automatically switch between telling the compositor the content + is a photo, video or possibly none depending on internal heuristics. + ``--wayland-disable-vsync=`` Disable mpv's internal vsync for Wayland-based video output (default: no). This is mainly useful for benchmarking wayland VOs when combined with diff --git a/generated/wayland/meson.build b/generated/wayland/meson.build index 7811f849e9..919a280107 100644 --- a/generated/wayland/meson.build +++ b/generated/wayland/meson.build @@ -10,6 +10,11 @@ wl_protocols_headers = [] features += {'wayland_protocols_1_24': wayland['deps'][2].version().version_compare('>=1.24')} +features += {'wayland_protocols_1_27': wayland['deps'][2].version().version_compare('>=1.27')} +if features['wayland_protocols_1_27'] + protocols += [[wl_protocol_dir, 'staging/content-type/content-type-v1.xml']] +endif + foreach p: protocols xml = join_paths(p) wl_protocols_source += custom_target(xml.underscorify() + '_c', diff --git a/options/options.c b/options/options.c index ad8bde5fc8..8785d78182 100644 --- a/options/options.c +++ b/options/options.c @@ -179,6 +179,10 @@ static const m_option_t mp_vo_opt_list[] = { {"x11-present", OPT_CHOICE(x11_present, {"no", 0}, {"auto", 1}, {"yes", 2})}, #endif +#if HAVE_WAYLAND + {"wayland-content-type", OPT_CHOICE(content_type, {"auto", -1}, {"none", 0}, + {"photo", 1}, {"video", 2}, {"game", 3})}, +#endif #if HAVE_WIN32_DESKTOP {"vo-mmcss-profile", OPT_STRING(mmcss_profile)}, #endif @@ -212,6 +216,7 @@ const struct m_sub_options vo_sub_opts = { .border = 1, .fit_border = 1, .appid = "mpv", + .content_type = -1, .WinID = -1, .window_scale = 1.0, .x11_bypass_compositor = 2, diff --git a/options/options.h b/options/options.h index 2956ade751..5560f40554 100644 --- a/options/options.h +++ b/options/options.h @@ -27,6 +27,7 @@ typedef struct mp_vo_opts { char *fsscreen_name; char *winname; char *appid; + int content_type; int x11_netwm; int x11_bypass_compositor; int x11_present; diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 53854c2465..6efd099ceb 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -42,6 +42,10 @@ #include "generated/wayland/xdg-shell.h" #include "generated/wayland/viewporter.h" +#if HAVE_WAYLAND_PROTOCOLS_1_27 +#include "generated/wayland/content-type-v1.h" +#endif + #if WAYLAND_VERSION_MAJOR > 1 || WAYLAND_VERSION_MINOR >= 20 #define HAVE_WAYLAND_1_20 #endif @@ -1232,6 +1236,12 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id wl->shm = wl_registry_bind(reg, id, &wl_shm_interface, 1); } +#if HAVE_WAYLAND_PROTOCOLS_1_27 + if (!strcmp(interface, wp_content_type_manager_v1_interface.name) && found++) { + wl->content_type_manager = wl_registry_bind(reg, id, &wp_content_type_manager_v1_interface, 1); + } +#endif + if (!strcmp(interface, wp_presentation_interface.name) && found++) { wl->presentation = wl_registry_bind(reg, id, &wp_presentation_interface, 1); wp_presentation_add_listener(wl->presentation, &pres_listener, wl); @@ -1520,6 +1530,20 @@ static void remove_output(struct vo_wayland_output *out) return; } +static void set_content_type(struct vo_wayland_state *wl) +{ + if (!wl->content_type_manager) + return; +#if HAVE_WAYLAND_PROTOCOLS_1_27 + // handle auto; + if (wl->vo_opts->content_type == -1) { + wp_content_type_v1_set_content_type(wl->content_type, wl->current_content_type); + } else { + wp_content_type_v1_set_content_type(wl->content_type, wl->vo_opts->content_type); + } +#endif +} + static int set_cursor_visibility(struct vo_wayland_state *wl, bool on) { wl->cursor_visible = on; @@ -1803,6 +1827,8 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg) &wl->vo_opts->border); } } + if (opt == &opts->content_type) + set_content_type(wl); if (opt == &opts->fullscreen) toggle_fullscreen(wl); if (opt == &opts->hidpi_window_scale) @@ -1825,6 +1851,13 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg) } return VO_TRUE; } + case VOCTRL_CONTENT_TYPE: { +#if HAVE_WAYLAND_PROTOCOLS_1_27 + wl->current_content_type = (enum mp_content_type)arg; + set_content_type(wl); +#endif + return VO_TRUE; + } case VOCTRL_GET_FOCUSED: { *(bool *)arg = wl->focused; return VO_TRUE; @@ -1967,6 +2000,15 @@ int vo_wayland_init(struct vo *vo) if (xdg_current_desktop != NULL && strstr(xdg_current_desktop, "GNOME")) MP_WARN(wl, "GNOME's wayland compositor lacks support for the idle inhibit protocol. This means the screen can blank during playback.\n"); +#if HAVE_WAYLAND_PROTOCOLS_1_27 + if (wl->content_type_manager) { + wl->content_type = wp_content_type_manager_v1_get_surface_content_type(wl->content_type_manager, wl->surface); + } else { + MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", + wp_content_type_manager_v1_interface.name); + } +#endif + if (wl->dnd_devman && wl->seat) { wl->dnd_ddev = wl_data_device_manager_get_data_device(wl->dnd_devman, wl->seat); wl_data_device_add_listener(wl->dnd_ddev, &data_device_listener, wl); @@ -2119,6 +2161,14 @@ void vo_wayland_uninit(struct vo *vo) if (wl->cursor_theme) wl_cursor_theme_destroy(wl->cursor_theme); +#if HAVE_WAYLAND_PROTOCOLS_1_27 + if (wl->content_type) + wp_content_type_v1_destroy(wl->content_type); + + if (wl->content_type_manager) + wp_content_type_manager_v1_destroy(wl->content_type_manager); +#endif + if (wl->dnd_ddev) wl_data_device_destroy(wl->dnd_ddev); diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index 541b4d0d28..627ea0d057 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -24,6 +24,7 @@ struct wayland_opts { int configure_bounds; + int content_type; int disable_vsync; int edge_pixels_pointer; int edge_pixels_touch; @@ -77,6 +78,12 @@ struct vo_wayland_state { int timeout_count; int wakeup_pipe[2]; + /* content-type */ + /* TODO: unvoid these if required wayland protocols is bumped to 1.27+ */ + void *content_type_manager; + void *content_type; + int current_content_type; + /* idle-inhibit */ struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; struct zwp_idle_inhibitor_v1 *idle_inhibitor; diff --git a/wscript b/wscript index e349d4103e..9fc7583225 100644 --- a/wscript +++ b/wscript @@ -535,6 +535,11 @@ video_output_features = [ 'desc': 'wayland-protocols version 1.24+', 'deps': 'wayland', 'func': check_pkg_config('wayland-protocols >= 1.24'), + } , { + 'name': 'wayland-protocols-1-27', + 'desc': 'wayland-protocols version 1.27+', + 'deps': 'wayland', + 'func': check_pkg_config('wayland-protocols >= 1.27'), } , { 'name': 'memfd_create', 'desc': "Linux's memfd_create()", diff --git a/wscript_build.py b/wscript_build.py index 16c8cf0895..1621b94b97 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -140,6 +140,14 @@ def build(ctx): protocol = "stable/viewporter/viewporter", target = "generated/wayland/viewporter.h") + if ctx.dependency_satisfied('wayland-protocols-1-27'): + ctx.wayland_protocol_code(proto_dir = ctx.env.WL_PROTO_DIR, + protocol = "staging/content-type/content-type-v1", + target = "generated/wayland/content-type-v1.c") + ctx.wayland_protocol_header(proto_dir = ctx.env.WL_PROTO_DIR, + protocol = "staging/content-type/content-type-v1", + target = "generated/wayland/content-type-v1.h") + ctx(features = "ebml_header", target = "generated/ebml_types.h") ctx(features = "ebml_definitions", target = "generated/ebml_defs.inc") @@ -540,6 +548,7 @@ def build(ctx): ( "video/out/vulkan/context_xlib.c", "vulkan && x11" ), ( "video/out/vulkan/utils.c", "vulkan" ), ( "video/out/w32_common.c", "win32-desktop" ), + ( "generated/wayland/content-type-v1.c", "wayland-protocols-1-27" ), ( "generated/wayland/idle-inhibit-unstable-v1.c", "wayland" ), ( "generated/wayland/presentation-time.c", "wayland" ), ( "generated/wayland/xdg-decoration-unstable-v1.c", "wayland" ),