qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Alon Levy <alevy@redhat.com>
To: qemu-devel@nongnu.org, kraxel@redhat.com, elmarco@redhat.com
Subject: [Qemu-devel] [RFC 7/7] qxl: add allocator
Date: Sun, 19 Feb 2012 23:28:06 +0200	[thread overview]
Message-ID: <1329686886-6853-8-git-send-email-alevy@redhat.com> (raw)
In-Reply-To: <1329686886-6853-1-git-send-email-alevy@redhat.com>

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 <alevy@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

  parent reply	other threads:[~2012-02-19 21:28 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-19 21:27 [Qemu-devel] [RFC 0/7] qxl: fix hangs caused by qxl_render_update Alon Levy
2012-02-19 21:28 ` [Qemu-devel] [RFC 1/7] sdl: remove NULL check, g_malloc0 can't fail Alon Levy
2012-02-19 21:28 ` [Qemu-devel] [RFC 2/7] qxl: drop qxl_spice_update_area_async definition Alon Levy
2012-02-19 21:28 ` [Qemu-devel] [RFC 3/7] qxl: introduce QXLCookie Alon Levy
2012-02-20 10:56   ` Gerd Hoffmann
2012-02-20 12:31     ` Alon Levy
2012-02-20 12:39       ` Gerd Hoffmann
2012-02-19 21:28 ` [Qemu-devel] [RFC 4/7] qxl: make qxl_render_update async Alon Levy
2012-02-20 11:10   ` Gerd Hoffmann
2012-02-20 12:32     ` Alon Levy
2012-02-20 12:45       ` Gerd Hoffmann
2012-02-19 21:28 ` [Qemu-devel] [RFC 5/7] qxl-render: call ppm_save on callback Alon Levy
2012-02-20 11:32   ` Gerd Hoffmann
2012-02-20 12:36     ` Alon Levy
2012-02-20 12:49       ` Gerd Hoffmann
2012-02-20 21:29     ` Eric Blake
2012-02-21  8:19       ` Alon Levy
2012-02-21 16:15         ` Eric Blake
2012-02-21 17:40           ` Alon Levy
2012-02-22 13:17             ` Luiz Capitulino
2012-02-22 13:22               ` Alon Levy
2012-02-22 13:49                 ` Luiz Capitulino
2012-02-22 14:22                   ` Gerd Hoffmann
2012-02-22 14:29                     ` Alon Levy
2012-02-22 15:55                       ` Luiz Capitulino
2012-02-22 16:35                         ` Alon Levy
2012-02-22 19:27                           ` Luiz Capitulino
2012-02-22 14:28                   ` Alon Levy
2012-02-22 14:47                     ` Gerd Hoffmann
2012-02-22 15:26                       ` Alon Levy
2012-02-19 21:28 ` [Qemu-devel] [RFC 6/7] qxl: use spice_qxl_update_area_dirty_async Alon Levy
2012-02-19 21:28 ` Alon Levy [this message]
2012-02-20 11:41   ` [Qemu-devel] [RFC 7/7] qxl: add allocator Gerd Hoffmann
2012-02-20 12:38     ` Alon Levy
2012-02-20 13:18       ` Gerd Hoffmann
2012-02-20 17:36         ` Alon Levy
2012-02-21  7:57           ` Gerd Hoffmann
2012-02-21  8:26             ` Alon Levy
2012-02-21  9:20               ` Gerd Hoffmann
2012-02-21  9:59                 ` Alon Levy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1329686886-6853-8-git-send-email-alevy@redhat.com \
    --to=alevy@redhat.com \
    --cc=elmarco@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).