From 4bceaf550574ac793f8c6e6e4ddd0c69e3e53271 Mon Sep 17 00:00:00 2001 From: Tudor Brindus <me@tbrindus.ca> Date: Sun, 3 Jan 2021 21:09:55 -0500 Subject: [PATCH] [client] fix hang in eglSwapBuffers when exiting while not visible eglSwapBuffers is allowed to block when called with a nonzero interval parameter. On Wayland, Mesa will block until a frame callback arrives. If an application is not visible, a compositor is free to not schedule frame callbacks (in order to save CPU time rendering something that is entirely invisible). Currently, starting Looking Glass from a terminal, hiding it entirely, and sending ^C will cause Looking Glass to hang joining the render thread until the window is made visible again. Calling eglDestroySurface is insufficient to unblock eglSwapBuffers, as it attempts to grab the same underlying mutex. Instead, this commit makes it so that we pass a 0 interval to eglSwapBuffers when running on Wayland, such that we don't block waiting for a frame callback. This is not entirely ideal as it *does* mean Looking Glass submits buffers while hidden, but it seems better than hanging on exit. It also forces opengl:vsync and egl:vsync flags to off when running on Wayland, as they are meaningless there. --- client/renderers/EGL/egl.c | 13 ++++++++++++- client/renderers/OpenGL/opengl.c | 14 +++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/client/renderers/EGL/egl.c b/client/renderers/EGL/egl.c index d194f566..36b888bd 100644 --- a/client/renderers/EGL/egl.c +++ b/client/renderers/EGL/egl.c @@ -97,6 +97,16 @@ struct Inst LG_FontObj fontObj; }; +static bool egl_vsync_option_validator(struct Option * opt, const char ** error) +{ + if (opt->value.x_bool && getenv("WAYLAND_DISPLAY")) + { + DEBUG_WARN("Cannot disable vsync on Wayland, forcing egl:vsync=off"); + opt->value.x_bool = false; + } + + return true; +} static struct Option egl_options[] = { @@ -105,7 +115,8 @@ static struct Option egl_options[] = .name = "vsync", .description = "Enable vsync", .type = OPTION_TYPE_BOOL, - .value.x_bool = false + .value.x_bool = false, + .validator = &vsync_option_validator }, { .module = "egl", diff --git a/client/renderers/OpenGL/opengl.c b/client/renderers/OpenGL/opengl.c index a00f46ae..f99fbf8d 100644 --- a/client/renderers/OpenGL/opengl.c +++ b/client/renderers/OpenGL/opengl.c @@ -48,6 +48,17 @@ Place, Suite 330, Boston, MA 02111-1307 USA #define FADE_TIME 1000000 +static bool opengl_vsync_option_validator(struct Option * opt, const char ** error) +{ + if (opt->value.x_bool && getenv("WAYLAND_DISPLAY")) + { + DEBUG_WARN("Cannot disable vsync on Wayland, forcing opengl:vsync=off"); + opt->value.x_bool = false; + } + + return true; +} + static struct Option opengl_options[] = { { @@ -62,7 +73,8 @@ static struct Option opengl_options[] = .name = "vsync", .description = "Enable vsync", .type = OPTION_TYPE_BOOL, - .value.x_bool = false + .value.x_bool = false, + .validator = &vsync_option_validator }, { .module = "opengl",