From: "Marc-André Lureau" <marcandre.lureau@redhat.com>
To: qemu-devel@nongnu.org
Subject: [GIT PULL 06/15] ui/gtk: Narrow DMA-BUF critical section
Date: Fri, 17 Jul 2026 15:52:45 +0400 [thread overview]
Message-ID: <20260717-fix-v1-6-cb9f7d49dc52@redhat.com> (raw)
In-Reply-To: <20260717-fix-v1-0-cb9f7d49dc52@redhat.com>
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Scanout operations need to be properly ordered to avoid tearing. The
virtio specification allows the guest to use pageflip. With pageflip,
the guest only modifies the invisible framebuffer while the host scans
out the visible framebuffer. The guest may choose not to use pageflip to
avoid its overhead, accepting the risk of tearing.
ui/gtk performs the following procedure to flush a scanout:
1) Queue a draw event.
2) The draw event gets triggered.
3) Blit the guest framebuffer to the host framebuffer.
When flushing a DMA-BUF scanout, ui/gtk blocks the device before 2) if
possible and unblocks it after 3) to enforce proper ordering. However,
blocking the device before 2) has two problems.
First, it can leave the device blocked indefinitely because GTK
sometimes decides to cancel 2) when the window is not visible for
example. ui/gtk regularly repeats 1) as a workaround, but it is not
applicable to GtkGLArea because it causes display corruption.
Second, the behavior is inconsistent with the other types of scanout
that leave the device unblocked between 1) and 2).
To fix these problems, let ui/gtk block the device only when the
queued draw event runs, immediately before 3). Blocking before that is
unnecessary since ui/gtk does not access the framebuffer yet. If the
guest does not use pageflip but instead updates the visible framebuffer
directly, ui/gtk should not add the overhead of a pre-draw block.
ui/gtk still blocks the device during 3) for DMA-BUF. Unlike the other
scanout types, 3) can happen asynchronously with the device for a
DMA-BUF, so ui/gtk needs to keep the visible guest framebuffer stable
for the blit.
With the problems fixed, the workaround to repeat 1) is no longer
necessary and is removed.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260628-gtk-v2-1-1e4839012f09@rsg.ci.i.u-tokyo.ac.jp>
---
ui/gtk-egl.c | 6 ++----
ui/gtk-gl-area.c | 23 +----------------------
2 files changed, 3 insertions(+), 26 deletions(-)
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 7c5c9b2428c..adc81f34b1c 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -91,6 +91,7 @@ void gd_egl_draw(VirtualConsole *vc)
} else {
qemu_dmabuf_set_draw_submitted(dmabuf, false);
}
+ qemu_console_hw_gl_block(vc->gfx.dcl.con, true);
}
#endif
gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
@@ -405,14 +406,11 @@ void gd_egl_flush(DisplayChangeListener *dcl,
if (vc->gfx.guest_fb.dmabuf &&
!qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
- qemu_console_hw_gl_block(vc->gfx.dcl.con, true);
qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
gtk_egl_set_scanout_mode(vc, true);
- gtk_widget_queue_draw_area(area, x, y, w, h);
- return;
}
- gd_egl_scanout_flush(&vc->gfx.dcl, x, y, w, h);
+ gtk_widget_queue_draw_area(area, x, y, w, h);
}
void gtk_egl_init(DisplayGLMode mode)
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index 23806b9d01b..29497019ee4 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -86,6 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc)
} else {
qemu_dmabuf_set_draw_submitted(dmabuf, false);
}
+ qemu_console_hw_gl_block(vc->gfx.dcl.con, true);
}
#endif
@@ -163,27 +164,6 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl)
gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area);
- if (vc->gfx.guest_fb.dmabuf &&
- qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
- /*
- * gd_egl_refresh() calls gd_egl_draw() if a DMA-BUF draw has already
- * been submitted, but this function does not call gd_gl_area_draw() in
- * such a case due to display corruption.
- *
- * Calling gd_gl_area_draw() is necessary to prevent a situation where
- * there is a scheduled draw event but it won't happen bacause the window
- * is currently in inactive state (minimized or tabified). If draw is not
- * done for a long time, gl_block timeout and/or fence timeout (on the
- * guest) will happen eventually.
- *
- * However, it is found that calling gd_gl_area_draw() here causes guest
- * display corruption on a Wayland Compositor. The display corruption is
- * more serious than the possible fence timeout so gd_gl_area_draw() is
- * omitted for now.
- */
- return;
- }
-
if (!vc->gfx.gls) {
if (!gtk_widget_get_realized(vc->gfx.drawing_area)) {
return;
@@ -347,7 +327,6 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
if (vc->gfx.guest_fb.dmabuf &&
!qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
- qemu_console_hw_gl_block(vc->gfx.dcl.con, true);
qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
gtk_gl_area_set_scanout_mode(vc, true);
}
--
2.55.0
next prev parent reply other threads:[~2026-07-17 11:53 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 01/15] i386/tdx: fix uninitialized variable warning in tdx_check_features Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 02/15] ui/vnc: fix OOB write in vnc_refresh_lossy_rect Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 03/15] ui/vnc: validate color shifts in SetPixelFormat Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 04/15] ui/vnc: use RFB wire types for client message handlers Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 05/15] ui/input-barrier: fix off-by-one in keycode bounds check Marc-André Lureau
2026-07-17 11:52 ` Marc-André Lureau [this message]
2026-07-17 11:52 ` [GIT PULL 07/15] ui/vnc: fix out-of-bounds write in lossy refresh dirty marking Marc-André Lureau
2026-07-21 8:17 ` Peter Maydell
2026-07-21 8:23 ` Marc-André Lureau
2026-07-21 8:34 ` Peter Maydell
2026-07-17 11:52 ` [GIT PULL 08/15] ui/vnc: validate SetPixelFormat field ranges Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 09/15] hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 10/15] hw/display/qxl: fix TOCTOU in cursor chunk data_size handling Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 11/15] hw/display/virtio-gpu: validate stride against width on scanout Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 12/15] hw/display/virtio-gpu: cap submit_3d command buffer allocation Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 13/15] hw/display/virtio-gpu: handle migration iov allocation failure Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 14/15] hw/display/virtio-gpu: reject strides exceeding INT_MAX Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 15/15] hw/display/virtio-gpu: Check pixman_image_create_bits() results Marc-André Lureau
2026-07-19 7:31 ` [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Michael Tokarev
2026-07-19 7:33 ` Michael Tokarev
2026-07-19 7:50 ` Akihiko Odaki
2026-07-19 8:07 ` Marc-André Lureau
2026-07-19 11:41 ` Akihiko Odaki
2026-07-20 9:59 ` Stefan Hajnoczi
2026-07-20 11:27 ` Michael Tokarev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260717-fix-v1-6-cb9f7d49dc52@redhat.com \
--to=marcandre.lureau@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.