wayland: Avoid busy waiting for vsync
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
diff --git a/src/video/wayland/SDL_waylandopengles.c b/src/video/wayland/SDL_waylandopengles.c
index 874da8e..f4beb8b 100644
--- a/src/video/wayland/SDL_waylandopengles.c
+++ b/src/video/wayland/SDL_waylandopengles.c
@@ -130,14 +130,28 @@ Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
struct wl_display *display = ((SDL_VideoData *)_this->driverdata)->display;
SDL_VideoDisplay *sdldisplay = SDL_GetDisplayForWindow(window);
const Uint32 max_wait = SDL_GetTicks() + (10000 / sdldisplay->current_mode.refresh_rate); /* ~10 frames, so we'll progress even if throttled to zero. */
- while ((SDL_AtomicGet(&data->swap_interval_ready) == 0) && (!SDL_TICKS_PASSED(SDL_GetTicks(), max_wait))) {
+ while (SDL_AtomicGet(&data->swap_interval_ready) == 0) {
+ Uint32 now;
+
/* !!! FIXME: this is just the crucial piece of Wayland_PumpEvents */
WAYLAND_wl_display_flush(display);
- if (SDL_IOReady(WAYLAND_wl_display_get_fd(display), SDL_FALSE, 0)) {
- WAYLAND_wl_display_dispatch(display);
- } else {
- WAYLAND_wl_display_dispatch_pending(display);
+ if (WAYLAND_wl_display_dispatch_pending(display) > 0) {
+ /* We dispatched some pending events. Check if the frame callback happened. */
+ continue;
+ }
+
+ now = SDL_GetTicks();
+ if (SDL_TICKS_PASSED(now, max_wait)) {
+ /* Timeout expired */
+ break;
}
+
+ if (SDL_IOReady(WAYLAND_wl_display_get_fd(display), SDL_FALSE, max_wait - now) <= 0) {
+ /* Error or timeout expired without any events for us */
+ break;
+ }
+
+ WAYLAND_wl_display_dispatch(display);
}
SDL_AtomicSet(&data->swap_interval_ready, 0);
}