summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2020-10-08 15:34:28 +0300
committerMarge Bot <marge-bot@gnome.org>2021-03-08 09:48:12 +0000
commit2ce3a050f02c3424f35c09cfb90cf80121a9bdb7 (patch)
tree39c8beb28b585224dd57cb4c83d7d248f13afb42
parentf0c220046645f3ff01891d2fedf1c79e74bc14b9 (diff)
downloadmutter-2ce3a050f02c3424f35c09cfb90cf80121a9bdb7.tar.gz
wayland: Wire up presentation-time machinery
- add surfaces to the presentation list, - move their feedbacks to the map in on-after-update, - fire the feedbacks in on_presented(). Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1484>
-rw-r--r--src/wayland/meta-wayland-presentation-time.c69
-rw-r--r--src/wayland/meta-wayland-surface.c6
-rw-r--r--src/wayland/meta-wayland.c48
3 files changed, 120 insertions, 3 deletions
diff --git a/src/wayland/meta-wayland-presentation-time.c b/src/wayland/meta-wayland-presentation-time.c
index 54351690a..be1319fd9 100644
--- a/src/wayland/meta-wayland-presentation-time.c
+++ b/src/wayland/meta-wayland-presentation-time.c
@@ -26,6 +26,7 @@
#include <glib.h>
+#include "compositor/meta-surface-actor-wayland.h"
#include "wayland/meta-wayland-private.h"
#include "wayland/meta-wayland-surface.h"
#include "wayland/meta-wayland-outputs.h"
@@ -112,10 +113,8 @@ wp_presentation_bind (struct wl_client *client,
}
static void
-destroy_feedback_list (gpointer data)
+discard_feedbacks (struct wl_list *feedbacks)
{
- struct wl_list *feedbacks = data;
-
while (!wl_list_empty (feedbacks))
{
MetaWaylandPresentationFeedback *feedback =
@@ -123,7 +122,67 @@ destroy_feedback_list (gpointer data)
meta_wayland_presentation_feedback_discard (feedback);
}
+}
+
+static void
+on_after_paint (ClutterStage *stage,
+ ClutterStageView *stage_view,
+ MetaWaylandCompositor *compositor)
+{
+ struct wl_list *feedbacks;
+ GList *l;
+
+ /*
+ * We just painted this stage view, which means that all feedbacks that didn't
+ * fire (e.g. due to page flip failing) are now obsolete and should be
+ * discarded.
+ */
+ feedbacks =
+ meta_wayland_presentation_time_ensure_feedbacks (&compositor->presentation_time,
+ stage_view);
+ discard_feedbacks (feedbacks);
+
+ l = compositor->presentation_time.feedback_surfaces;
+ while (l)
+ {
+ GList *l_cur = l;
+ MetaWaylandSurface *surface = l->data;
+ MetaSurfaceActor *actor;
+ ClutterStageView *surface_primary_view;
+
+ l = l->next;
+
+ actor = meta_wayland_surface_get_actor (surface);
+ if (!actor)
+ continue;
+
+ surface_primary_view =
+ meta_surface_actor_wayland_get_current_primary_view (actor, stage);
+ if (stage_view != surface_primary_view)
+ continue;
+
+ if (!wl_list_empty (&surface->presentation_time.feedback_list))
+ {
+ /* Add feedbacks to the list to be fired on presentation. */
+ wl_list_insert_list (feedbacks,
+ &surface->presentation_time.feedback_list);
+ wl_list_init (&surface->presentation_time.feedback_list);
+
+ surface->presentation_time.needs_sequence_update = TRUE;
+ }
+
+ compositor->presentation_time.feedback_surfaces =
+ g_list_delete_link (compositor->presentation_time.feedback_surfaces,
+ l_cur);
+ }
+}
+static void
+destroy_feedback_list (gpointer data)
+{
+ struct wl_list *feedbacks = data;
+
+ discard_feedbacks (feedbacks);
g_free (feedbacks);
}
@@ -141,6 +200,7 @@ meta_wayland_init_presentation_time (MetaWaylandCompositor *compositor)
MetaBackend *backend = compositor->backend;
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
+ ClutterActor *stage = meta_backend_get_stage (backend);
compositor->presentation_time.feedbacks =
g_hash_table_new_full (NULL, NULL, NULL, destroy_feedback_list);
@@ -148,6 +208,9 @@ meta_wayland_init_presentation_time (MetaWaylandCompositor *compositor)
g_signal_connect (monitor_manager, "monitors-changed-internal",
G_CALLBACK (on_monitors_changed), compositor);
+ g_signal_connect (stage, "after-paint",
+ G_CALLBACK (on_after_paint), compositor);
+
if (wl_global_create (compositor->wayland_display,
&wp_presentation_interface,
META_WP_PRESENTATION_VERSION,
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index db0d7f2f3..962ab05ff 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -799,6 +799,10 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface,
&state->presentation_feedback_list);
wl_list_init (&state->presentation_feedback_list);
+ if (!wl_list_empty (&surface->presentation_time.feedback_list))
+ meta_wayland_compositor_add_presentation_feedback_surface (surface->compositor,
+ surface);
+
if (surface->role)
{
meta_wayland_surface_role_apply_state (surface->role, state);
@@ -1390,6 +1394,8 @@ wl_surface_destructor (struct wl_resource *resource)
cairo_region_destroy (surface->input_region);
meta_wayland_compositor_remove_frame_callback_surface (compositor, surface);
+ meta_wayland_compositor_remove_presentation_feedback_surface (compositor,
+ surface);
g_hash_table_foreach (surface->outputs,
surface_output_disconnect_signals,
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 731e24727..b032a8bfc 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -230,6 +230,52 @@ on_after_update (ClutterStage *stage,
}
}
+static MetaWaylandOutput *
+get_output_for_stage_view (MetaWaylandCompositor *compositor,
+ ClutterStageView *stage_view)
+{
+ MetaCrtc *crtc;
+ MetaOutput *output;
+ MetaMonitor *monitor;
+ MetaLogicalMonitor *logical_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);
+ logical_monitor = meta_monitor_get_logical_monitor (monitor);
+ return g_hash_table_lookup (compositor->outputs, &logical_monitor->winsys_id);
+}
+
+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_compositor_handle_event:
* @compositor: the #MetaWaylandCompositor instance
@@ -438,6 +484,8 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *compositor)
g_signal_connect (stage, "after-update",
G_CALLBACK (on_after_update), compositor);
+ g_signal_connect (stage, "presented",
+ G_CALLBACK (on_presented), compositor);
if (!wl_global_create (compositor->wayland_display,
&wl_compositor_interface,