Fix wxGLCanvas performance when using Wayland
See #23554. (cherry picked from commit 414140113c19b100986f340e5875e209fca1fac1)
This commit is contained in:
parent
056023cd3a
commit
0ded71ff10
@ -41,6 +41,8 @@
|
|||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
|
static const char* TRACE_EGL = "glegl";
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxGLContextAttrs: OpenGL rendering context attributes
|
// wxGLContextAttrs: OpenGL rendering context attributes
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -436,6 +438,8 @@ static void wl_frame_callback_handler(void* data,
|
|||||||
struct wl_callback *,
|
struct wl_callback *,
|
||||||
uint32_t)
|
uint32_t)
|
||||||
{
|
{
|
||||||
|
wxLogTrace(TRACE_EGL, "In frame callback handler");
|
||||||
|
|
||||||
wxGLCanvasEGL *glc = static_cast<wxGLCanvasEGL *>(data);
|
wxGLCanvasEGL *glc = static_cast<wxGLCanvasEGL *>(data);
|
||||||
glc->m_readyToDraw = true;
|
glc->m_readyToDraw = true;
|
||||||
g_clear_pointer(&glc->m_wlFrameCallbackHandler, wl_callback_destroy);
|
g_clear_pointer(&glc->m_wlFrameCallbackHandler, wl_callback_destroy);
|
||||||
@ -483,7 +487,6 @@ bool wxGLCanvasEGL::CreateSurface()
|
|||||||
m_xwindow = GDK_WINDOW_XID(window);
|
m_xwindow = GDK_WINDOW_XID(window);
|
||||||
m_surface = eglCreatePlatformWindowSurface(m_display, *m_config,
|
m_surface = eglCreatePlatformWindowSurface(m_display, *m_config,
|
||||||
&m_xwindow, NULL);
|
&m_xwindow, NULL);
|
||||||
m_readyToDraw = true;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef GDK_WINDOWING_WAYLAND
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
@ -520,6 +523,10 @@ bool wxGLCanvasEGL::CreateSurface()
|
|||||||
&wl_frame_listener, this);
|
&wl_frame_listener, this);
|
||||||
g_signal_connect(m_widget, "size-allocate",
|
g_signal_connect(m_widget, "size-allocate",
|
||||||
G_CALLBACK(gtk_glcanvas_size_callback), this);
|
G_CALLBACK(gtk_glcanvas_size_callback), this);
|
||||||
|
|
||||||
|
// Ensure that eglSwapBuffers() doesn't block, as we use the surface
|
||||||
|
// callback to know when we should draw ourselves already.
|
||||||
|
eglSwapInterval(m_display, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -647,11 +654,42 @@ void wxGLCanvasEGL::FreeDefaultConfig()
|
|||||||
|
|
||||||
bool wxGLCanvasEGL::SwapBuffers()
|
bool wxGLCanvasEGL::SwapBuffers()
|
||||||
{
|
{
|
||||||
// Under Wayland, if eglSwapBuffers() is called before the wl_surface has
|
GdkWindow* const window = GTKGetDrawingWindow();
|
||||||
// been realized, it will deadlock. Thus, we need to avoid swapping before
|
#ifdef GDK_WINDOWING_X11
|
||||||
// this has happened.
|
if (wxGTKImpl::IsX11(window))
|
||||||
if ( !m_readyToDraw )
|
{
|
||||||
return false;
|
if ( !IsShownOnScreen() )
|
||||||
|
{
|
||||||
|
// Trying to draw on a hidden window is useless and can actually be
|
||||||
|
// harmful if the compositor blocks in eglSwapBuffers() in this
|
||||||
|
// case, so avoid it.
|
||||||
|
wxLogTrace(TRACE_EGL, "Not drawing hidden window");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // GDK_WINDOWING_X11
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
if (wxGTKImpl::IsWayland(window))
|
||||||
|
{
|
||||||
|
// Under Wayland, we must not draw before we're actually ready to, as
|
||||||
|
// this would be inefficient at best and could result in a deadlock at
|
||||||
|
// worst if we're called before the window is realized.
|
||||||
|
if ( !m_readyToDraw )
|
||||||
|
{
|
||||||
|
wxLogTrace(TRACE_EGL, "Not ready to draw yet");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that we redraw again when the frame becomes ready.
|
||||||
|
m_readyToDraw = false;
|
||||||
|
wl_surface* surface = gdk_wayland_window_get_wl_surface(window);
|
||||||
|
m_wlFrameCallbackHandler = wl_surface_frame(surface);
|
||||||
|
wl_callback_add_listener(m_wlFrameCallbackHandler,
|
||||||
|
&wl_frame_listener, this);
|
||||||
|
}
|
||||||
|
#endif // GDK_WINDOWING_WAYLAND
|
||||||
|
|
||||||
|
wxLogTrace(TRACE_EGL, "Swapping buffers");
|
||||||
|
|
||||||
return eglSwapBuffers(m_display, m_surface);
|
return eglSwapBuffers(m_display, m_surface);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user