Fix calculation of frame times when X server time overflows
* etc/TODO: Add TODO about frame synchronization and animations. * src/xterm.c (x_display_set_last_user_time): Handle cases when the monotonic time is not the server time due to the latter overflowing.
This commit is contained in:
parent
b7a3770ecc
commit
12a78711c9
2 changed files with 48 additions and 3 deletions
20
etc/TODO
20
etc/TODO
|
@ -1763,6 +1763,26 @@ enough environment under which the fix can be tested.
|
|||
The MPX code has not been tested under X toolkit or GTK+ 2.x builds
|
||||
and is not expected to work there.
|
||||
|
||||
** Framework for doing animations
|
||||
Emacs does animations all over the place, usually "pluse" animations.
|
||||
These currently animate by waiting for a small but fixed amount of
|
||||
time between each redisplay, which causes screen tearing by not
|
||||
synchronizing with the vertical refresh. Frame synchronization works
|
||||
by causing redisplay to delay until the next time the monitor can
|
||||
refresh; this works, but can cause substandard frame rate when
|
||||
redisplay happens less often than the monitor refreshing, as redisplay
|
||||
will have to continually wait for missed monitor refresh.
|
||||
|
||||
The right remedy for this problem is to define a function that returns
|
||||
the amount of time remaining before the next vertical blanking period,
|
||||
and to schedule animation redisplay within that period, using the
|
||||
information provided by the _NET_WM_FRAME_DRAWN and
|
||||
_NET_WM_FRAME_TIMINGS compositor messages on X and the
|
||||
BScreen::GetMonitorInfo function on Haiku. Ideally, all features
|
||||
performing animations should be modified to use that method of
|
||||
scheduling redisplay. Examples include xref-pulse-momentarily and
|
||||
pixel-scroll-precision-start-momentum.
|
||||
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
|
|
31
src/xterm.c
31
src/xterm.c
|
@ -7607,6 +7607,11 @@ static void
|
|||
x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
|
||||
bool send_event)
|
||||
{
|
||||
#if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
|
||||
uint_fast64_t monotonic_time;
|
||||
uint_fast64_t monotonic_ms;
|
||||
int_fast64_t diff_ms;
|
||||
#endif
|
||||
#ifndef USE_GTK
|
||||
struct frame *focus_frame;
|
||||
Time old_time;
|
||||
|
@ -7627,9 +7632,8 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
|
|||
{
|
||||
/* See if the current CLOCK_MONOTONIC time is reasonably close
|
||||
to the X server time. */
|
||||
uint_fast64_t monotonic_time = x_sync_current_monotonic_time ();
|
||||
uint_fast64_t monotonic_ms = monotonic_time / 1000;
|
||||
int_fast64_t diff_ms;
|
||||
monotonic_time = x_sync_current_monotonic_time ();
|
||||
monotonic_ms = monotonic_time / 1000;
|
||||
|
||||
dpyinfo->server_time_monotonic_p
|
||||
= (monotonic_time != 0
|
||||
|
@ -7647,6 +7651,27 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
|
|||
monotonic_time,
|
||||
&dpyinfo->server_time_offset))
|
||||
dpyinfo->server_time_offset = 0;
|
||||
|
||||
/* If the server time is reasonably close to the monotonic
|
||||
time after the latter is truncated to CARD32, simply make
|
||||
the offset that between the server time in ms and the
|
||||
actual time in ms. */
|
||||
|
||||
monotonic_ms = monotonic_ms & 0xffffffff;
|
||||
if (!INT_SUBTRACT_WRAPV (time, monotonic_ms, &diff_ms)
|
||||
&& -500 < diff_ms && diff_ms < 500)
|
||||
{
|
||||
/* The server timestamp overflowed. Make the time
|
||||
offset exactly how much it overflowed by. */
|
||||
|
||||
if (INT_SUBTRACT_WRAPV (monotonic_time / 1000, monotonic_ms,
|
||||
&dpyinfo->server_time_offset)
|
||||
|| INT_MULTIPLY_WRAPV (dpyinfo->server_time_offset,
|
||||
1000, &dpyinfo->server_time_offset)
|
||||
|| INT_SUBTRACT_WRAPV (0, dpyinfo->server_time_offset,
|
||||
&dpyinfo->server_time_offset))
|
||||
dpyinfo->server_time_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue