From 72dfa74b3eabea80d8a3581ed3be9d7422a6067c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 28 Jun 2022 09:25:24 +0530 Subject: [PATCH] Avoid an extra buffer swap during startup glfw should not be swapping buffers behind the clients back. Since we control the client, we can ensure that the OpenGL VRAM is cleared before the window is shown. Also fixes the issue with the glfw wayland backend where the buffer was being created before the surface was configured --- glfw/context.c | 9 --------- glfw/wl_window.c | 4 ++++ kitty/glfw.c | 37 +++++++++++++++---------------------- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/glfw/context.c b/glfw/context.c index b2d9199af..67e5dd402 100644 --- a/glfw/context.c +++ b/glfw/context.c @@ -396,15 +396,6 @@ bool _glfwRefreshContextAttribs(_GLFWwindow* window, window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH; } - // Clearing the front buffer to black to avoid garbage pixels left over from - // previous uses of our bit of VRAM - { - PFNGLCLEARPROC glClear = (PFNGLCLEARPROC) - window->context.getProcAddress("glClear"); - glClear(GL_COLOR_BUFFER_BIT); - window->context.swapBuffers(window); - } - glfwMakeContextCurrent((GLFWwindow*) previous); return true; } diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 8423bcb9f..5c5deaf49 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -496,6 +496,9 @@ static void xdgSurfaceHandleConfigure(void* data, int height = window->wl.pending.height; if (!window->wl.surface_configured_once) { window->wl.surface_configured_once = true; + // this will attach the buffer to the surface, the client is responsible for clearing the buffer to an appropriate blank + window->context.swapBuffers(window); + if (!width && !height && !new_states && !window->wl.decorations.serverSide && getenv("XAUTHORITY") && strstr(getenv("XAUTHORITY"), "mutter")) { // https://github.com/kovidgoyal/kitty/issues/4802 debug("Ignoring first empty surface configure event on mutter.\n"); @@ -1062,6 +1065,7 @@ void _glfwPlatformHideWindow(_GLFWwindow* window) xdg_surface_destroy(window->wl.xdg.surface); window->wl.xdg.toplevel = NULL; window->wl.xdg.surface = NULL; + window->wl.surface_configured_once = false; } window->wl.visible = false; } diff --git a/kitty/glfw.c b/kitty/glfw.c index 500a513f1..b6af74148 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -811,12 +811,6 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { if (ret == NULL) return NULL; int width = PyLong_AsLong(PyTuple_GET_ITEM(ret, 0)), height = PyLong_AsLong(PyTuple_GET_ITEM(ret, 1)); Py_CLEAR(ret); - // The GLFW Wayland backend cannot create and show windows separately so we - // cannot call the pre_show_callback. See - // https://github.com/glfw/glfw/issues/1268 It doesn't matter since there - // is no startup notification in Wayland anyway. It amazes me that anyone - // uses Wayland as anything other than a butt for jokes. - if (global_state.is_wayland) glfwWindowHint(GLFW_VISIBLE, true); GLFWwindow *glfw_window = glfwCreateWindow(width, height, title, NULL, temp_window ? temp_window : common_context); if (temp_window) { glfwDestroyWindow(temp_window); temp_window = NULL; } if (glfw_window == NULL) { PyErr_SetString(PyExc_ValueError, "Failed to create GLFWwindow"); return NULL; } @@ -831,25 +825,24 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { #ifndef __APPLE__ if (is_first_window) glfwSwapInterval(OPT(sync_to_monitor) && !global_state.is_wayland ? 1 : 0); #endif - glfwSwapBuffers(glfw_window); + // On Wayland the initial swap is allowed only after the first XDG configure event + if (!global_state.is_wayland) glfwSwapBuffers(glfw_window); glfwSetInputMode(glfw_window, GLFW_LOCK_KEY_MODS, true); - if (!global_state.is_wayland) { - PyObject *pret = PyObject_CallFunction(pre_show_callback, "N", native_window_handle(glfw_window)); - if (pret == NULL) return NULL; - Py_DECREF(pret); - if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y); - glfwShowWindow(glfw_window); + PyObject *pret = PyObject_CallFunction(pre_show_callback, "N", native_window_handle(glfw_window)); + if (pret == NULL) return NULL; + Py_DECREF(pret); + if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y); + glfwShowWindow(glfw_window); #ifdef __APPLE__ - float n_xscale, n_yscale; - double n_xdpi, n_ydpi; - get_window_content_scale(glfw_window, &n_xscale, &n_yscale, &n_xdpi, &n_ydpi); - if (n_xdpi != xdpi || n_ydpi != ydpi) { - // this can happen if the window is moved by the OS to a different monitor when shown - xdpi = n_xdpi; ydpi = n_ydpi; - fonts_data = load_fonts_data(OPT(font_size), xdpi, ydpi); - } -#endif + float n_xscale, n_yscale; + double n_xdpi, n_ydpi; + get_window_content_scale(glfw_window, &n_xscale, &n_yscale, &n_xdpi, &n_ydpi); + if (n_xdpi != xdpi || n_ydpi != ydpi) { + // this can happen if the window is moved by the OS to a different monitor when shown + xdpi = n_xdpi; ydpi = n_ydpi; + fonts_data = load_fonts_data(OPT(font_size), xdpi, ydpi); } +#endif if (is_first_window) { PyObject *ret = PyObject_CallFunction(load_programs, "O", is_semi_transparent ? Py_True : Py_False); if (ret == NULL) return NULL;