From: Dongwon Kim <[email protected]> Currently, the texture associated with a DisplaySurface is not deleted when the surface is switched or freed, leading to a memory leak in the GPU process. This occurs because the GTK backend lacks a mapping for the 'dpy_gl_ctx_destroy_texture' operation.
This patch implements the necessary cleanup functions for both EGL and GL Area backends. Each implementation ensures the appropriate GL context is made current before calling surface_gl_destroy_texture(), ensuring that the underlying GL texture ID is safely released by the driver. Cc: Gerd Hoffmann <[email protected]> Cc: Marc-André Lureau <[email protected]> Cc: Vivek Kasireddy <[email protected]> Signed-off-by: Dongwon Kim <[email protected]> --- include/ui/gtk.h | 4 ++++ ui/gtk-egl.c | 10 ++++++++++ ui/gtk-gl-area.c | 8 ++++++++ ui/gtk.c | 2 ++ 4 files changed, 24 insertions(+) diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 3e6ce3cb48..f1765ad5cb 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -170,6 +170,8 @@ void gd_egl_switch(DisplayChangeListener *dcl, DisplaySurface *surface); QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc, QEMUGLParams *params); +void gd_egl_destroy_texture(DisplayGLCtx *dgc, + DisplaySurface *surface); void gd_egl_scanout_disable(DisplayChangeListener *dcl); void gd_egl_scanout_texture(DisplayChangeListener *dcl, uint32_t backing_id, @@ -206,6 +208,8 @@ QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc, QEMUGLParams *params); void gd_gl_area_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx); +void gd_gl_area_destroy_texture(DisplayGLCtx *dgc, + DisplaySurface *surface); void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl, QemuDmaBuf *dmabuf); void gd_gl_area_scanout_texture(DisplayChangeListener *dcl, diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index ae9239999c..c1b32bc41b 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -225,6 +225,16 @@ QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc, return qemu_egl_create_context(dgc, params); } +void gd_egl_destroy_texture(DisplayGLCtx *dgc, DisplaySurface *surface) +{ + VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc); + + eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, + vc->gfx.esurface, vc->gfx.ectx); + + surface_gl_destroy_texture(dgc->gls, surface); +} + void gd_egl_scanout_disable(DisplayChangeListener *dcl) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index cd86022d26..84e41f4221 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -299,6 +299,14 @@ void gd_gl_area_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx) g_clear_object(&ctx); } +void gd_gl_area_destroy_texture(DisplayGLCtx *dgc, DisplaySurface *surface) +{ + VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc); + + gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); + surface_gl_destroy_texture(dgc->gls, surface); +} + void gd_gl_area_scanout_texture(DisplayChangeListener *dcl, uint32_t backing_id, bool backing_y_0_top, diff --git a/ui/gtk.c b/ui/gtk.c index 9ebe7e8df0..217f425075 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -636,6 +636,7 @@ static const DisplayGLCtxOps gl_area_ctx_ops = { .dpy_gl_ctx_is_compatible_dcl = gd_gl_area_is_compatible_dcl, .dpy_gl_ctx_create = gd_gl_area_create_context, .dpy_gl_ctx_destroy = gd_gl_area_destroy_context, + .dpy_gl_ctx_destroy_texture = gd_gl_area_destroy_texture, .dpy_gl_ctx_make_current = gd_gl_area_make_current, }; @@ -670,6 +671,7 @@ static const DisplayGLCtxOps egl_ctx_ops = { .dpy_gl_ctx_is_compatible_dcl = gd_egl_is_compatible_dcl, .dpy_gl_ctx_create = gd_egl_create_context, .dpy_gl_ctx_destroy = qemu_egl_destroy_context, + .dpy_gl_ctx_destroy_texture = gd_egl_destroy_texture, .dpy_gl_ctx_make_current = gd_egl_make_current, }; #endif -- 2.43.0
