wayland: Use per-view & per-frame list of pending presentation feedbacks
Instead of a single hash table with a list of feedbacks per stage view, there's a nested hash table per stage view with a list of feedbacks per view frame counter. This ensures that presentation feedbacks don't get mixed up between different frames. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3937 v2: * Use ClutterFrame(Info)::frame_count. (Jonas Ådahl) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4306>
This commit is contained in:
parent
34b203ed99
commit
903f6281f9
@ -97,9 +97,11 @@ meta_hw_cursor_inhibitor_default_init (MetaHwCursorInhibitorInterface *iface)
|
||||
void
|
||||
meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
ClutterStageView *stage_view)
|
||||
ClutterStageView *stage_view,
|
||||
int64_t view_frame_counter)
|
||||
{
|
||||
g_signal_emit (renderer, signals[CURSOR_PAINTED], 0, cursor_sprite, stage_view);
|
||||
g_signal_emit (renderer, signals[CURSOR_PAINTED], 0, cursor_sprite,
|
||||
stage_view, view_frame_counter);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -203,7 +205,8 @@ meta_cursor_renderer_after_paint (ClutterStage *stage,
|
||||
{
|
||||
meta_cursor_renderer_emit_painted (renderer,
|
||||
priv->displayed_cursor,
|
||||
stage_view);
|
||||
stage_view,
|
||||
frame->frame_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -331,9 +334,10 @@ meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 2,
|
||||
G_TYPE_NONE, 3,
|
||||
G_TYPE_POINTER,
|
||||
CLUTTER_TYPE_STAGE_VIEW);
|
||||
CLUTTER_TYPE_STAGE_VIEW,
|
||||
G_TYPE_INT64);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -70,7 +70,8 @@ graphene_rect_t meta_cursor_renderer_calculate_rect (MetaCursorRenderer *rendere
|
||||
|
||||
void meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
ClutterStageView *stage_view);
|
||||
ClutterStageView *stage_view,
|
||||
int64_t view_frame_counter);
|
||||
ClutterInputDevice * meta_cursor_renderer_get_input_device (MetaCursorRenderer *renderer);
|
||||
|
||||
void meta_cursor_renderer_update_stage_overlay (MetaCursorRenderer *renderer,
|
||||
|
@ -248,7 +248,8 @@ meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_rend
|
||||
{
|
||||
meta_cursor_renderer_emit_painted (cursor_renderer,
|
||||
cursor_sprite,
|
||||
CLUTTER_STAGE_VIEW (view));
|
||||
CLUTTER_STAGE_VIEW (view),
|
||||
frame->frame_count);
|
||||
cursor_stage_view->needs_emit_painted = FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -491,6 +491,7 @@ static void
|
||||
on_cursor_painted (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *displayed_sprite,
|
||||
ClutterStageView *stage_view,
|
||||
int64_t view_frame_counter,
|
||||
MetaWaylandCursorSurface *cursor_surface)
|
||||
{
|
||||
MetaWaylandCursorSurfacePrivate *priv =
|
||||
@ -519,6 +520,7 @@ on_cursor_painted (MetaCursorRenderer *renderer,
|
||||
|
||||
meta_wayland_presentation_time_cursor_painted (&compositor->presentation_time,
|
||||
stage_view,
|
||||
view_frame_counter,
|
||||
cursor_surface);
|
||||
}
|
||||
|
||||
|
@ -56,9 +56,11 @@ void meta_wayland_presentation_feedback_present (MetaWaylandPresentationFeedback
|
||||
ClutterFrameInfo *frame_info,
|
||||
MetaWaylandOutput *output);
|
||||
|
||||
struct wl_list * meta_wayland_presentation_time_ensure_feedbacks (MetaWaylandPresentationTime *presentation_time,
|
||||
ClutterStageView *stage_view);
|
||||
void meta_wayland_presentation_time_present_feedbacks (MetaWaylandCompositor *compositor,
|
||||
ClutterStageView *stage_view,
|
||||
ClutterFrameInfo *frame_info);
|
||||
|
||||
void meta_wayland_presentation_time_cursor_painted (MetaWaylandPresentationTime *presentation_time,
|
||||
ClutterStageView *stage_view,
|
||||
int64_t view_frame_counter,
|
||||
MetaWaylandCursorSurface *cursor_surface);
|
||||
|
@ -111,6 +111,11 @@ wp_presentation_bind (struct wl_client *client,
|
||||
wp_presentation_send_clock_id (resource, CLOCK_MONOTONIC);
|
||||
}
|
||||
|
||||
static struct wl_list *
|
||||
meta_wayland_presentation_time_ensure_feedbacks (MetaWaylandPresentationTime *presentation_time,
|
||||
ClutterStageView *stage_view,
|
||||
int64_t view_frame_counter);
|
||||
|
||||
static void
|
||||
discard_non_cursor_feedbacks (struct wl_list *feedbacks)
|
||||
{
|
||||
@ -146,7 +151,7 @@ on_after_paint (ClutterStage *stage,
|
||||
*/
|
||||
feedbacks =
|
||||
meta_wayland_presentation_time_ensure_feedbacks (&compositor->presentation_time,
|
||||
stage_view);
|
||||
stage_view, frame->frame_count);
|
||||
discard_non_cursor_feedbacks (feedbacks);
|
||||
|
||||
l = compositor->presentation_time.feedback_surfaces;
|
||||
@ -229,7 +234,8 @@ meta_wayland_init_presentation_time (MetaWaylandCompositor *compositor)
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
|
||||
compositor->presentation_time.feedbacks =
|
||||
g_hash_table_new_full (NULL, NULL, NULL, destroy_feedback_list);
|
||||
g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) g_hash_table_destroy);
|
||||
|
||||
g_signal_connect (monitor_manager, "monitors-changed-internal",
|
||||
G_CALLBACK (on_monitors_changed), compositor);
|
||||
@ -390,27 +396,93 @@ meta_wayland_presentation_feedback_present (MetaWaylandPresentationFeedback *fee
|
||||
wl_resource_destroy (feedback->resource);
|
||||
}
|
||||
|
||||
struct wl_list *
|
||||
static struct wl_list *
|
||||
meta_wayland_presentation_time_ensure_feedbacks (MetaWaylandPresentationTime *presentation_time,
|
||||
ClutterStageView *stage_view)
|
||||
ClutterStageView *stage_view,
|
||||
int64_t view_frame_counter)
|
||||
{
|
||||
if (!g_hash_table_contains (presentation_time->feedbacks, stage_view))
|
||||
GHashTable *hash_table;
|
||||
struct wl_list *list;
|
||||
|
||||
hash_table = g_hash_table_lookup (presentation_time->feedbacks, stage_view);
|
||||
if (!hash_table)
|
||||
{
|
||||
struct wl_list *list;
|
||||
|
||||
list = g_new0 (struct wl_list, 1);
|
||||
wl_list_init (list);
|
||||
g_hash_table_insert (presentation_time->feedbacks, stage_view, list);
|
||||
|
||||
return list;
|
||||
hash_table = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free,
|
||||
destroy_feedback_list);
|
||||
g_hash_table_insert (presentation_time->feedbacks, stage_view, hash_table);
|
||||
}
|
||||
|
||||
return g_hash_table_lookup (presentation_time->feedbacks, stage_view);
|
||||
list = g_hash_table_lookup (hash_table, &view_frame_counter);
|
||||
if (!list)
|
||||
{
|
||||
int64_t *key;
|
||||
|
||||
key = g_new (int64_t, 1);
|
||||
*key = view_frame_counter;
|
||||
list = g_new0 (struct wl_list, 1);
|
||||
wl_list_init (list);
|
||||
g_hash_table_insert (hash_table, key, list);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static MetaWaylandOutput *
|
||||
get_output_for_stage_view (MetaWaylandCompositor *compositor,
|
||||
ClutterStageView *stage_view)
|
||||
{
|
||||
MetaCrtc *crtc;
|
||||
MetaOutput *output;
|
||||
MetaMonitor *monitor;
|
||||
|
||||
crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (stage_view));
|
||||
|
||||
/*
|
||||
* All outputs occupy the same region of the screen, as their contents are
|
||||
* the same, so pick the first one.
|
||||
*/
|
||||
output = meta_crtc_get_outputs (crtc)->data;
|
||||
|
||||
monitor = meta_output_get_monitor (output);
|
||||
return g_hash_table_lookup (compositor->outputs,
|
||||
meta_monitor_get_spec (monitor));
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_presentation_time_present_feedbacks (MetaWaylandCompositor *compositor,
|
||||
ClutterStageView *stage_view,
|
||||
ClutterFrameInfo *frame_info)
|
||||
{
|
||||
MetaWaylandPresentationFeedback *feedback, *next;
|
||||
struct wl_list *feedbacks;
|
||||
MetaWaylandOutput *output;
|
||||
GHashTable *hash_table;
|
||||
|
||||
hash_table = g_hash_table_lookup (compositor->presentation_time.feedbacks,
|
||||
stage_view);
|
||||
if (!hash_table)
|
||||
return;
|
||||
|
||||
feedbacks = g_hash_table_lookup (hash_table, &frame_info->view_frame_counter);
|
||||
if (!feedbacks)
|
||||
return;
|
||||
|
||||
output = get_output_for_stage_view (compositor, stage_view);
|
||||
|
||||
wl_list_for_each_safe (feedback, next, feedbacks, link)
|
||||
{
|
||||
meta_wayland_presentation_feedback_present (feedback,
|
||||
frame_info,
|
||||
output);
|
||||
}
|
||||
|
||||
g_hash_table_remove (hash_table, &frame_info->view_frame_counter);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_presentation_time_cursor_painted (MetaWaylandPresentationTime *presentation_time,
|
||||
ClutterStageView *stage_view,
|
||||
int64_t view_frame_counter,
|
||||
MetaWaylandCursorSurface *cursor_surface)
|
||||
{
|
||||
struct wl_list *feedbacks;
|
||||
@ -420,7 +492,8 @@ meta_wayland_presentation_time_cursor_painted (MetaWaylandPresentationTime *pres
|
||||
|
||||
feedbacks =
|
||||
meta_wayland_presentation_time_ensure_feedbacks (presentation_time,
|
||||
stage_view);
|
||||
stage_view,
|
||||
view_frame_counter);
|
||||
|
||||
/* Discard previous feedbacks for this cursor as now it has gone stale. */
|
||||
wl_list_for_each_safe (feedback, next, feedbacks, link)
|
||||
|
@ -538,49 +538,15 @@ meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
||||
meta_wayland_seat_update (compositor->seat, event);
|
||||
}
|
||||
|
||||
static MetaWaylandOutput *
|
||||
get_output_for_stage_view (MetaWaylandCompositor *compositor,
|
||||
ClutterStageView *stage_view)
|
||||
{
|
||||
MetaCrtc *crtc;
|
||||
MetaOutput *output;
|
||||
MetaMonitor *monitor;
|
||||
|
||||
crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (stage_view));
|
||||
|
||||
/*
|
||||
* All outputs occupy the same region of the screen, as their contents are
|
||||
* the same, so pick the first one.
|
||||
*/
|
||||
output = meta_crtc_get_outputs (crtc)->data;
|
||||
|
||||
monitor = meta_output_get_monitor (output);
|
||||
return g_hash_table_lookup (compositor->outputs,
|
||||
meta_monitor_get_spec (monitor));
|
||||
}
|
||||
|
||||
static void
|
||||
on_presented (ClutterStage *stage,
|
||||
ClutterStageView *stage_view,
|
||||
ClutterFrameInfo *frame_info,
|
||||
MetaWaylandCompositor *compositor)
|
||||
{
|
||||
MetaWaylandPresentationFeedback *feedback, *next;
|
||||
struct wl_list *feedbacks;
|
||||
MetaWaylandOutput *output;
|
||||
|
||||
feedbacks =
|
||||
meta_wayland_presentation_time_ensure_feedbacks (&compositor->presentation_time,
|
||||
stage_view);
|
||||
|
||||
output = get_output_for_stage_view (compositor, stage_view);
|
||||
|
||||
wl_list_for_each_safe (feedback, next, feedbacks, link)
|
||||
{
|
||||
meta_wayland_presentation_feedback_present (feedback,
|
||||
frame_info,
|
||||
output);
|
||||
}
|
||||
meta_wayland_presentation_time_present_feedbacks (compositor,
|
||||
stage_view,
|
||||
frame_info);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
x
Reference in New Issue
Block a user