From 0189553bed9cd8e3032428008a33aaf4d1bcfcec Mon Sep 17 00:00:00 2001 From: Erik Kurzinger Date: Thu, 28 Aug 2025 11:08:37 -0400 Subject: [PATCH] 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. --- Libraries/LibWeb/WebGL/OpenGLContext.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Libraries/LibWeb/WebGL/OpenGLContext.cpp b/Libraries/LibWeb/WebGL/OpenGLContext.cpp index fb16795b1e2..1cfdd72bd6b 100644 --- a/Libraries/LibWeb/WebGL/OpenGLContext.cpp +++ b/Libraries/LibWeb/WebGL/OpenGLContext.cpp @@ -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);