diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/display/qxl.c | 126 | ||||
-rw-r--r-- | hw/display/qxl.h | 7 | ||||
-rw-r--r-- | hw/display/trace-events | 2 | ||||
-rw-r--r-- | hw/display/virtio-gpu-3d.c | 5 | ||||
-rw-r--r-- | hw/display/virtio-gpu.c | 10 |
5 files changed, 96 insertions, 54 deletions
diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 919dc5cd36..46cc86690c 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -504,6 +504,7 @@ static void interface_set_compression_level(QXLInstance *sin, int level) qxl_rom_set_dirty(qxl); } +#if SPICE_NEEDS_SET_MM_TIME static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time) { PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); @@ -517,6 +518,7 @@ static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time) qxl->rom->mm_clock = cpu_to_le32(mm_time); qxl_rom_set_dirty(qxl); } +#endif static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) { @@ -893,7 +895,8 @@ static void interface_update_area_complete(QXLInstance *sin, int qxl_i; qemu_mutex_lock(&qxl->ssd.lock); - if (surface_id != 0 || !qxl->render_update_cookie_num) { + if (surface_id != 0 || !num_updated_rects || + !qxl->render_update_cookie_num) { qemu_mutex_unlock(&qxl->ssd.lock); return; } @@ -1068,7 +1071,9 @@ static const QXLInterface qxl_interface = { .attache_worker = interface_attach_worker, .set_compression_level = interface_set_compression_level, +#if SPICE_NEEDS_SET_MM_TIME .set_mm_time = interface_set_mm_time, +#endif .get_init_info = interface_get_init_info, /* the callbacks below are called from spice server thread context */ @@ -1243,6 +1248,7 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, int pci_region; pcibus_t pci_start; pcibus_t pci_end; + MemoryRegion *mr; intptr_t virt_start; QXLDevMemSlot memslot; int i; @@ -1289,11 +1295,11 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, switch (pci_region) { case QXL_RAM_RANGE_INDEX: - virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vga.vram); + mr = &d->vga.vram; break; case QXL_VRAM_RANGE_INDEX: case 4 /* vram 64bit */: - virt_start = (intptr_t)memory_region_get_ram_ptr(&d->vram_bar); + mr = &d->vram_bar; break; default: /* should not happen */ @@ -1301,6 +1307,7 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, return 1; } + virt_start = (intptr_t)memory_region_get_ram_ptr(mr); memslot.slot_id = slot_id; memslot.slot_group_id = MEMSLOT_GROUP_GUEST; /* guest group */ memslot.virt_start = virt_start + (guest_start - pci_start); @@ -1310,7 +1317,8 @@ static int qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta, qxl_rom_set_dirty(d); qemu_spice_add_memslot(&d->ssd, &memslot, async); - d->guest_slots[slot_id].ptr = (void*)memslot.virt_start; + d->guest_slots[slot_id].mr = mr; + d->guest_slots[slot_id].offset = memslot.virt_start - virt_start; d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start; d->guest_slots[slot_id].delta = delta; d->guest_slots[slot_id].active = 1; @@ -1337,39 +1345,60 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) } /* can be also called from spice server thread context */ -void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id) +static bool qxl_get_check_slot_offset(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, + uint32_t *s, uint64_t *o) { uint64_t phys = le64_to_cpu(pqxl); uint32_t slot = (phys >> (64 - 8)) & 0xff; uint64_t offset = phys & 0xffffffffffff; - switch (group_id) { - case MEMSLOT_GROUP_HOST: - return (void *)(intptr_t)offset; - case MEMSLOT_GROUP_GUEST: - if (slot >= NUM_MEMSLOTS) { - qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot, - NUM_MEMSLOTS); - return NULL; - } - if (!qxl->guest_slots[slot].active) { - qxl_set_guest_bug(qxl, "inactive slot %d\n", slot); - return NULL; - } - if (offset < qxl->guest_slots[slot].delta) { - qxl_set_guest_bug(qxl, + if (slot >= NUM_MEMSLOTS) { + qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot, + NUM_MEMSLOTS); + return false; + } + if (!qxl->guest_slots[slot].active) { + qxl_set_guest_bug(qxl, "inactive slot %d\n", slot); + return false; + } + if (offset < qxl->guest_slots[slot].delta) { + qxl_set_guest_bug(qxl, "slot %d offset %"PRIu64" < delta %"PRIu64"\n", slot, offset, qxl->guest_slots[slot].delta); - return NULL; - } - offset -= qxl->guest_slots[slot].delta; - if (offset > qxl->guest_slots[slot].size) { - qxl_set_guest_bug(qxl, + return false; + } + offset -= qxl->guest_slots[slot].delta; + if (offset > qxl->guest_slots[slot].size) { + qxl_set_guest_bug(qxl, "slot %d offset %"PRIu64" > size %"PRIu64"\n", slot, offset, qxl->guest_slots[slot].size); + return false; + } + + *s = slot; + *o = offset; + return true; +} + +/* can be also called from spice server thread context */ +void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id) +{ + uint64_t offset; + uint32_t slot; + void *ptr; + + switch (group_id) { + case MEMSLOT_GROUP_HOST: + offset = le64_to_cpu(pqxl) & 0xffffffffffff; + return (void *)(intptr_t)offset; + case MEMSLOT_GROUP_GUEST: + if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset)) { return NULL; } - return qxl->guest_slots[slot].ptr + offset; + ptr = memory_region_get_ram_ptr(qxl->guest_slots[slot].mr); + ptr += qxl->guest_slots[slot].offset; + ptr += offset; + return ptr; } return NULL; } @@ -1784,9 +1813,23 @@ static void qxl_hw_update(void *opaque) qxl_render_update(qxl); } +static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, + uint32_t height, int32_t stride) +{ + uint64_t offset; + uint32_t slot, size; + bool rc; + + rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset); + assert(rc == true); + size = height * abs(stride); + trace_qxl_surfaces_dirty(qxl->id, (int)offset, size); + qxl_set_dirty(qxl->guest_slots[slot].mr, + qxl->guest_slots[slot].offset + offset, size); +} + static void qxl_dirty_surfaces(PCIQXLDevice *qxl) { - uintptr_t vram_start; int i; if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) { @@ -1794,16 +1837,13 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl) } /* dirty the primary surface */ - qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset, - qxl->shadow_rom.surface0_area_size); - - vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar); + qxl_dirty_one_surface(qxl, qxl->guest_primary.surface.mem, + qxl->guest_primary.surface.height, + qxl->guest_primary.surface.stride); /* dirty the off-screen surfaces */ for (i = 0; i < qxl->ssd.num_surfaces; i++) { QXLSurfaceCmd *cmd; - intptr_t surface_offset; - int surface_size; if (qxl->guest_surfaces.cmds[i] == 0) { continue; @@ -1813,15 +1853,9 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl) MEMSLOT_GROUP_GUEST); assert(cmd); assert(cmd->type == QXL_SURFACE_CMD_CREATE); - surface_offset = (intptr_t)qxl_phys2virt(qxl, - cmd->u.surface_create.data, - MEMSLOT_GROUP_GUEST); - assert(surface_offset); - surface_offset -= vram_start; - surface_size = cmd->u.surface_create.height * - abs(cmd->u.surface_create.stride); - trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size); - qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size); + qxl_dirty_one_surface(qxl, cmd->u.surface_create.data, + cmd->u.surface_create.height, + cmd->u.surface_create.stride); } } @@ -1914,7 +1948,7 @@ static void qxl_init_ramsize(PCIQXLDevice *qxl) /* vram (surfaces, 64bit, bar 4+5) */ if (qxl->vram_size_mb != -1) { - qxl->vram_size = qxl->vram_size_mb * 1024 * 1024; + qxl->vram_size = (uint64_t)qxl->vram_size_mb * 1024 * 1024; } if (qxl->vram_size < qxl->vram32_size) { qxl->vram_size = qxl->vram32_size; @@ -2020,9 +2054,9 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp) dprint(qxl, 1, "ram/%s: %d MB [region 0]\n", qxl->id == 0 ? "pri" : "sec", qxl->vga.vram_size / (1024*1024)); - dprint(qxl, 1, "vram/32: %d MB [region 1]\n", + dprint(qxl, 1, "vram/32: %" PRIx64 "d MB [region 1]\n", qxl->vram32_size / (1024*1024)); - dprint(qxl, 1, "vram/64: %d MB %s\n", + dprint(qxl, 1, "vram/64: %" PRIx64 "d MB %s\n", qxl->vram_size / (1024*1024), qxl->vram32_size < qxl->vram_size ? "[region 4]" : "[unmapped]"); @@ -2276,7 +2310,7 @@ static VMStateDescription qxl_vmstate = { static Property qxl_properties[] = { DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024), - DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram32_size, + DEFINE_PROP_UINT64("vram_size", PCIQXLDevice, vram32_size, 64 * 1024 * 1024), DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, QXL_DEFAULT_REVISION), diff --git a/hw/display/qxl.h b/hw/display/qxl.h index 2ddf065e1f..fdb619d4a7 100644 --- a/hw/display/qxl.h +++ b/hw/display/qxl.h @@ -53,7 +53,8 @@ typedef struct PCIQXLDevice { struct guest_slots { QXLMemSlot slot; - void *ptr; + MemoryRegion *mr; + uint64_t offset; uint64_t size; uint64_t delta; uint32_t active; @@ -104,9 +105,9 @@ typedef struct PCIQXLDevice { #endif /* vram pci bar */ - uint32_t vram_size; + uint64_t vram_size; MemoryRegion vram_bar; - uint32_t vram32_size; + uint64_t vram32_size; MemoryRegion vram32_bar; /* io bar */ diff --git a/hw/display/trace-events b/hw/display/trace-events index 30bebffd8b..9dd82cecde 100644 --- a/hw/display/trace-events +++ b/hw/display/trace-events @@ -105,7 +105,7 @@ qxl_spice_reset_image_cache(int qid) "%d" qxl_spice_reset_memslots(int qid) "%d" qxl_spice_update_area(int qid, uint32_t surface_id, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) "%d sid=%d [%d,%d,%d,%d]" qxl_spice_update_area_rest(int qid, uint32_t num_dirty_rects, uint32_t clear_dirty_region) "%d #d=%d clear=%d" -qxl_surfaces_dirty(int qid, int surface, int offset, int size) "%d surface=%d offset=%d size=%d" +qxl_surfaces_dirty(int qid, int offset, int size) "%d offset=%d size=%d" qxl_send_events(int qid, uint32_t events) "%d %d" qxl_send_events_vm_stopped(int qid, uint32_t events) "%d %d" qxl_set_guest_bug(int qid) "%d" diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c index 29918a090b..d6c8c6e2dc 100644 --- a/hw/display/virtio-gpu-3d.c +++ b/hw/display/virtio-gpu-3d.c @@ -171,13 +171,14 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g, virgl_renderer_force_ctx_0(); dpy_gl_scanout(g->scanout[ss.scanout_id].con, info.tex_id, info.flags & 1 /* FIXME: Y_0_TOP */, + info.width, info.height, ss.r.x, ss.r.y, ss.r.width, ss.r.height); } else { if (ss.scanout_id != 0) { dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL); } dpy_gl_scanout(g->scanout[ss.scanout_id].con, 0, false, - 0, 0, 0, 0); + 0, 0, 0, 0, 0, 0); } g->scanout[ss.scanout_id].resource_id = ss.resource_id; } @@ -580,7 +581,7 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g) if (i != 0) { dpy_gfx_replace_surface(g->scanout[i].con, NULL); } - dpy_gl_scanout(g->scanout[i].con, 0, false, 0, 0, 0, 0); + dpy_gl_scanout(g->scanout[i].con, 0, false, 0, 0, 0, 0, 0, 0); } } diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 136c095b7d..f8b0274752 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -934,8 +934,14 @@ static void virtio_gpu_gl_block(void *opaque, bool block) { VirtIOGPU *g = opaque; - g->renderer_blocked = block; - if (!block) { + if (block) { + g->renderer_blocked++; + } else { + g->renderer_blocked--; + } + assert(g->renderer_blocked >= 0); + + if (g->renderer_blocked == 0) { virtio_gpu_process_cmdq(g); } } |