mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-02 15:46:33 +00:00
LibGfx: Free WebGL painting surface resources on resize
If a WebGL canvas is resized through the set_size function, we will re-create the painting surface. However, this currently leaks all of the associated EGL/OpenGL objects. This change introduces the free_surface_resources function which will free all resources associated with the painting surface. It will be called before allocating a new surface and during context destruction. It keeps track of the OpenGL texture for the color buffer in m_impl instead of just storing it on the stack.
This commit is contained in:
parent
41f1e920d8
commit
df09472d4d
Notes:
github-actions[bot]
2025-08-18 22:31:44 +00:00
Author: https://github.com/erik-kz
Commit: df09472d4d
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5864
Reviewed-by: https://github.com/kalenikaliaksandr ✅
2 changed files with 36 additions and 8 deletions
|
@ -35,6 +35,7 @@ struct OpenGLContext::Impl {
|
|||
EGLSurface surface { nullptr };
|
||||
|
||||
GLuint framebuffer { 0 };
|
||||
GLuint color_buffer { 0 };
|
||||
GLuint depth_buffer { 0 };
|
||||
#endif
|
||||
};
|
||||
|
@ -49,15 +50,38 @@ OpenGLContext::OpenGLContext(NonnullRefPtr<Gfx::SkiaBackendContext> skia_backend
|
|||
OpenGLContext::~OpenGLContext()
|
||||
{
|
||||
#ifdef AK_OS_MACOS
|
||||
free_surface_resources();
|
||||
eglMakeCurrent(m_impl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
glDeleteFramebuffers(1, &m_impl->framebuffer);
|
||||
glDeleteRenderbuffers(1, &m_impl->depth_buffer);
|
||||
eglDestroyContext(m_impl->display, m_impl->context);
|
||||
eglReleaseTexImage(m_impl->display, m_impl->surface, EGL_BACK_BUFFER);
|
||||
eglDestroySurface(m_impl->display, m_impl->surface);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
void OpenGLContext::free_surface_resources()
|
||||
{
|
||||
if (m_impl->framebuffer) {
|
||||
glDeleteFramebuffers(1, &m_impl->framebuffer);
|
||||
m_impl->framebuffer = 0;
|
||||
}
|
||||
|
||||
if (m_impl->color_buffer) {
|
||||
glDeleteTextures(1, &m_impl->color_buffer);
|
||||
m_impl->color_buffer = 0;
|
||||
}
|
||||
|
||||
if (m_impl->depth_buffer) {
|
||||
glDeleteRenderbuffers(1, &m_impl->depth_buffer);
|
||||
m_impl->depth_buffer = 0;
|
||||
}
|
||||
|
||||
if (m_impl->surface != EGL_NO_SURFACE) {
|
||||
eglReleaseTexImage(m_impl->display, m_impl->surface, EGL_BACK_BUFFER);
|
||||
eglDestroySurface(m_impl->display, m_impl->surface);
|
||||
m_impl->surface = EGL_NO_SURFACE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
static EGLConfig get_egl_config(EGLDisplay display)
|
||||
{
|
||||
|
@ -174,6 +198,7 @@ void OpenGLContext::allocate_painting_surface_if_needed()
|
|||
return;
|
||||
|
||||
VERIFY(!m_size.is_empty());
|
||||
free_surface_resources();
|
||||
|
||||
auto iosurface = Core::IOSurfaceHandle::create(m_size.width(), m_size.height());
|
||||
|
||||
|
@ -212,15 +237,14 @@ void OpenGLContext::allocate_painting_surface_if_needed()
|
|||
eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_TARGET_ANGLE, &texture_target_name);
|
||||
VERIFY(texture_target_name == EGL_TEXTURE_RECTANGLE_ANGLE || texture_target_name == EGL_TEXTURE_2D);
|
||||
|
||||
GLuint texture = 0;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(texture_target_name == EGL_TEXTURE_RECTANGLE_ANGLE ? GL_TEXTURE_RECTANGLE_ANGLE : GL_TEXTURE_2D, texture);
|
||||
glGenTextures(1, &m_impl->color_buffer);
|
||||
glBindTexture(texture_target_name == EGL_TEXTURE_RECTANGLE_ANGLE ? GL_TEXTURE_RECTANGLE_ANGLE : GL_TEXTURE_2D, m_impl->color_buffer);
|
||||
auto result = eglBindTexImage(display, m_impl->surface, EGL_BACK_BUFFER);
|
||||
VERIFY(result == EGL_TRUE);
|
||||
|
||||
glGenFramebuffers(1, &m_impl->framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_impl->framebuffer);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target_name == EGL_TEXTURE_RECTANGLE_ANGLE ? GL_TEXTURE_RECTANGLE_ANGLE : GL_TEXTURE_2D, texture, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target_name == EGL_TEXTURE_RECTANGLE_ANGLE ? GL_TEXTURE_RECTANGLE_ANGLE : GL_TEXTURE_2D, m_impl->color_buffer, 0);
|
||||
|
||||
// NOTE: ANGLE doesn't allocate depth buffer for us, so we need to do it manually
|
||||
// FIXME: Depth buffer only needs to be allocated if it's configured in WebGL context attributes
|
||||
|
|
|
@ -50,6 +50,10 @@ private:
|
|||
NonnullOwnPtr<Impl> m_impl;
|
||||
Optional<Vector<String>> m_requestable_extensions;
|
||||
WebGLVersion m_webgl_version;
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
void free_surface_resources();
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue