On 2026/08/25 19:20, Marc-André Lureau wrote:
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.
Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
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);
}