diff options
author | Po Lu <luangruo@yahoo.com> | 2022-08-04 15:37:54 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2022-08-04 15:38:23 +0800 |
commit | 78129dcf53ab2b1ce49eab28dba89dea9f687284 (patch) | |
tree | 78e86ecfacea3de899bd0958225f2c4c097cda84 /src | |
parent | 3e60f7f3c31a8491b085684121e5229be56b3538 (diff) | |
download | emacs-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.c | 4 | ||||
-rw-r--r-- | src/xterm.c | 92 | ||||
-rw-r--r-- | src/xterm.h | 16 |
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); |