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>
This commit is contained in:
Ivan Molodetskikh 2020-10-08 15:34:28 +03:00 committed by Marge Bot
parent f0c2200466
commit 2ce3a050f0
3 changed files with 120 additions and 3 deletions

View File

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

View File

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

View File

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