Skip to content

Commit

Permalink
wayland: add support for content-type protocol
Browse files Browse the repository at this point in the history
The content-type protocol allows mpv to send compositor a hint about the
type of content being displayed on its surface so it could potentially
make some sort of optimization. Fundamentally, this is pretty simple but
since this requires a very new wayland-protocols version (1.27), we have
to mess with the build to add a new define and add a bunch of if's in
here. The protocol itself exposes 4 different types of content: none,
photo, video, and game. For mpv, we of course send video by default but
it is certainly common to view images/photos as well. Additionally,
maybe the compositor is bugged in some way and one would like to turn
this off. In light of that, a new option has also been added
(wayland-content-type) that lets users control what content hint to send
to the compositor. For completion's sake, game is also allowed here, but
in practice there shouldn't ever be a reason to use that.
  • Loading branch information
Dudemanguy committed Oct 16, 2022
1 parent cdcbd73 commit 18a4f6f
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 0 deletions.
5 changes: 5 additions & 0 deletions DOCS/man/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5581,6 +5581,11 @@ 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=<none|photo|video|game>``
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. By default,
``video`` is selected.

``--wayland-disable-vsync=<yes|no>``
Disable mpv's internal vsync for Wayland-based video output (default: no).
This is mainly useful for benchmarking wayland VOs when combined with
Expand Down
5 changes: 5 additions & 0 deletions generated/wayland/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ protocols = [[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml']
wl_protocols_source = []
wl_protocols_headers = []

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',
Expand Down
5 changes: 5 additions & 0 deletions options/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,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, {"none", 0},
{"photo", 1}, {"video", 2}, {"game", 3})},
#endif
#if HAVE_WIN32_DESKTOP
{"vo-mmcss-profile", OPT_STRING(mmcss_profile)},
#endif
Expand Down Expand Up @@ -211,6 +215,7 @@ const struct m_sub_options vo_sub_opts = {
.border = 1,
.fit_border = 1,
.appid = "mpv",
.content_type = 2,
.WinID = -1,
.window_scale = 1.0,
.x11_bypass_compositor = 2,
Expand Down
1 change: 1 addition & 0 deletions options/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
38 changes: 38 additions & 0 deletions video/out/wayland_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1158,6 +1162,12 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id
wl->idle_inhibit_manager = wl_registry_bind(reg, id, &zwp_idle_inhibit_manager_v1_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 (found > 1)
MP_VERBOSE(wl, "Registered for protocol %s\n", interface);
}
Expand Down Expand Up @@ -1427,6 +1437,14 @@ static void remove_output(struct vo_wayland_output *out)
return;
}

static void set_content_type(struct vo_wayland_state *wl)
{
#if HAVE_WAYLAND_PROTOCOLS_1_27
if (wl->content_type_manager)
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;
Expand Down Expand Up @@ -1706,6 +1724,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)
Expand Down Expand Up @@ -1864,6 +1884,16 @@ 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);
set_content_type(wl);
} 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);
Expand Down Expand Up @@ -1997,6 +2027,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);

Expand Down
7 changes: 7 additions & 0 deletions video/out/wayland_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

struct wayland_opts {
int configure_bounds;
int content_type;
int disable_vsync;
int edge_pixels_pointer;
int edge_pixels_touch;
Expand Down Expand Up @@ -77,6 +78,12 @@ struct vo_wayland_state {
int timeout_count;
int wakeup_pipe[2];

#ifdef HAVE_WAYLAND_PROTOCOLS_1_27
/* content-type */
struct wp_content_type_manager_v1 *content_type_manager;
struct wp_content_type_v1 *content_type;
#endif

/* idle-inhibit */
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
Expand Down
5 changes: 5 additions & 0 deletions wscript
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,11 @@ video_output_features = [
'func': check_pkg_config('wayland-client', '>= 1.15.0',
'wayland-cursor', '>= 1.15.0',
'xkbcommon', '>= 0.3.0'),
} , {
'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()",
Expand Down
9 changes: 9 additions & 0 deletions wscript_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down Expand Up @@ -536,6 +544,7 @@ def swift(task):
( "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" ),
Expand Down

0 comments on commit 18a4f6f

Please sign in to comment.