display/ui: add a callback to indicate GL state is flushed
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>
This commit is contained in:
parent
f8f3c2719e
commit
3cddb8b9e0
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
@ -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
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
@ -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 = {
|
||||
|
@ -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) \
|
||||
|
@ -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,
|
||||
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user