Commit 7eff64f15d for qemu.org
commit 7eff64f15da49e581430053ac39eb640aa080dcb
Author: Marc-André Lureau <marcandre.lureau@redhat.com>
Date: Mon Aug 24 14:16:23 2026 +0400
ui/gtk: move GL fence tracking from QemuDmaBuf to VirtualGfxConsole
The sync and fence_fd fields on QemuDmaBuf are only used by the GTK
display backend for GPU fence synchronization during draw. They are not
intrinsic properties of the DMA-BUF itself but transient GL state tied
to the display listener.
Move fence_fd to VirtualGfxConsole and keep the EGL sync local to the
draw operation. Change egl_dmabuf_create_sync() and
egl_dmabuf_create_fence() to return values instead of storing them on the
dmabuf. This makes the fence lifecycle independent of the dmabuf
lifetime.
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h
index 3decdca497..381583bd53 100644
--- a/include/ui/dmabuf.h
+++ b/include/ui/dmabuf.h
@@ -41,13 +41,9 @@ uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf);
bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf);
-void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf);
-int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf);
bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf);
bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf);
void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture);
-void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd);
-void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync);
void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted);
#endif
diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
index 679c79eacd..533d9afc37 100644
--- a/include/ui/egl-helpers.h
+++ b/include/ui/egl-helpers.h
@@ -54,8 +54,8 @@ bool egl_dmabuf_export_texture(uint32_t tex_id, int *fd, EGLint *offset,
void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf);
void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf);
-void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf);
-void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf);
+EGLSyncKHR egl_create_sync(void);
+int egl_create_fence(EGLSyncKHR sync);
#endif
diff --git a/include/ui/gtk.h b/include/ui/gtk.h
index 5c9c34a069..4b4ef50e37 100644
--- a/include/ui/gtk.h
+++ b/include/ui/gtk.h
@@ -58,6 +58,7 @@ typedef struct VirtualGfxConsole {
bool y0_top;
bool scanout_mode;
bool has_dmabuf;
+ int gl_fence_fd;
#endif
} VirtualGfxConsole;
@@ -160,7 +161,7 @@ extern bool gtk_use_gl_area;
/* ui/gtk.c */
void gd_update_windowsize(VirtualConsole *vc);
void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget);
-void gd_hw_gl_flushed(void *vc);
+void gd_gl_wait_sync(VirtualConsole *vc, void *sync);
/* ui/gtk-egl.c */
void gd_egl_init(VirtualConsole *vc);
@@ -190,8 +191,9 @@ void gd_egl_cursor_position(DisplayChangeListener *dcl,
uint32_t pos_x, uint32_t pos_y);
void gd_egl_flush(DisplayChangeListener *dcl,
uint32_t x, uint32_t y, uint32_t w, uint32_t h);
-void gd_egl_scanout_flush(DisplayChangeListener *dcl,
- uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+void *gd_egl_scanout_flush(DisplayChangeListener *dcl,
+ uint32_t x, uint32_t y,
+ uint32_t w, uint32_t h);
void gtk_egl_init(DisplayGLMode mode);
int gd_egl_make_current(DisplayGLCtx *dgc,
QEMUGLContext ctx);
diff --git a/ui/dmabuf.c b/ui/dmabuf.c
index 7433a268f0..b61dc7ad27 100644
--- a/ui/dmabuf.c
+++ b/ui/dmabuf.c
@@ -25,8 +25,6 @@ struct QemuDmaBuf {
uint32_t backing_width;
uint32_t backing_height;
bool y0_top;
- void *sync;
- int fence_fd;
bool allow_fences;
bool draw_submitted;
};
@@ -57,7 +55,6 @@ QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height,
memcpy(dmabuf->fd, dmabuf_fd, num_planes * sizeof(*dmabuf_fd));
dmabuf->allow_fences = allow_fences;
dmabuf->y0_top = y0_top;
- dmabuf->fence_fd = -1;
dmabuf->num_planes = num_planes;
return dmabuf;
@@ -208,20 +205,6 @@ bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf)
return dmabuf->y0_top;
}
-void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf)
-{
- assert(dmabuf != NULL);
-
- return dmabuf->sync;
-}
-
-int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf)
-{
- assert(dmabuf != NULL);
-
- return dmabuf->fence_fd;
-}
-
bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
@@ -242,18 +225,6 @@ void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture)
dmabuf->texture = texture;
}
-void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd)
-{
- assert(dmabuf != NULL);
- dmabuf->fence_fd = fence_fd;
-}
-
-void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync)
-{
- assert(dmabuf != NULL);
- dmabuf->sync = sync;
-}
-
void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted)
{
assert(dmabuf != NULL);
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 8e3729a54d..cb9c1e839c 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -432,7 +432,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf)
qemu_dmabuf_set_texture(dmabuf, 0);
}
-void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
+EGLSyncKHR egl_create_sync(void)
{
EGLSyncKHR sync;
@@ -443,23 +443,24 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
sync = eglCreateSyncKHR(qemu_egl_display,
EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
if (sync != EGL_NO_SYNC_KHR) {
- qemu_dmabuf_set_sync(dmabuf, sync);
+ return sync;
}
}
+
+ return NULL;
}
-void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
+int egl_create_fence(EGLSyncKHR sync)
{
- void *sync = qemu_dmabuf_get_sync(dmabuf);
- int fence_fd;
+ int fence_fd = -1;
if (sync) {
fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
sync);
- qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
eglDestroySyncKHR(qemu_egl_display, sync);
- qemu_dmabuf_set_sync(dmabuf, NULL);
}
+
+ return fence_fd;
}
#endif /* CONFIG_GBM */
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index adc81f34b1..c671aabd11 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -68,7 +68,7 @@ void gd_egl_draw(VirtualConsole *vc)
GdkWindow *window;
#ifdef CONFIG_GBM
QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
- int fence_fd;
+ EGLSyncKHR sync;
#endif
int ww, wh, pw, ph, gs;
@@ -94,7 +94,11 @@ void gd_egl_draw(VirtualConsole *vc)
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);
+#ifdef CONFIG_GBM
+ sync =
+#endif
+ gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0,
+ vc->gfx.w, vc->gfx.h);
gd_update_scale(vc, ww, wh,
surface_width(vc->gfx.ds),
@@ -103,13 +107,7 @@ void gd_egl_draw(VirtualConsole *vc)
glFlush();
#ifdef CONFIG_GBM
if (dmabuf) {
- egl_dmabuf_create_fence(dmabuf);
- fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
- if (fence_fd >= 0) {
- qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc);
- return;
- }
- qemu_console_hw_gl_block(vc->gfx.dcl.con, false);
+ gd_gl_wait_sync(vc, sync);
}
#endif
} else {
@@ -330,10 +328,12 @@ void gd_egl_cursor_position(DisplayChangeListener *dcl,
vc->gfx.cursor_y = pos_y * vc->gfx.scale_y;
}
-void gd_egl_scanout_flush(DisplayChangeListener *dcl,
- uint32_t x, uint32_t y, uint32_t w, uint32_t h)
+EGLSyncKHR gd_egl_scanout_flush(DisplayChangeListener *dcl,
+ uint32_t x, uint32_t y,
+ uint32_t w, uint32_t h)
{
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
+ EGLSyncKHR sync = EGL_NO_SYNC_KHR;
GdkWindow *window;
int px_offset, py_offset;
int gs;
@@ -342,10 +342,10 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl,
int fbw, fbh;
if (!vc->gfx.scanout_mode) {
- return;
+ return sync;
}
if (!vc->gfx.guest_fb.framebuffer) {
- return;
+ return sync;
}
eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
@@ -391,11 +391,13 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl,
#ifdef CONFIG_GBM
if (vc->gfx.guest_fb.dmabuf) {
- egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf);
+ sync = egl_create_sync();
}
#endif
eglSwapBuffers(qemu_egl_display, vc->gfx.esurface);
+
+ return sync;
}
void gd_egl_flush(DisplayChangeListener *dcl,
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index 29497019ee..29d1b1e411 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -41,6 +41,7 @@ void gd_gl_area_draw(VirtualConsole *vc)
{
#ifdef CONFIG_GBM
QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+ EGLSyncKHR sync = EGL_NO_SYNC_KHR;
#endif
int pw, ph, gs, y1, y2;
int ww, wh;
@@ -119,20 +120,13 @@ void gd_gl_area_draw(VirtualConsole *vc)
GL_COLOR_BUFFER_BIT, GL_NEAREST);
#ifdef CONFIG_GBM
if (dmabuf) {
- egl_dmabuf_create_sync(dmabuf);
+ sync = egl_create_sync();
}
#endif
glFlush();
#ifdef CONFIG_GBM
if (dmabuf) {
- int fence_fd;
- egl_dmabuf_create_fence(dmabuf);
- fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
- if (fence_fd >= 0) {
- qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc);
- return;
- }
- qemu_console_hw_gl_block(vc->gfx.dcl.con, false);
+ gd_gl_wait_sync(vc, sync);
}
#endif
} else {
diff --git a/ui/gtk.c b/ui/gtk.c
index 7078d89d67..1c75b9ea3c 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -597,21 +597,32 @@ static void gd_gl_release_dmabuf(DisplayChangeListener *dcl,
#endif
}
-void gd_hw_gl_flushed(void *vcon)
+#ifdef CONFIG_GBM
+static void gd_gl_fence_cb(void *vcon)
{
VirtualConsole *vc = vcon;
- QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
- int fence_fd;
-
- fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
- if (fence_fd >= 0) {
- qemu_set_fd_handler(fence_fd, NULL, NULL, NULL);
- close(fence_fd);
- qemu_dmabuf_set_fence_fd(dmabuf, -1);
+
+ if (vc->gfx.gl_fence_fd >= 0) {
+ qemu_set_fd_handler(vc->gfx.gl_fence_fd, NULL, NULL, NULL);
+ g_clear_fd(&vc->gfx.gl_fence_fd, NULL);
qemu_console_hw_gl_block(vc->gfx.dcl.con, false);
}
}
+void gd_gl_wait_sync(VirtualConsole *vc, EGLSyncKHR sync)
+{
+ assert(vc->gfx.gl_fence_fd < 0);
+
+ vc->gfx.gl_fence_fd = egl_create_fence(sync);
+ if (vc->gfx.gl_fence_fd >= 0) {
+ qemu_set_fd_handler(vc->gfx.gl_fence_fd,
+ gd_gl_fence_cb, NULL, vc);
+ } else {
+ qemu_console_hw_gl_block(vc->gfx.dcl.con, false);
+ }
+}
+#endif
+
/** DisplayState Callbacks (opengl version) **/
static const DisplayChangeListenerOps dcl_gl_area_ops = {
@@ -2355,6 +2366,7 @@ add_gfx_console(GtkDisplayState *s, QemuConsole *con)
vc->gfx.scale_y = vc->gfx.preferred_scale;
#if defined(CONFIG_OPENGL)
+ vc->gfx.gl_fence_fd = -1;
if (display_opengl) {
if (gtk_use_gl_area) {
vc->gfx.drawing_area = gtk_gl_area_new();
@@ -2647,6 +2659,9 @@ static void gd_vc_free(void *p)
switch (vc->type) {
case GD_VC_GFX:
+#if defined(CONFIG_OPENGL) && defined(CONFIG_GBM)
+ gd_gl_fence_cb(vc);
+#endif
qemu_console_unregister_listener(&vc->gfx.dcl);
#if defined(CONFIG_OPENGL)
if (display_opengl) {