diff --git a/video/out/opengl/context_wayland.c b/video/out/opengl/context_wayland.c index eeaeb11cc151d..595dcad217cf2 100644 --- a/video/out/opengl/context_wayland.c +++ b/video/out/opengl/context_wayland.c @@ -63,10 +63,9 @@ static bool wayland_egl_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_ { struct ra_ctx *ctx = sw->ctx; struct vo_wayland_state *wl = ctx->vo->wl; - bool render = wl->render || wl->opts->disable_vsync; wl->frame_wait = true; - return render ? ra_gl_ctx_start_frame(sw, out_fbo) : false; + return wl->suspended ? false : ra_gl_ctx_start_frame(sw, out_fbo); } static void wayland_egl_swap_buffers(struct ra_swapchain *sw) diff --git a/video/out/vo_wlshm.c b/video/out/vo_wlshm.c index 69cfdd9dccca8..5288a61221e28 100644 --- a/video/out/vo_wlshm.c +++ b/video/out/vo_wlshm.c @@ -218,10 +218,9 @@ static void draw_image(struct vo *vo, struct mp_image *src) struct priv *p = vo->priv; struct vo_wayland_state *wl = vo->wl; struct buffer *buf; - bool render = wl->render || wl->opts->disable_vsync; wl->frame_wait = true; - if (!render) + if (wl->suspended) return; buf = p->free_buffers; diff --git a/video/out/vulkan/context_wayland.c b/video/out/vulkan/context_wayland.c index d711a855c4798..0bbe2369e4b60 100644 --- a/video/out/vulkan/context_wayland.c +++ b/video/out/vulkan/context_wayland.c @@ -32,10 +32,8 @@ struct priv { static bool wayland_vk_start_frame(struct ra_ctx *ctx) { struct vo_wayland_state *wl = ctx->vo->wl; - bool render = wl->render || wl->opts->disable_vsync; wl->frame_wait = true; - - return render; + return !wl->suspended; } static void wayland_vk_swap_buffers(struct ra_ctx *ctx) diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 850c8d362d4dd..739d45f2d88c8 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -30,17 +30,12 @@ #include "win_state.h" #include "wayland_common.h" -// Generated from xdg-shell.xml -#include "generated/wayland/xdg-shell.h" - -// Generated from idle-inhibit-unstable-v1.xml +// Generated from wayland-protocols #include "generated/wayland/idle-inhibit-unstable-v1.h" - -// Generated from xdg-decoration-unstable-v1.xml -#include "generated/wayland/xdg-decoration-unstable-v1.h" - -// Generated from presentation-time.xml #include "generated/wayland/presentation-time.h" +#include "generated/wayland/surface-suspension.h" +#include "generated/wayland/xdg-decoration-unstable-v1.h" +#include "generated/wayland/xdg-shell.h" #define OPT_BASE_STRUCT struct wayland_opts const struct m_sub_options wayland_conf = { @@ -1013,6 +1008,27 @@ static const struct wl_callback_listener frame_listener = { frame_callback, }; +static void surface_suspended(void *data, struct wp_surface_suspension_v1 *surface_suspension) +{ + struct vo_wayland_state *wl = data; + wl->suspended = true; +} + +static void surface_resumed(void *data, struct wp_surface_suspension_v1 *surface_suspension) +{ + struct vo_wayland_state *wl = data; + wl->suspended = false; + + /* If the surface comes back into view, force a redraw. */ + vo_wayland_wait_frame(wl); + wl->pending_vo_events |= VO_EVENT_EXPOSE; +} + +static const struct wp_surface_suspension_v1_listener surface_suspension_listener = { + surface_suspended, + surface_resumed, +}; + static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id, const char *interface, uint32_t ver) { @@ -1026,6 +1042,10 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id wl_surface_add_listener(wl->surface, &surface_listener, wl); } + 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); + } + if (!strcmp(interface, wl_output_interface.name) && (ver >= 2) && found++) { struct vo_wayland_output *output = talloc_zero(wl, struct vo_wayland_output); @@ -1038,12 +1058,6 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id wl_list_insert(&wl->output_list, &output->link); } - if (!strcmp(interface, xdg_wm_base_interface.name) && found++) { - ver = MPMIN(ver, 2); /* We can use either 1 or 2 */ - wl->wm_base = wl_registry_bind(reg, id, &xdg_wm_base_interface, ver); - xdg_wm_base_add_listener(wl->wm_base, &xdg_wm_base_listener, wl); - } - if (!strcmp(interface, wl_seat_interface.name) && found++) { wl->seat = wl_registry_bind(reg, id, &wl_seat_interface, 1); wl_seat_add_listener(wl->seat, &seat_listener, wl); @@ -1053,17 +1067,24 @@ 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 (!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); + 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); } - if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name) && found++) { - wl->xdg_decoration_manager = wl_registry_bind(reg, id, &zxdg_decoration_manager_v1_interface, 1); + if (!strcmp(interface, wp_surface_suspension_manager_v1_interface.name) && found++) { + wl->surface_suspension_manager = wl_registry_bind(reg, id, &wp_surface_suspension_manager_v1_interface, 1); } - 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); + if (!strcmp(interface, xdg_wm_base_interface.name) && found++) { + ver = MPMIN(ver, 2); /* We can use either 1 or 2 */ + wl->wm_base = wl_registry_bind(reg, id, &xdg_wm_base_interface, ver); + xdg_wm_base_add_listener(wl->wm_base, &xdg_wm_base_listener, wl); + } + + + if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name) && found++) { + wl->xdg_decoration_manager = wl_registry_bind(reg, id, &zxdg_decoration_manager_v1_interface, 1); } if (!strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) && found++) { @@ -1178,12 +1199,6 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, { wl->focused = !wl->focused; wl->pending_vo_events |= VO_EVENT_FOCUS; - - if (wl->activated) { - /* If the surface comes back into view, force a redraw. */ - vo_wayland_wait_frame(wl); - wl->pending_vo_events |= VO_EVENT_EXPOSE; - } } } @@ -1363,6 +1378,14 @@ int vo_wayland_init(struct vo *vo) wp_presentation_interface.name); } + if (wl->surface_suspension_manager) { + wl->surface_suspension = wp_surface_suspension_manager_v1_get_surface_suspension(wl->surface_suspension_manager, wl->surface); + wp_surface_suspension_v1_add_listener(wl->surface_suspension, &surface_suspension_listener, wl); + } else { + MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", + wp_surface_suspension_manager_v1_interface.name); + } + if (wl->xdg_decoration_manager) { wl->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(wl->xdg_decoration_manager, wl->xdg_toplevel); set_border_decorations(wl, wl->vo_opts->border); @@ -1453,6 +1476,12 @@ void vo_wayland_uninit(struct vo *vo) if (wl->surface) wl_surface_destroy(wl->surface); + if (wl->surface_suspension) + wp_surface_suspension_v1_destroy(wl->surface_suspension); + + if (wl->surface_suspension_manager) + wp_surface_suspension_manager_v1_destroy(wl->surface_suspension_manager); + if (wl->frame_callback) wl_callback_destroy(wl->frame_callback); @@ -1933,22 +1962,6 @@ void vo_wayland_wait_frame(struct vo_wayland_state *wl) * that this wait is accurate. Do a hacky block with wl_display_roundtrip. */ if (!wl->presentation && !wl_display_get_error(wl->display)) wl_display_roundtrip(wl->display); - - if (wl->frame_wait) { - // Only consider consecutive missed callbacks. - if (wl->timeout_count > 1) { - wl->render = false; - return; - } else { - wl->timeout_count += 1; - wl->render = true; - return; - } - } - - wl->timeout_count = 0; - wl->render = true; - return; } void vo_wayland_wait_events(struct vo *vo, int64_t until_time_us) diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index bbdfdf82d2e50..38aa99358a5e3 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -73,14 +73,13 @@ struct vo_wayland_state { int gcd; int reduced_width; int reduced_height; + bool activated; + bool focused; bool frame_wait; - bool render; + bool has_keyboard_input; bool state_change; + bool suspended; bool toplevel_configured; - bool activated; - bool has_keyboard_input; - bool focused; - int timeout_count; int wakeup_pipe[2]; int pending_vo_events; int mouse_x; @@ -104,6 +103,8 @@ struct vo_wayland_state { struct xdg_surface *xdg_surface; struct wp_presentation *presentation; struct wp_presentation_feedback *feedback; + struct wp_surface_suspension_v1 *surface_suspension; + struct wp_surface_suspension_manager_v1 *surface_suspension_manager; struct zxdg_decoration_manager_v1 *xdg_decoration_manager; struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration; struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; diff --git a/wscript b/wscript index 1a5ff5aa650be..a4d7b6f77aa7c 100644 --- a/wscript +++ b/wscript @@ -498,6 +498,7 @@ video_output_features = [ 'desc': 'wayland-scanner', 'func': check_program('wayland-scanner', 'WAYSCAN') } , { + #TODO: add a version check here for whenever the protocol gets merged 'name': '--wayland-protocols', 'desc': 'wayland-protocols', 'func': check_wl_protocols diff --git a/wscript_build.py b/wscript_build.py index fbec5006f8c3e..8dced8c8c0fa2 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -109,6 +109,12 @@ def build(ctx): ctx.wayland_protocol_header(proto_dir = ctx.env.WL_PROTO_DIR, protocol = "stable/xdg-shell/xdg-shell", target = "generated/wayland/xdg-shell.h") + ctx.wayland_protocol_code(proto_dir = ctx.env.WL_PROTO_DIR, + protocol = "staging/surface-suspension/surface-suspension-v1", + target = "generated/wayland/surface-suspension.c") + ctx.wayland_protocol_header(proto_dir = ctx.env.WL_PROTO_DIR, + protocol = "staging/surface-suspension/surface-suspension-v1", + target = "generated/wayland/surface-suspension.h") ctx.wayland_protocol_code(proto_dir = ctx.env.WL_PROTO_DIR, protocol = "unstable/idle-inhibit/idle-inhibit-unstable-v1", target = "generated/wayland/idle-inhibit-unstable-v1.c") @@ -515,6 +521,7 @@ def swift(task): ( "video/out/w32_common.c", "win32-desktop" ), ( "generated/wayland/idle-inhibit-unstable-v1.c", "wayland" ), ( "generated/wayland/presentation-time.c", "wayland" ), + ( "generated/wayland/surface-suspension.c", "wayland" ), ( "generated/wayland/xdg-decoration-unstable-v1.c", "wayland" ), ( "generated/wayland/xdg-shell.c", "wayland" ), ( "video/out/wayland_common.c", "wayland" ),