From 228a7d8e5458b00e057f6e71ce353975ab7f0bec Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Mon, 13 Oct 2025 13:04:27 -0400
Subject: [PATCH] wayland: Better handle event times that cross zero
Detect times that cross forward/backward across the zero timepoint, and handle them appropriately, so that events with an old timestamp don't mangle the time base offset, or have their timestamps mangled.
---
src/video/wayland/SDL_waylandevents.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 48ef0dea79061..695af204a8258 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -215,16 +215,32 @@ static Uint64 Wayland_AdjustEventTimestampBase(Uint64 nsTimestamp)
*/
static Uint64 Wayland_EventTimestampMSToNS(Uint32 wl_timestamp_ms)
{
+ static const Uint32 ROLLOVER_INTERVAL_LOW = SDL_MAX_UINT32 / 16;
+ static const Uint32 ROLLOVER_INTERVAL_HIGH = ROLLOVER_INTERVAL_LOW * 15;
+
static Uint64 timestamp_offset = 0;
static Uint32 last = 0;
+ Uint64 timestamp = SDL_MS_TO_NS(wl_timestamp_ms) + timestamp_offset;
- // Handle 32-bit timer rollover.
- if (wl_timestamp_ms < last) {
- timestamp_offset += SDL_MS_TO_NS(SDL_UINT64_C(0x100000000));
+ if (wl_timestamp_ms >= last) {
+ if (timestamp_offset && last < ROLLOVER_INTERVAL_LOW && wl_timestamp_ms > ROLLOVER_INTERVAL_HIGH) {
+ // A time that crossed backwards across zero was received. Subtract the increased time base offset.
+ timestamp -= SDL_MS_TO_NS(SDL_UINT64_C(0x100000000));
+ } else {
+ last = wl_timestamp_ms;
+ }
+ } else {
+ /* Only increment the base time offset if the timer actually crossed forward across 0,
+ * and not if this is just a timestamp from a slightly older event.
+ */
+ if (wl_timestamp_ms < ROLLOVER_INTERVAL_LOW && last > ROLLOVER_INTERVAL_HIGH) {
+ timestamp_offset += SDL_MS_TO_NS(SDL_UINT64_C(0x100000000));
+ timestamp += SDL_MS_TO_NS(SDL_UINT64_C(0x100000000));
+ last = wl_timestamp_ms;
+ }
}
- last = wl_timestamp_ms;
- return SDL_MS_TO_NS(wl_timestamp_ms) + timestamp_offset;
+ return timestamp;
}
/* Even if high-res timestamps are available, the millisecond timestamps are still processed