From b1be1e86e9b4c365ef971b49d984336c8ad94a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 29 Apr 2022 16:05:50 +0200 Subject: [PATCH] screen-cast: Always wait for an update before sending cursor-only frames With the unthrottled input emission, we ended up often getting the cursor updates long before any damage had been posted, meaning that if you moved around the mouse pointer where the mouse had a high enough refresh rate, we'd effectively stall the screen cast stream by only sending cursor updates and nothing else. Fix this by scheduling an update when we get a cursor update, then sending a cursor-only frame after any damage and relayout has been processed, but only if there is no queued damage that will cause an actual repaint. Part-of: --- .../meta-screen-cast-area-stream-src.c | 19 ++++++++++++- .../meta-screen-cast-monitor-stream-src.c | 20 +++++++++++++- .../meta-screen-cast-virtual-stream-src.c | 25 ++++++++++++++--- .../meta-screen-cast-window-stream-src.c | 27 ++++++++++++++++++- 4 files changed, 85 insertions(+), 6 deletions(-) diff --git a/src/backends/meta-screen-cast-area-stream-src.c b/src/backends/meta-screen-cast-area-stream-src.c index aa1548101..fe376db05 100644 --- a/src/backends/meta-screen-cast-area-stream-src.c +++ b/src/backends/meta-screen-cast-area-stream-src.c @@ -44,6 +44,7 @@ struct _MetaScreenCastAreaStreamSrc gulong position_invalidated_handler_id; gulong cursor_changed_handler_id; + gulong prepare_frame_handler_id; guint maybe_record_idle_id; }; @@ -174,7 +175,9 @@ static void pointer_position_invalidated (MetaCursorTracker *cursor_tracker, MetaScreenCastAreaStreamSrc *area_src) { - sync_cursor_state (area_src); + ClutterStage *stage = get_stage (area_src); + + clutter_stage_schedule_update (stage); } static void @@ -185,6 +188,14 @@ cursor_changed (MetaCursorTracker *cursor_tracker, sync_cursor_state (area_src); } +static void +on_prepare_frame (ClutterStage *stage, + ClutterStageView *stage_view, + MetaScreenCastAreaStreamSrc *area_src) +{ + sync_cursor_state (area_src); +} + static void inhibit_hw_cursor (MetaScreenCastAreaStreamSrc *area_src) { @@ -371,6 +382,10 @@ meta_screen_cast_area_stream_src_enable (MetaScreenCastStreamSrc *src) g_signal_connect_after (cursor_tracker, "cursor-changed", G_CALLBACK (cursor_changed), area_src); + area_src->prepare_frame_handler_id = + g_signal_connect_after (stage, "prepare-frame", + G_CALLBACK (on_prepare_frame), + area_src); meta_cursor_tracker_track_position (cursor_tracker); G_GNUC_FALLTHROUGH; case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: @@ -420,6 +435,8 @@ meta_screen_cast_area_stream_src_disable (MetaScreenCastStreamSrc *src) cursor_tracker); g_clear_signal_handler (&area_src->cursor_changed_handler_id, cursor_tracker); + g_clear_signal_handler (&area_src->prepare_frame_handler_id, + stage); g_clear_handle_id (&area_src->maybe_record_idle_id, g_source_remove); diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c index 307500901..f30a52d1d 100644 --- a/src/backends/meta-screen-cast-monitor-stream-src.c +++ b/src/backends/meta-screen-cast-monitor-stream-src.c @@ -48,6 +48,7 @@ struct _MetaScreenCastMonitorStreamSrc gulong position_invalidated_handler_id; gulong cursor_changed_handler_id; + gulong stage_prepare_frame_handler_id; guint maybe_record_idle_id; }; @@ -269,7 +270,9 @@ static void pointer_position_invalidated (MetaCursorTracker *cursor_tracker, MetaScreenCastMonitorStreamSrc *monitor_src) { - sync_cursor_state (monitor_src); + ClutterStage *stage = get_stage (monitor_src); + + clutter_stage_schedule_update (stage); } static void @@ -280,6 +283,14 @@ cursor_changed (MetaCursorTracker *cursor_tracker, sync_cursor_state (monitor_src); } +static void +on_prepare_frame (ClutterStage *stage, + ClutterStageView *stage_view, + MetaScreenCastMonitorStreamSrc *monitor_src) +{ + sync_cursor_state (monitor_src); +} + static void inhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src) { @@ -402,6 +413,7 @@ meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src) MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); + ClutterStage *stage = get_stage (monitor_src); MetaScreenCastStream *stream; stream = meta_screen_cast_stream_src_get_stream (src); @@ -417,6 +429,10 @@ meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src) g_signal_connect_after (cursor_tracker, "cursor-changed", G_CALLBACK (cursor_changed), monitor_src); + monitor_src->stage_prepare_frame_handler_id = + g_signal_connect_after (stage, "prepare-frame", + G_CALLBACK (on_prepare_frame), + monitor_src); meta_cursor_tracker_track_position (cursor_tracker); break; case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: @@ -465,6 +481,8 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src) cursor_tracker); g_clear_signal_handler (&monitor_src->cursor_changed_handler_id, cursor_tracker); + g_clear_signal_handler (&monitor_src->stage_prepare_frame_handler_id, + stage); g_clear_handle_id (&monitor_src->maybe_record_idle_id, g_source_remove); diff --git a/src/backends/meta-screen-cast-virtual-stream-src.c b/src/backends/meta-screen-cast-virtual-stream-src.c index 3341aedd9..56f9bfaa2 100644 --- a/src/backends/meta-screen-cast-virtual-stream-src.c +++ b/src/backends/meta-screen-cast-virtual-stream-src.c @@ -42,6 +42,7 @@ struct _MetaScreenCastVirtualStreamSrc gulong position_invalidated_handler_id; gulong cursor_changed_handler_id; + gulong prepare_frame_handler_id; gulong monitors_changed_handler_id; }; @@ -126,10 +127,12 @@ sync_cursor_state (MetaScreenCastVirtualStreamSrc *virtual_src) } static void -pointer_position_invalidated (MetaCursorTracker *cursor_tracker, - MetaScreenCastVirtualStreamSrc *virtual_src) +pointer_position_invalidated (MetaCursorTracker *cursor_tracker, + MetaScreenCastStreamSrc *src) { - sync_cursor_state (virtual_src); + ClutterStage *stage = stage_from_src (src); + + clutter_stage_schedule_update (stage); } static void @@ -140,6 +143,14 @@ cursor_changed (MetaCursorTracker *cursor_tracker, sync_cursor_state (virtual_src); } +static void +on_prepare_frame (ClutterStage *stage, + ClutterStageView *stage_view, + MetaScreenCastVirtualStreamSrc *virtual_src) +{ + sync_cursor_state (virtual_src); +} + static void inhibit_hw_cursor (MetaScreenCastVirtualStreamSrc *virtual_src) { @@ -220,6 +231,7 @@ init_record_callbacks (MetaScreenCastVirtualStreamSrc *virtual_src) meta_backend_get_monitor_manager (backend); MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); + ClutterStage *stage = stage_from_src (src); switch (meta_screen_cast_stream_get_cursor_mode (stream)) { @@ -232,6 +244,10 @@ init_record_callbacks (MetaScreenCastVirtualStreamSrc *virtual_src) g_signal_connect_after (cursor_tracker, "cursor-changed", G_CALLBACK (cursor_changed), virtual_src); + virtual_src->prepare_frame_handler_id = + g_signal_connect_after (stage, "prepare-frame", + G_CALLBACK (on_prepare_frame), + virtual_src); G_GNUC_FALLTHROUGH; case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: @@ -284,6 +300,7 @@ meta_screen_cast_virtual_stream_src_disable (MetaScreenCastStreamSrc *src) MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); + ClutterStage *stage = stage_from_src (src); if (virtual_src->hw_cursor_inhibited) uninhibit_hw_cursor (virtual_src); @@ -299,6 +316,8 @@ meta_screen_cast_virtual_stream_src_disable (MetaScreenCastStreamSrc *src) cursor_tracker); g_clear_signal_handler (&virtual_src->cursor_changed_handler_id, cursor_tracker); + g_clear_signal_handler (&virtual_src->prepare_frame_handler_id, + stage); g_clear_signal_handler (&virtual_src->monitors_changed_handler_id, monitor_manager); diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c index 9e77db021..b353a76df 100644 --- a/src/backends/meta-screen-cast-window-stream-src.c +++ b/src/backends/meta-screen-cast-window-stream-src.c @@ -39,6 +39,7 @@ struct _MetaScreenCastWindowStreamSrc gulong screen_cast_window_destroyed_handler_id; gulong position_invalidated_handler_id; gulong cursor_changed_handler_id; + gulong prepare_frame_handler_id; gboolean cursor_bitmap_invalid; }; @@ -59,6 +60,12 @@ get_backend (MetaScreenCastWindowStreamSrc *window_src) return meta_screen_cast_get_backend (screen_cast); } +static ClutterStage * +get_stage (MetaScreenCastWindowStreamSrc *window_src) +{ + return CLUTTER_STAGE (meta_backend_get_stage (get_backend (window_src))); +} + static MetaScreenCastWindowStream * get_window_stream (MetaScreenCastWindowStreamSrc *window_src) { @@ -320,6 +327,7 @@ meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_s MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); MetaBackend *backend = get_backend (window_src); MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); + ClutterStage *stage = get_stage (window_src); if (!window_src->screen_cast_window) return; @@ -332,6 +340,8 @@ meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_s cursor_tracker); g_clear_signal_handler (&window_src->cursor_changed_handler_id, cursor_tracker); + g_clear_signal_handler (&window_src->prepare_frame_handler_id, + stage); switch (meta_screen_cast_stream_get_cursor_mode (stream)) { @@ -380,7 +390,9 @@ static void pointer_position_invalidated (MetaCursorTracker *cursor_tracker, MetaScreenCastWindowStreamSrc *window_src) { - sync_cursor_state (window_src); + ClutterStage *stage = get_stage (window_src); + + clutter_stage_schedule_update (stage); } static void @@ -391,12 +403,21 @@ cursor_changed (MetaCursorTracker *cursor_tracker, sync_cursor_state (window_src); } +static void +on_prepare_frame (ClutterStage *stage, + ClutterStageView *stage_view, + MetaScreenCastWindowStreamSrc *window_src) +{ + sync_cursor_state (window_src); +} + static void meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src) { MetaScreenCastWindowStreamSrc *window_src = META_SCREEN_CAST_WINDOW_STREAM_SRC (src); MetaBackend *backend = get_backend (window_src); + ClutterStage *stage = get_stage (window_src); MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); MetaWindowActor *window_actor; MetaScreenCastStream *stream; @@ -433,6 +454,10 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src) g_signal_connect_after (cursor_tracker, "cursor-changed", G_CALLBACK (cursor_changed), window_src); + window_src->prepare_frame_handler_id = + g_signal_connect_after (stage, "prepare_frame", + G_CALLBACK (on_prepare_frame), + window_src); meta_cursor_tracker_track_position (cursor_tracker); break; case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: