emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 12a78711c9: Fix calculation of frame times when X server time ove


From: Po Lu
Subject: master 12a78711c9: Fix calculation of frame times when X server time overflows
Date: Fri, 30 Sep 2022 02:54:39 -0400 (EDT)

branch: master
commit 12a78711c94ccf5c46dd4e9653596c87b6fe0a18
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    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.
---
 etc/TODO    | 20 ++++++++++++++++++++
 src/xterm.c | 31 ++++++++++++++++++++++++++++---
 2 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/etc/TODO b/etc/TODO
index fefc586123..d884539037 100644
--- a/etc/TODO
+++ b/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.
 
diff --git a/src/xterm.c b/src/xterm.c
index cb5d540dd3..947cf7edb5 100644
--- a/src/xterm.c
+++ b/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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]