@@ -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 */
/* ---------------------------------------------------------------------- */
@@ -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);
}
@@ -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;
}
@@ -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);
}