Add an implementation of the DisplayAllocator callbacks for qxl. Uses the QEMU_ALLOCATED_FLAG to ensure vga/vga_draw_graphic does the 24 to 32 bits per pixel line convertion. Since free/resize/create are defined in qxl.c, it is easy to ensure consistent usage of the flag (it means QXL_ALLOCATED basically).
With this patch and the previous two screendump works for vga and qxl modes when using qxl and spice together. This might break sdl/vnc with spice, untested since it isn't of known use. Signed-off-by: Alon Levy <al...@redhat.com> --- hw/qxl-render.c | 34 +----------------- hw/qxl.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++--- ui/spice-display.c | 1 + ui/spice-display.h | 2 + 4 files changed, 101 insertions(+), 39 deletions(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index 7b120ab..8280b91 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -82,7 +82,6 @@ void qxl_render_update(PCIQXLDevice *qxl, const char *filename) { VGACommonState *vga = &qxl->vga; QXLRect dirty[32]; - void *ptr; int redraw = 0; QXLRenderUpdateData *data; QXLCookie *cookie; @@ -96,38 +95,7 @@ void qxl_render_update(PCIQXLDevice *qxl, const char *filename) if (qxl->guest_primary.resized) { qxl->guest_primary.resized = 0; - - if (qxl->guest_primary.flipped) { - g_free(qxl->guest_primary.flipped); - qxl->guest_primary.flipped = NULL; - } - qemu_free_displaysurface(vga->ds); - - qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram); - if (qxl->guest_primary.qxl_stride < 0) { - /* spice surface is upside down -> need extra buffer to flip */ - qxl->guest_primary.flipped = - g_malloc(qxl->guest_primary.surface.width * - qxl->guest_primary.abs_stride); - ptr = qxl->guest_primary.flipped; - } else { - ptr = qxl->guest_primary.data; - } - dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d, flip %s\n", - __FUNCTION__, - qxl->guest_primary.surface.width, - qxl->guest_primary.surface.height, - qxl->guest_primary.qxl_stride, - qxl->guest_primary.bytes_pp, - qxl->guest_primary.bits_pp, - qxl->guest_primary.flipped ? "yes" : "no"); - vga->ds->surface = - qemu_create_displaysurface_from(qxl->guest_primary.surface.width, - qxl->guest_primary.surface.height, - qxl->guest_primary.bits_pp, - qxl->guest_primary.abs_stride, - ptr); - dpy_resize(vga->ds); + qemu_resize_displaysurface(qxl->vga.ds, 0, 0); } if (!qxl->guest_primary.commands) { diff --git a/hw/qxl.c b/hw/qxl.c index 6e25bd1..ec43c4e 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -138,6 +138,92 @@ void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) } } +static DisplaySurface *qxl_create_displaysurface(int width, int height) +{ + PCIQXLDevice *qxl = qxl0; + DisplaySurface *ret; + void *ptr; + + dprint(qxl, 1, "%s: %d x %d (have %d, %d)\n", __func__, + width, height, + qxl->guest_primary.surface.width, + qxl->guest_primary.surface.height); + if (width != 0 && height != 0 && + (qxl->mode == QXL_MODE_VGA || qxl->mode == QXL_MODE_UNDEFINED)) { + /* initial surface creation in vga mode, use give width and height */ + qxl->guest_primary.surface.width = width; + qxl->guest_primary.surface.height = height; + qxl->guest_primary.qxl_stride = width * 4; + qxl->guest_primary.abs_stride = width * 4; + qxl->guest_primary.bytes_pp = 4; + qxl->guest_primary.bits_pp = 32; + qxl->guest_primary.flipped = 0; + qxl->guest_primary.data = qxl->ssd.buf; + } else { + if (qxl->guest_primary.flipped) { + g_free(qxl->guest_primary.flipped); + qxl->guest_primary.flipped = NULL; + } + qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram); + } + if (qxl->guest_primary.qxl_stride < 0) { + /* spice surface is upside down -> need extra buffer to flip */ + qxl->guest_primary.flipped = + g_malloc(qxl->guest_primary.surface.width * + qxl->guest_primary.abs_stride); + ptr = qxl->guest_primary.flipped; + } else { + ptr = qxl->guest_primary.data; + } + dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d, flip %s\n", + __func__, + qxl->guest_primary.surface.width, + qxl->guest_primary.surface.height, + qxl->guest_primary.qxl_stride, + qxl->guest_primary.bytes_pp, + qxl->guest_primary.bits_pp, + qxl->guest_primary.flipped ? "yes" : "no"); + ret = qemu_create_displaysurface_from(qxl->guest_primary.surface.width, + qxl->guest_primary.surface.height, + qxl->guest_primary.bits_pp, + qxl->guest_primary.abs_stride, + ptr); + /* + * set this flag to ensure vga_draw_graphic treats this as a non shared + * buffer, and so does the correct convertion to 32 bits that we always use. + */ + ret->flags |= QEMU_ALLOCATED_FLAG; + return ret; +} + +static void qxl_free_displaysurface(DisplaySurface *surface) +{ + g_free(surface); +} + +static DisplaySurface *qxl_resize_displaysurface(DisplaySurface *surface, + int width, int height) +{ + if (surface != qxl0->vga.ds->surface) { + qxl_free_displaysurface(surface); + } + return qxl_create_displaysurface(width, height); +} + +static struct DisplayAllocator qxl_displaysurface_allocator = { + qxl_create_displaysurface, + qxl_resize_displaysurface, + qxl_free_displaysurface +}; + +void qxl_set_allocator(DisplayState *ds) +{ + if (register_displayallocator(ds, &qxl_displaysurface_allocator) == + &qxl_displaysurface_allocator) { + printf("qxl_set_allocator success\n"); + dpy_resize(ds); + } +} void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, struct QXLRect *area, struct QXLRect *dirty_rects, @@ -1493,9 +1579,18 @@ static void qxl_hw_invalidate(void *opaque) static void qxl_hw_screen_dump(void *opaque, const char *filename) { PCIQXLDevice *qxl = opaque; - VGACommonState *vga = &qxl->vga; switch (qxl->mode) { + case QXL_MODE_VGA: + /* + * TODO: vga_hw_screen_dump needless does a number of ppm_save calls + * fix it instead of redoing it correctly here (needs testing which is + * why it isn't yet done) + */ + qxl->vga.invalidate(&qxl->vga); + vga_hw_update(); + ppm_save(filename, qxl->ssd.ds->surface); + break; case QXL_MODE_COMPAT: case QXL_MODE_NATIVE: /* @@ -1508,9 +1603,6 @@ static void qxl_hw_screen_dump(void *opaque, const char *filename) */ qxl_render_update(qxl, filename); break; - case QXL_MODE_VGA: - vga->screen_dump(vga, filename); - break; default: break; } @@ -1682,9 +1774,8 @@ static int qxl_init_primary(PCIDevice *dev) vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate, qxl_hw_screen_dump, qxl_hw_text_update, qxl); - qemu_spice_display_init_common(&qxl->ssd, vga->ds); - qxl0 = qxl; + qemu_spice_display_init_common(&qxl->ssd, vga->ds); register_displaychangelistener(vga->ds, &display_listener); return qxl_init_common(qxl); diff --git a/ui/spice-display.c b/ui/spice-display.c index 680e6f4..7fd18f4 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -295,6 +295,7 @@ void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds) ssd->mouse_y = -1; ssd->bufsize = (16 * 1024 * 1024); ssd->buf = g_malloc(ssd->bufsize); + qxl_set_allocator(ds); } /* display listener callbacks */ diff --git a/ui/spice-display.h b/ui/spice-display.h index 8f286f8..9f24097 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -123,3 +123,5 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, void qemu_spice_wakeup(SimpleSpiceDisplay *ssd); void qemu_spice_start(SimpleSpiceDisplay *ssd); void qemu_spice_stop(SimpleSpiceDisplay *ssd); + +void qxl_set_allocator(DisplayState *ds); -- 1.7.9