Skip to content

Commit

Permalink
display/ui: add a callback to indicate GL state is flushed
Browse files Browse the repository at this point in the history
Displaying rendered resources requires blocking qemu GPU to avoid extra
framebuffer copies. For an external display, via Spice currently, there
is a callback to block/unblock the rendering in the same thread.

But with the vhost-user-gpu backend, the qemu process doesn't handle
the rendering itself, and the blocking callback isn't effective.
Instead, the backend must be notified when the display code is done.

Fix this by adding a new GraphicHwOps callback to indicate the GL state
is flushed, and we are done manipulating the shared GL resources. Call
it from gtk and spice display.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20210204105232.834642-19-marcandre.lureau@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
  • Loading branch information
elmarco authored and kraxel committed Feb 4, 2021
1 parent f8f3c27 commit 3cddb8b
Show file tree
Hide file tree
Showing 11 changed files with 48 additions and 10 deletions.
4 changes: 2 additions & 2 deletions hw/display/vhost-user-gpu.c
Expand Up @@ -360,7 +360,7 @@ vhost_user_gpu_update_blocked(VhostUserGPU *g, bool blocked)
}

static void
vhost_user_gpu_gl_unblock(VirtIOGPUBase *b)
vhost_user_gpu_gl_flushed(VirtIOGPUBase *b)
{
VhostUserGPU *g = VHOST_USER_GPU(b);

Expand Down Expand Up @@ -578,7 +578,7 @@ vhost_user_gpu_class_init(ObjectClass *klass, void *data)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
VirtIOGPUBaseClass *vgc = VIRTIO_GPU_BASE_CLASS(klass);

vgc->gl_unblock = vhost_user_gpu_gl_unblock;
vgc->gl_flushed = vhost_user_gpu_gl_flushed;

vdc->realize = vhost_user_gpu_device_realize;
vdc->reset = vhost_user_gpu_reset;
Expand Down
17 changes: 12 additions & 5 deletions hw/display/virtio-gpu-base.c
Expand Up @@ -97,21 +97,27 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
}

static void
virtio_gpu_gl_block(void *opaque, bool block)
virtio_gpu_gl_flushed(void *opaque)
{
VirtIOGPUBase *g = opaque;
VirtIOGPUBaseClass *vgc = VIRTIO_GPU_BASE_GET_CLASS(g);

if (vgc->gl_flushed) {
vgc->gl_flushed(g);
}
}

static void
virtio_gpu_gl_block(void *opaque, bool block)
{
VirtIOGPUBase *g = opaque;

if (block) {
g->renderer_blocked++;
} else {
g->renderer_blocked--;
}
assert(g->renderer_blocked >= 0);

if (g->renderer_blocked == 0) {
vgc->gl_unblock(g);
}
}

static int
Expand All @@ -138,6 +144,7 @@ static const GraphicHwOps virtio_gpu_ops = {
.text_update = virtio_gpu_text_update,
.ui_info = virtio_gpu_ui_info,
.gl_block = virtio_gpu_gl_block,
.gl_flushed = virtio_gpu_gl_flushed,
};

bool
Expand Down
4 changes: 2 additions & 2 deletions hw/display/virtio-gpu.c
Expand Up @@ -850,7 +850,7 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
g->processing_cmdq = false;
}

static void virtio_gpu_gl_unblock(VirtIOGPUBase *b)
static void virtio_gpu_gl_flushed(VirtIOGPUBase *b)
{
VirtIOGPU *g = VIRTIO_GPU(b);

Expand Down Expand Up @@ -1257,7 +1257,7 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
VirtIOGPUBaseClass *vgc = VIRTIO_GPU_BASE_CLASS(klass);

vgc->gl_unblock = virtio_gpu_gl_unblock;
vgc->gl_flushed = virtio_gpu_gl_flushed;
vdc->realize = virtio_gpu_device_realize;
vdc->reset = virtio_gpu_reset;
vdc->get_config = virtio_gpu_get_config;
Expand Down
11 changes: 11 additions & 0 deletions hw/display/virtio-vga.c
Expand Up @@ -68,6 +68,16 @@ static void virtio_vga_base_gl_block(void *opaque, bool block)
}
}

static void virtio_vga_base_gl_flushed(void *opaque)
{
VirtIOVGABase *vvga = opaque;
VirtIOGPUBase *g = vvga->vgpu;

if (g->hw_ops->gl_flushed) {
g->hw_ops->gl_flushed(g);
}
}

static int virtio_vga_base_get_flags(void *opaque)
{
VirtIOVGABase *vvga = opaque;
Expand All @@ -83,6 +93,7 @@ static const GraphicHwOps virtio_vga_base_ops = {
.text_update = virtio_vga_base_text_update,
.ui_info = virtio_vga_base_ui_info,
.gl_block = virtio_vga_base_gl_block,
.gl_flushed = virtio_vga_base_gl_flushed,
};

static const VMStateDescription vmstate_virtio_vga_base = {
Expand Down
2 changes: 1 addition & 1 deletion include/hw/virtio/virtio-gpu.h
Expand Up @@ -121,7 +121,7 @@ struct VirtIOGPUBase {
struct VirtIOGPUBaseClass {
VirtioDeviceClass parent;

void (*gl_unblock)(VirtIOGPUBase *g);
void (*gl_flushed)(VirtIOGPUBase *g);
};

#define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf) \
Expand Down
2 changes: 2 additions & 0 deletions include/ui/console.h
Expand Up @@ -387,6 +387,7 @@ typedef struct GraphicHwOps {
void (*update_interval)(void *opaque, uint64_t interval);
int (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info);
void (*gl_block)(void *opaque, bool block);
void (*gl_flushed)(void *opaque);
} GraphicHwOps;

QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head,
Expand All @@ -402,6 +403,7 @@ void graphic_hw_update_done(QemuConsole *con);
void graphic_hw_invalidate(QemuConsole *con);
void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata);
void graphic_hw_gl_block(QemuConsole *con, bool block);
void graphic_hw_gl_flushed(QemuConsole *con);

void qemu_console_early_init(void);

Expand Down
9 changes: 9 additions & 0 deletions ui/console.c
Expand Up @@ -294,6 +294,15 @@ void graphic_hw_gl_block(QemuConsole *con, bool block)
}
}

void graphic_hw_gl_flushed(QemuConsole *con)
{
assert(con != NULL);

if (con->hw_ops->gl_flushed) {
con->hw_ops->gl_flushed(con->hw);
}
}

int qemu_console_get_window_id(QemuConsole *con)
{
return con->window_id;
Expand Down
3 changes: 3 additions & 0 deletions ui/gtk-egl.c
Expand Up @@ -92,6 +92,9 @@ void gd_egl_draw(VirtualConsole *vc)
vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
}

glFlush();
graphic_hw_gl_flushed(vc->gfx.dcl.con);
}

void gd_egl_update(DisplayChangeListener *dcl,
Expand Down
3 changes: 3 additions & 0 deletions ui/gtk-gl-area.c
Expand Up @@ -70,6 +70,9 @@ void gd_gl_area_draw(VirtualConsole *vc)
surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh);
surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);
}

glFlush();
graphic_hw_gl_flushed(vc->gfx.dcl.con);
}

void gd_gl_area_update(DisplayChangeListener *dcl,
Expand Down
2 changes: 2 additions & 0 deletions ui/sdl2-gl.c
Expand Up @@ -58,6 +58,7 @@ static void sdl2_gl_render_surface(struct sdl2_console *scon)

surface_gl_render_texture(scon->gls, scon->surface);
SDL_GL_SwapWindow(scon->real_window);
graphic_hw_gl_flushed(scon->dcl.con);
}

void sdl2_gl_update(DisplayChangeListener *dcl,
Expand Down Expand Up @@ -240,4 +241,5 @@ void sdl2_gl_scanout_flush(DisplayChangeListener *dcl,
egl_fb_blit(&scon->win_fb, &scon->guest_fb, !scon->y0_top);

SDL_GL_SwapWindow(scon->real_window);
graphic_hw_gl_flushed(dcl->con);
}
1 change: 1 addition & 0 deletions ui/spice-display.c
Expand Up @@ -826,6 +826,7 @@ static void qemu_spice_gl_unblock_bh(void *opaque)
SimpleSpiceDisplay *ssd = opaque;

qemu_spice_gl_block(ssd, false);
graphic_hw_gl_flushed(ssd->dcl.con);
}

static void qemu_spice_gl_block_timer(void *opaque)
Expand Down

0 comments on commit 3cddb8b

Please sign in to comment.