From a9fbce5e94d6b68ec8404f8a466fde873ba2bc73 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 15 Feb 2022 00:13:35 +0400 Subject: ui/console: fix crash when using gl context with non-gl listeners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit 7cc712e98 ("ui: dispatch GL events to all listener") mechanically replaced the dpy_gl calls with a dispatch loop, using the same pre-conditions. However, it didn't take into account that all listeners do not have to implement the GL callbacks. Add the missing pre-conditions before calling the callbacks. Fix crash when running a GL-enabled VM with "-device virtio-gpu-gl-pci -display egl-headless -vnc :0". Fixes: 7cc712e98 ("ui: dispatch GL events to all listener") Reported-by: Akihiko Odaki Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220214201337.1814787-2-marcandre.lureau@redhat.com> Signed-off-by: Gerd Hoffmann --- ui/console.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'ui/console.c') diff --git a/ui/console.c b/ui/console.c index 40eebb6d2c..79a01afd1e 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1860,7 +1860,9 @@ void dpy_gl_scanout_disable(QemuConsole *con) con->scanout.kind = SCANOUT_NONE; } QLIST_FOREACH(dcl, &s->listeners, next) { - dcl->ops->dpy_gl_scanout_disable(dcl); + if (dcl->ops->dpy_gl_scanout_disable) { + dcl->ops->dpy_gl_scanout_disable(dcl); + } } } @@ -1881,10 +1883,12 @@ void dpy_gl_scanout_texture(QemuConsole *con, x, y, width, height }; QLIST_FOREACH(dcl, &s->listeners, next) { - dcl->ops->dpy_gl_scanout_texture(dcl, backing_id, - backing_y_0_top, - backing_width, backing_height, - x, y, width, height); + if (dcl->ops->dpy_gl_scanout_texture) { + dcl->ops->dpy_gl_scanout_texture(dcl, backing_id, + backing_y_0_top, + backing_width, backing_height, + x, y, width, height); + } } } @@ -1897,7 +1901,9 @@ void dpy_gl_scanout_dmabuf(QemuConsole *con, con->scanout.kind = SCANOUT_DMABUF; con->scanout.dmabuf = dmabuf; QLIST_FOREACH(dcl, &s->listeners, next) { - dcl->ops->dpy_gl_scanout_dmabuf(dcl, dmabuf); + if (dcl->ops->dpy_gl_scanout_dmabuf) { + dcl->ops->dpy_gl_scanout_dmabuf(dcl, dmabuf); + } } } @@ -1951,7 +1957,9 @@ void dpy_gl_update(QemuConsole *con, graphic_hw_gl_block(con, true); QLIST_FOREACH(dcl, &s->listeners, next) { - dcl->ops->dpy_gl_update(dcl, x, y, w, h); + if (dcl->ops->dpy_gl_update) { + dcl->ops->dpy_gl_update(dcl, x, y, w, h); + } } graphic_hw_gl_block(con, false); } -- cgit 1.4.1 From cb8962c146b2633a4b04562281de9b2703bba849 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 15 Feb 2022 00:13:37 +0400 Subject: ui: do not create a surface when resizing a GL scanout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qemu_console_resize() will create a blank surface and replace the current scanout with it if called while the current scanout is GL (texture or dmabuf). This is not only very costly, but also can produce glitches on the display/listener side. Instead, compare the current console size with the fitting console functions, which also works when the scanout is GL. Note: there might be still an unnecessary surface creation on calling qemu_console_resize() when the size is actually changing, but display backends currently rely on DisplaySurface details during dpy_gfx_switch() to handle various resize aspects. We would need more refactoring to handle resize without DisplaySurface, this is left for a future improvement. Signed-off-by: Marc-André Lureau Message-Id: <20220214201337.1814787-4-marcandre.lureau@redhat.com> Signed-off-by: Gerd Hoffmann --- ui/console.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'ui/console.c') diff --git a/ui/console.c b/ui/console.c index 79a01afd1e..365a2c14b8 100644 --- a/ui/console.c +++ b/ui/console.c @@ -2400,13 +2400,12 @@ static void vc_chr_open(Chardev *chr, void qemu_console_resize(QemuConsole *s, int width, int height) { - DisplaySurface *surface = qemu_console_surface(s); + DisplaySurface *surface; assert(s->console_type == GRAPHIC_CONSOLE); - if (surface && (surface->flags & QEMU_ALLOCATED_FLAG) && - pixman_image_get_width(surface->image) == width && - pixman_image_get_height(surface->image) == height) { + if (qemu_console_get_width(s, -1) == width && + qemu_console_get_height(s, -1) == height) { return; } -- cgit 1.4.1