Fix Linux Impeller support broken by incorrect deletion of stencil buffer. (#168668)

The buffer was leaking and deleted in
9d8e5e0b2f. This fixes the location where
the buffer is deleted.
This commit is contained in:
Robert Ancell 2025-05-14 20:31:16 +12:00 committed by GitHub
parent 9a67219ea0
commit 0b9f9288ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 58 additions and 8 deletions

View File

@ -20,6 +20,9 @@ struct _FlFramebuffer {
// Texture backing framebuffer. // Texture backing framebuffer.
GLuint texture_id; GLuint texture_id;
// Stencil buffer associated with this framebuffer.
GLuint depth_stencil;
}; };
G_DEFINE_TYPE(FlFramebuffer, fl_framebuffer, G_TYPE_OBJECT) G_DEFINE_TYPE(FlFramebuffer, fl_framebuffer, G_TYPE_OBJECT)
@ -29,6 +32,7 @@ static void fl_framebuffer_dispose(GObject* object) {
glDeleteFramebuffers(1, &self->framebuffer_id); glDeleteFramebuffers(1, &self->framebuffer_id);
glDeleteTextures(1, &self->texture_id); glDeleteTextures(1, &self->texture_id);
glDeleteRenderbuffers(1, &self->depth_stencil);
G_OBJECT_CLASS(fl_framebuffer_parent_class)->dispose(object); G_OBJECT_CLASS(fl_framebuffer_parent_class)->dispose(object);
} }
@ -63,19 +67,17 @@ FlFramebuffer* fl_framebuffer_new(GLint format, size_t width, size_t height) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
provider->texture_id, 0); provider->texture_id, 0);
GLuint depth_stencil; glGenRenderbuffers(1, &provider->depth_stencil);
glGenRenderbuffers(1, &depth_stencil); glBindRenderbuffer(GL_RENDERBUFFER, provider->depth_stencil);
glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil);
glRenderbufferStorage(GL_RENDERBUFFER, // target glRenderbufferStorage(GL_RENDERBUFFER, // target
GL_DEPTH24_STENCIL8, // internal format GL_DEPTH24_STENCIL8, // internal format
width, // width width, // width
height // height height // height
); );
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depth_stencil); GL_RENDERBUFFER, provider->depth_stencil);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, depth_stencil); GL_RENDERBUFFER, provider->depth_stencil);
glDeleteRenderbuffers(1, &depth_stencil);
return provider; return provider;
} }

View File

@ -24,3 +24,17 @@ TEST(FlFramebufferTest, HasDepthStencil) {
&stencil_type); &stencil_type);
EXPECT_NE(stencil_type, GL_NONE); EXPECT_NE(stencil_type, GL_NONE);
} }
TEST(FlFramebufferTest, ResourcesRemoved) {
::testing::NiceMock<flutter::testing::MockEpoxy> epoxy;
EXPECT_CALL(epoxy, glGenFramebuffers);
EXPECT_CALL(epoxy, glGenTextures);
EXPECT_CALL(epoxy, glGenRenderbuffers);
FlFramebuffer* framebuffer = fl_framebuffer_new(GL_RGB, 100, 100);
EXPECT_CALL(epoxy, glDeleteFramebuffers);
EXPECT_CALL(epoxy, glDeleteTextures);
EXPECT_CALL(epoxy, glDeleteRenderbuffers);
g_object_unref(framebuffer);
}

View File

@ -401,11 +401,25 @@ GLuint _glCreateShader(GLenum shaderType) {
return 0; return 0;
} }
void _glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {} void _glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {
if (mock) {
mock->glDeleteFramebuffers(n, framebuffers);
}
}
void _glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
if (mock) {
mock->glDeleteRenderbuffers(n, renderbuffers);
}
}
void _glDeleteShader(GLuint shader) {} void _glDeleteShader(GLuint shader) {}
void _glDeleteTextures(GLsizei n, const GLuint* textures) {} void _glDeleteTextures(GLsizei n, const GLuint* textures) {
if (mock) {
mock->glDeleteTextures(n, textures);
}
}
static void _glFramebufferRenderbuffer(GLenum target, static void _glFramebufferRenderbuffer(GLenum target,
GLenum attachment, GLenum attachment,
@ -424,18 +438,27 @@ static void _glGenTextures(GLsizei n, GLuint* textures) {
for (GLsizei i = 0; i < n; i++) { for (GLsizei i = 0; i < n; i++) {
textures[i] = 0; textures[i] = 0;
} }
if (mock) {
mock->glGenTextures(n, textures);
}
} }
static void _glGenFramebuffers(GLsizei n, GLuint* framebuffers) { static void _glGenFramebuffers(GLsizei n, GLuint* framebuffers) {
for (GLsizei i = 0; i < n; i++) { for (GLsizei i = 0; i < n; i++) {
framebuffers[i] = 0; framebuffers[i] = 0;
} }
if (mock) {
mock->glGenFramebuffers(n, framebuffers);
}
} }
static void _glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) { static void _glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) {
for (GLsizei i = 0; i < n; i++) { for (GLsizei i = 0; i < n; i++) {
renderbuffers[i] = 0; renderbuffers[i] = 0;
} }
if (mock) {
mock->glGenRenderbuffers(n, renderbuffers);
}
} }
static void _glGetFramebufferAttachmentParameteriv(GLenum target, static void _glGetFramebufferAttachmentParameteriv(GLenum target,
@ -659,6 +682,7 @@ static void library_init() {
epoxy_glCreateProgram = _glCreateProgram; epoxy_glCreateProgram = _glCreateProgram;
epoxy_glCreateShader = _glCreateShader; epoxy_glCreateShader = _glCreateShader;
epoxy_glDeleteFramebuffers = _glDeleteFramebuffers; epoxy_glDeleteFramebuffers = _glDeleteFramebuffers;
epoxy_glDeleteRenderbuffers = _glDeleteRenderbuffers;
epoxy_glDeleteShader = _glDeleteShader; epoxy_glDeleteShader = _glDeleteShader;
epoxy_glDeleteTextures = _glDeleteTextures; epoxy_glDeleteTextures = _glDeleteTextures;
epoxy_glFramebufferRenderbuffer = _glFramebufferRenderbuffer; epoxy_glFramebufferRenderbuffer = _glFramebufferRenderbuffer;

View File

@ -34,6 +34,16 @@ class MockEpoxy {
GLint dstY1, GLint dstY1,
GLbitfield mask, GLbitfield mask,
GLenum filter)); GLenum filter));
MOCK_METHOD(void,
glDeleteFramebuffers,
(GLsizei n, const GLuint* framebuffers));
MOCK_METHOD(void,
glDeleteRenderbuffers,
(GLsizei n, const GLuint* renderbuffers));
MOCK_METHOD(void, glDeleteTextures, (GLsizei n, const GLuint* textures));
MOCK_METHOD(void, glGenFramebuffers, (GLsizei n, GLuint* framebuffers));
MOCK_METHOD(void, glGenRenderbuffers, (GLsizei n, GLuint* renderbuffers));
MOCK_METHOD(void, glGenTextures, (GLsizei n, GLuint* textures));
MOCK_METHOD(const GLubyte*, glGetString, (GLenum pname)); MOCK_METHOD(const GLubyte*, glGetString, (GLenum pname));
}; };