LibWeb/WebGL: Avoid freeing GL objects belonging to other contexts

The free_surface_resources() function in OpenGLContext.cpp is
responsible for freeing all GL and EGL objects tied to the lifetime of
the painting surface. It is called when the associated canvas is resized
or destroyed. However, if there are multiple WebGL canvases and another
canvas's context is current when the function is called, it will
unintentionally free GL objects belonging to that other context.

To fix this, we call eglMakeCurrent at the start of
free_surface_resources(). This ensures that we will be deleting the
intended objects.

Note that m_impl->surface could be EGL_NO_SURFACE if
free_surface_resources() is called before the painting surface has been
created, but that should be fine. EGL_KHR_surfaceless_context support is
ubiquitous at this point.
This commit is contained in:
Erik Kurzinger 2025-08-28 11:08:37 -04:00 committed by Alexander Kalenik
commit 0189553bed
Notes: github-actions[bot] 2025-08-30 13:50:22 +00:00

View file

@ -31,10 +31,10 @@ extern "C" {
namespace Web::WebGL {
struct OpenGLContext::Impl {
EGLDisplay display { nullptr };
EGLConfig config { nullptr };
EGLContext context { nullptr };
EGLSurface surface { nullptr };
EGLDisplay display { EGL_NO_DISPLAY };
EGLConfig config { EGL_NO_CONFIG_KHR };
EGLContext context { EGL_NO_CONTEXT };
EGLSurface surface { EGL_NO_SURFACE };
GLuint framebuffer { 0 };
GLuint color_buffer { 0 };
@ -69,6 +69,8 @@ OpenGLContext::~OpenGLContext()
void OpenGLContext::free_surface_resources()
{
#ifdef ENABLE_WEBGL
eglMakeCurrent(m_impl->display, m_impl->surface, m_impl->surface, m_impl->context);
if (m_impl->framebuffer) {
glDeleteFramebuffers(1, &m_impl->framebuffer);
m_impl->framebuffer = 0;
@ -377,6 +379,7 @@ void OpenGLContext::allocate_painting_surface_if_needed()
allocate_vkimage_painting_surface();
# endif
VERIFY(m_painting_surface);
VERIFY(eglGetCurrentContext() == m_impl->context);
glGenFramebuffers(1, &m_impl->framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_impl->framebuffer);