From 0cbc5296400cbde30ae31a83c9d916b2f2434f2a Mon Sep 17 00:00:00 2001 From: Quantum Date: Mon, 19 Jul 2021 04:01:19 -0400 Subject: [PATCH] [client] ds: refactor common EGL swap with damage logic This commit creates a new utility library, eglutil.h, which contains code to detect and use EGL_KHR_swap_buffers_with_damage or its EXT equivalent. This logic used to be duplicated between the X11 and Wayland display servers, which is not ideal. --- client/CMakeLists.txt | 1 + client/displayservers/Wayland/gl.c | 47 +++------------- client/displayservers/Wayland/wayland.h | 6 +- client/displayservers/X11/x11.c | 38 ++----------- client/include/eglutil.h | 41 ++++++++++++++ client/src/eglutil.c | 73 +++++++++++++++++++++++++ 6 files changed, 129 insertions(+), 77 deletions(-) create mode 100644 client/include/eglutil.h create mode 100644 client/src/eglutil.c diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 71861cd6..648988dd 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -119,6 +119,7 @@ set(SOURCES src/clipboard.c src/kb.c src/egl_dynprocs.c + src/eglutil.c ) # Force cimgui to build as a static library. diff --git a/client/displayservers/Wayland/gl.c b/client/displayservers/Wayland/gl.c index 73309309..cbef6b3d 100644 --- a/client/displayservers/Wayland/gl.c +++ b/client/displayservers/Wayland/gl.c @@ -32,6 +32,7 @@ #if defined(ENABLE_EGL) || defined(ENABLE_OPENGL) #include "egl_dynprocs.h" +#include "eglutil.h" bool waylandEGLInit(int w, int h) { @@ -71,53 +72,19 @@ EGLDisplay waylandGetEGLDisplay(void) void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct Rect * damage, int count) { - if (!wlWm.eglSwapWithDamageInit) + if (!wlWm.swapWithDamage.init) { - const char *exts = eglQueryString(display, EGL_EXTENSIONS); - wlWm.eglSwapWithDamageInit = true; if (wl_proxy_get_version((struct wl_proxy *) wlWm.surface) < 4) + { DEBUG_INFO("Swapping buffers with damage: not supported, need wl_compositor v4"); - else if (util_hasGLExt(exts, "EGL_KHR_swap_buffers_with_damage") && g_egl_dynProcs.eglSwapBuffersWithDamageKHR) - { - wlWm.eglSwapWithDamage = g_egl_dynProcs.eglSwapBuffersWithDamageKHR; - DEBUG_INFO("Using EGL_KHR_swap_buffers_with_damage"); - } - else if (util_hasGLExt(exts, "EGL_EXT_swap_buffers_with_damage") && g_egl_dynProcs.eglSwapBuffersWithDamageEXT) - { - wlWm.eglSwapWithDamage = g_egl_dynProcs.eglSwapBuffersWithDamageEXT; - DEBUG_INFO("Using EGL_EXT_swap_buffers_with_damage"); + swapWithDamageDisable(&wlWm.swapWithDamage); } else - DEBUG_INFO("Swapping buffers with damage: not supported"); + swapWithDamageInit(&wlWm.swapWithDamage, display); } - if (wlWm.eglSwapWithDamage && count) - { - if (count * 4 > wlWm.eglDamageRectCount) - { - free(wlWm.eglDamageRects); - wlWm.eglDamageRects = malloc(sizeof(EGLint) * count * 4); - if (!wlWm.eglDamageRects) - DEBUG_FATAL("Out of memory"); - wlWm.eglDamageRectCount = count * 4; - } - - for (int i = 0; i < count; ++i) - { - wlWm.eglDamageRects[i*4+0] = damage[i].x; - wlWm.eglDamageRects[i*4+1] = damage[i].y; - wlWm.eglDamageRects[i*4+2] = damage[i].w; - wlWm.eglDamageRects[i*4+3] = damage[i].h; - } - - waylandPresentationFrame(); - wlWm.eglSwapWithDamage(display, surface, wlWm.eglDamageRects, count); - } - else - { - waylandPresentationFrame(); - eglSwapBuffers(display, surface); - } + waylandPresentationFrame(); + swapWithDamage(&wlWm.swapWithDamage, display, surface, damage, count); if (wlWm.needsResize) { diff --git a/client/displayservers/Wayland/wayland.h b/client/displayservers/Wayland/wayland.h index 5cabe320..a4442d65 100644 --- a/client/displayservers/Wayland/wayland.h +++ b/client/displayservers/Wayland/wayland.h @@ -27,6 +27,7 @@ # include # include # include +# include "eglutil.h" #endif #include "app.h" @@ -101,10 +102,7 @@ struct WaylandDSState #if defined(ENABLE_EGL) || defined(ENABLE_OPENGL) struct wl_egl_window * eglWindow; - bool eglSwapWithDamageInit; - eglSwapBuffersWithDamageKHR_t eglSwapWithDamage; - EGLint * eglDamageRects; - int eglDamageRectCount; + struct SwapWithDamageData swapWithDamage; #endif #ifdef ENABLE_OPENGL diff --git a/client/displayservers/X11/x11.c b/client/displayservers/X11/x11.c index c3ffae74..2ab504f2 100644 --- a/client/displayservers/X11/x11.c +++ b/client/displayservers/X11/x11.c @@ -38,6 +38,7 @@ #ifdef ENABLE_EGL #include #include "egl_dynprocs.h" +#include "eglutil.h" #endif #include "app.h" @@ -943,40 +944,11 @@ static EGLNativeWindowType x11GetEGLNativeWindow(void) static void x11EGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct Rect * damage, int count) { - static bool detectDone = false; - static eglSwapBuffersWithDamageKHR_t swapWithDamage = NULL; + static struct SwapWithDamageData data = {0}; + if (!data.init) + swapWithDamageInit(&data, display); - if (!detectDone) - { - const char *exts = eglQueryString(display, EGL_EXTENSIONS); - DEBUG_INFO("%s", exts); - if (util_hasGLExt(exts, "EGL_KHR_swap_buffers_with_damage")) - swapWithDamage = g_egl_dynProcs.eglSwapBuffersWithDamageKHR; - else if (util_hasGLExt(exts, "EGL_EXT_swap_buffers_with_damage")) - swapWithDamage = g_egl_dynProcs.eglSwapBuffersWithDamageEXT; - - if (swapWithDamage) - DEBUG_INFO("Using eglSwapBuffersWithDamage"); - - detectDone = true; - } - - if (swapWithDamage && count) - { - EGLint rects[count*4]; - EGLint *p = rects; - for(int i = 0; i < count; ++i, p += 4) - { - p[0] = damage[i].x; - p[1] = damage[i].y; - p[2] = damage[i].w; - p[3] = damage[i].h; - } - - swapWithDamage(display, surface, rects, count); - } - else - eglSwapBuffers(display, surface); + swapWithDamage(&data, display, surface, damage, count); } #endif diff --git a/client/include/eglutil.h b/client/include/eglutil.h new file mode 100644 index 00000000..f6a17641 --- /dev/null +++ b/client/include/eglutil.h @@ -0,0 +1,41 @@ +/** + * Looking Glass + * Copyright (C) 2017-2021 The Looking Glass Authors + * https://looking-glass.io + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _H_LG_GLUTIL_ +#define _H_LG_GLUTIL_ + +#include +#include + +#include "common/types.h" +#include "egl_dynprocs.h" + +struct SwapWithDamageData +{ + bool init; + eglSwapBuffersWithDamageKHR_t func; +}; + +void swapWithDamageInit(struct SwapWithDamageData * data, EGLDisplay display); +void swapWithDamageDisable(struct SwapWithDamageData * data); +void swapWithDamage(struct SwapWithDamageData * data, EGLDisplay display, EGLSurface surface, + const struct Rect * damage, int count); + +#endif diff --git a/client/src/eglutil.c b/client/src/eglutil.c new file mode 100644 index 00000000..9090ce4b --- /dev/null +++ b/client/src/eglutil.c @@ -0,0 +1,73 @@ +/** + * Looking Glass + * Copyright (C) 2017-2021 The Looking Glass Authors + * https://looking-glass.io + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "eglutil.h" + +#include "common/debug.h" +#include "egl_dynprocs.h" +#include "util.h" + +void swapWithDamageInit(struct SwapWithDamageData * data, EGLDisplay display) +{ + const char *exts = eglQueryString(display, EGL_EXTENSIONS); + data->init = true; + + if (util_hasGLExt(exts, "EGL_KHR_swap_buffers_with_damage") && g_egl_dynProcs.eglSwapBuffersWithDamageKHR) + { + data->func = g_egl_dynProcs.eglSwapBuffersWithDamageKHR; + DEBUG_INFO("Using EGL_KHR_swap_buffers_with_damage"); + } + else if (util_hasGLExt(exts, "EGL_EXT_swap_buffers_with_damage") && g_egl_dynProcs.eglSwapBuffersWithDamageEXT) + { + data->func = g_egl_dynProcs.eglSwapBuffersWithDamageEXT; + DEBUG_INFO("Using EGL_EXT_swap_buffers_with_damage"); + } + else + { + data->func = NULL; + DEBUG_INFO("Swapping buffers with damage: not supported"); + } +} + +void swapWithDamageDisable(struct SwapWithDamageData * data) +{ + data->init = false; + data->func = NULL; +} + +void swapWithDamage(struct SwapWithDamageData * data, EGLDisplay display, EGLSurface surface, + const struct Rect * damage, int count) +{ + if (!data->func || !count) + { + eglSwapBuffers(display, surface); + return; + } + + EGLint rects[count * 4]; + for (int i = 0; i < count; ++i) + { + rects[i * 4 + 0] = damage[i].x; + rects[i * 4 + 1] = damage[i].y; + rects[i * 4 + 2] = damage[i].w; + rects[i * 4 + 3] = damage[i].h; + } + data->func(display, surface, rects, count); +}