emacs-diffs
[Top][All Lists]
Advanced

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

master 80bfd6dc5b: Make frame synchronization more robust


From: Po Lu
Subject: master 80bfd6dc5b: Make frame synchronization more robust
Date: Sun, 27 Nov 2022 06:21:15 -0500 (EST)

branch: master
commit 80bfd6dc5bc3738db595a4972893b149b1224800
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Make frame synchronization more robust
    
    * src/xterm.c (x_sync_wait_for_frame_drawn_event)
    (x_sync_handle_frame_drawn): Only cancel frame synchronization
    if hanging twice or more in a row.
    * src/xterm.h (struct x_output, FRAME_X_DRAW_JUST_HUNG): New
    flag.
---
 src/xterm.c | 46 +++++++++++++++++++++++++++++++++++++++-------
 src/xterm.h |  6 ++++++
 2 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index ec605f5e91..7eaf59d54b 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -6919,13 +6919,27 @@ x_sync_wait_for_frame_drawn_event (struct frame *f)
                  x_sync_is_frame_drawn_event, (XPointer) f,
                  make_timespec (1, 0)))
     {
-      /* TODO: display this warning in the echo area.  */
-      fprintf (stderr, "Warning: compositing manager spent more than 1 second "
-              "drawing a frame.  Frame synchronization has been disabled\n");
-      FRAME_X_OUTPUT (f)->use_vsync_p = false;
+      /* The first time a draw hangs, treat it as a random fluctuation
+        on the part of the compositor.  If the next draw continues to
+        hang, disable frame synchronization.  */
+      if (FRAME_X_DRAW_JUST_HUNG (f))
+       {
+         fprintf (stderr, "Warning: compositing manager spent more than 1 "
+                  "second drawing a frame.  Frame synchronization has "
+                  "been disabled\n");
+         FRAME_X_OUTPUT (f)->use_vsync_p = false;
 
-      /* Also change the frame parameter to reflect the new state.  */
-      store_frame_param (f, Quse_frame_synchronization, Qnil);
+         /* Also change the frame parameter to reflect the new
+            state.  */
+         store_frame_param (f, Quse_frame_synchronization, Qnil);
+       }
+      else
+       {
+         fprintf (stderr, "Warning: compositing manager spent more than 1 "
+                  "second drawing a frame.  Frame synchronization will be "
+                  "disabled if this happens again\n");
+         FRAME_X_DRAW_JUST_HUNG (f) = true;
+       }
     }
   else
     x_sync_note_frame_times (FRAME_DISPLAY_INFO (f), f, &event);
@@ -7128,8 +7142,26 @@ static void
 x_sync_handle_frame_drawn (struct x_display_info *dpyinfo,
                           XEvent *message, struct frame *f)
 {
+  XSyncValue value, counter;
+
   if (FRAME_OUTER_WINDOW (f) == message->xclient.window)
-    FRAME_X_WAITING_FOR_DRAW (f) = false;
+    {
+      counter = FRAME_X_COUNTER_VALUE (f);
+
+      /* Check that the counter in the message is the same as the
+        counter in the frame.  */
+      XSyncIntsToValue (&value,
+                       message->xclient.data.l[0] & 0xffffffff,
+                       message->xclient.data.l[1] & 0xffffffff);
+
+      if (XSyncValueEqual (value, counter))
+       FRAME_X_WAITING_FOR_DRAW (f) = false;
+
+      /* As long as a _NET_WM_FRAME_DRAWN message arrives, we know
+        that the compositor is still sending events, so avoid timing
+        out.  */
+      FRAME_X_DRAW_JUST_HUNG (f) = false;
+    }
 
   x_sync_note_frame_times (dpyinfo, f, message);
 }
diff --git a/src/xterm.h b/src/xterm.h
index c36920081d..ee429e9c68 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1179,6 +1179,10 @@ struct x_output
      frame.  */
   bool_bf waiting_for_frame_p : 1;
 
+  /* Whether or not Emacs just skipped waiting for a frame due to a
+     timeout.  */
+  bool_bf draw_just_hung_p : 1;
+
 #if !defined USE_GTK && defined HAVE_CLOCK_GETTIME
   /* Whether or not Emacs should wait for the compositing manager to
      draw frames before starting a new frame.  */
@@ -1392,6 +1396,8 @@ extern void x_mark_frame_dirty (struct frame *f);
   FRAME_X_OUTPUT (f)->extended_frame_counter
 #define FRAME_X_WAITING_FOR_DRAW(f)            \
   FRAME_X_OUTPUT (f)->waiting_for_frame_p
+#define FRAME_X_DRAW_JUST_HUNG(f)              \
+  FRAME_X_OUTPUT (f)->draw_just_hung_p
 #define FRAME_X_COUNTER_VALUE(f)               \
   FRAME_X_OUTPUT (f)->current_extended_counter_value
 #endif



reply via email to

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