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.

Signed-off-by: Marc-André Lureau <[email protected]>
---
 include/ui/dmabuf.h      |  4 ----
 include/ui/egl-helpers.h |  4 ++--
 include/ui/gtk.h         |  8 +++++---
 ui/dmabuf.c              | 29 -----------------------------
 ui/egl-helpers.c         | 15 ++++++++-------
 ui/gtk-egl.c             | 30 ++++++++++++++++--------------
 ui/gtk-gl-area.c         | 12 +++---------
 ui/gtk.c                 | 31 +++++++++++++++++++++++--------
 8 files changed, 57 insertions(+), 76 deletions(-)

diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h
index 3decdca4979c..381583bd536c 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 405ddd912591..023427b505ed 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 5c9c34a069ea..4b4ef50e3701 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 7433a268f0df..b61dc7ad2783 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 d689f187c4e5..54b4aa6e9fcb 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 adc81f34b1c8..c671aabd11b3 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 29497019ee46..29d1b1e4116f 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 7078d89d6797..1c75b9ea3c4d 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) {

-- 
2.55.0.543.g5ebe2ebe4ea8


Reply via email to