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
