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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2393>
This commit is contained in:
Jonas Ådahl 2022-04-29 16:05:50 +02:00 committed by Marge Bot
parent c5410b61d2
commit b1be1e86e9
4 changed files with 85 additions and 6 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;
};
@ -127,9 +128,11 @@ sync_cursor_state (MetaScreenCastVirtualStreamSrc *virtual_src)
static void
pointer_position_invalidated (MetaCursorTracker *cursor_tracker,
MetaScreenCastVirtualStreamSrc *virtual_src)
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);

View File

@ -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: