emacs-diffs
[Top][All Lists]
Advanced

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

master 1cdc64cdda: Implement extended frame synchronization


From: Po Lu
Subject: master 1cdc64cdda: Implement extended frame synchronization
Date: Thu, 28 Jul 2022 22:14:19 -0400 (EDT)

branch: master
commit 1cdc64cdda59fd6ff84e0fd6da9b61c5451cb9e5
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Implement extended frame synchronization
    
    * src/xterm.c (x_atom_refs): New atom _NET_WM_FRAME_TIMINGS.
    (x_sync_update_finish, x_sync_update_begin): New frame.
    (x_update_begin, x_update_end, XTframe_up_to_date): Begin and
    end frames accordingly if extended frame synchronization is
    enabled.
    (handle_one_xevent): Ignore timing and frame drawn events.
    
    * src/xterm.h (struct x_display_info): New atom.
    (FRAME_X_COUNTER_VALUE): New macro.
---
 src/xterm.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 src/xterm.h |  10 +++--
 2 files changed, 116 insertions(+), 17 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index e7222d35b3..acdac92d94 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -998,6 +998,7 @@ static const struct x_atom_ref x_atom_refs[] =
     ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST", Xatom_net_wm_sync_request)
     ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST_COUNTER", 
Xatom_net_wm_sync_request_counter)
     ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn)
+    ATOM_REFS_INIT ("_NET_WM_FRAME_TIMINGS", Xatom_net_wm_frame_timings)
     ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time)
     ATOM_REFS_INIT ("_NET_WM_USER_TIME_WINDOW", Xatom_net_wm_user_time_window)
     ATOM_REFS_INIT ("_NET_CLIENT_LIST_STACKING", 
Xatom_net_client_list_stacking)
@@ -6595,6 +6596,82 @@ x_set_frame_alpha (struct frame *f)
                    Starting and ending an update
  ***********************************************************************/
 
+#if defined HAVE_XSYNC && !defined USE_GTK
+/* Tell the compositing manager to postpone updates of F until a frame
+   has finished drawing.  */
+
+static void
+x_sync_update_begin (struct frame *f)
+{
+  XSyncValue value, add;
+  Bool overflow;
+
+  if (FRAME_X_EXTENDED_COUNTER (f) == None)
+    return;
+
+  value = FRAME_X_COUNTER_VALUE (f);
+
+  /* Since a frame is already in progress, there is no point in
+     continuing.  */
+  if (XSyncValueLow32 (value) % 2)
+    return;
+
+  /* Since Emacs needs a non-urgent redraw, ensure that value % 4 ==
+     0.  */
+  if (XSyncValueLow32 (value) % 4 == 2)
+    XSyncIntToValue (&add, 3);
+  else
+    XSyncIntToValue (&add, 1);
+
+  XSyncValueAdd (&FRAME_X_COUNTER_VALUE (f),
+                value, add, &overflow);
+
+  if (XSyncValueLow32 (FRAME_X_COUNTER_VALUE (f)) % 4 != 1)
+    emacs_abort ();
+
+  if (overflow)
+    XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 1);
+
+  XSyncSetCounter (FRAME_X_DISPLAY (f),
+                  FRAME_X_EXTENDED_COUNTER (f),
+                  FRAME_X_COUNTER_VALUE (f));
+}
+
+/* Tell the compositing manager that FRAME has been drawn and can be
+   updated.  */
+
+static void
+x_sync_update_finish (struct frame *f)
+{
+  XSyncValue value, add;
+  Bool overflow;
+
+  if (FRAME_X_EXTENDED_COUNTER (f) == None)
+    return;
+
+  if (FRAME_X_OUTPUT (f)->ext_sync_end_pending_p)
+    return;
+
+  value = FRAME_X_COUNTER_VALUE (f);
+
+  if (!(XSyncValueLow32 (value) % 2))
+    return;
+
+  XSyncIntToValue (&add, 1);
+  XSyncValueAdd (&FRAME_X_COUNTER_VALUE (f),
+                value, add, &overflow);
+
+  if (overflow)
+    XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 0);
+
+  XSyncSetCounter (FRAME_X_DISPLAY (f),
+                  FRAME_X_EXTENDED_COUNTER (f),
+                  FRAME_X_COUNTER_VALUE (f));
+
+  /* TODO: implement sync fences.  */
+}
+#endif
+
 /* Start an update of frame F.  This function is installed as a hook
    for update_begin, i.e. it is called when update_begin is called.
    This function is called prior to calls to gui_update_window_begin for
@@ -6604,7 +6681,11 @@ x_set_frame_alpha (struct frame *f)
 static void
 x_update_begin (struct frame *f)
 {
+#if defined HAVE_XSYNC && !defined USE_GTK
+  x_sync_update_begin (f);
+#else
   /* Nothing to do.  */
+#endif
 }
 
 /* Draw a vertical window border from (x,y0) to (x,y1)  */
@@ -6750,17 +6831,17 @@ x_update_end (struct frame *f)
 
 #ifdef USE_CAIRO
   if (!FRAME_X_DOUBLE_BUFFERED_P (f) && FRAME_CR_CONTEXT (f))
-    {
-      block_input ();
-      cairo_surface_flush (cairo_get_target (FRAME_CR_CONTEXT (f)));
-      unblock_input ();
-    }
+    cairo_surface_flush (cairo_get_target (FRAME_CR_CONTEXT (f)));
 #endif
 
-#ifndef XFlush
-  block_input ();
-  XFlush (FRAME_X_DISPLAY (f));
-  unblock_input ();
+  /* If double buffering is disabled, finish the update here.
+     Otherwise, finish the update when the back buffer is next
+     displayed.  */
+#if defined HAVE_XSYNC && !defined USE_GTK
+#ifdef HAVE_XDBE
+  if (!FRAME_X_DOUBLE_BUFFERED_P (f))
+#endif
+    x_sync_update_finish (f);
 #endif
 }
 
@@ -6788,6 +6869,11 @@ XTframe_up_to_date (struct frame *f)
   if (!buffer_flipping_blocked_p ()
       && FRAME_X_NEED_BUFFER_FLIP (f))
     show_back_buffer (f);
+
+#if defined HAVE_XSYNC && !defined USE_GTK
+  if (FRAME_X_DOUBLE_BUFFERED_P (f))
+    x_sync_update_finish (f);
+#endif
 #endif
 
 #ifdef HAVE_XSYNC
@@ -6804,14 +6890,14 @@ XTframe_up_to_date (struct frame *f)
   if (FRAME_X_OUTPUT (f)->ext_sync_end_pending_p
       && FRAME_X_EXTENDED_COUNTER (f) != None)
     {
-      current = FRAME_X_OUTPUT (f)->current_extended_counter_value;
+      current = FRAME_X_COUNTER_VALUE (f);
 
       if (XSyncValueLow32 (current) % 2)
        XSyncIntToValue (&add, 1);
       else
        XSyncIntToValue (&add, 2);
 
-      XSyncValueAdd (&FRAME_X_OUTPUT (f)->current_extended_counter_value,
+      XSyncValueAdd (&FRAME_X_COUNTER_VALUE (f),
                     current, add, &overflow_p);
 
       if (overflow_p)
@@ -6819,7 +6905,7 @@ XTframe_up_to_date (struct frame *f)
 
       XSyncSetCounter (FRAME_X_DISPLAY (f),
                       FRAME_X_EXTENDED_COUNTER (f),
-                      FRAME_X_OUTPUT (f)->current_extended_counter_value);
+                      FRAME_X_COUNTER_VALUE (f));
 
       FRAME_X_OUTPUT (f)->ext_sync_end_pending_p = false;
     }
@@ -16861,8 +16947,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                      }
                    else if (event->xclient.data.l[4] == 1)
                      {
-                       XSyncIntsToValue (&FRAME_X_OUTPUT 
(f)->current_extended_counter_value,
-                                         event->xclient.data.l[2], 
event->xclient.data.l[3]);
+                       XSyncIntsToValue (&FRAME_X_COUNTER_VALUE (f),
+                                         event->xclient.data.l[2],
+                                         event->xclient.data.l[3]);
                        FRAME_X_OUTPUT (f)->ext_sync_end_pending_p = true;
                      }
 
@@ -16979,6 +17066,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
             goto done;
           }
 
+#if defined HAVE_XSYNC && !defined USE_GTK
+       /* These messages are sent by the compositing manager after a
+          frame is drawn under extended synchronization.  */
+       if (event->xclient.message_type == dpyinfo->Xatom_net_wm_frame_drawn
+           || event->xclient.message_type == 
dpyinfo->Xatom_net_wm_frame_timings)
+         goto done;
+#endif
+
         xft_settings_event (dpyinfo, event);
 
        f = any;
diff --git a/src/xterm.h b/src/xterm.h
index b9e7b094e3..3e237158e7 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -614,7 +614,7 @@ struct x_display_info
     Xatom_net_wm_state_shaded, Xatom_net_frame_extents, 
Xatom_net_current_desktop,
     Xatom_net_workarea, Xatom_net_wm_opaque_region, Xatom_net_wm_ping,
     Xatom_net_wm_sync_request, Xatom_net_wm_sync_request_counter,
-    Xatom_net_wm_frame_drawn, Xatom_net_wm_user_time,
+    Xatom_net_wm_frame_drawn, Xatom_net_wm_frame_timings, 
Xatom_net_wm_user_time,
     Xatom_net_wm_user_time_window, Xatom_net_client_list_stacking,
     Xatom_net_wm_pid;
 
@@ -1211,8 +1211,12 @@ extern void x_mark_frame_dirty (struct frame *f);
 #endif
 
 #ifdef HAVE_XSYNC
-#define FRAME_X_BASIC_COUNTER(f) FRAME_X_OUTPUT (f)->basic_frame_counter
-#define FRAME_X_EXTENDED_COUNTER(f) FRAME_X_OUTPUT (f)->extended_frame_counter
+#define FRAME_X_BASIC_COUNTER(f)               \
+  FRAME_X_OUTPUT (f)->basic_frame_counter
+#define FRAME_X_EXTENDED_COUNTER(f)            \
+  FRAME_X_OUTPUT (f)->extended_frame_counter
+#define FRAME_X_COUNTER_VALUE(f)               \
+  FRAME_X_OUTPUT (f)->current_extended_counter_value
 #endif
 
 /* This is the Colormap which frame F uses.  */



reply via email to

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