From 1df907b1ba3b206a5e336176cac4c78b4f58e4ea Mon Sep 17 00:00:00 2001
From: vanfanel <[EMAIL REDACTED]>
Date: Wed, 17 Jul 2024 20:40:30 +0200
Subject: [PATCH] Add SDL_VIDEO_DOUBLE_BUFFER support to the Wayland backend.
(cherry picked from commit 9e6b8d56e33f77dab507236d84a3f76b6fea7b2a)
---
include/SDL_hints.h | 1 +
src/video/wayland/SDL_waylandopengles.c | 26 ++++++++++++++++++++-----
src/video/wayland/SDL_waylandwindow.c | 5 +++++
src/video/wayland/SDL_waylandwindow.h | 1 +
4 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index a26ab60e869d4..8c38d86edd684 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -1912,6 +1912,7 @@ extern "C" {
* Since it's driver-specific, it's only supported where possible and
* implemented. Currently supported the following drivers:
*
+ * - Wayland (wayland)
* - KMSDRM (kmsdrm)
* - Raspberry Pi (raspberrypi)
*/
diff --git a/src/video/wayland/SDL_waylandopengles.c b/src/video/wayland/SDL_waylandopengles.c
index 22311a63e65fa..c107df9091b98 100644
--- a/src/video/wayland/SDL_waylandopengles.c
+++ b/src/video/wayland/SDL_waylandopengles.c
@@ -120,6 +120,20 @@ int Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
return 0;
}
+ /* By default, we wait for Wayland frame callback and then issue pageflip (eglSwapBuffers),
+ * but if we want low latency (double buffer scheme), we issue the pageflip
+ * and then wait immediately for Wayland frame callback.
+ */
+
+ if (data->double_buffer) {
+ /* Feed the frame to Wayland. This will set it so the wl_surface_frame callback can fire again. */
+ if (!_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, data->egl_surface)) {
+ return SDL_EGL_SetError("unable to show color buffer in an OS-native window", "eglSwapBuffers");
+ }
+
+ WAYLAND_wl_display_flush(data->waylandData->display);
+ }
+
/* Control swap interval ourselves. See comments on Wayland_GLES_SetSwapInterval */
if (swap_interval != 0) {
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
@@ -162,12 +176,14 @@ int Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
SDL_AtomicSet(&data->swap_interval_ready, 0);
}
- /* Feed the frame to Wayland. This will set it so the wl_surface_frame callback can fire again. */
- if (!_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, data->egl_surface)) {
- return SDL_EGL_SetError("unable to show color buffer in an OS-native window", "eglSwapBuffers");
- }
+ if (!data->double_buffer) {
+ /* Feed the frame to Wayland. This will set it so the wl_surface_frame callback can fire again. */
+ if (!_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, data->egl_surface)) {
+ return SDL_EGL_SetError("unable to show color buffer in an OS-native window", "eglSwapBuffers");
+ }
- WAYLAND_wl_display_flush(data->waylandData->display);
+ WAYLAND_wl_display_flush(data->waylandData->display);
+ }
return 0;
}
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index c8d55def1754d..ad89748465f2a 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -2023,6 +2023,11 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
}
}
+ data->double_buffer = SDL_FALSE;
+ if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) {
+ data->double_buffer = SDL_TRUE;
+ }
+
data->outputs = NULL;
data->num_outputs = 0;
diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h
index 36600a4d2783e..e22e6baa64dd4 100644
--- a/src/video/wayland/SDL_waylandwindow.h
+++ b/src/video/wayland/SDL_waylandwindow.h
@@ -116,6 +116,7 @@ typedef struct
SDL_bool is_fullscreen;
SDL_bool in_fullscreen_transition;
Uint32 fullscreen_flags;
+ SDL_bool double_buffer;
} SDL_WindowData;
extern void Wayland_ShowWindow(_THIS, SDL_Window *window);