LibWeb/WebGL: Use eglWaitUntilWorkScheduledANGLE instead of glFlush

With the Metal backend, glFlush flushes the command buffer, but doesn't
wait for the commands to be scheduled on the GPU.

eglWaitUntilWorkScheduledANGLE does wait, hence the name.

This fixes flickering on Rive animations rendered with WebGL.
This commit is contained in:
Luke Wilde 2025-03-23 11:27:39 +00:00 committed by Andrew Kaster
commit 3139f6a25a
Notes: github-actions[bot] 2025-06-09 21:41:43 +00:00
4 changed files with 29 additions and 20 deletions

View file

@ -13,7 +13,10 @@
#ifdef AK_OS_MACOS
# include <EGL/egl.h>
# include <EGL/eglext.h>
# define EGL_EGLEXT_PROTOTYPES 1
extern "C" {
# include <EGL/eglext_angle.h>
}
# define GL_GLEXT_PROTOTYPES 1
# include <GLES2/gl2.h>
# include <GLES2/gl2ext.h>
@ -245,6 +248,28 @@ void OpenGLContext::make_current()
#endif
}
void OpenGLContext::present(bool preserve_drawing_buffer)
{
make_current();
// "Before the drawing buffer is presented for compositing the implementation shall ensure that all rendering operations have been flushed to the drawing buffer."
// With Metal, glFlush flushes the command buffer, but without waiting for it to be scheduled or completed.
// eglWaitUntilWorkScheduledANGLE flushes the command buffer, and waits until it has been scheduled, hence the name.
// eglWaitUntilWorkScheduledANGLE only has an effect on CGL and Metal backends, so we only use it on macOS.
#ifdef AK_OS_MACOS
eglWaitUntilWorkScheduledANGLE(m_impl->display);
#else
// FIXME: When enabling WebGL for Linux, we need to use glFlush() here.
#endif
// "By default, after compositing the contents of the drawing buffer shall be cleared to their default values, as shown in the table above.
// This default behavior can be changed by setting the preserveDrawingBuffer attribute of the WebGLContextAttributes object.
// If this flag is true, the contents of the drawing buffer shall be preserved until the author either clears or overwrites them."
if (!preserve_drawing_buffer) {
clear_buffer_to_default_values();
}
}
RefPtr<Gfx::PaintingSurface> OpenGLContext::surface()
{
return m_painting_surface;