spice and qxl bugfixes.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJXfNLqAAoJEEy22O7T6HE41IQQANvL1W2WNdzbhjKypNK/R4lU dXu1RYks0zs/R4e9jGz9f7BR13WltOkuADOWjyECmQ8KZGlX/Dr0H7UeSA74hs9U ZqMXZm1L0Hr8vJIp+JtqejSXKVFWzgb2jduAjA/Oedly8IGuRm6pY8XM6CnGcrAt w9A9NG3KKgWoYB5laF7UZUgs+QaREgZT2JGbQJOUxHA/q0Ony3NF4OjTJaT5QkLP yoVaBQ1LiXFgOJVub+6rAgturW3fmp/vcAeA5KTaRHqFHD0fbMBtaGnRwDdKtDf+ 8YqYWNCL/QfVL6B+uSEUdFn8TgApr7RiAIeAPgSqaz354Lm99/TJNd217CKgsJrE PHq7mXrHcll5PmDcBbXJISVl3a1/kxsgXV2yH1wweIW+MPxvu3bAHweKWKBJCIvw aZTBpc7WFNJ7BxoRbTpKL0dHG2TSYSvhjislQqcwftoR/glimX+nTnChJ75yQX8F 0q5v3MG37yZFEdSNbaMQlfvm0FdLb1DZrTmvR/23IWfd6HfE9hpsyvM9cQL0wIJt tPmLv39yqABajfa0inVzyHaqZdui4hGtvwYHt7BeL8t8UC7LRD9v/L6mFK9pVhK2 YWC/XEnzg0d+MF7zCDoD99coI3iS5jgpKuRo01nRGwhK7pnbvbcYYz2WqMx42f1I oZO0u11rjQ0v+9yNPpsM =ZUKP -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/spice/tags/pull-spice-20160706-1' into staging spice and qxl bugfixes. # gpg: Signature made Wed 06 Jul 2016 10:44:10 BST # gpg: using RSA key 0x4CB6D8EED3E87138 # 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>" # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/spice/tags/pull-spice-20160706-1: virgl: pass whole GL scanout dimensions spice: use the right head for multi-monitor virgl: count the calls to gl_block spice: avoid .set_mm_time on >= 0.12.6 qxl: fix surface migration qxl: store memory region and offset instead of pointer for guest slots qxl: factor out qxl_get_check_slot_offset qxl: handle no updates in interface_update_area_complete qxl: use uint64_t for vram size Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
0c56c6ab68
126
hw/display/qxl.c
126
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),
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ typedef struct VirtIOGPU {
|
||||
|
||||
bool use_virgl_renderer;
|
||||
bool renderer_inited;
|
||||
bool renderer_blocked;
|
||||
int renderer_blocked;
|
||||
QEMUTimer *fence_poll;
|
||||
QEMUTimer *print_stats;
|
||||
|
||||
|
@ -217,6 +217,7 @@ typedef struct DisplayChangeListenerOps {
|
||||
|
||||
void (*dpy_gl_scanout)(DisplayChangeListener *dcl,
|
||||
uint32_t backing_id, bool backing_y_0_top,
|
||||
uint32_t backing_width, uint32_t backing_height,
|
||||
uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
void (*dpy_gl_update)(DisplayChangeListener *dcl,
|
||||
uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
@ -285,6 +286,7 @@ bool dpy_gfx_check_format(QemuConsole *con,
|
||||
|
||||
void dpy_gl_scanout(QemuConsole *con,
|
||||
uint32_t backing_id, bool backing_y_0_top,
|
||||
uint32_t backing_width, uint32_t backing_height,
|
||||
uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
void dpy_gl_update(QemuConsole *con,
|
||||
uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
|
@ -101,6 +101,7 @@ QEMUGLContext gd_egl_create_context(DisplayChangeListener *dcl,
|
||||
QEMUGLParams *params);
|
||||
void gd_egl_scanout(DisplayChangeListener *dcl,
|
||||
uint32_t backing_id, bool backing_y_0_top,
|
||||
uint32_t backing_width, uint32_t backing_height,
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t w, uint32_t h);
|
||||
void gd_egl_scanout_flush(DisplayChangeListener *dcl,
|
||||
|
@ -42,6 +42,9 @@ int qemu_spice_set_pw_expire(time_t expires);
|
||||
int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
|
||||
const char *subject);
|
||||
|
||||
#define SPICE_NEEDS_SET_MM_TIME \
|
||||
(!defined(SPICE_SERVER_VERSION) || (SPICE_SERVER_VERSION < 0xc06))
|
||||
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
void qemu_spice_register_ports(void);
|
||||
#else
|
||||
|
@ -64,6 +64,7 @@ QEMUGLContext sdl2_gl_get_current_context(DisplayChangeListener *dcl);
|
||||
|
||||
void sdl2_gl_scanout(DisplayChangeListener *dcl,
|
||||
uint32_t backing_id, bool backing_y_0_top,
|
||||
uint32_t backing_width, uint32_t backing_height,
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t w, uint32_t h);
|
||||
void sdl2_gl_scanout_flush(DisplayChangeListener *dcl,
|
||||
|
@ -1709,11 +1709,13 @@ QEMUGLContext dpy_gl_ctx_get_current(QemuConsole *con)
|
||||
|
||||
void dpy_gl_scanout(QemuConsole *con,
|
||||
uint32_t backing_id, bool backing_y_0_top,
|
||||
uint32_t backing_width, uint32_t backing_height,
|
||||
uint32_t x, uint32_t y, uint32_t width, uint32_t height)
|
||||
{
|
||||
assert(con->gl);
|
||||
con->gl->ops->dpy_gl_scanout(con->gl, backing_id,
|
||||
backing_y_0_top,
|
||||
backing_width, backing_height,
|
||||
x, y, width, height);
|
||||
}
|
||||
|
||||
|
@ -172,6 +172,7 @@ QEMUGLContext gd_egl_create_context(DisplayChangeListener *dcl,
|
||||
|
||||
void gd_egl_scanout(DisplayChangeListener *dcl,
|
||||
uint32_t backing_id, bool backing_y_0_top,
|
||||
uint32_t backing_width, uint32_t backing_height,
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t w, uint32_t h)
|
||||
{
|
||||
|
@ -186,6 +186,7 @@ QEMUGLContext sdl2_gl_get_current_context(DisplayChangeListener *dcl)
|
||||
|
||||
void sdl2_gl_scanout(DisplayChangeListener *dcl,
|
||||
uint32_t backing_id, bool backing_y_0_top,
|
||||
uint32_t backing_width, uint32_t backing_height,
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t w, uint32_t h)
|
||||
{
|
||||
|
@ -527,11 +527,13 @@ static void interface_set_compression_level(QXLInstance *sin, int level)
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
#if SPICE_NEEDS_SET_MM_TIME
|
||||
static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
|
||||
{
|
||||
dprint(3, "%s/%d:\n", __func__, sin->id);
|
||||
/* nothing to do */
|
||||
}
|
||||
#endif
|
||||
|
||||
static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
|
||||
{
|
||||
@ -686,6 +688,7 @@ static int interface_client_monitors_config(QXLInstance *sin,
|
||||
{
|
||||
SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
|
||||
QemuUIInfo info;
|
||||
int head;
|
||||
|
||||
if (!dpy_ui_info_supported(ssd->dcl.con)) {
|
||||
return 0; /* == not supported by guest */
|
||||
@ -695,14 +698,12 @@ static int interface_client_monitors_config(QXLInstance *sin,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: multihead is tricky due to the way
|
||||
* spice has multihead implemented.
|
||||
*/
|
||||
memset(&info, 0, sizeof(info));
|
||||
if (mc->num_of_monitors > 0) {
|
||||
info.width = mc->monitors[0].width;
|
||||
info.height = mc->monitors[0].height;
|
||||
|
||||
head = qemu_console_get_head(ssd->dcl.con);
|
||||
if (mc->num_of_monitors > head) {
|
||||
info.width = mc->monitors[head].width;
|
||||
info.height = mc->monitors[head].height;
|
||||
}
|
||||
dpy_set_ui_info(ssd->dcl.con, &info);
|
||||
dprint(1, "%s/%d: size %dx%d\n", __func__, ssd->qxl.id,
|
||||
@ -718,7 +719,9 @@ static const QXLInterface dpy_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 */
|
||||
@ -858,6 +861,8 @@ static QEMUGLContext qemu_spice_gl_create_context(DisplayChangeListener *dcl,
|
||||
static void qemu_spice_gl_scanout(DisplayChangeListener *dcl,
|
||||
uint32_t tex_id,
|
||||
bool y_0_top,
|
||||
uint32_t backing_width,
|
||||
uint32_t backing_height,
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t w, uint32_t h)
|
||||
{
|
||||
@ -880,9 +885,7 @@ static void qemu_spice_gl_scanout(DisplayChangeListener *dcl,
|
||||
assert(!tex_id || fd >= 0);
|
||||
|
||||
/* note: spice server will close the fd */
|
||||
spice_qxl_gl_scanout(&ssd->qxl, fd,
|
||||
surface_width(ssd->ds),
|
||||
surface_height(ssd->ds),
|
||||
spice_qxl_gl_scanout(&ssd->qxl, fd, backing_width, backing_height,
|
||||
stride, fourcc, y_0_top);
|
||||
|
||||
qemu_spice_gl_monitor_config(ssd, x, y, w, h);
|
||||
|
Loading…
Reference in New Issue
Block a user