The dpy_gl_release_dmabuf callbacks in the GTK, SDL, egl-headless, and spice backends call egl_dmabuf_release_texture(), which calls glDeleteTextures(), without first making the owning GL context current. This is reachable after another console's surface update leaves EGL_NO_CONTEXT current (e.g. gd_egl_update clears the context on return). The deletion then silently fails, leaking the GL texture and its backing storage. With an unshared context current, a coincident texture name could even be deleted from the wrong context.
Fix by making the appropriate GL context current in each backend's release callback before calling egl_dmabuf_release_texture(): - GTK EGL: eglMakeCurrent with the VC's EGL context - GTK GL Area: gtk_gl_area_make_current - SDL: SDL_GL_MakeCurrent with the console's window context - egl-headless: eglMakeCurrent with the render-node context - spice: eglMakeCurrent with the render-node context For GTK, the previously shared gd_gl_release_dmabuf is split into backend-specific gd_egl_release_dmabuf and gd_gl_area_release_dmabuf, matching the existing pattern where each backend manages its own context. Reviewed-by: Akihiko Odaki <[email protected]> Signed-off-by: Marc-André Lureau <[email protected]> --- include/ui/gtk.h | 5 +++++ ui/egl-headless.c | 2 ++ ui/gtk-egl.c | 12 ++++++++++++ ui/gtk-gl-area.c | 11 +++++++++++ ui/gtk.c | 13 ++++--------- ui/sdl2-gl.c | 1 + ui/spice-display.c | 2 ++ 7 files changed, 37 insertions(+), 9 deletions(-) diff --git a/include/ui/gtk.h b/include/ui/gtk.h index b66b9ca5c519..6b62e9758813 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -163,6 +163,7 @@ extern bool gtk_use_gl_area; void gd_update_windowsize(VirtualConsole *vc); void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget); void gd_gl_wait_sync(VirtualConsole *vc, void *sync); +void gd_release_dmabuf(VirtualConsole *vc, QemuDmaBuf *dmabuf); /* ui/gtk-egl.c */ void gd_egl_init(VirtualConsole *vc); @@ -190,6 +191,8 @@ void gd_egl_cursor_dmabuf(DisplayChangeListener *dcl, uint32_t hot_x, uint32_t hot_y); void gd_egl_cursor_position(DisplayChangeListener *dcl, uint32_t pos_x, uint32_t pos_y); +void gd_egl_release_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf); void gd_egl_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); void *gd_egl_scanout_flush(DisplayChangeListener *dcl, @@ -221,6 +224,8 @@ void gd_gl_area_scanout_texture(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h, void *d3d_tex2d); +void gd_gl_area_release_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf); void gd_gl_area_scanout_disable(DisplayChangeListener *dcl); void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); diff --git a/ui/egl-headless.c b/ui/egl-headless.c index ba27efcf4c3e..ffe7b30f919b 100644 --- a/ui/egl-headless.c +++ b/ui/egl-headless.c @@ -126,6 +126,8 @@ static void egl_cursor_dmabuf(DisplayChangeListener *dcl, static void egl_release_dmabuf(DisplayChangeListener *dcl, QemuDmaBuf *dmabuf) { + eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, + EGL_NO_SURFACE, qemu_egl_rn_ctx); egl_dmabuf_release_texture(dmabuf); } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 8623181336e9..d595916476d9 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -426,6 +426,18 @@ void gtk_egl_init(DisplayGLMode mode) display_opengl = 1; } +void gd_egl_release_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf) +{ +#ifdef CONFIG_GBM + VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + + eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, + vc->gfx.esurface, vc->gfx.ectx); + gd_release_dmabuf(vc, dmabuf); +#endif +} + int gd_egl_make_current(DisplayGLCtx *dgc, QEMUGLContext ctx) { diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 45c0c8c81a11..effd88f28721 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -360,6 +360,17 @@ void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl, #endif } +void gd_gl_area_release_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf) +{ +#ifdef CONFIG_GBM + VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + + gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); + gd_release_dmabuf(vc, dmabuf); +#endif +} + void gtk_gl_area_init(void) { display_opengl = 1; diff --git a/ui/gtk.c b/ui/gtk.c index 55e45e8445bc..c615d35451b6 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -584,21 +584,16 @@ static bool gd_has_dmabuf(DisplayChangeListener *dcl) return vc->gfx.has_dmabuf; } -static void gd_gl_release_dmabuf(DisplayChangeListener *dcl, - QemuDmaBuf *dmabuf) -{ #ifdef CONFIG_GBM - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); - +void gd_release_dmabuf(VirtualConsole *vc, QemuDmaBuf *dmabuf) +{ egl_dmabuf_release_texture(dmabuf); if (vc->gfx.guest_fb.dmabuf == dmabuf) { vc->gfx.guest_fb.dmabuf = NULL; vc->gfx.draw_submitted = false; } -#endif } -#ifdef CONFIG_GBM static void gd_gl_fence_cb(void *vcon) { VirtualConsole *vc = vcon; @@ -639,7 +634,7 @@ static const DisplayChangeListenerOps dcl_gl_area_ops = { .dpy_gl_scanout_disable = gd_gl_area_scanout_disable, .dpy_gl_update = gd_gl_area_scanout_flush, .dpy_gl_scanout_dmabuf = gd_gl_area_scanout_dmabuf, - .dpy_gl_release_dmabuf = gd_gl_release_dmabuf, + .dpy_gl_release_dmabuf = gd_gl_area_release_dmabuf, .dpy_has_dmabuf = gd_has_dmabuf, }; @@ -673,7 +668,7 @@ static const DisplayChangeListenerOps dcl_egl_ops = { .dpy_gl_cursor_dmabuf = gd_egl_cursor_dmabuf, .dpy_gl_cursor_position = gd_egl_cursor_position, .dpy_gl_update = gd_egl_flush, - .dpy_gl_release_dmabuf = gd_gl_release_dmabuf, + .dpy_gl_release_dmabuf = gd_egl_release_dmabuf, .dpy_has_dmabuf = gd_has_dmabuf, }; diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c index 46eff768c968..3a5aa09618ca 100644 --- a/ui/sdl2-gl.c +++ b/ui/sdl2-gl.c @@ -288,6 +288,7 @@ void sdl2_gl_release_dmabuf(DisplayChangeListener *dcl, { struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + SDL_GL_MakeCurrent(scon->real_window, scon->winctx); egl_dmabuf_release_texture(dmabuf); if (scon->guest_fb.dmabuf == dmabuf) { scon->guest_fb.dmabuf = NULL; diff --git a/ui/spice-display.c b/ui/spice-display.c index 75c7df7bb5e0..22cd1e266caa 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -1176,6 +1176,8 @@ static void qemu_spice_gl_release_dmabuf(DisplayChangeListener *dcl, ssd->guest_dmabuf = NULL; ssd->guest_dmabuf_refresh = false; } + eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, + EGL_NO_SURFACE, qemu_egl_rn_ctx); egl_dmabuf_release_texture(dmabuf); } -- 2.55.0.543.g5ebe2ebe4ea8
