Add egl_cleanup() to tear down the EGL render node context, GBM device, and EGL display. Add egl_headless_cleanup() to unregister listeners, destroy framebuffers, and free per-console state tracked via a new GPtrArray.
Signed-off-by: Marc-André Lureau <[email protected]> --- include/ui/egl-helpers.h | 1 + ui/egl-headless.c | 31 +++++++++++++++++++++++++++++++ ui/egl-helpers.c | 19 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index acf993fcf52..dba788fead7 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -76,6 +76,7 @@ EGLContext qemu_egl_init_ctx(void); bool qemu_egl_has_dmabuf(void); bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp); +void egl_cleanup(void); const char *qemu_egl_get_error_string(void); diff --git a/ui/egl-headless.c b/ui/egl-headless.c index 878bfebb40c..ba27efcf4c3 100644 --- a/ui/egl-headless.c +++ b/ui/egl-headless.c @@ -9,6 +9,7 @@ typedef struct egl_dpy { DisplayChangeListener dcl; + DisplayGLCtx *ctx; DisplaySurface *ds; QemuGLShader *gls; egl_fb guest_fb; @@ -19,6 +20,8 @@ typedef struct egl_dpy { uint32_t pos_y; } egl_dpy; +static GPtrArray *egl_dpys; + /* ------------------------------------------------------------------ */ static void egl_refresh(DisplayChangeListener *dcl) @@ -220,6 +223,8 @@ static void egl_headless_init(DisplayState *ds, DisplayOptions *opts) egl_dpy *edpy; int idx; + egl_dpys = g_ptr_array_new(); + for (idx = 0;; idx++) { DisplayGLCtx *ctx; @@ -232,15 +237,41 @@ static void egl_headless_init(DisplayState *ds, DisplayOptions *opts) edpy->gls = qemu_gl_init_shader(); ctx = g_new0(DisplayGLCtx, 1); ctx->ops = &eglctx_ops; + edpy->ctx = ctx; qemu_console_set_display_gl_ctx(con, ctx); qemu_console_register_listener(con, &edpy->dcl, &egl_ops); + g_ptr_array_add(egl_dpys, edpy); + } +} + +static void egl_headless_cleanup(void) +{ + if (!egl_dpys) { + return; } + + for (guint i = 0; i < egl_dpys->len; i++) { + egl_dpy *edpy = g_ptr_array_index(egl_dpys, i); + + qemu_console_unregister_listener(&edpy->dcl); + qemu_console_set_display_gl_ctx(edpy->dcl.con, NULL); + egl_fb_destroy(&edpy->guest_fb); + egl_fb_destroy(&edpy->cursor_fb); + egl_fb_destroy(&edpy->blit_fb); + qemu_gl_fini_shader(edpy->gls); + g_free(edpy->ctx); + g_free(edpy); + } + g_clear_pointer(&egl_dpys, g_ptr_array_unref); + + egl_cleanup(); } static QemuDisplay qemu_display_egl = { .type = DISPLAY_TYPE_EGL_HEADLESS, .early_init = early_egl_headless_init, .init = egl_headless_init, + .cleanup = egl_headless_cleanup, }; static void register_egl(void) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index e3f2872cc14..a7bfb15fd88 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -733,3 +733,22 @@ bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp) display_opengl = 1; return true; } + +void egl_cleanup(void) +{ + if (qemu_egl_rn_ctx) { + eglDestroyContext(qemu_egl_display, qemu_egl_rn_ctx); + qemu_egl_rn_ctx = NULL; + } + +#ifdef CONFIG_GBM + g_clear_pointer(&qemu_egl_rn_gbm_dev, gbm_device_destroy); + g_clear_fd(&qemu_egl_rn_fd, NULL); +#endif + + if (qemu_egl_display) { + eglReleaseThread(); + eglTerminate(qemu_egl_display); + qemu_egl_display = NULL; + } +} -- 2.54.0
