Hi

On Tue, Mar 3, 2026 at 4:13 AM <[email protected]> wrote:
>
> 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,

But there is no dpy_gl_ctx_create_texture(), how can
dpy_gl_ctx_destroy_texture() get called?

>  };
>  #endif
> --
> 2.43.0
>
>


-- 
Marc-André Lureau

Reply via email to