Skip to content

Commit 63cf612

Browse files
committed
Merge remote-tracking branch 'remotes/kraxel/tags/vga-20210916-pull-request' into staging
virtio-gpu + ui: fence syncronization. qxl: unbreak live migration. # gpg: Signature made Thu 16 Sep 2021 06:56:03 BST # gpg: using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <[email protected]>" [full] # gpg: aka "Gerd Hoffmann <[email protected]>" [full] # gpg: aka "Gerd Hoffmann (private) <[email protected]>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/vga-20210916-pull-request: virtio-gpu: Add gl_flushed callback ui/gtk-egl: Wait for the draw signal for dmabuf blobs ui: Create sync objects and fences only for blobs ui/egl: Add egl helpers to help with synchronization ui/gtk: Create a common release_dmabuf helper qxl: fix pre-save logic Signed-off-by: Peter Maydell <[email protected]>
2 parents 57b6f58 + b3a5dfd commit 63cf612

File tree

10 files changed

+157
-15
lines changed

10 files changed

+157
-15
lines changed

hw/display/qxl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2252,7 +2252,7 @@ static int qxl_pre_save(void *opaque)
22522252
} else {
22532253
d->last_release_offset = (uint8_t *)d->last_release - ram_start;
22542254
}
2255-
if (d->last_release_offset < d->vga.vram_size) {
2255+
if (d->last_release_offset >= d->vga.vram_size) {
22562256
return 1;
22572257
}
22582258

hw/display/virtio-gpu-udmabuf.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ static VGPUDMABuf
185185
dmabuf->buf.stride = fb->stride;
186186
dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
187187
dmabuf->buf.fd = res->dmabuf_fd;
188+
dmabuf->buf.allow_fences = true;
188189

189190
dmabuf->scanout_id = scanout_id;
190191
QTAILQ_INSERT_HEAD(&g->dmabuf.bufs, dmabuf, next);

hw/display/virtio-gpu.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -985,8 +985,10 @@ void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
985985
break;
986986
}
987987
if (!cmd->finished) {
988-
virtio_gpu_ctrl_response_nodata(g, cmd, cmd->error ? cmd->error :
989-
VIRTIO_GPU_RESP_OK_NODATA);
988+
if (!g->parent_obj.renderer_blocked) {
989+
virtio_gpu_ctrl_response_nodata(g, cmd, cmd->error ? cmd->error :
990+
VIRTIO_GPU_RESP_OK_NODATA);
991+
}
990992
}
991993
}
992994

@@ -1042,6 +1044,30 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
10421044
g->processing_cmdq = false;
10431045
}
10441046

1047+
static void virtio_gpu_process_fenceq(VirtIOGPU *g)
1048+
{
1049+
struct virtio_gpu_ctrl_command *cmd, *tmp;
1050+
1051+
QTAILQ_FOREACH_SAFE(cmd, &g->fenceq, next, tmp) {
1052+
trace_virtio_gpu_fence_resp(cmd->cmd_hdr.fence_id);
1053+
virtio_gpu_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA);
1054+
QTAILQ_REMOVE(&g->fenceq, cmd, next);
1055+
g_free(cmd);
1056+
g->inflight--;
1057+
if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
1058+
fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
1059+
}
1060+
}
1061+
}
1062+
1063+
static void virtio_gpu_handle_gl_flushed(VirtIOGPUBase *b)
1064+
{
1065+
VirtIOGPU *g = container_of(b, VirtIOGPU, parent_obj);
1066+
1067+
virtio_gpu_process_fenceq(g);
1068+
virtio_gpu_process_cmdq(g);
1069+
}
1070+
10451071
static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
10461072
{
10471073
VirtIOGPU *g = VIRTIO_GPU(vdev);
@@ -1400,10 +1426,12 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data)
14001426
DeviceClass *dc = DEVICE_CLASS(klass);
14011427
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
14021428
VirtIOGPUClass *vgc = VIRTIO_GPU_CLASS(klass);
1429+
VirtIOGPUBaseClass *vgbc = &vgc->parent;
14031430

14041431
vgc->handle_ctrl = virtio_gpu_handle_ctrl;
14051432
vgc->process_cmd = virtio_gpu_simple_process_cmd;
14061433
vgc->update_cursor_data = virtio_gpu_update_cursor_data;
1434+
vgbc->gl_flushed = virtio_gpu_handle_gl_flushed;
14071435

14081436
vdc->realize = virtio_gpu_device_realize;
14091437
vdc->reset = virtio_gpu_reset;

include/ui/console.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ typedef struct QemuDmaBuf {
168168
uint64_t modifier;
169169
uint32_t texture;
170170
bool y0_top;
171+
void *sync;
172+
int fence_fd;
173+
bool allow_fences;
171174
} QemuDmaBuf;
172175

173176
typedef struct DisplayState DisplayState;

include/ui/egl-helpers.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ typedef struct egl_fb {
1919
GLuint texture;
2020
GLuint framebuffer;
2121
bool delete_texture;
22+
QemuDmaBuf *dmabuf;
2223
} egl_fb;
2324

2425
void egl_fb_destroy(egl_fb *fb);
@@ -45,6 +46,8 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc,
4546

4647
void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf);
4748
void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf);
49+
void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf);
50+
void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf);
4851

4952
#endif
5053

include/ui/gtk.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ extern bool gtk_use_gl_area;
155155
/* ui/gtk.c */
156156
void gd_update_windowsize(VirtualConsole *vc);
157157
int gd_monitor_update_interval(GtkWidget *widget);
158+
void gd_hw_gl_flushed(void *vc);
158159

159160
/* ui/gtk-egl.c */
160161
void gd_egl_init(VirtualConsole *vc);
@@ -181,8 +182,8 @@ void gd_egl_cursor_dmabuf(DisplayChangeListener *dcl,
181182
uint32_t hot_x, uint32_t hot_y);
182183
void gd_egl_cursor_position(DisplayChangeListener *dcl,
183184
uint32_t pos_x, uint32_t pos_y);
184-
void gd_egl_release_dmabuf(DisplayChangeListener *dcl,
185-
QemuDmaBuf *dmabuf);
185+
void gd_egl_flush(DisplayChangeListener *dcl,
186+
uint32_t x, uint32_t y, uint32_t w, uint32_t h);
186187
void gd_egl_scanout_flush(DisplayChangeListener *dcl,
187188
uint32_t x, uint32_t y, uint32_t w, uint32_t h);
188189
void gtk_egl_init(DisplayGLMode mode);

ui/egl-helpers.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,32 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf)
287287
dmabuf->texture = 0;
288288
}
289289

290+
void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
291+
{
292+
EGLSyncKHR sync;
293+
294+
if (epoxy_has_egl_extension(qemu_egl_display,
295+
"EGL_KHR_fence_sync") &&
296+
epoxy_has_egl_extension(qemu_egl_display,
297+
"EGL_ANDROID_native_fence_sync")) {
298+
sync = eglCreateSyncKHR(qemu_egl_display,
299+
EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
300+
if (sync != EGL_NO_SYNC_KHR) {
301+
dmabuf->sync = sync;
302+
}
303+
}
304+
}
305+
306+
void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
307+
{
308+
if (dmabuf->sync) {
309+
dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
310+
dmabuf->sync);
311+
eglDestroySyncKHR(qemu_egl_display, dmabuf->sync);
312+
dmabuf->sync = NULL;
313+
}
314+
}
315+
290316
#endif /* CONFIG_GBM */
291317

292318
/* ---------------------------------------------------------------------- */

ui/gtk-egl.c

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313

1414
#include "qemu/osdep.h"
15+
#include "qemu/main-loop.h"
1516

1617
#include "trace.h"
1718

@@ -94,6 +95,18 @@ void gd_egl_draw(VirtualConsole *vc)
9495
}
9596

9697
glFlush();
98+
#ifdef CONFIG_GBM
99+
if (vc->gfx.guest_fb.dmabuf) {
100+
QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
101+
102+
egl_dmabuf_create_fence(dmabuf);
103+
if (dmabuf->fence_fd > 0) {
104+
qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
105+
return;
106+
}
107+
graphic_hw_gl_block(vc->gfx.dcl.con, false);
108+
}
109+
#endif
97110
graphic_hw_gl_flushed(vc->gfx.dcl.con);
98111
}
99112

@@ -209,6 +222,8 @@ void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
209222
QemuDmaBuf *dmabuf)
210223
{
211224
#ifdef CONFIG_GBM
225+
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
226+
212227
egl_dmabuf_import_texture(dmabuf);
213228
if (!dmabuf->texture) {
214229
return;
@@ -217,6 +232,10 @@ void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
217232
gd_egl_scanout_texture(dcl, dmabuf->texture,
218233
false, dmabuf->width, dmabuf->height,
219234
0, 0, dmabuf->width, dmabuf->height);
235+
236+
if (dmabuf->allow_fences) {
237+
vc->gfx.guest_fb.dmabuf = dmabuf;
238+
}
220239
#endif
221240
}
222241

@@ -249,14 +268,6 @@ void gd_egl_cursor_position(DisplayChangeListener *dcl,
249268
vc->gfx.cursor_y = pos_y * vc->gfx.scale_y;
250269
}
251270

252-
void gd_egl_release_dmabuf(DisplayChangeListener *dcl,
253-
QemuDmaBuf *dmabuf)
254-
{
255-
#ifdef CONFIG_GBM
256-
egl_dmabuf_release_texture(dmabuf);
257-
#endif
258-
}
259-
260271
void gd_egl_scanout_flush(DisplayChangeListener *dcl,
261272
uint32_t x, uint32_t y, uint32_t w, uint32_t h)
262273
{
@@ -289,9 +300,30 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl,
289300
egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top);
290301
}
291302

303+
#ifdef CONFIG_GBM
304+
if (vc->gfx.guest_fb.dmabuf) {
305+
egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf);
306+
}
307+
#endif
308+
292309
eglSwapBuffers(qemu_egl_display, vc->gfx.esurface);
293310
}
294311

312+
void gd_egl_flush(DisplayChangeListener *dcl,
313+
uint32_t x, uint32_t y, uint32_t w, uint32_t h)
314+
{
315+
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
316+
GtkWidget *area = vc->gfx.drawing_area;
317+
318+
if (vc->gfx.guest_fb.dmabuf) {
319+
graphic_hw_gl_block(vc->gfx.dcl.con, true);
320+
gtk_widget_queue_draw_area(area, x, y, w, h);
321+
return;
322+
}
323+
324+
gd_egl_scanout_flush(&vc->gfx.dcl, x, y, w, h);
325+
}
326+
295327
void gtk_egl_init(DisplayGLMode mode)
296328
{
297329
GdkDisplay *gdk_display = gdk_display_get_default();

ui/gtk-gl-area.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99

1010
#include "qemu/osdep.h"
11+
#include "qemu/main-loop.h"
1112

1213
#include "trace.h"
1314

@@ -71,7 +72,25 @@ void gd_gl_area_draw(VirtualConsole *vc)
7172
surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);
7273
}
7374

75+
#ifdef CONFIG_GBM
76+
if (vc->gfx.guest_fb.dmabuf) {
77+
egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf);
78+
}
79+
#endif
80+
7481
glFlush();
82+
#ifdef CONFIG_GBM
83+
if (vc->gfx.guest_fb.dmabuf) {
84+
QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
85+
86+
egl_dmabuf_create_fence(dmabuf);
87+
if (dmabuf->fence_fd > 0) {
88+
qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
89+
return;
90+
}
91+
graphic_hw_gl_block(vc->gfx.dcl.con, false);
92+
}
93+
#endif
7594
graphic_hw_gl_flushed(vc->gfx.dcl.con);
7695
}
7796

@@ -213,6 +232,9 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
213232
{
214233
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
215234

235+
if (vc->gfx.guest_fb.dmabuf) {
236+
graphic_hw_gl_block(vc->gfx.dcl.con, true);
237+
}
216238
gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area));
217239
}
218240

@@ -231,6 +253,10 @@ void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl,
231253
gd_gl_area_scanout_texture(dcl, dmabuf->texture,
232254
false, dmabuf->width, dmabuf->height,
233255
0, 0, dmabuf->width, dmabuf->height);
256+
257+
if (dmabuf->allow_fences) {
258+
vc->gfx.guest_fb.dmabuf = dmabuf;
259+
}
234260
#endif
235261
}
236262

ui/gtk.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "qapi/qapi-commands-machine.h"
3737
#include "qapi/qapi-commands-misc.h"
3838
#include "qemu/cutils.h"
39+
#include "qemu/main-loop.h"
3940

4041
#include "ui/console.h"
4142
#include "ui/gtk.h"
@@ -575,6 +576,26 @@ static bool gd_has_dmabuf(DisplayChangeListener *dcl)
575576
return vc->gfx.has_dmabuf;
576577
}
577578

579+
static void gd_gl_release_dmabuf(DisplayChangeListener *dcl,
580+
QemuDmaBuf *dmabuf)
581+
{
582+
#ifdef CONFIG_GBM
583+
egl_dmabuf_release_texture(dmabuf);
584+
#endif
585+
}
586+
587+
void gd_hw_gl_flushed(void *vcon)
588+
{
589+
VirtualConsole *vc = vcon;
590+
QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
591+
592+
graphic_hw_gl_block(vc->gfx.dcl.con, false);
593+
graphic_hw_gl_flushed(vc->gfx.dcl.con);
594+
qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL);
595+
close(dmabuf->fence_fd);
596+
dmabuf->fence_fd = -1;
597+
}
598+
578599
/** DisplayState Callbacks (opengl version) **/
579600

580601
static const DisplayChangeListenerOps dcl_gl_area_ops = {
@@ -593,6 +614,7 @@ static const DisplayChangeListenerOps dcl_gl_area_ops = {
593614
.dpy_gl_scanout_disable = gd_gl_area_scanout_disable,
594615
.dpy_gl_update = gd_gl_area_scanout_flush,
595616
.dpy_gl_scanout_dmabuf = gd_gl_area_scanout_dmabuf,
617+
.dpy_gl_release_dmabuf = gd_gl_release_dmabuf,
596618
.dpy_has_dmabuf = gd_has_dmabuf,
597619
};
598620

@@ -615,8 +637,8 @@ static const DisplayChangeListenerOps dcl_egl_ops = {
615637
.dpy_gl_scanout_dmabuf = gd_egl_scanout_dmabuf,
616638
.dpy_gl_cursor_dmabuf = gd_egl_cursor_dmabuf,
617639
.dpy_gl_cursor_position = gd_egl_cursor_position,
618-
.dpy_gl_release_dmabuf = gd_egl_release_dmabuf,
619-
.dpy_gl_update = gd_egl_scanout_flush,
640+
.dpy_gl_update = gd_egl_flush,
641+
.dpy_gl_release_dmabuf = gd_gl_release_dmabuf,
620642
.dpy_has_dmabuf = gd_has_dmabuf,
621643
};
622644

0 commit comments

Comments
 (0)