From patchwork Sun Feb 19 21:28:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alon Levy X-Patchwork-Id: 142076 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C5FDFB6FA1 for ; Mon, 20 Feb 2012 09:20:19 +1100 (EST) Received: from localhost ([::1]:55591 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RzEJM-0005Sd-FW for incoming@patchwork.ozlabs.org; Sun, 19 Feb 2012 16:28:48 -0500 Received: from eggs.gnu.org ([140.186.70.92]:48605) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RzEJ3-0004oD-6N for qemu-devel@nongnu.org; Sun, 19 Feb 2012 16:28:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RzEJ0-0004V5-TT for qemu-devel@nongnu.org; Sun, 19 Feb 2012 16:28:29 -0500 Received: from mx1.redhat.com ([209.132.183.28]:57257) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RzEJ0-0004V0-HU for qemu-devel@nongnu.org; Sun, 19 Feb 2012 16:28:26 -0500 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q1JLSPmr003944 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sun, 19 Feb 2012 16:28:25 -0500 Received: from garlic.redhat.com (vpn-200-5.tlv.redhat.com [10.35.200.5]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q1JLS6Yv003257; Sun, 19 Feb 2012 16:28:24 -0500 From: Alon Levy To: qemu-devel@nongnu.org, kraxel@redhat.com, elmarco@redhat.com Date: Sun, 19 Feb 2012 23:28:06 +0200 Message-Id: <1329686886-6853-8-git-send-email-alevy@redhat.com> In-Reply-To: <1329686886-6853-1-git-send-email-alevy@redhat.com> References: <1329686886-6853-1-git-send-email-alevy@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC 7/7] qxl: add allocator X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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);