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:
commit
87574621b1
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
10
ui/console.c
10
ui/console.c
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user