From 1df907b1ba3b206a5e336176cac4c78b4f58e4ea Mon Sep 17 00:00:00 2001 From: vanfanel 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);