clutter/stage-cogl: Reschedule update on present

If an update (new frame) had been scheduled already before
`_clutter_stage_cogl_presented` was called then that means it was
scheduled for the wrong time. Because the `last_presentation_time` has
changed since then. And using an `update_time` based on an outdated
presentation time results in scheduling frames too early, filling the
buffer queue (triple buffering or worse) and high visual latency.

So if we do receive a presentation event when an update is already
scheduled, remember to reschedule the update based on the newer
`last_presentation_time`. This way we avoid overfilling the buffer queue
and limit ourselves to double buffering for less visible lag.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/334

Prerequisite: https://gitlab.gnome.org/GNOME/mutter/merge_requests/520

https://gitlab.gnome.org/GNOME/mutter/merge_requests/281
This commit is contained in:
Daniel van Vugt 2018-10-29 19:05:46 +08:00 committed by Marco Trevisan
parent 91ac64bb44
commit 4faeb12731
2 changed files with 18 additions and 0 deletions

View File

@ -77,6 +77,10 @@ enum
PROP_LAST PROP_LAST
}; };
static void
clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
gint sync_delay);
static void static void
clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window) clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window)
{ {
@ -122,6 +126,16 @@ _clutter_stage_cogl_presented (ClutterStageCogl *stage_cogl,
} }
_clutter_stage_presented (stage_cogl->wrapper, frame_event, frame_info); _clutter_stage_presented (stage_cogl->wrapper, frame_event, frame_info);
if (frame_event == COGL_FRAME_EVENT_COMPLETE &&
stage_cogl->update_time != -1)
{
ClutterStageWindow *stage_window = CLUTTER_STAGE_WINDOW (stage_cogl);
stage_cogl->update_time = -1;
clutter_stage_cogl_schedule_update (stage_window,
stage_cogl->last_sync_delay);
}
} }
static gboolean static gboolean
@ -159,6 +173,8 @@ clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
if (stage_cogl->update_time != -1) if (stage_cogl->update_time != -1)
return; return;
stage_cogl->last_sync_delay = sync_delay;
now = g_get_monotonic_time (); now = g_get_monotonic_time ();
if (sync_delay < 0) if (sync_delay < 0)

View File

@ -59,6 +59,8 @@ struct _ClutterStageCogl
* junk frames to start with. */ * junk frames to start with. */
unsigned int frame_count; unsigned int frame_count;
gint last_sync_delay;
cairo_rectangle_int_t bounding_redraw_clip; cairo_rectangle_int_t bounding_redraw_clip;
guint initialized_redraw_clip : 1; guint initialized_redraw_clip : 1;