Any extra draw call for the same blob resource representing guest scanout
before the previous drawing is not finished can break synchronous draw
sequence. To prevent this, drawing is now done only once for each draw
submission (when draw_submitted == true).
v2:
- removed mutex
- updated commit msg
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Vivek Kasireddy <vivek.kasireddy@intel.com>
Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
Message-Id: <
20210924225105.24930-1-dongwon.kim@intel.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
dmabuf->buf.fd = res->dmabuf_fd;
dmabuf->buf.allow_fences = true;
-
+ dmabuf->buf.draw_submitted = false;
dmabuf->scanout_id = scanout_id;
QTAILQ_INSERT_HEAD(&g->dmabuf.bufs, dmabuf, next);
void *sync;
int fence_fd;
bool allow_fences;
+ bool draw_submitted;
} QemuDmaBuf;
typedef struct DisplayState DisplayState;
void gd_egl_draw(VirtualConsole *vc)
{
GdkWindow *window;
+#ifdef CONFIG_GBM
+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
int ww, wh;
if (!vc->gfx.gls) {
wh = gdk_window_get_height(window);
if (vc->gfx.scanout_mode) {
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ if (!dmabuf->draw_submitted) {
+ return;
+ } else {
+ dmabuf->draw_submitted = false;
+ }
+ }
+#endif
gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
vc->gfx.scale_x = (double)ww / vc->gfx.w;
vc->gfx.scale_y = (double)wh / vc->gfx.h;
+
+ glFlush();
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ egl_dmabuf_create_fence(dmabuf);
+ if (dmabuf->fence_fd > 0) {
+ qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
+ return;
+ }
+ graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ }
+#endif
} else {
if (!vc->gfx.ds) {
return;
vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
- }
-
- glFlush();
-#ifdef CONFIG_GBM
- if (vc->gfx.guest_fb.dmabuf) {
- QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
- egl_dmabuf_create_fence(dmabuf);
- if (dmabuf->fence_fd > 0) {
- qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
- return;
- }
- graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ glFlush();
}
-#endif
+
graphic_hw_gl_flushed(vc->gfx.dcl.con);
}
if (vc->gfx.guest_fb.dmabuf) {
graphic_hw_gl_block(vc->gfx.dcl.con, true);
+ vc->gfx.guest_fb.dmabuf->draw_submitted = true;
gtk_widget_queue_draw_area(area, x, y, w, h);
return;
}
void gd_gl_area_draw(VirtualConsole *vc)
{
+#ifdef CONFIG_GBM
+ QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
int ww, wh, y1, y2;
if (!vc->gfx.gls) {
return;
}
+#ifdef CONFIG_GBM
+ if (dmabuf) {
+ if (!dmabuf->draw_submitted) {
+ return;
+ } else {
+ dmabuf->draw_submitted = false;
+ }
+ }
+#endif
+
glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer);
/* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */
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) {
+ qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
+ return;
+ }
+ graphic_hw_gl_block(vc->gfx.dcl.con, false);
+ }
+#endif
} else {
if (!vc->gfx.ds) {
return;
surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);
}
-#ifdef CONFIG_GBM
- if (vc->gfx.guest_fb.dmabuf) {
- egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf);
- }
-#endif
-
- glFlush();
-#ifdef CONFIG_GBM
- if (vc->gfx.guest_fb.dmabuf) {
- QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
-
- egl_dmabuf_create_fence(dmabuf);
- if (dmabuf->fence_fd > 0) {
- qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
- return;
- }
- graphic_hw_gl_block(vc->gfx.dcl.con, false);
- }
-#endif
graphic_hw_gl_flushed(vc->gfx.dcl.con);
}
if (vc->gfx.guest_fb.dmabuf) {
graphic_hw_gl_block(vc->gfx.dcl.con, true);
+ vc->gfx.guest_fb.dmabuf->draw_submitted = true;
}
gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area));
}