virtio-gpu: bugfixes and spice support preparation

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJWscyhAAoJEEy22O7T6HE47qIQAJs/xOS3lRN+JrCJkBZtvi0x
 dGLzSWBcyw3pipFQIHa1kJwjKZRs5b6+KnvtpY889CW13zCmbUT+UxMSsymcz8/5
 o94Oi4dktYpY6kKa7ceCc1ZInsVC0gB0A7JFJPckn0DzvrW//ArXmwoORdQq2f7b
 3tQpeo4FCrzbWxrUn4wIVAznzcxpME09pJdu7u4lGlV1GtP0mEAy04heekoAlpLu
 V5JO/mRFpCEDhIxc2cGsq1Mtev+22NPHS3KxIVKrSwm0ubGLd6/A7+suf/ZPb3yr
 2w1OpRBCXldbAiJP0UeeSoAoMH34J6035fWzzqVeNDrXWT03AE29r1utEIn+BVpS
 xgJFJOC+TEYBNJjyXl6BAPD3W36VFIWBfp17lk27obxdDRAiBkvvfqg6Zb8I5TBD
 8f5Fu3nDiVEvDrW37sSiMVAD/UtTocW7nUI87jhasHkSyrGNefp+PQ8iBwEUVrAh
 IaY0eMm4hf5rSN1HluscN9fumdgzm6ChI+A+7nS43LiA8sA0Cw96MMjok6OQylUj
 sCTvcNXfAJrEpk2RE277QXn5ThWyZJLDQPiBqLSpnKvgrBLqKmBFRd8ynOjWULEn
 tSQ5rBK7m1ib+1vyqBBYd02bSi3gpebd7dK5T21SGicWYUN24FfjWqKH/LT4911T
 CFQd2e9V/5Yu+yzZq+LA
 =r/rk
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/pull-vga-20160203-1' into staging

virtio-gpu: bugfixes and spice support preparation

# gpg: Signature made Wed 03 Feb 2016 09:47:13 GMT using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-vga-20160203-1:
  virtio-gpu: block any rendering until client (ui) is done
  virtio-gpu: add support to enable/disable command processing
  virtio-gpu: maintain command queue
  virtio-gpu: fix memory leak in error path
  console: block rendering until client is done
  zap qemu_egl_has_ext in include/ui/egl-helpers.h

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-02-03 12:23:48 +00:00
commit 87574621b1
7 changed files with 85 additions and 20 deletions

View File

@ -198,7 +198,7 @@ static void virgl_cmd_submit_3d(VirtIOGPU *g,
qemu_log_mask(LOG_GUEST_ERROR, "%s: size mismatch (%zd/%d)",
__func__, s, cs.size);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
return;
goto out;
}
if (virtio_gpu_stats_enabled(g->conf)) {
@ -208,6 +208,7 @@ static void virgl_cmd_submit_3d(VirtIOGPU *g,
virgl_renderer_submit_cmd(buf, cs.hdr.ctx_id, cs.size / 4);
out:
g_free(buf);
}
@ -382,6 +383,11 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
{
VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
cmd->waiting = g->renderer_blocked;
if (cmd->waiting) {
return;
}
virgl_renderer_force_ctx_0();
switch (cmd->cmd_hdr.type) {
case VIRTIO_GPU_CMD_CTX_CREATE:
@ -553,7 +559,8 @@ static void virtio_gpu_fence_poll(void *opaque)
VirtIOGPU *g = opaque;
virgl_renderer_poll();
if (g->inflight) {
virtio_gpu_process_cmdq(g);
if (!QTAILQ_EMPTY(&g->cmdq) || !QTAILQ_EMPTY(&g->fenceq)) {
timer_mod(g->fence_poll, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 10);
}
}

View File

@ -755,6 +755,39 @@ static void virtio_gpu_handle_cursor_cb(VirtIODevice *vdev, VirtQueue *vq)
qemu_bh_schedule(g->cursor_bh);
}
void virtio_gpu_process_cmdq(VirtIOGPU *g)
{
struct virtio_gpu_ctrl_command *cmd;
while (!QTAILQ_EMPTY(&g->cmdq)) {
cmd = QTAILQ_FIRST(&g->cmdq);
/* process command */
VIRGL(g, virtio_gpu_virgl_process_cmd, virtio_gpu_simple_process_cmd,
g, cmd);
if (cmd->waiting) {
break;
}
QTAILQ_REMOVE(&g->cmdq, cmd, next);
if (virtio_gpu_stats_enabled(g->conf)) {
g->stats.requests++;
}
if (!cmd->finished) {
QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next);
g->inflight++;
if (virtio_gpu_stats_enabled(g->conf)) {
if (g->stats.max_inflight < g->inflight) {
g->stats.max_inflight = g->inflight;
}
fprintf(stderr, "inflight: %3d (+)\r", g->inflight);
}
} else {
g_free(cmd);
}
}
}
static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
@ -776,26 +809,14 @@ static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
cmd->vq = vq;
cmd->error = 0;
cmd->finished = false;
if (virtio_gpu_stats_enabled(g->conf)) {
g->stats.requests++;
}
VIRGL(g, virtio_gpu_virgl_process_cmd, virtio_gpu_simple_process_cmd,
g, cmd);
if (!cmd->finished) {
QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next);
g->inflight++;
if (virtio_gpu_stats_enabled(g->conf)) {
if (g->stats.max_inflight < g->inflight) {
g->stats.max_inflight = g->inflight;
}
fprintf(stderr, "inflight: %3d (+)\r", g->inflight);
}
cmd = g_new(struct virtio_gpu_ctrl_command, 1);
}
cmd->waiting = false;
QTAILQ_INSERT_TAIL(&g->cmdq, cmd, next);
cmd = g_new(struct virtio_gpu_ctrl_command, 1);
}
g_free(cmd);
virtio_gpu_process_cmdq(g);
#ifdef CONFIG_VIRGL
if (g->use_virgl_renderer) {
virtio_gpu_virgl_fence_poll(g);
@ -876,11 +897,22 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
return 0;
}
static void virtio_gpu_gl_block(void *opaque, bool block)
{
VirtIOGPU *g = opaque;
g->renderer_blocked = block;
if (!block) {
virtio_gpu_process_cmdq(g);
}
}
const GraphicHwOps virtio_gpu_ops = {
.invalidate = virtio_gpu_invalidate_display,
.gfx_update = virtio_gpu_update_display,
.text_update = virtio_gpu_text_update,
.ui_info = virtio_gpu_ui_info,
.gl_block = virtio_gpu_gl_block,
};
static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
@ -921,6 +953,7 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g);
g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g);
QTAILQ_INIT(&g->reslist);
QTAILQ_INIT(&g->cmdq);
QTAILQ_INIT(&g->fenceq);
g->enabled_output_bitmask = 1;

View File

@ -66,11 +66,21 @@ static int virtio_vga_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
return -1;
}
static void virtio_vga_gl_block(void *opaque, bool block)
{
VirtIOVGA *vvga = opaque;
if (virtio_gpu_ops.gl_block) {
virtio_gpu_ops.gl_block(&vvga->vdev, block);
}
}
static const GraphicHwOps virtio_vga_ops = {
.invalidate = virtio_vga_invalidate_display,
.gfx_update = virtio_vga_update_display,
.text_update = virtio_vga_text_update,
.ui_info = virtio_vga_ui_info,
.gl_block = virtio_vga_gl_block,
};
/* VGA device wrapper around PCI device around virtio GPU */

View File

@ -76,6 +76,7 @@ struct virtio_gpu_ctrl_command {
VirtQueue *vq;
struct virtio_gpu_ctrl_hdr cmd_hdr;
uint32_t error;
bool waiting;
bool finished;
QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
};
@ -94,6 +95,7 @@ typedef struct VirtIOGPU {
DeviceState *qdev;
QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUT];
@ -105,6 +107,7 @@ typedef struct VirtIOGPU {
bool use_virgl_renderer;
bool renderer_inited;
bool renderer_blocked;
QEMUTimer *fence_poll;
QEMUTimer *print_stats;
@ -151,6 +154,7 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
struct virtio_gpu_ctrl_command *cmd,
struct iovec **iov);
void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count);
void virtio_gpu_process_cmdq(VirtIOGPU *g);
/* virtio-gpu-3d.c */
void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,

View File

@ -362,6 +362,7 @@ typedef struct GraphicHwOps {
void (*text_update)(void *opaque, console_ch_t *text);
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);
} GraphicHwOps;
QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head,
@ -374,6 +375,7 @@ void graphic_console_set_hwops(QemuConsole *con,
void graphic_hw_update(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);
QemuConsole *qemu_console_lookup_by_index(unsigned int index);
QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head);

View File

@ -11,6 +11,5 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win);
int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug);
EGLContext qemu_egl_init_ctx(void);
bool qemu_egl_has_ext(const char *haystack, const char *needle);
#endif /* EGL_HELPERS_H */

View File

@ -261,6 +261,16 @@ void graphic_hw_update(QemuConsole *con)
}
}
void graphic_hw_gl_block(QemuConsole *con, bool block)
{
if (!con) {
con = active_console;
}
if (con && con->hw_ops->gl_block) {
con->hw_ops->gl_block(con->hw, block);
}
}
void graphic_hw_invalidate(QemuConsole *con)
{
if (!con) {