server timestamp TIMESTAMP. Return 0 if the necessary information
is not available. */
-static uint64_t
+static uint_fast64_t
x_sync_get_monotonic_time (struct x_display_info *dpyinfo,
- uint64_t timestamp)
+ uint_fast64_t timestamp)
{
if (dpyinfo->server_time_monotonic_p)
return timestamp;
if (!dpyinfo->server_time_offset)
return 0;
- return timestamp - dpyinfo->server_time_offset;
+ uint_fast64_t t;
+ return (INT_SUBTRACT_WRAPV (timestamp, dpyinfo->server_time_offset, &t)
+ ? 0 : t);
}
+# ifndef CLOCK_MONOTONIC
+# define CLOCK_MONOTONIC CLOCK_REALTIME
+# endif
+
/* Return the current monotonic time in the same format as a
- high-resolution server timestamp. */
+ high-resolution server timestamp, or 0 if not available. */
-static uint64_t
+static uint_fast64_t
x_sync_current_monotonic_time (void)
{
struct timespec time;
-
- clock_gettime (CLOCK_MONOTONIC, &time);
- return time.tv_sec * 1000000 + time.tv_nsec / 1000;
+ uint_fast64_t t;
+ return (((clock_gettime (CLOCK_MONOTONIC, &time) != 0
+ && (CLOCK_MONOTONIC == CLOCK_REALTIME
+ || clock_gettime (CLOCK_REALTIME, &time) != 0))
+ || INT_MULTIPLY_WRAPV (time.tv_sec, 1000000, &t)
+ || INT_ADD_WRAPV (t, time.tv_nsec / 1000, &t))
+ ? 0 : t);
}
/* Decode a _NET_WM_FRAME_DRAWN message and calculate the time it took
x_sync_note_frame_times (struct x_display_info *dpyinfo,
struct frame *f, XEvent *event)
{
- uint64_t low, high, time;
+ uint_fast64_t low, high, time;
struct x_output *output;
low = event->xclient.data.l[2];
time = x_sync_get_monotonic_time (dpyinfo, low | (high << 32));
- if (time)
- output->last_frame_time = time - output->temp_frame_time;
+ if (!time || !output->temp_frame_time
+ || INT_SUBTRACT_WRAPV (time, output->temp_frame_time,
+ &output->last_frame_time))
+ output->last_frame_time = 0;
#ifdef FRAME_DEBUG
- fprintf (stderr, "Drawing the last frame took: %lu ms (%lu)\n",
- output->last_frame_time / 1000, time);
+ uint_fast64_t last_frame_ms = output->last_frame_time / 1000;
+ fprintf (stderr,
+ "Drawing the last frame took: %"PRIuFAST64" ms (%"PRIuFAST64")\n",
+ last_frame_ms, time);
#endif
}
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;
+ bool idx = !! (XSyncValueLow32 (value) & 4);
#ifdef FRAME_DEBUG
- fprintf (stderr, "Triggering synchronization fence: %lu\n", idx);
+ fprintf (stderr, "Triggering synchronization fence: %d\n", idx);
#endif
XSyncTriggerFence (FRAME_X_DISPLAY (f),
#ifndef USE_GTK
struct frame *focus_frame;
Time old_time;
-#if defined HAVE_XSYNC && defined HAVE_CLOCK_GETTIME
- uint64_t monotonic_time;
-#endif
focus_frame = dpyinfo->x_focus_frame;
old_time = dpyinfo->last_user_time;
{
/* See if the current CLOCK_MONOTONIC time is reasonably close
to the X server time. */
- monotonic_time = x_sync_current_monotonic_time ();
+ uint_fast64_t monotonic_time = x_sync_current_monotonic_time ();
+ uint_fast64_t monotonic_ms = monotonic_time / 1000;
+ int_fast64_t diff_ms;
- if (time * 1000 > monotonic_time - 500 * 1000
- && time * 1000 < monotonic_time + 500 * 1000)
- dpyinfo->server_time_monotonic_p = true;
- else
+ dpyinfo->server_time_monotonic_p
+ = (monotonic_time != 0
+ && !INT_SUBTRACT_WRAPV (time, monotonic_ms, &diff_ms)
+ && -500 < diff_ms && diff_ms < 500);
+
+ if (!dpyinfo->server_time_monotonic_p)
{
/* Compute an offset that can be subtracted from the server
time to estimate the monotonic time on the X server. */
- dpyinfo->server_time_monotonic_p = false;
- dpyinfo->server_time_offset
- = ((int64_t) time * 1000) - monotonic_time;
+ if (!monotonic_time
+ || INT_MULTIPLY_WRAPV (time, 1000, &dpyinfo->server_time_offset)
+ || INT_SUBTRACT_WRAPV (dpyinfo->server_time_offset,
+ monotonic_time,
+ &dpyinfo->server_time_offset))
+ dpyinfo->server_time_offset = 0;
}
}
#endif
drag-and-drop emulation. */
Time pending_dnd_time;
-#if defined HAVE_XSYNC && !defined USE_GTK
+#if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
/* Whether or not the server time is probably the same as
"clock_gettime (CLOCK_MONOTONIC, ...)". */
bool server_time_monotonic_p;
/* The time difference between the X server clock and the monotonic
- clock. */
- int64_t server_time_offset;
+ clock, or 0 if unknown (FIXME: what if the difference is zero?). */
+ int_fast64_t server_time_offset;
#endif
};
bool_bf use_vsync_p : 1;
/* The time (in microseconds) it took to draw the last frame. */
- uint64_t last_frame_time;
+ uint_fast64_t last_frame_time;
/* A temporary time used to calculate that value. */
- uint64_t temp_frame_time;
+ uint_fast64_t temp_frame_time;
#ifdef HAVE_XSYNCTRIGGERFENCE
/* An array of two sync fences that are triggered in order after a