summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-08-04 15:37:54 +0800
committerPo Lu <luangruo@yahoo.com>2022-08-04 15:38:23 +0800
commit78129dcf53ab2b1ce49eab28dba89dea9f687284 (patch)
tree78e86ecfacea3de899bd0958225f2c4c097cda84 /src
parent3e60f7f3c31a8491b085684121e5229be56b3538 (diff)
downloademacs-78129dcf53ab2b1ce49eab28dba89dea9f687284.tar.gz
Correctly implement refresh synchronization fences
* configure.ac (HAVE_XSYNC): Also check for XSyncTriggerFence. * src/xfns.c (Fx_create_frame): Create fences. * src/xterm.c (x_atom_refs): New atom. (x_sync_trigger_fence, x_sync_init_fences, x_sync_free_fences): New functions. (x_sync_update_finish): Trigger the appropriate fence. (x_free_frame_resources): Free fences. * src/xterm.h (struct x_display_info): New atom `_NET_WM_SYNC_FENCES'. (struct x_output): New field `sync_fences'.
Diffstat (limited to 'src')
-rw-r--r--src/xfns.c4
-rw-r--r--src/xterm.c92
-rw-r--r--src/xterm.h16
3 files changed, 107 insertions, 5 deletions
diff --git a/src/xfns.c b/src/xfns.c
index 614a5b34551..672097c0d80 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -5157,6 +5157,10 @@ This function is an internal primitive--use `make-frame' instead. */)
(unsigned char *) &counters,
((STRINGP (value)
&& !strcmp (SSDATA (value), "extended")) ? 2 : 1));
+
+#if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK
+ x_sync_init_fences (f);
+#endif
#endif
}
#endif
diff --git a/src/xterm.c b/src/xterm.c
index 7e304bcd6e1..33e90603f80 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -997,6 +997,7 @@ static const struct x_atom_ref x_atom_refs[] =
ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
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_SYNC_FENCES", Xatom_net_wm_sync_fences)
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)
@@ -6812,6 +6813,85 @@ x_sync_update_begin (struct frame *f)
FRAME_X_COUNTER_VALUE (f));
}
+#ifdef HAVE_XSYNCTRIGGERFENCE
+
+/* Trigger the sync fence for counter VALUE immediately before a frame
+ finishes. */
+
+static void
+x_sync_trigger_fence (struct frame *f, XSyncValue value)
+{
+ uint64_t n, low, high, idx;
+
+ /* Sync fences aren't supported by the X server. */
+ if (FRAME_DISPLAY_INFO (f)->xsync_major < 3
+ || (FRAME_DISPLAY_INFO (f)->xsync_major == 3
+ && FRAME_DISPLAY_INFO (f)->xsync_minor < 1))
+ return;
+
+ low = XSyncValueLow32 (value);
+ high = XSyncValueHigh32 (value);
+
+ n = low | (high << 32);
+ idx = (n / 4) % 2;
+
+#ifdef FRAME_DEBUG
+ fprintf (stderr, "Triggering synchonization fence: %lu\n", idx);
+#endif
+
+ XSyncTriggerFence (FRAME_X_DISPLAY (f),
+ FRAME_X_OUTPUT (f)->sync_fences[idx]);
+}
+
+/* Initialize the sync fences on F. */
+
+void
+x_sync_init_fences (struct frame *f)
+{
+ struct x_output *output;
+ struct x_display_info *dpyinfo;
+
+ output = FRAME_X_OUTPUT (f);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ /* Sync fences aren't supported by the X server. */
+ if (dpyinfo->xsync_major < 3
+ || (dpyinfo->xsync_major == 3
+ && dpyinfo->xsync_minor < 1))
+ return;
+
+ output->sync_fences[0]
+ = XSyncCreateFence (FRAME_X_DISPLAY (f),
+ /* The drawable given below is only used to
+ determine the screen on which the fence is
+ created. */
+ FRAME_X_WINDOW (f),
+ False);
+ output->sync_fences[1]
+ = XSyncCreateFence (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ False);
+
+ XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_net_wm_sync_fences, XA_CARDINAL,
+ 32, PropModeReplace,
+ (unsigned char *) &output->sync_fences, 1);
+}
+
+static void
+x_sync_free_fences (struct frame *f)
+{
+ if (FRAME_X_OUTPUT (f)->sync_fences[0] != None)
+ XSyncDestroyFence (FRAME_X_DISPLAY (f),
+ FRAME_X_OUTPUT (f)->sync_fences[0]);
+
+ if (FRAME_X_OUTPUT (f)->sync_fences[1] != None)
+ XSyncDestroyFence (FRAME_X_DISPLAY (f),
+ FRAME_X_OUTPUT (f)->sync_fences[1]);
+}
+
+#endif
+
/* Tell the compositing manager that FRAME has been drawn and can be
updated. */
@@ -6844,12 +6924,15 @@ x_sync_update_finish (struct frame *f)
if (overflow)
XSyncIntToValue (&FRAME_X_COUNTER_VALUE (f), 0);
+ /* Trigger any sync fences if necessary. */
+#ifdef HAVE_XSYNCTRIGGERFENCE
+ x_sync_trigger_fence (f, FRAME_X_COUNTER_VALUE (f));
+#endif
+
XSyncSetCounter (FRAME_X_DISPLAY (f),
FRAME_X_EXTENDED_COUNTER (f),
FRAME_X_COUNTER_VALUE (f));
- /* FIXME: this leads to freezes if the compositing manager crashes
- in the meantime. */
if (FRAME_OUTPUT_DATA (f)->use_vsync_p)
FRAME_X_WAITING_FOR_DRAW (f) = true;
}
@@ -26282,6 +26365,11 @@ x_free_frame_resources (struct frame *f)
XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_edge_cursor);
if (f->output_data.x->bottom_left_corner_cursor != 0)
XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_left_corner_cursor);
+
+ /* Free sync fences. */
+#if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK
+ x_sync_free_fences (f);
+#endif
}
#ifdef HAVE_GTK3
diff --git a/src/xterm.h b/src/xterm.h
index fb099e92ea0..c1a944d3cd6 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -614,9 +614,9 @@ 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_frame_timings, Xatom_net_wm_user_time,
- Xatom_net_wm_user_time_window, Xatom_net_client_list_stacking,
- Xatom_net_wm_pid;
+ Xatom_net_wm_sync_fences, 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;
/* XSettings atoms and windows. */
Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
@@ -1077,6 +1077,13 @@ struct x_output
/* A temporary time used to calculate that value. */
uint64_t temp_frame_time;
+
+#ifdef HAVE_XSYNCTRIGGERFENCE
+ /* An array of two sync fences that are triggered in order after a
+ frame completes. Not initialized if the XSync extension is too
+ old to support sync fences. */
+ XSyncFence sync_fences[2];
+#endif
#endif
#endif
@@ -1516,6 +1523,9 @@ extern void x_make_frame_invisible (struct frame *);
extern void x_iconify_frame (struct frame *);
extern void x_free_frame_resources (struct frame *);
extern void x_wm_set_size_hint (struct frame *, long, bool);
+#if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK
+extern void x_sync_init_fences (struct frame *);
+#endif
extern void x_delete_terminal (struct terminal *);
extern Cursor x_create_font_cursor (struct x_display_info *, int);