Disable swap interval in GLX wxGLCanvas implementation too

We need to do it when using XWayland for the same reasons as we had to
do it in the EGL version when using either XWayland or Wayland directly:
without this, we can block for up to 1 second in glXSwapBuffers() if the
window is hidden, see #23512.

Closes #24163.

Closes #24165.
This commit is contained in:
Vadim Zeitlin 2023-12-25 21:42:07 +01:00
parent 11ebffe7b0
commit 3dde6bdeb0
2 changed files with 57 additions and 1 deletions

View file

@ -99,6 +99,8 @@ public:
private:
GLXFBConfig *m_fbc;
void* m_vi;
bool m_swapIntervalSet = false;
};
// ----------------------------------------------------------------------------

View file

@ -124,6 +124,13 @@ typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC)
#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
#endif
namespace
{
constexpr const char* TRACE_GLX = "glx";
} // anonymous namespace
// ----------------------------------------------------------------------------
// wxGLContextAttrs: OpenGL rendering context attributes
// ----------------------------------------------------------------------------
@ -762,12 +769,59 @@ int wxGLCanvasX11::GetGLXVersion()
return s_glxVersion;
}
namespace
{
// Call glXSwapIntervalEXT() if present.
//
// For now just try using EXT_swap_control extension, in principle there is
// also a MESA one, but it's not clear if it's worth falling back on it (or
// preferring to use it?).
void wxGLSetSwapInterval(Display* dpy, GLXDrawable drawable, int interval)
{
typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display *dpy,
GLXDrawable drawable,
int interval);
static PFNGLXSWAPINTERVALEXTPROC s_glXSwapIntervalEXT = nullptr;
static bool s_glXSwapIntervalEXTInit = false;
if ( !s_glXSwapIntervalEXTInit )
{
s_glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT");
s_glXSwapIntervalEXTInit = true;
}
if ( s_glXSwapIntervalEXT )
{
wxLogTrace(TRACE_GLX, "Setting GLX swap interval to %d", interval);
s_glXSwapIntervalEXT(dpy, drawable, interval);
}
}
} // anonymous namespace
bool wxGLCanvasX11::SwapBuffers()
{
const Window xid = GetXWindow();
wxCHECK2_MSG( xid, return false, wxT("window must be shown") );
glXSwapBuffers(wxGetX11Display(), xid);
const auto dpy = wxGetX11Display();
// Disable blocking in glXSwapBuffers, as this is needed under XWayland for
// the reasons explained in wxGLCanvasEGL::SwapBuffers().
if ( !m_swapIntervalSet )
{
wxGLSetSwapInterval(dpy, xid, 0);
// Don't try again in any case, if we failed this time, we'll fail the
// next one anyhow.
m_swapIntervalSet = true;
}
glXSwapBuffers(dpy, xid);
return true;
}