forked from AuroraMiddleware/gtk
Fix irregular gdk_frame_clock_get_frame_time
This fixes stuttering in animations that rely on the regularity of gdk_frame_clock_get_frame_time. https://bugzilla.gnome.org/show_bug.cgi?id=787665 BEFORE gdkgears: 58 FPS and visibly stuttering gnome-maps on a 59.95Hz monitor: "paint" g_get_monotonic_time +17278μs, gdk_frame_clock_get_frame_time +17278μs "paint" g_get_monotonic_time +17449μs, gdk_frame_clock_get_frame_time +17426μs "paint" g_get_monotonic_time +17620μs, gdk_frame_clock_get_frame_time +17600μs AFTER gdkgears: 60 FPS and smoother gnome-maps on a 59.95Hz monitor: "paint" g_get_monotonic_time +18228μs, gdk_frame_clock_get_frame_time +16680μs "paint" g_get_monotonic_time +15010μs, gdk_frame_clock_get_frame_time +16680μs "paint" g_get_monotonic_time +17134μs, gdk_frame_clock_get_frame_time +16680μs
This commit is contained in:
parent
7a17865b22
commit
3b2f939590
@ -123,6 +123,7 @@ gdk_frame_clock_idle_init (GdkFrameClockIdle *frame_clock_idle)
|
||||
frame_clock_idle->priv = priv =
|
||||
gdk_frame_clock_idle_get_instance_private (frame_clock_idle);
|
||||
|
||||
priv->frame_time = g_get_monotonic_time (); /* more sane than zero */
|
||||
priv->freeze_count = 0;
|
||||
}
|
||||
|
||||
@ -350,9 +351,37 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
case GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT:
|
||||
if (priv->freeze_count == 0)
|
||||
{
|
||||
priv->frame_time = compute_frame_time (clock_idle);
|
||||
gint64 frame_interval = FRAME_INTERVAL;
|
||||
gint64 reset_frame_time;
|
||||
gint64 smoothest_frame_time;
|
||||
gint64 frame_time_error;
|
||||
GdkFrameTimings *prev_timings =
|
||||
gdk_frame_clock_get_current_timings (clock);
|
||||
|
||||
if (prev_timings && prev_timings->refresh_interval)
|
||||
frame_interval = prev_timings->refresh_interval;
|
||||
|
||||
/* We are likely not getting precisely even callbacks in real
|
||||
* time, particularly if the event loop is busy.
|
||||
* This is a documented limitation in the precision of
|
||||
* gdk_threads_add_timeout_full and g_timeout_add_full.
|
||||
*
|
||||
* In order to avoid this imprecision from compounding between
|
||||
* frames and affecting visual smoothness, we correct frame_time
|
||||
* to more precisely match the even refresh interval of the
|
||||
* physical display. This also means we proactively avoid (most)
|
||||
* missed frames before they occur.
|
||||
*/
|
||||
smoothest_frame_time = priv->frame_time + frame_interval;
|
||||
reset_frame_time = compute_frame_time (clock_idle);
|
||||
frame_time_error = ABS (reset_frame_time - smoothest_frame_time);
|
||||
if (frame_time_error >= frame_interval)
|
||||
priv->frame_time = reset_frame_time;
|
||||
else
|
||||
priv->frame_time = smoothest_frame_time;
|
||||
|
||||
_gdk_frame_clock_begin_frame (clock);
|
||||
/* Note "current" is different now so timings != prev_timings */
|
||||
timings = gdk_frame_clock_get_current_timings (clock);
|
||||
|
||||
timings->frame_time = priv->frame_time;
|
||||
|
Loading…
Reference in New Issue
Block a user