A scanout may hold an active QemuDmaBuf when a SET_SCANOUT switches to CPU-backed display data. Force surface recreation and release the old buffer in this case.
Signed-off-by: Marc-André Lureau <[email protected]> --- hw/display/virtio-gpu.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 5362f7a4c269..a74475dc6741 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -658,9 +658,11 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout; uint32_t bytes_pp = virtio_gpu_format_bytes_pp(fb->format); + bool was_dmabuf; uint8_t *data; scanout = &g->parent_obj.scanout[scanout_id]; + was_dmabuf = scanout->dmabuf != NULL; if (!virtio_gpu_check_scanout_bounds(scanout_id, res->resource_id, fb->width, fb->height, r, error)) { @@ -687,12 +689,11 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g, if (res->blob) { if (qemu_console_has_gl(scanout->con)) { - if (!virtio_gpu_update_dmabuf(g, scanout_id, res, fb, r)) { - virtio_gpu_update_scanout(g, scanout_id, res, fb, r); - } else { + if (virtio_gpu_update_dmabuf(g, scanout_id, res, fb, r)) { *error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY; return false; } + virtio_gpu_update_scanout(g, scanout_id, res, fb, r); return true; } @@ -702,7 +703,8 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g, } /* create a surface for this scanout */ - if ((res->blob && !qemu_console_has_gl(scanout->con)) || + if (was_dmabuf || + (res->blob && !qemu_console_has_gl(scanout->con)) || !scanout->ds || surface_data(scanout->ds) != data + fb->offset || scanout->width != r->width || @@ -727,6 +729,9 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g, qemu_displaysurface_set_share_handle(scanout->ds, res->share_handle, fb->offset); pixman_image_unref(rect); + if (was_dmabuf) { + virtio_gpu_release_scanout_dmabuf(g, scanout_id); + } qemu_console_set_surface(g->parent_obj.scanout[scanout_id].con, scanout->ds); } -- 2.55.0.543.g5ebe2ebe4ea8
