Skip to content

Commit ed5bda4

Browse files
Linux reuse sibling (#183653)
Add reuse render_sibling to avoid memory leak. to @robert-ancell PR #183539 We observed a memory leak on Linux Desktop with Wayland on embedded ARM cpu and an OpenGL ES driver. While the fix works in our environment, I'm not sure it's correct in all scenarios. Maybe someone with more experience in the Flutter Linux rendering can review and provide some feedback. The memory leak seems related to issue mentioned below. #182192 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [AI contribution guidelines]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Robert Ancell <robert.ancell@canonical.com>
1 parent 985580f commit ed5bda4

1 file changed

Lines changed: 14 additions & 5 deletions

File tree

engine/src/flutter/shell/platform/linux/fl_compositor_opengl.cc

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ struct _FlCompositorOpenGL {
5353
// Last rendered frame.
5454
FlFramebuffer* framebuffer;
5555

56+
// Reusable sibling framebuffer for gdk_cairo_draw_from_gl (Wayland).
57+
// Avoids per-frame texture churn that GTK/Wayland retains.
58+
FlFramebuffer* render_sibling;
59+
5660
// Last rendered frame pixels (only set if shareable is TRUE).
5761
uint8_t* pixels;
5862

@@ -251,9 +255,12 @@ static gboolean fl_compositor_opengl_present_layers(FlCompositor* compositor,
251255
if (self->framebuffer == nullptr ||
252256
fl_framebuffer_get_width(self->framebuffer) != width ||
253257
fl_framebuffer_get_height(self->framebuffer) != height) {
254-
g_clear_object(&self->framebuffer);
255-
self->framebuffer =
258+
// Allocate new framebuffer before disposing old ones to avoid GL texture
259+
// ID collision (engine may dispose backing stores later with recycled IDs).
260+
FlFramebuffer* new_framebuffer =
256261
fl_framebuffer_new(general_format, width, height, self->shareable);
262+
g_clear_object(&self->framebuffer);
263+
self->framebuffer = new_framebuffer;
257264

258265
// If not shareable make buffer to copy frame pixels into.
259266
if (!self->shareable) {
@@ -423,9 +430,10 @@ static gboolean fl_compositor_opengl_render(FlCompositor* compositor,
423430
}
424431

425432
if (fl_framebuffer_get_shareable(self->framebuffer)) {
426-
g_autoptr(FlFramebuffer) sibling =
427-
fl_framebuffer_create_sibling(self->framebuffer);
428-
gdk_cairo_draw_from_gl(cr, window, fl_framebuffer_get_texture_id(sibling),
433+
g_clear_object(&self->render_sibling);
434+
self->render_sibling = fl_framebuffer_create_sibling(self->framebuffer);
435+
gdk_cairo_draw_from_gl(cr, window,
436+
fl_framebuffer_get_texture_id(self->render_sibling),
429437
GL_TEXTURE, scale_factor, 0, 0, width, height);
430438
} else {
431439
GLint saved_texture_binding;
@@ -459,6 +467,7 @@ static void fl_compositor_opengl_dispose(GObject* object) {
459467

460468
g_clear_object(&self->task_runner);
461469
g_clear_object(&self->opengl_manager);
470+
g_clear_object(&self->render_sibling);
462471
g_clear_object(&self->framebuffer);
463472
g_clear_pointer(&self->pixels, g_free);
464473
g_mutex_clear(&self->frame_mutex);

0 commit comments

Comments
 (0)