Signed-off-by: Alon Levy <al...@redhat.com> --- hw/qxl.c | 252 +++++++++++++++++++++++++++++++++++++++++++--------- hw/qxl.h | 15 +++- ui/spice-display.c | 46 ++++++++-- ui/spice-display.h | 25 +++++- 4 files changed, 282 insertions(+), 56 deletions(-)
diff --git a/hw/qxl.c b/hw/qxl.c index e5dce92..b34e8d0 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -146,16 +146,42 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, num_dirty_rects, clear_dirty_region); } -void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id) +#if SPICE_INTERFACE_QXL_MINOR >= 1 +void qxl_spice_update_area_async(PCIQXLDevice *qxl, uint32_t surface_id, + struct QXLRect *area, + uint32_t clear_dirty_region, int is_vga) +{ + qxl->ssd.worker->update_area_async(qxl->ssd.worker, surface_id, area, + clear_dirty_region, + is_vga ? QXL_COOKIE_VGA : 0); +} +#endif + +static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl, + uint32_t id) { qemu_mutex_lock(&qxl->track_lock); - PANIC_ON(id >= NUM_SURFACES); - qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); qxl->guest_surfaces.cmds[id] = 0; qxl->guest_surfaces.count--; qemu_mutex_unlock(&qxl->track_lock); } +static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id, + qxl_async_io async) +{ + if (async) { +#if SPICE_INTERFACE_QXL_MINOR < 1 + abort(); +#else + qxl->ssd.worker->destroy_surface_wait_async(qxl->ssd.worker, id, + (uint64_t)id); +#endif + } else { + qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); + qxl_spice_destroy_surface_wait_complete(qxl, id); + } +} + void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, uint32_t count) { @@ -172,15 +198,28 @@ void qxl_spice_reset_memslots(PCIQXLDevice *qxl) qxl->ssd.worker->reset_memslots(qxl->ssd.worker); } -void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl) +static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl) { qemu_mutex_lock(&qxl->track_lock); - qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker); memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds)); qxl->guest_surfaces.count = 0; qemu_mutex_unlock(&qxl->track_lock); } +static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async) +{ + if (async) { +#if SPICE_INTERFACE_QXL_MINOR < 1 + abort(); +#else + qxl->ssd.worker->destroy_surfaces_async(qxl->ssd.worker, 0); +#endif + } else { + qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker); + qxl_spice_destroy_surfaces_complete(qxl); + } +} + void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) { qxl->ssd.worker->reset_image_cache(qxl->ssd.worker); @@ -706,6 +745,43 @@ static int interface_flush_resources(QXLInstance *sin) return ret; } +static void qxl_create_guest_primary_complete(PCIQXLDevice *d); + +#if SPICE_INTERFACE_QXL_MINOR >= 1 + +/* called from spice server thread context only */ +static void interface_async_complete(QXLInstance *sin, uint64_t cookie) +{ + PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); + uint32_t current_async; + + if (cookie == QXL_COOKIE_VGA) { + dprint(qxl, 3, "ignoring async from vga update\n"); + return; + } + + qemu_mutex_lock(&qxl->async_lock); + current_async = qxl->current_async; + qxl->current_async = QXL_UNDEFINED_IO; + qemu_mutex_unlock(&qxl->async_lock); + + dprint(qxl, 2, "async_complete: %d (%ld) done\n", current_async, cookie); + switch (current_async) { + case QXL_IO_CREATE_PRIMARY_ASYNC: + qxl_create_guest_primary_complete(qxl); + break; + case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: + qxl_spice_destroy_surfaces_complete(qxl); + break; + case QXL_IO_DESTROY_SURFACE_ASYNC: + qxl_spice_destroy_surface_wait_complete(qxl, (uint32_t)cookie); + break; + } + qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD); +} + +#endif + static const QXLInterface qxl_interface = { .base.type = SPICE_INTERFACE_QXL, .base.description = "qxl gpu", @@ -725,6 +801,9 @@ static const QXLInterface qxl_interface = { .req_cursor_notification = interface_req_cursor_notification, .notify_update = interface_notify_update, .flush_resources = interface_flush_resources, +#if SPICE_INTERFACE_QXL_MINOR >= 1 + .async_complete = interface_async_complete, +#endif }; static void qxl_enter_vga_mode(PCIQXLDevice *d) @@ -746,7 +825,7 @@ static void qxl_exit_vga_mode(PCIQXLDevice *d) dprint(d, 1, "%s\n", __FUNCTION__); if (d->mode != QXL_MODE_UNDEFINED) { d->mode = QXL_MODE_UNDEFINED; - qemu_spice_destroy_primary_surface(&d->ssd, 0); + qemu_spice_destroy_primary_surface(&d->ssd, 0, QXL_SYNC); } } @@ -852,14 +931,15 @@ static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) dprint(qxl, 1, "%s\n", __FUNCTION__); if (qxl->mode != QXL_MODE_UNDEFINED) { qxl->mode = QXL_MODE_UNDEFINED; - qemu_spice_destroy_primary_surface(&qxl->ssd, 0); + qemu_spice_destroy_primary_surface(&qxl->ssd, 0, QXL_SYNC); } qxl_soft_reset(qxl); } vga_ioport_write(opaque, addr, val); } -static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta) +static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, + qxl_async_io async) { static const int regions[] = { QXL_RAM_RANGE_INDEX, @@ -929,7 +1009,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta) __FUNCTION__, memslot.slot_id, memslot.virt_start, memslot.virt_end); - qemu_spice_add_memslot(&d->ssd, &memslot); + qemu_spice_add_memslot(&d->ssd, &memslot, async); d->guest_slots[slot_id].ptr = (void*)memslot.virt_start; d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start; d->guest_slots[slot_id].delta = delta; @@ -954,7 +1034,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) { dprint(d, 1, "%s:\n", __FUNCTION__); d->mode = QXL_MODE_UNDEFINED; - qxl_spice_destroy_surfaces(d); + qxl_spice_destroy_surfaces(d, QXL_SYNC); } /* called from spice server thread context only */ @@ -979,7 +1059,14 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id) } } -static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm) +static void qxl_create_guest_primary_complete(PCIQXLDevice *qxl) +{ + /* for local rendering */ + qxl_render_resize(qxl); +} + +static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm, + qxl_async_io async) { QXLDevSurfaceCreate surface; QXLSurfaceCreate *sc = &qxl->guest_primary.surface; @@ -1007,10 +1094,11 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm) qxl->mode = QXL_MODE_NATIVE; qxl->cmdflags = 0; - qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface); + qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface, async); - /* for local rendering */ - qxl_render_resize(qxl); + if (async == QXL_SYNC) { + qxl_create_guest_primary_complete(qxl); + } } static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm) @@ -1040,10 +1128,10 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm) } d->guest_slots[0].slot = slot; - qxl_add_memslot(d, 0, devmem); + qxl_add_memslot(d, 0, devmem, QXL_SYNC); d->guest_primary.surface = surface; - qxl_create_guest_primary(d, 0); + qxl_create_guest_primary(d, 0, QXL_SYNC); d->mode = QXL_MODE_COMPAT; d->cmdflags = QXL_COMMAND_FLAG_COMPAT; @@ -1061,13 +1149,16 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) { PCIQXLDevice *d = opaque; uint32_t io_port = addr - d->io_base; + qxl_async_io async = QXL_SYNC; switch (io_port) { case QXL_IO_RESET: case QXL_IO_SET_MODE: case QXL_IO_MEMSLOT_ADD: + case QXL_IO_MEMSLOT_ADD_ASYNC: case QXL_IO_MEMSLOT_DEL: case QXL_IO_CREATE_PRIMARY: + case QXL_IO_CREATE_PRIMARY_ASYNC: case QXL_IO_UPDATE_IRQ: case QXL_IO_LOG: break; @@ -1076,10 +1167,52 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) break; dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n", __func__, io_port, io_port_to_string(io_port)); + /* be nice to buggy guest drivers */ + if (io_port >= QXL_IO_UPDATE_AREA_ASYNC && + io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) { + qxl_send_events(d, QXL_INTERRUPT_IO_CMD); + } return; } switch (io_port) { + case QXL_IO_UPDATE_AREA_ASYNC: + case QXL_IO_MEMSLOT_ADD_ASYNC: + case QXL_IO_CREATE_PRIMARY_ASYNC: + case QXL_IO_DESTROY_PRIMARY_ASYNC: + case QXL_IO_DESTROY_SURFACE_ASYNC: + case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: +#if SPICE_INTERFACE_QXL_MINOR < 1 + fprintf(stderr, "qxl: error: async not supported by libspice" + "but guest driver used it\n"); + return; +#else + async = QXL_ASYNC; + qemu_mutex_lock(&d->async_lock); + if (d->current_async != QXL_UNDEFINED_IO) { + qxl_guest_bug(d, "%d async started before last (%d) complete\n", + io_port, d->current_async); + qemu_mutex_unlock(&d->async_lock); + return; + } + d->current_async = io_port; + qemu_mutex_unlock(&d->async_lock); + dprint(d, 2, "start async %d (%d)\n", io_port, val); + break; +#endif + default: + break; + } + + switch (io_port) { +#if SPICE_INTERFACE_QXL_MINOR >= 1 + case QXL_IO_UPDATE_AREA_ASYNC: { + QXLRect update = d->ram->update_area; + qxl_spice_update_area_async(d, d->ram->update_surface, + &update, 0, 0); + break; + } +#endif case QXL_IO_UPDATE_AREA: { QXLRect update = d->ram->update_area; @@ -1122,6 +1255,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) dprint(d, 1, "QXL_IO_RESET\n"); qxl_hard_reset(d, 0); break; + case QXL_IO_MEMSLOT_ADD_ASYNC: case QXL_IO_MEMSLOT_ADD: if (val >= NUM_MEMSLOTS) { qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range\n"); @@ -1133,7 +1267,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) break; } d->guest_slots[val].slot = d->ram->mem_slot; - qxl_add_memslot(d, val, 0); + qxl_add_memslot(d, val, 0, async); break; case QXL_IO_MEMSLOT_DEL: if (val >= NUM_MEMSLOTS) { @@ -1142,36 +1276,69 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) } qxl_del_memslot(d, val); break; + case QXL_IO_CREATE_PRIMARY_ASYNC: case QXL_IO_CREATE_PRIMARY: if (val != 0) { - qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY: val != 0\n"); - break; + qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY (async=%d): val != 0\n", + async); + goto cancel_async; } - dprint(d, 1, "QXL_IO_CREATE_PRIMARY\n"); + dprint(d, 1, "QXL_IO_CREATE_PRIMARY async=%d\n", async); d->guest_primary.surface = d->ram->create_surface; - qxl_create_guest_primary(d, 0); + qxl_create_guest_primary(d, 0, async); break; + case QXL_IO_DESTROY_PRIMARY_ASYNC: case QXL_IO_DESTROY_PRIMARY: if (val != 0) { - qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY: val != 0\n"); - break; + qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0\n", + async); + goto cancel_async; } - dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (%s)\n", qxl_mode_to_string(d->mode)); + dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (async=%d) (%s)\n", async, + qxl_mode_to_string(d->mode)); if (d->mode != QXL_MODE_UNDEFINED) { d->mode = QXL_MODE_UNDEFINED; - qemu_spice_destroy_primary_surface(&d->ssd, 0); + qemu_spice_destroy_primary_surface(&d->ssd, 0, async); + } else { +#if SPICE_INTERFACE_QXL_MINOR >= 1 + if (async) { + dprint(d, 1, "QXL_IO_DESTROY_PRIMARY_ASYNC in %s, ignored\n", + qxl_mode_to_string(d->mode)); + qxl_send_events(d, QXL_INTERRUPT_IO_CMD); + goto cancel_async; + } +#endif } break; + case QXL_IO_DESTROY_SURFACE_ASYNC: case QXL_IO_DESTROY_SURFACE_WAIT: - qxl_spice_destroy_surface_wait(d, val); + if (val >= NUM_SURFACES) { + qxl_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):" + "%d >= NUM_SURFACES", async, val); + goto cancel_async; + } + qxl_spice_destroy_surface_wait(d, val, async); break; + case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: case QXL_IO_DESTROY_ALL_SURFACES: - qxl_spice_destroy_surfaces(d); + d->mode = QXL_MODE_UNDEFINED; + qxl_spice_destroy_surfaces(d, async); break; default: fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port); abort(); } + return; +cancel_async: +#if SPICE_INTERFACE_QXL_MINOR >= 1 + if (async) { + qemu_mutex_lock(&d->async_lock); + d->current_async = QXL_UNDEFINED_IO; + qemu_mutex_unlock(&d->async_lock); + } +#else + return; +#endif } static uint32_t ioport_read(void *opaque, uint32_t addr) @@ -1376,7 +1543,6 @@ static DisplayChangeListener display_listener = { static int qxl_init_common(PCIQXLDevice *qxl) { uint8_t* config = qxl->pci.config; - uint32_t pci_device_rev; uint32_t io_size; qxl->mode = QXL_MODE_UNDEFINED; @@ -1384,23 +1550,25 @@ static int qxl_init_common(PCIQXLDevice *qxl) qxl->num_memslots = NUM_MEMSLOTS; qxl->num_surfaces = NUM_SURFACES; qemu_mutex_init(&qxl->track_lock); - +#if SPICE_INTERFACE_QXL_MINOR >= 1 + qemu_mutex_init(&qxl->async_lock); + qxl->current_async = QXL_UNDEFINED_IO; +#endif switch (qxl->revision) { - case 1: /* spice 0.4 -- qxl-1 */ - pci_device_rev = QXL_REVISION_STABLE_V04; - break; - case 2: /* spice 0.6 -- qxl-2 */ - pci_device_rev = QXL_REVISION_STABLE_V06; - break; + case QXL_REVISION_STABLE_V04: /* spice 0.4 -- qxl-1 */ + case QXL_REVISION_STABLE_V06: /* spice 0.6 -- qxl-2 */ #if SPICE_INTERFACE_QXL_MINOR >= 1 - case 3: /* qxl-3 */ + case QXL_REVISION_STABLE_V10: /* spice 0.10? -- qxl-3 */ + break; #endif default: - pci_device_rev = QXL_DEFAULT_REVISION; + fprintf(stderr, "invalid revision %d, resetting to %d\n", qxl->revision, + QXL_DEFAULT_REVISION); + qxl->revision = QXL_DEFAULT_REVISION; break; } - pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev); + pci_set_byte(&config[PCI_REVISION_ID], qxl->revision); pci_set_byte(&config[PCI_INTERRUPT_PIN], 1); qxl->rom_size = qxl_rom_size(); @@ -1411,14 +1579,14 @@ static int qxl_init_common(PCIQXLDevice *qxl) if (qxl->vram_size < 16 * 1024 * 1024) { qxl->vram_size = 16 * 1024 * 1024; } - if (qxl->revision == 1) { + if (qxl->revision == QXL_REVISION_STABLE_V04) { qxl->vram_size = 4096; } qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1); qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vram", qxl->vram_size); io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1); - if (qxl->revision == 1) { + if (qxl->revision == QXL_REVISION_STABLE_V04) { io_size = 8; } @@ -1553,9 +1721,9 @@ static int qxl_post_load(void *opaque, int version) if (!d->guest_slots[i].active) { continue; } - qxl_add_memslot(d, i, 0); + qxl_add_memslot(d, i, 0, QXL_SYNC); } - qxl_create_guest_primary(d, 1); + qxl_create_guest_primary(d, 1, QXL_SYNC); /* replay surface-create and cursor-set commands */ cmds = qemu_mallocz(sizeof(QXLCommandExt) * (NUM_SURFACES + 1)); diff --git a/hw/qxl.h b/hw/qxl.h index 3dbe0df..d91519a 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -15,6 +15,8 @@ enum qxl_mode { QXL_MODE_NATIVE, }; +#define QXL_UNDEFINED_IO UINT32_MAX + typedef struct PCIQXLDevice { PCIDevice pci; SimpleSpiceDisplay ssd; @@ -30,6 +32,11 @@ typedef struct PCIQXLDevice { int32_t num_memslots; int32_t num_surfaces; +#if SPICE_INTERFACE_QXL_MINOR >= 1 + uint32_t current_async; + QemuMutex async_lock; +#endif + struct guest_slots { QXLMemSlot slot; void *ptr; @@ -111,12 +118,10 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, struct QXLRect *area, struct QXLRect *dirty_rects, uint32_t num_dirty_rects, uint32_t clear_dirty_region); -void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id); void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, uint32_t count); void qxl_spice_oom(PCIQXLDevice *qxl); void qxl_spice_reset_memslots(PCIQXLDevice *qxl); -void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl); void qxl_spice_reset_image_cache(PCIQXLDevice *qxl); void qxl_spice_reset_cursor(PCIQXLDevice *qxl); @@ -128,3 +133,9 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext); void qxl_render_resize(PCIQXLDevice *qxl); void qxl_render_update(PCIQXLDevice *qxl); void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext); +#if SPICE_INTERFACE_QXL_MINOR >= 1 +void qxl_spice_update_area_async(PCIQXLDevice *qxl, uint32_t surface_id, + struct QXLRect *area, + uint32_t clear_dirty_region, + int is_vga); +#endif diff --git a/ui/spice-display.c b/ui/spice-display.c index feb333c..fb1436e 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -62,9 +62,18 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r) dest->right = MAX(dest->right, r->right); } -void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot) -{ - ssd->worker->add_memslot(ssd->worker, memslot); +void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot, + qxl_async_io async) +{ + if (async != QXL_SYNC) { +#if SPICE_INTERFACE_QXL_MINOR >= 1 + ssd->worker->add_memslot_async(ssd->worker, memslot, 0); +#else + abort(); +#endif + } else { + ssd->worker->add_memslot(ssd->worker, memslot); + } } void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid) @@ -73,14 +82,33 @@ void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid) } void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, - QXLDevSurfaceCreate *surface) -{ - ssd->worker->create_primary_surface(ssd->worker, id, surface); + QXLDevSurfaceCreate *surface, + qxl_async_io async) +{ + if (async != QXL_SYNC) { +#if SPICE_INTERFACE_QXL_MINOR >= 1 + ssd->worker->create_primary_surface_async(ssd->worker, id, surface, 0); +#else + abort(); +#endif + } else { + ssd->worker->create_primary_surface(ssd->worker, id, surface); + } } -void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id) + +void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, + uint32_t id, qxl_async_io async) { - ssd->worker->destroy_primary_surface(ssd->worker, id); + if (async != QXL_SYNC) { +#if SPICE_INTERFACE_QXL_MINOR >= 1 + ssd->worker->destroy_primary_surface_async(ssd->worker, id, 0); +#else + abort(); +#endif + } else { + ssd->worker->destroy_primary_surface(ssd->worker, id); + } } void qemu_spice_wakeup(SimpleSpiceDisplay *ssd) @@ -197,7 +225,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd) memset(&memslot, 0, sizeof(memslot)); memslot.slot_group_id = MEMSLOT_GROUP_HOST; memslot.virt_end = ~0; - qemu_spice_add_memslot(ssd, &memslot); + qemu_spice_add_memslot(ssd, &memslot, QXL_SYNC); } void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) @@ -217,14 +245,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) surface.mem = (intptr_t)ssd->buf; surface.group_id = MEMSLOT_GROUP_HOST; - qemu_spice_create_primary_surface(ssd, 0, &surface); + qemu_spice_create_primary_surface(ssd, 0, &surface, QXL_SYNC); } void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) { dprint(1, "%s:\n", __FUNCTION__); - qemu_spice_destroy_primary_surface(ssd, 0); + qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC); } void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) diff --git a/ui/spice-display.h b/ui/spice-display.h index abe99c7..fdfa952 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -33,6 +33,22 @@ #define NUM_SURFACES 1024 +/* + * Internal enum to differenciate between options for + * io calls that have a sync (old) version and an _async (new) + * version: + * QXL_SYNC: use the old version + * QXL_ASYNC: use the new version and make sure there are no two + * happening at the same time. This is used for guest initiated + * calls + */ +typedef enum qxl_async_io { + QXL_SYNC, + QXL_ASYNC, +} qxl_async_io; + +#define QXL_COOKIE_VGA ((uint64_t)-1) + typedef struct SimpleSpiceDisplay SimpleSpiceDisplay; typedef struct SimpleSpiceUpdate SimpleSpiceUpdate; @@ -82,12 +98,15 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, void qemu_spice_display_resize(SimpleSpiceDisplay *ssd); void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd); -void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot); +void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot, + qxl_async_io async); void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid); void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, - QXLDevSurfaceCreate *surface); -void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id); + QXLDevSurfaceCreate *surface, + qxl_async_io async); +void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, + uint32_t id, qxl_async_io async); void qemu_spice_wakeup(SimpleSpiceDisplay *ssd); void qemu_spice_start(SimpleSpiceDisplay *ssd); void qemu_spice_stop(SimpleSpiceDisplay *ssd); -- 1.7.6