From f0c220046645f3ff01891d2fedf1c79e74bc14b9 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Mon, 12 Oct 2020 14:10:43 +0300 Subject: [PATCH] wayland: Store map of ready presentation feedbacks These are feedbacks for updates that were drawn or otherwise displayed on screen, and need to be fired as soon as their presentation happens. Part-of: --- .../meta-wayland-presentation-time-private.h | 10 ++++ src/wayland/meta-wayland-presentation-time.c | 52 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/wayland/meta-wayland-presentation-time-private.h b/src/wayland/meta-wayland-presentation-time-private.h index 234ac3495..0a1298bbf 100644 --- a/src/wayland/meta-wayland-presentation-time-private.h +++ b/src/wayland/meta-wayland-presentation-time-private.h @@ -39,6 +39,13 @@ typedef struct _MetaWaylandPresentationFeedback typedef struct _MetaWaylandPresentationTime { GList *feedback_surfaces; + + /* + * A mapping from (ClutterStageView *) to a + * (MetaWaylandPresentationFeedback *) wl_list of presentation-time feedbacks + * that are scheduled to be presented. + */ + GHashTable *feedbacks; } MetaWaylandPresentationTime; void meta_wayland_init_presentation_time (MetaWaylandCompositor *compositor); @@ -49,4 +56,7 @@ 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); + #endif /* META_WAYLAND_PRESENTATION_TIME_PRIVATE_H */ diff --git a/src/wayland/meta-wayland-presentation-time.c b/src/wayland/meta-wayland-presentation-time.c index ef74d1150..54351690a 100644 --- a/src/wayland/meta-wayland-presentation-time.c +++ b/src/wayland/meta-wayland-presentation-time.c @@ -111,9 +111,43 @@ wp_presentation_bind (struct wl_client *client, wp_presentation_send_clock_id (resource, CLOCK_MONOTONIC); } +static void +destroy_feedback_list (gpointer data) +{ + struct wl_list *feedbacks = data; + + while (!wl_list_empty (feedbacks)) + { + MetaWaylandPresentationFeedback *feedback = + wl_container_of (feedbacks->next, feedback, link); + + meta_wayland_presentation_feedback_discard (feedback); + } + + g_free (feedbacks); +} + +static void +on_monitors_changed (MetaMonitorManager *manager, + MetaWaylandCompositor *compositor) +{ + /* All ClutterStageViews were re-created, so clear our map. */ + g_hash_table_remove_all (compositor->presentation_time.feedbacks); +} + void meta_wayland_init_presentation_time (MetaWaylandCompositor *compositor) { + MetaBackend *backend = compositor->backend; + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + + compositor->presentation_time.feedbacks = + g_hash_table_new_full (NULL, NULL, NULL, destroy_feedback_list); + + g_signal_connect (monitor_manager, "monitors-changed-internal", + G_CALLBACK (on_monitors_changed), compositor); + if (wl_global_create (compositor->wayland_display, &wp_presentation_interface, META_WP_PRESENTATION_VERSION, @@ -252,3 +286,21 @@ meta_wayland_presentation_feedback_present (MetaWaylandPresentationFeedback *fee wl_resource_destroy (feedback->resource); } + +struct wl_list * +meta_wayland_presentation_time_ensure_feedbacks (MetaWaylandPresentationTime *presentation_time, + ClutterStageView *stage_view) +{ + if (!g_hash_table_contains (presentation_time->feedbacks, stage_view)) + { + 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; + } + + return g_hash_table_lookup (presentation_time->feedbacks, stage_view); +}