Skip to content

Commit 45ac258

Browse files
committed
Ensure that we call eglSwapInterval() for the correct context
Calling it from the frame callback might change the swap interval for the wrong context if the active context got changed in the meanwhile, but by the time SwapBuffers() is called the correct context must be set. Doing it there also allows to unify X11 and Wayland code branches. See wxWidgets#24014. (cherry picked from commit 64afa9d)
1 parent 414faff commit 45ac258

File tree

1 file changed

+28
-21
lines changed

1 file changed

+28
-21
lines changed

src/unix/glegl.cpp

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -453,24 +453,6 @@ void wxGLCanvasEGL::OnWLFrameCallback()
453453
#ifdef GDK_WINDOWING_WAYLAND
454454
wxLogTrace(TRACE_EGL, "In frame callback handler for %p", this);
455455

456-
if ( !gs_alreadySetSwapInterval.count(this) )
457-
{
458-
// Ensure that eglSwapBuffers() doesn't block, as we use the surface
459-
// callback to know when we should draw ourselves already.
460-
if ( eglSwapInterval(m_display, 0) )
461-
{
462-
wxLogTrace(TRACE_EGL, "Set EGL swap interval to 0 for %p", this);
463-
464-
// It shouldn't be necessary to set it again.
465-
gs_alreadySetSwapInterval.insert(this);
466-
}
467-
else
468-
{
469-
wxLogTrace(TRACE_EGL, "eglSwapInterval(0) failed for %p: %#x",
470-
this, eglGetError());
471-
}
472-
}
473-
474456
m_readyToDraw = true;
475457
g_clear_pointer(&m_wlFrameCallbackHandler, wl_callback_destroy);
476458
SendSizeEvent();
@@ -803,15 +785,40 @@ void wxGLCanvasEGL::FreeDefaultConfig()
803785

804786
bool wxGLCanvasEGL::SwapBuffers()
805787
{
788+
// Before doing anything else, ensure that eglSwapBuffers() doesn't block:
789+
// under Wayland we don't want it to because we use the surface callback to
790+
// know when we should draw anyhow and with X11 it blocks for up to a
791+
// second when the window is entirely occluded and because we can't detect
792+
// this currently (our IsShownOnScreen() doesn't account for all cases in
793+
// which this happens) we must prevent it from blocking to avoid making the
794+
// entire application completely unusable just because one of its windows
795+
// using wxGLCanvas got occluded or unmapped (e.g. due to a move to another
796+
// workspace).
797+
if ( !gs_alreadySetSwapInterval.count(this) )
798+
{
799+
// Ensure that eglSwapBuffers() doesn't block, as we use the surface
800+
// callback to know when we should draw ourselves already.
801+
if ( eglSwapInterval(m_display, 0) )
802+
{
803+
wxLogTrace(TRACE_EGL, "Set EGL swap interval to 0 for %p", this);
804+
805+
// It shouldn't be necessary to set it again.
806+
gs_alreadySetSwapInterval.insert(this);
807+
}
808+
else
809+
{
810+
wxLogTrace(TRACE_EGL, "eglSwapInterval(0) failed for %p: %#x",
811+
this, eglGetError());
812+
}
813+
}
814+
806815
GdkWindow* const window = GTKGetDrawingWindow();
807816
#ifdef GDK_WINDOWING_X11
808817
if (wxGTKImpl::IsX11(window))
809818
{
810819
if ( !IsShownOnScreen() )
811820
{
812-
// Trying to draw on a hidden window is useless and can actually be
813-
// harmful if the compositor blocks in eglSwapBuffers() in this
814-
// case, so avoid it.
821+
// Trying to draw on a hidden window is useless.
815822
wxLogTrace(TRACE_EGL, "Window %p is hidden, not drawing", this);
816823
return false;
817824
}

0 commit comments

Comments
 (0)