gl_engine: fix memoty leak on target resize

We must to remove offscreen render buffers during removing render target

https://github.com/thorvg/thorvg/issues/3210
This commit is contained in:
Sergii Liebodkin 2025-05-22 16:46:57 +03:00
parent 32c38041db
commit ac7f067702
3 changed files with 26 additions and 20 deletions

View file

@ -22,25 +22,18 @@
#include "tvgGlRenderTarget.h"
GlRenderTarget::GlRenderTarget(uint32_t width, uint32_t height): mWidth(width), mHeight(height) {}
GlRenderTarget::GlRenderTarget() {}
GlRenderTarget::~GlRenderTarget()
{
if (mFbo == 0) return;
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
GL_CHECK(glDeleteFramebuffers(1, &mFbo));
if (mColorTex != 0) {
GL_CHECK(glDeleteTextures(1, &mColorTex));
}
if (mDepthStencilBuffer != 0) {
GL_CHECK(glDeleteRenderbuffers(1, &mDepthStencilBuffer));
}
reset();
}
void GlRenderTarget::init(GLint resolveId)
void GlRenderTarget::init(uint32_t width, uint32_t height, GLint resolveId)
{
if (mFbo != GL_INVALID_VALUE || mWidth == 0 || mHeight == 0) return;
if (mFbo != GL_INVALID_VALUE || width == 0 || height == 0) return;
mWidth = width;
mHeight = height;
//TODO: fbo is used. maybe we can consider the direct rendering with resolveId as well.
GL_CHECK(glGenFramebuffers(1, &mFbo));
@ -82,6 +75,18 @@ void GlRenderTarget::init(GLint resolveId)
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, resolveId));
}
void GlRenderTarget::reset()
{
if (mFbo == 0) return;
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
GL_CHECK(glDeleteFramebuffers(1, &mFbo));
GL_CHECK(glDeleteRenderbuffers(1, &mColorBuffer));
GL_CHECK(glDeleteRenderbuffers(1, &mDepthStencilBuffer));
GL_CHECK(glDeleteFramebuffers(1, &mResolveFbo));
GL_CHECK(glDeleteTextures(1, &mColorTex));
mFbo = GL_INVALID_VALUE;
}
GlRenderTargetPool::GlRenderTargetPool(uint32_t maxWidth, uint32_t maxHeight): mMaxWidth(maxWidth), mMaxHeight(maxHeight), mPool() {}
GlRenderTargetPool::~GlRenderTargetPool()
@ -125,8 +130,8 @@ GlRenderTarget* GlRenderTargetPool::getRenderTarget(const RenderRegion& vp, GLui
}
}
auto rt = new GlRenderTarget(width, height);
rt->init(resolveId);
auto rt = new GlRenderTarget();
rt->init(width, height, resolveId);
rt->setViewport(vp);
mPool.push(rt);
return rt;

View file

@ -28,11 +28,11 @@
class GlRenderTarget
{
public:
GlRenderTarget() = default;
GlRenderTarget(uint32_t width, uint32_t height);
GlRenderTarget();
~GlRenderTarget();
void init(GLint resolveId);
void init(uint32_t width, uint32_t height, GLint resolveId);
void reset();
GLuint getFboId() { return mFbo; }
GLuint getResolveFboId() { return mResolveFbo; }

View file

@ -52,6 +52,8 @@ void GlRenderer::flush()
{
clearDisposes();
mRootTarget.reset();
ARRAY_FOREACH(p, mComposePool) delete(*p);
mComposePool.clear();
@ -834,9 +836,8 @@ bool GlRenderer::target(void* context, int32_t id, uint32_t w, uint32_t h)
currentContext();
mRootTarget = GlRenderTarget(surface.w, surface.h);
mRootTarget.setViewport({0, 0, static_cast<int32_t>(surface.w), static_cast<int32_t>(surface.h)});
mRootTarget.init(mTargetFboId);
mRootTarget.init(surface.w, surface.h, mTargetFboId);
return true;
}