[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v4] ui/gtk: flush display pipeline before saving vmstate when blo
From: |
dongwon . kim |
Subject: |
[PATCH v4] ui/gtk: flush display pipeline before saving vmstate when blob=true |
Date: |
Wed, 20 Mar 2024 18:53:57 -0700 |
From: Dongwon Kim <dongwon.kim@intel.com>
It is required to ensure the current scanout frame is completed
before transitioning guest's run-state to save to prevent potential
guest waiting for the response on the resource flush of the old
scanout frame upon resume.
v2: Giving some time for the fence to be signaled before flushing
the pipeline
v3: Prevent redudant call of gd_hw_gl_flushed by checking dmabuf
and fence_fd >= 0 in it (e.g. during and after eglClientWaitSync
in gd_change_runstate)
v4: Rewrote the commit msg
Creating fence_fd in the same function where sync is created to
handle the case where the valid sync is created but fence_fd is
failed to be created.
0 is a valid fd so any fence_fd > -1 for the fence in draw function
in gtk-egl.c and gtk-gl-area.c will be considered valid
egl_sync and fence_fd for it are created in the same function
Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
Cc: Vivek Kasireddy <vivek.kasireddy@intel.com>
Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
---
ui/egl-helpers.c | 16 ++++++----------
ui/gtk-egl.c | 10 ++--------
ui/gtk-gl-area.c | 9 ++-------
ui/gtk.c | 31 +++++++++++++++++++++++++++----
4 files changed, 37 insertions(+), 29 deletions(-)
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 3d19dbe382..b6a8169ffc 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -376,20 +376,16 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
if (sync != EGL_NO_SYNC_KHR) {
dmabuf->sync = sync;
+ dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
+ dmabuf->sync);
+ if (dmabuf->fence_fd < 0) {
+ eglDestroySyncKHR(qemu_egl_display, dmabuf->sync);
+ dmabuf->sync = NULL;
+ }
}
}
}
-void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
-{
- if (dmabuf->sync) {
- dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
- dmabuf->sync);
- eglDestroySyncKHR(qemu_egl_display, dmabuf->sync);
- dmabuf->sync = NULL;
- }
-}
-
#endif /* CONFIG_GBM */
/* ---------------------------------------------------------------------- */
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 3af5ac5bcf..683a87c6b3 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -98,8 +98,8 @@ void gd_egl_draw(VirtualConsole *vc)
glFlush();
#ifdef CONFIG_GBM
if (dmabuf) {
- egl_dmabuf_create_fence(dmabuf);
- if (dmabuf->fence_fd > 0) {
+ egl_dmabuf_create_sync(dmabuf);
+ if (dmabuf->fence_fd > -1) {
qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL,
vc);
return;
}
@@ -348,12 +348,6 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl,
egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top);
}
-#ifdef CONFIG_GBM
- if (vc->gfx.guest_fb.dmabuf) {
- egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf);
- }
-#endif
-
eglSwapBuffers(qemu_egl_display, vc->gfx.esurface);
}
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index 52dcac161e..7791498646 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -77,16 +77,11 @@ void gd_gl_area_draw(VirtualConsole *vc)
glBlitFramebuffer(0, y1, vc->gfx.w, y2,
0, 0, ww, wh,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
-#ifdef CONFIG_GBM
- if (dmabuf) {
- egl_dmabuf_create_sync(dmabuf);
- }
-#endif
glFlush();
#ifdef CONFIG_GBM
if (dmabuf) {
- egl_dmabuf_create_fence(dmabuf);
- if (dmabuf->fence_fd > 0) {
+ egl_dmabuf_create_sync(dmabuf);
+ if (dmabuf->fence_fd > -1) {
qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL,
vc);
return;
}
diff --git a/ui/gtk.c b/ui/gtk.c
index 810d7fc796..bbe05a0baf 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -597,10 +597,14 @@ void gd_hw_gl_flushed(void *vcon)
VirtualConsole *vc = vcon;
QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
- qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL);
- close(dmabuf->fence_fd);
- dmabuf->fence_fd = -1;
- graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ if (dmabuf && dmabuf->fence_fd > -1) {
+ qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL);
+ close(dmabuf->fence_fd);
+ dmabuf->fence_fd = -1;
+ eglDestroySyncKHR(qemu_egl_display, dmabuf->sync);
+ dmabuf->sync = NULL;
+ graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ }
}
/** DisplayState Callbacks (opengl version) **/
@@ -678,6 +682,25 @@ static const DisplayGLCtxOps egl_ctx_ops = {
static void gd_change_runstate(void *opaque, bool running, RunState state)
{
GtkDisplayState *s = opaque;
+ int i;
+
+ if (state == RUN_STATE_SAVE_VM) {
+ for (i = 0; i < s->nb_vcs; i++) {
+ VirtualConsole *vc = &s->vc[i];
+
+ if (vc->gfx.guest_fb.dmabuf &&
+ vc->gfx.guest_fb.dmabuf->fence_fd >= 0) {
+ eglClientWaitSync(qemu_egl_display,
+ vc->gfx.guest_fb.dmabuf->sync,
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
+ 100000000);
+
+ /* force flushing current scanout blob rendering process
+ * just in case the fence is still not signaled */
+ gd_hw_gl_flushed(vc);
+ }
+ }
+ }
gd_update_caption(s);
}
--
2.34.1
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH v4] ui/gtk: flush display pipeline before saving vmstate when blob=true,
dongwon . kim <=