On Wed, Sep 9, 2026 at 3:30 AM <[email protected]> wrote: > > From: Dongwon Kim <[email protected]> > > When a VC is detached into an independent window or re-attached back > to the main window via gd_tab_window_close(), its underlying EGL surface > and context are destroyed and recreated. > > However, the associated FB objects (guest_fb, win_fb, cursor_fb), > display surface textures, and shader instances were not being cleaned up > during these transitions, leading to potential resource leaks. > > Introduce a helper function, gd_gl_release_resources(), to make the > appropriate GL context current, delete the textures and framebuffers, > release the shader instance, and reset state pointers. > > Use this helper in gd_tab_window_close(), gd_menu_untabify(), and refactor > gd_vc_free() to use it as well. > > Cc: Daniel P. Berrangé <[email protected]> > Cc: Marc-André Lureau <[email protected]> > Signed-off-by: Dongwon Kim <[email protected]>
Reviewed-by: Marc-André Lureau <[email protected]> > --- > ui/gtk.c | 67 +++++++++++++++++++++++++++++++++++--------------------- > 1 file changed, 42 insertions(+), 25 deletions(-) > > diff --git a/ui/gtk.c b/ui/gtk.c > index 0b5139ef31..c2324d273e 100644 > --- a/ui/gtk.c > +++ b/ui/gtk.c > @@ -1490,6 +1490,28 @@ static int gd_vc_notebook_pos(GtkDisplayState *s, > VirtualConsole *target) > g_assert_not_reached(); > } > > +#if defined(CONFIG_OPENGL) > +static void gd_gl_release_resources(VirtualConsole *vc) > +{ > + if (vc->gfx.ectx) { > + eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, > + vc->gfx.esurface, vc->gfx.ectx); > + } else if (gtk_use_gl_area) { > + gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); > + } > + > + if (vc->gfx.gls) { > + surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds); > + qemu_gl_fini_shader(vc->gfx.gls); > + vc->gfx.gls = NULL; > + } > + > + egl_fb_destroy(&vc->gfx.guest_fb); > + egl_fb_destroy(&vc->gfx.win_fb); > + egl_fb_destroy(&vc->gfx.cursor_fb); > +} > +#endif > + > static gboolean gd_tab_window_close(GtkWidget *widget, GdkEvent *event, > void *opaque) > { > @@ -1506,13 +1528,17 @@ static gboolean gd_tab_window_close(GtkWidget > *widget, GdkEvent *event, > gtk_widget_destroy(vc->window); > vc->window = NULL; > #if defined(CONFIG_OPENGL) > - if (vc->gfx.esurface) { > - eglDestroySurface(qemu_egl_display, vc->gfx.esurface); > - vc->gfx.esurface = NULL; > - } > - if (vc->gfx.ectx) { > - eglDestroyContext(qemu_egl_display, vc->gfx.ectx); > - vc->gfx.ectx = NULL; > + if (vc->type == GD_VC_GFX) { > + gd_gl_release_resources(vc); > + > + if (vc->gfx.esurface) { > + eglDestroySurface(qemu_egl_display, vc->gfx.esurface); > + vc->gfx.esurface = NULL; > + } > + if (vc->gfx.ectx) { > + eglDestroyContext(qemu_egl_display, vc->gfx.ectx); > + vc->gfx.ectx = NULL; > + } > } > #endif > > @@ -1549,12 +1575,9 @@ static void gd_menu_untabify(GtkMenuItem *item, void > *opaque) > > if (vc->type == GD_VC_GFX && > qemu_console_is_graphic(vc->gfx.dcl.con)) { > - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), > - FALSE); > - } > - if (!vc->window) { > - vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); > #if defined(CONFIG_OPENGL) > + gd_gl_release_resources(vc); > + > if (vc->gfx.esurface) { > eglDestroySurface(qemu_egl_display, vc->gfx.esurface); > vc->gfx.esurface = NULL; > @@ -1564,6 +1587,11 @@ static void gd_menu_untabify(GtkMenuItem *item, void > *opaque) > vc->gfx.ectx = NULL; > } > #endif > + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), > + FALSE); > + } > + if (!vc->window) { > + vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); > gd_widget_reparent(s->notebook, vc->window, vc->tab_item); > > g_signal_connect(vc->window, "delete-event", > @@ -2696,19 +2724,8 @@ static void gd_vc_free(void *p) > if (display_opengl) { > qemu_console_set_display_gl_ctx(vc->gfx.dcl.con, NULL); > } > - if (vc->gfx.ectx) { > - eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, > - vc->gfx.esurface, vc->gfx.ectx); > - } else if (gtk_use_gl_area) { > - gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); > - } > - if (vc->gfx.gls) { > - surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds); > - qemu_gl_fini_shader(vc->gfx.gls); > - } > - egl_fb_destroy(&vc->gfx.guest_fb); > - egl_fb_destroy(&vc->gfx.win_fb); > - egl_fb_destroy(&vc->gfx.cursor_fb); > + gd_gl_release_resources(vc); > + > if (vc->gfx.esurface) { > eglDestroySurface(qemu_egl_display, vc->gfx.esurface); > } > -- > 2.43.0 > > -- Marc-André Lureau
