From 82e838f1fdadd7dd346f4bce51c6ebdd1e26dd35 Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Tue, 28 Nov 2023 16:35:39 +0100 Subject: Adds OpenGL swap_interval for Wayland and X11. --- src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H | 2 + .../Wayland/Fl_Wayland_Gl_Window_Driver.cxx | 18 +++++ src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx | 87 +++++++++++++++++----- 3 files changed, 88 insertions(+), 19 deletions(-) diff --git a/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H b/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H index 83b13e155..df321fc10 100644 --- a/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H +++ b/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H @@ -46,6 +46,8 @@ private: void swap_buffers() FL_OVERRIDE; void resize(int is_a_resize, int w, int h) FL_OVERRIDE; char swap_type() FL_OVERRIDE; + void swap_interval(int) FL_OVERRIDE; + int swap_interval() const FL_OVERRIDE; Fl_Gl_Choice *find(int m, const int *alistp) FL_OVERRIDE; GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) FL_OVERRIDE; void set_gl_context(Fl_Window* w, GLContext context) FL_OVERRIDE; diff --git a/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx index 4553c1a0e..ac625fe6f 100644 --- a/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx @@ -63,6 +63,9 @@ struct gl_start_support { // to support use of gl_start / gl_finish static EGLConfig wld_egl_conf = NULL; +static EGLint swap_interval_ = 1; +static EGLint max_swap_interval = 1000; +static EGLint min_swap_interval = 0; EGLDisplay Fl_Wayland_Gl_Window_Driver::egl_display = EGL_NO_DISPLAY; @@ -170,6 +173,9 @@ Fl_Gl_Choice *Fl_Wayland_Gl_Window_Driver::find(int m, const int *alistp) Fl::fatal("failed to choose an EGL config\n"); } + eglGetConfigAttrib(egl_display, g->egl_conf, EGL_MAX_SWAP_INTERVAL, &max_swap_interval); + eglGetConfigAttrib(egl_display, g->egl_conf, EGL_MIN_SWAP_INTERVAL, &min_swap_interval); + first = g; return g; } @@ -431,6 +437,18 @@ void Fl_Wayland_Gl_Window_Driver::gl_start() { glClear(GL_COLOR_BUFFER_BIT); } +void Fl_Wayland_Gl_Window_Driver::swap_interval(int interval) { + if (interval < min_swap_interval) interval = min_swap_interval; + if (interval > max_swap_interval) interval = max_swap_interval; + if (egl_display && eglSwapInterval(egl_display, interval)) + swap_interval_ = interval; + // printf("swap_interval_=%d\n",swap_interval_); +} + + +int Fl_Wayland_Gl_Window_Driver::swap_interval() const { + return swap_interval_; +} FL_EXPORT EGLContext fl_wl_glcontext(GLContext rc) { return (EGLContext)rc; } diff --git a/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx b/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx index fd07308fa..c2611e739 100644 --- a/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx +++ b/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx @@ -397,41 +397,90 @@ char Fl_X11_Gl_Window_Driver::swap_type() { return copy; } -typedef void (*SWAPINTERVALPROC) (Display *dpy, GLXDrawable drawable, int interval); -static SWAPINTERVALPROC glXSwapIntervalEXT = NULL; -static bool glXSwapIntervalChecked = false; -static void checkGlxXSwapInterval() { - if (!glXSwapIntervalChecked) { - glXSwapIntervalChecked = true; - glXSwapIntervalEXT = (SWAPINTERVALPROC)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT"); + +// Start of swap_interval implementation in the three possibel ways for X11 + +// -1 = not yet initialized, 0 = none found, 1 = GLX, 2 = MESA, 3 = SGI +static signed char swap_interval_type = -1; + +typedef void (*GLX_Set_Swap_Iterval_Proc) (Display *dpy, GLXDrawable drawable, int interval); +typedef int (*MESA_Set_Swap_Iterval_Proc) (unsigned int interval); +typedef int (*MESA_Get_Swap_Iterval_Proc) (); +typedef int (*SGI_Set_Swap_Iterval_Proc) (int interval); + +static union { + GLX_Set_Swap_Iterval_Proc glXSwapIntervalEXT = NULL; + MESA_Set_Swap_Iterval_Proc glXSwapIntervalMESA; + SGI_Set_Swap_Iterval_Proc glXSwapIntervalSGI; +}; + +static MESA_Get_Swap_Iterval_Proc glXGetSwapIntervalMESA = NULL; + +static void init_swap_interval() { + if (swap_interval_type != -1) return; + int major = 1, minor = 0; + glXQueryVersion(fl_display, &major, &minor); + swap_interval_type = 0; + const char *extensions = glXQueryExtensionsString(fl_display, fl_screen); + if (strstr(extensions, "GLX_EXT_swap_control") && ((major > 1) || (minor >= 3))) { + glXSwapIntervalEXT = (GLX_Set_Swap_Iterval_Proc)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT"); + swap_interval_type = 1; + } else if (strstr(extensions, "GLX_MESA_swap_control")) { + glXSwapIntervalMESA = (MESA_Set_Swap_Iterval_Proc)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalMESA"); + glXGetSwapIntervalMESA = (MESA_Get_Swap_Iterval_Proc)glXGetProcAddressARB((const GLubyte*)"glXGetSwapIntervalMESA"); + swap_interval_type = 2; + } else if (strstr(extensions, "GLX_SGI_swap_control")) { + glXSwapIntervalSGI = (SGI_Set_Swap_Iterval_Proc)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalSGI"); + swap_interval_type = 3; } } void Fl_X11_Gl_Window_Driver::swap_interval(int interval) { if (!fl_xid(pWindow)) return; - if (!glXSwapIntervalChecked) checkGlxXSwapInterval(); - if (glXSwapIntervalEXT) { - glXSwapIntervalEXT(fl_display, fl_xid(pWindow), interval); + if (swap_interval_type == -1) + init_swap_interval(); + switch (swap_interval_type) { + case 1: + if (glXSwapIntervalEXT) + glXSwapIntervalEXT(fl_display, fl_xid(pWindow), interval); + break; + case 2: + if (glXSwapIntervalMESA) + glXSwapIntervalMESA((unsigned int)interval); + break; + case 3: + if (glXSwapIntervalSGI) + glXSwapIntervalSGI(interval); + break; } } int Fl_X11_Gl_Window_Driver::swap_interval() const { if (!fl_xid(pWindow)) return -1; - if (!glXSwapIntervalChecked) checkGlxXSwapInterval(); - if (!glXSwapIntervalEXT) return -1; - static bool ext_checked = false, ext_exists = false; - if (!ext_checked) { - ext_checked = true; - ext_exists = (strstr(glXQueryExtensionsString(fl_display, fl_screen), "GLX_EXT_swap_control") != NULL); + if (swap_interval_type == -1) + init_swap_interval(); + int interval = -1; + switch (swap_interval_type) { + case 1: { + unsigned int val = 0; + glXQueryDrawable(fl_display, fl_xid(pWindow), 0x20F1 /*GLX_SWAP_INTERVAL_EXT*/, &val); + interval = (int)val; + break; } + case 2: + if (glXGetSwapIntervalMESA) + interval = glXGetSwapIntervalMESA(); + break; + case 3: + // not available + break; } - if (!ext_exists) return -1; - unsigned int interval = -1; - glXQueryDrawable(fl_display, fl_xid(pWindow), 0x20F1 /*GLX_SWAP_INTERVAL_EXT*/, &interval); return interval; } +// end of swap_interval implementation + void Fl_X11_Gl_Window_Driver::waitGL() { glXWaitGL(); } -- cgit v1.2.3