clutter/stage-cogl: Stop schedule_update repeatedly returning now

That could happen if the backend did not provide presentation timestamps,
or if the screen was not changing other than the hardware cursor:

  if (stage_cogl->last_presentation_time == 0||
      stage_cogl->last_presentation_time < now - 150000)
    {
      stage_cogl->update_time = now;
      return;
    }

By setting `update_time` to `now`, master_clock_get_swap_wait_time()
returns 0:

  gint64 now = g_source_get_time (master_clock->source);
  if (min_update_time < now)
    {
      return 0;
    }
  else
    {
      gint64 delay_us = min_update_time - now;
      return (delay_us + 999) / 1000;
    }

However, zero is a value unsupported by the default master clock
due to:

  if (swap_delay != 0)
    return swap_delay;

All cases are now handled by extrapolating when the next presentation
time would be and calculating an appropriate update time to meet that.

We also need to add a check for `update_time == last_update_time`, which
is a situation that just became possible since we support old (or zero)
values of `last_presentation_time`. This avoids getting more than one
stage update per frame interval when input events arrive without
triggering a stage redraw (e.g. moving the hardware cursor).

https://gitlab.gnome.org/GNOME/mutter/merge_requests/363
This commit is contained in:
Daniel van Vugt 2018-12-20 17:24:09 +08:00 committed by Georges Basile Stavracas Neto
parent a76762a05e
commit 35aa278194
No known key found for this signature in database
GPG Key ID: 886C17EE170D1385
2 changed files with 5 additions and 12 deletions

View File

@ -185,18 +185,6 @@ clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
return; return;
} }
/* We only extrapolate presentation times for 150ms - this is somewhat
* arbitrary. The reasons it might not be accurate for larger times are
* that the refresh interval might be wrong or the vertical refresh
* might be downclocked if nothing is going on onscreen.
*/
if (stage_cogl->last_presentation_time == 0||
stage_cogl->last_presentation_time < now - 150000)
{
stage_cogl->update_time = now;
return;
}
refresh_rate = stage_cogl->refresh_rate; refresh_rate = stage_cogl->refresh_rate;
if (refresh_rate <= 0.0) if (refresh_rate <= 0.0)
refresh_rate = clutter_get_default_frame_rate (); refresh_rate = clutter_get_default_frame_rate ();
@ -220,6 +208,9 @@ clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
next_presentation_time += refresh_interval; next_presentation_time += refresh_interval;
stage_cogl->update_time = next_presentation_time - max_render_time_allowed; stage_cogl->update_time = next_presentation_time - max_render_time_allowed;
if (stage_cogl->update_time == stage_cogl->last_update_time)
stage_cogl->update_time = stage_cogl->last_update_time + refresh_interval;
} }
static gint64 static gint64
@ -238,6 +229,7 @@ clutter_stage_cogl_clear_update_time (ClutterStageWindow *stage_window)
{ {
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
stage_cogl->last_update_time = stage_cogl->update_time;
stage_cogl->update_time = -1; stage_cogl->update_time = -1;
} }

View File

@ -53,6 +53,7 @@ struct _ClutterStageCogl
gint64 last_presentation_time; gint64 last_presentation_time;
gint64 update_time; gint64 update_time;
int64_t last_update_time;
/* We only enable clipped redraws after 2 frames, since we've seen /* We only enable clipped redraws after 2 frames, since we've seen
* a lot of drivers can struggle to get going and may output some * a lot of drivers can struggle to get going and may output some