[Spice-commits] 11 commits - hw/display hw/usb include/hw include/ui trace-events ui/console.c ui/qemu-pixman.c ui/sdl.c ui/vnc-enc-tight.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Fri Sep 12 04:40:03 PDT 2014


 hw/display/qxl-render.c  |    7 -
 hw/display/vga.c         |   12 +-
 hw/display/vmware_vga.c  |    6 -
 hw/display/xenfb.c       |    8 -
 hw/usb/hcd-xhci.c        |    6 -
 include/hw/i386/pc.h     |    5 
 include/ui/console.h     |   25 ++--
 include/ui/qemu-pixman.h |    4 
 trace-events             |    2 
 ui/console.c             |  253 ++++++++++++++++++++---------------------------
 ui/qemu-pixman.c         |   90 ++++++++++++++++
 ui/sdl.c                 |    5 
 ui/vnc-enc-tight.c       |   12 --
 13 files changed, 260 insertions(+), 175 deletions(-)

New commits:
commit 0dfa7e30126364c434a48cb37a1a41119e536c2a
Merge: fc3b9aa 77bfcf2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Sep 11 11:44:16 2014 +0100

    Merge remote-tracking branch 'remotes/kraxel/tags/pull-console-20140905-2' into staging
    
    console: pixman switchover continued, add some infrastructure to make it
             easier using pixman in display device emulation.
    
    # gpg: Signature made Fri 05 Sep 2014 14:38:57 BST using RSA key ID D3E87138
    # gpg: Good signature from "Gerd Hoffmann (work) <kraxel at redhat.com>"
    # gpg:                 aka "Gerd Hoffmann <gerd at kraxel.org>"
    # gpg:                 aka "Gerd Hoffmann (private) <kraxel at gmail.com>"
    
    * remotes/kraxel/tags/pull-console-20140905-2:
      console: Remove unused QEMU_BIG_ENDIAN_FLAG
      console: add qemu_pixman_linebuf_copy
      console: add dpy_gfx_update_dirty
      console: add qemu_create_displaysurface_guestmem
      console: stop using PixelFormat
      console: reimplement qemu_default_pixelformat
      console: add qemu_default_pixman_format
      console: add qemu_pixelformat_from_pixman
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit fc3b9aa876901ab2317923ce1ab09043eee7f2a4
Merge: 10601be e6043e9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Sep 11 10:36:50 2014 +0100

    Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20140910-1' into staging
    
    xhci PCIe endpoint migration compatibility fix
    
    # gpg: Signature made Wed 10 Sep 2014 06:35:20 BST using RSA key ID D3E87138
    # gpg: Good signature from "Gerd Hoffmann (work) <kraxel at redhat.com>"
    # gpg:                 aka "Gerd Hoffmann <gerd at kraxel.org>"
    # gpg:                 aka "Gerd Hoffmann (private) <kraxel at gmail.com>"
    
    * remotes/kraxel/tags/pull-usb-20140910-1:
      xhci PCIe endpoint migration compatibility fix
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit e6043e92c2812a56b8f6cf35d5512067c746ce21
Author: Dr. David Alan Gilbert <dgilbert at redhat.com>
Date:   Tue Sep 9 11:19:43 2014 +0100

    xhci PCIe endpoint migration compatibility fix
    
    Add back the PCIe config capabilities on XHCI cards in non-PCIe slots,
    but only for machine types before 2.1.
    
    This fixes a migration incompatibility in the XHCI PCI devices
    caused by:
       058fdcf52cdbf57b67e7 - xhci: add endpoint cap on express bus only
    
    Note that in fixing it for compatibility with older QEMUs, it breaks
    compatibility with existing QEMU 2.1's on older machine types.
    
    The status before this patch was (if it used an XHCI adapter):
       machine type | source qemu
         any           pre-2.1     - FAIL
         any           2.1...      - PASS
    
    With this patch:
       machine type | source qemu
         any           pre-2.1    - PASS
         pre-2.1       2.1...     - FAIL
         2.1           2.1...     - PASS
    
    A test to trigger it is to add '-device nec-usb-xhci,id=xhci,addr=0x12'
    to the command line.
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Dr. David Alan Gilbert <dgilbert at redhat.com>
    Acked-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index bbe4c5f..73ced1f 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -499,6 +499,7 @@ enum xhci_flags {
     XHCI_FLAG_USE_MSI = 1,
     XHCI_FLAG_USE_MSI_X,
     XHCI_FLAG_SS_FIRST,
+    XHCI_FLAG_FORCE_PCIE_ENDCAP,
 };
 
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
@@ -3626,7 +3627,8 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
                      PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
                      &xhci->mem);
 
-    if (pci_bus_is_express(dev->bus)) {
+    if (pci_bus_is_express(dev->bus) ||
+        xhci_get_flag(xhci, XHCI_FLAG_FORCE_PCIE_ENDCAP)) {
         ret = pcie_endpoint_cap_init(dev, 0xa0);
         assert(ret >= 0);
     }
@@ -3855,6 +3857,8 @@ static Property xhci_properties[] = {
     DEFINE_PROP_BIT("msix",     XHCIState, flags, XHCI_FLAG_USE_MSI_X, true),
     DEFINE_PROP_BIT("superspeed-ports-first",
                     XHCIState, flags, XHCI_FLAG_SS_FIRST, true),
+    DEFINE_PROP_BIT("force-pcie-endcap", XHCIState, flags,
+                    XHCI_FLAG_FORCE_PCIE_ENDCAP, false),
     DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS),
     DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS),
     DEFINE_PROP_UINT32("p2",    XHCIState, numports_2, 4),
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index a39cb42..77316d5 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -330,6 +330,11 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
             .value    = "off",\
         },\
         {\
+            .driver   = "nec-usb-xhci",\
+            .property = "force-pcie-endcap",\
+            .value    = "on",\
+        },\
+        {\
             .driver   = "pci-serial",\
             .property = "prog_if",\
             .value    = stringify(0),\
commit 77bfcf28f1ee92bbc9e077abb9a494b12406846f
Author: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Date:   Sat Jun 21 14:58:06 2014 +1000

    console: Remove unused QEMU_BIG_ENDIAN_FLAG
    
    If we need to, we should use the pixman formats instead but for
    now this is unused except in commented out code so take it out
    to avoid further confusion about surface endianness.
    
    Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/console.h b/include/ui/console.h
index 58a7d4b..cde0faf 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -102,8 +102,7 @@ struct QemuConsoleClass {
     ObjectClass parent_class;
 };
 
-#define QEMU_BIG_ENDIAN_FLAG    0x01
-#define QEMU_ALLOCATED_FLAG     0x02
+#define QEMU_ALLOCATED_FLAG     0x01
 
 struct PixelFormat {
     uint8_t bits_per_pixel;
diff --git a/ui/console.c b/ui/console.c
index d1342ca..5d73d81 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1237,9 +1237,6 @@ static void qemu_alloc_display(DisplaySurface *surface, int width, int height)
     assert(surface->image != NULL);
 
     surface->flags = QEMU_ALLOCATED_FLAG;
-#ifdef HOST_WORDS_BIGENDIAN
-    surface->flags |= QEMU_BIG_ENDIAN_FLAG;
-#endif
 }
 
 DisplaySurface *qemu_create_displaysurface(int width, int height)
@@ -1264,10 +1261,6 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height,
                                               (void *)data, linesize);
     assert(surface->image != NULL);
 
-#ifdef HOST_WORDS_BIGENDIAN
-    surface->flags = QEMU_BIG_ENDIAN_FLAG;
-#endif
-
     return surface;
 }
 
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index f02352c..3d1b5cd 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -220,8 +220,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
         unsigned int errors;                                            \
         unsigned char *buf = vs->tight.tight.buffer;                    \
                                                                         \
-        endian = 0; /* FIXME: ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
-                      (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); */ \
+        endian = 0; /* FIXME */                                         \
                                                                         \
                                                                         \
         max[0] = vs->client_pf.rmax;                                  \
@@ -563,8 +562,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
     buf32 = (uint32_t *)buf;
     memset(vs->tight.gradient.buffer, 0, w * 3 * sizeof(int));
 
-    if (1 /* FIXME: (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
-             (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) */) {
+    if (1 /* FIXME */) {
         shift[0] = vs->client_pf.rshift;
         shift[1] = vs->client_pf.gshift;
         shift[2] = vs->client_pf.bshift;
@@ -621,8 +619,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
                                                                         \
         memset (vs->tight.gradient.buffer, 0, w * 3 * sizeof(int));     \
                                                                         \
-        endian = 0; /* FIXME: ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
-                       (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); */ \
+        endian = 0; /* FIXME */                                         \
                                                                         \
         max[0] = vs->client_pf.rmax;                                    \
         max[1] = vs->client_pf.gmax;                                    \
@@ -898,8 +895,7 @@ static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret)
 
     buf32 = (uint32_t *)buf;
 
-    if (1 /* FIXME: (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
-             (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) */) {
+    if (1 /* FIXME */) {
         rshift = vs->client_pf.rshift;
         gshift = vs->client_pf.gshift;
         bshift = vs->client_pf.bshift;
commit 43c7d8bd449d1c0f435775aefe391666a4b86dd6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 19 13:19:01 2014 +0200

    console: add qemu_pixman_linebuf_copy
    
    Helper function for copying data from linebuf to framebuffer using
    pixman, possibly converting in case src and dst formats differ.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h
index 80ed94a..381969d 100644
--- a/include/ui/qemu-pixman.h
+++ b/include/ui/qemu-pixman.h
@@ -42,6 +42,8 @@ pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format,
                                            int width);
 void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb,
                               int width, int x, int y);
+void qemu_pixman_linebuf_copy(pixman_image_t *fb, int width, int x, int y,
+                              pixman_image_t *linebuf);
 pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format,
                                           pixman_image_t *image);
 void qemu_pixman_image_unref(pixman_image_t *image);
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index 5d8bd46..30c7fdd 100644
--- a/ui/qemu-pixman.c
+++ b/ui/qemu-pixman.c
@@ -133,6 +133,7 @@ pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format,
     return image;
 }
 
+/* fill linebuf from framebuffer */
 void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb,
                               int width, int x, int y)
 {
@@ -140,6 +141,14 @@ void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb,
                            x, y, 0, 0, 0, 0, width, 1);
 }
 
+/* copy linebuf to framebuffer */
+void qemu_pixman_linebuf_copy(pixman_image_t *fb, int width, int x, int y,
+                              pixman_image_t *linebuf)
+{
+    pixman_image_composite(PIXMAN_OP_SRC, linebuf, NULL, fb,
+                           0, 0, 0, 0, x, y, width, 1);
+}
+
 pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format,
                                           pixman_image_t *image)
 {
commit 4c38762fb5cab19f50d2ba004736d7426abba3c0
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 19 08:52:17 2014 +0200

    console: add dpy_gfx_update_dirty
    
    Calls dpy_gfx_update for all dirty scanlines. Works for
    DisplaySurfaces backed by guest memory (i.e. the ones created
    using qemu_create_displaysurface_guestmem).
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/console.h b/include/ui/console.h
index 61901f7..58a7d4b 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -232,6 +232,10 @@ void dpy_text_resize(QemuConsole *con, int w, int h);
 void dpy_mouse_set(QemuConsole *con, int x, int y, int on);
 void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor);
 bool dpy_cursor_define_supported(QemuConsole *con);
+void dpy_gfx_update_dirty(QemuConsole *con,
+                          MemoryRegion *address_space,
+                          uint64_t base,
+                          bool invalidate);
 
 static inline int surface_stride(DisplaySurface *s)
 {
diff --git a/ui/console.c b/ui/console.c
index 654c0d3..d1342ca 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1581,6 +1581,67 @@ bool dpy_cursor_define_supported(QemuConsole *con)
     return false;
 }
 
+/*
+ * Call dpy_gfx_update for all dirity scanlines.  Works for
+ * DisplaySurfaces backed by guest memory (i.e. the ones created
+ * using qemu_create_displaysurface_guestmem).
+ */
+void dpy_gfx_update_dirty(QemuConsole *con,
+                          MemoryRegion *address_space,
+                          hwaddr base,
+                          bool invalidate)
+{
+    DisplaySurface *ds = qemu_console_surface(con);
+    int width = surface_stride(ds);
+    int height = surface_height(ds);
+    hwaddr size = width * height;
+    MemoryRegionSection mem_section;
+    MemoryRegion *mem;
+    ram_addr_t addr;
+    int first, last, i;
+    bool dirty;
+
+    mem_section = memory_region_find(address_space, base, size);
+    mem = mem_section.mr;
+    if (int128_get64(mem_section.size) != size ||
+        !memory_region_is_ram(mem_section.mr)) {
+        goto out;
+    }
+    assert(mem);
+
+    memory_region_sync_dirty_bitmap(mem);
+    addr = mem_section.offset_within_region;
+
+    first = -1;
+    last = -1;
+    for (i = 0; i < height; i++, addr += width) {
+        dirty = invalidate ||
+            memory_region_get_dirty(mem, addr, width, DIRTY_MEMORY_VGA);
+        if (dirty) {
+            if (first == -1) {
+                first = i;
+            }
+            last = i;
+        }
+        if (first != -1 && !dirty) {
+            assert(last != -1 && last >= first);
+            dpy_gfx_update(con, 0, first, surface_width(ds),
+                           last - first + 1);
+            first = -1;
+        }
+    }
+    if (first != -1) {
+        assert(last != -1 && last >= first);
+        dpy_gfx_update(con, 0, first, surface_width(ds),
+                       last - first + 1);
+    }
+
+    memory_region_reset_dirty(mem, mem_section.offset_within_region, size,
+                              DIRTY_MEMORY_VGA);
+out:
+    memory_region_unref(mem);
+}
+
 /***********************************************************/
 /* register display */
 
commit a77549b3ffcc24c32ee4e8b5ec32049186120360
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jun 19 08:46:08 2014 +0200

    console: add qemu_create_displaysurface_guestmem
    
    This patch adds a qemu_create_displaysurface_guestmem helper function.
    Works simliar to qemu_create_displaysurface_from, but accepts a
    guest address instead of a host pointer and it handles
    cpu_physical_memory_{map,unmap} for you.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/console.h b/include/ui/console.h
index 68ac362..61901f7 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -189,6 +189,10 @@ DisplayState *init_displaystate(void);
 DisplaySurface *qemu_create_displaysurface_from(int width, int height,
                                                 pixman_format_code_t format,
                                                 int linesize, uint8_t *data);
+DisplaySurface *qemu_create_displaysurface_guestmem(int width, int height,
+                                                    pixman_format_code_t format,
+                                                    int linesize,
+                                                    uint64_t addr);
 PixelFormat qemu_different_endianness_pixelformat(int bpp);
 PixelFormat qemu_default_pixelformat(int bpp);
 
diff --git a/ui/console.c b/ui/console.c
index 968aaaf..654c0d3 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -28,6 +28,7 @@
 #include "qmp-commands.h"
 #include "sysemu/char.h"
 #include "trace.h"
+#include "exec/memory.h"
 
 #define DEFAULT_BACKSCROLL 512
 #define CONSOLE_CURSOR_PERIOD 500
@@ -1270,6 +1271,42 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height,
     return surface;
 }
 
+static void qemu_unmap_displaysurface_guestmem(pixman_image_t *image,
+                                               void *unused)
+{
+    void *data = pixman_image_get_data(image);
+    uint32_t size = pixman_image_get_stride(image) *
+        pixman_image_get_height(image);
+    cpu_physical_memory_unmap(data, size, 0, 0);
+}
+
+DisplaySurface *qemu_create_displaysurface_guestmem(int width, int height,
+                                                    pixman_format_code_t format,
+                                                    int linesize, uint64_t addr)
+{
+    DisplaySurface *surface;
+    hwaddr size;
+    void *data;
+
+    if (linesize == 0) {
+        linesize = width * PIXMAN_FORMAT_BPP(format) / 8;
+    }
+
+    size = linesize * height;
+    data = cpu_physical_memory_map(addr, &size, 0);
+    if (size != linesize * height) {
+        cpu_physical_memory_unmap(data, size, 0, 0);
+        return NULL;
+    }
+
+    surface = qemu_create_displaysurface_from
+        (width, height, format, linesize, data);
+    pixman_image_set_destroy_function
+        (surface->image, qemu_unmap_displaysurface_guestmem, NULL);
+
+    return surface;
+}
+
 static DisplaySurface *qemu_create_message_surface(int w, int h,
                                                    const char *msg)
 {
commit 30f1e661b640de58ba1e8178f7f2290179a7e01c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 18 11:03:15 2014 +0200

    console: stop using PixelFormat
    
    With this patch the qemu console core stops using PixelFormat and pixman
    format codes side-by-side, pixman format code is the primary way to
    specify the DisplaySurface format:
    
     * DisplaySurface stops carrying a PixelFormat field.
     * qemu_create_displaysurface_from() expects a pixman format now.
    
    Functions to convert PixelFormat to pixman_format_code_t (and back)
    exist for those who still use PixelFormat.   As PixelFormat allows
    easy access to masks and shifts it will probably continue to exist.
    
    [ xenfb added by Benjamin Herrenschmidt ]
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index bcc5c37..e812ddd 100644
--- a/hw/display/qxl-render.c
+++ b/hw/display/qxl-render.c
@@ -116,13 +116,14 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
                qxl->guest_primary.bytes_pp,
                qxl->guest_primary.bits_pp);
         if (qxl->guest_primary.qxl_stride > 0) {
+            pixman_format_code_t format =
+                qemu_default_pixman_format(qxl->guest_primary.bits_pp, true);
             surface = qemu_create_displaysurface_from
                 (qxl->guest_primary.surface.width,
                  qxl->guest_primary.surface.height,
-                 qxl->guest_primary.bits_pp,
+                 format,
                  qxl->guest_primary.abs_stride,
-                 qxl->guest_primary.data,
-                 false);
+                 qxl->guest_primary.data);
         } else {
             surface = qemu_create_displaysurface
                 (qxl->guest_primary.surface.width,
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 65dab8d..948265a 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1689,9 +1689,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         height != s->last_height ||
         s->last_depth != depth) {
         if (depth == 32 || (depth == 16 && !byteswap)) {
+            pixman_format_code_t format =
+                qemu_default_pixman_format(depth, !byteswap);
             surface = qemu_create_displaysurface_from(disp_width,
-                    height, depth, s->line_offset,
-                    s->vram_ptr + (s->start_addr * 4), byteswap);
+                    height, format, s->line_offset,
+                    s->vram_ptr + (s->start_addr * 4));
             dpy_gfx_replace_surface(s->con, surface);
         } else {
             qemu_console_resize(s->con, disp_width, height);
@@ -1707,9 +1709,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     } else if (is_buffer_shared(surface) &&
                (full_update || surface_data(surface) != s->vram_ptr
                 + (s->start_addr * 4))) {
+        pixman_format_code_t format =
+            qemu_default_pixman_format(depth, !byteswap);
         surface = qemu_create_displaysurface_from(disp_width,
-                height, depth, s->line_offset,
-                s->vram_ptr + (s->start_addr * 4), byteswap);
+                height, format, s->line_offset,
+                s->vram_ptr + (s->start_addr * 4));
         dpy_gfx_replace_surface(s->con, surface);
     }
 
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 591b645..b8901d0 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -1052,10 +1052,12 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s)
         s->new_height != surface_height(surface) ||
         s->new_depth != surface_bits_per_pixel(surface)) {
         int stride = (s->new_depth * s->new_width) / 8;
+        pixman_format_code_t format =
+            qemu_default_pixman_format(s->new_depth, true);
         trace_vmware_setmode(s->new_width, s->new_height, s->new_depth);
         surface = qemu_create_displaysurface_from(s->new_width, s->new_height,
-                                                  s->new_depth, stride,
-                                                  s->vga.vram_ptr, false);
+                                                  format, stride,
+                                                  s->vga.vram_ptr);
         dpy_gfx_replace_surface(s->vga.con, surface);
         s->invalidated = 1;
     }
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 07ddc9d..8a61e95 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -713,15 +713,17 @@ static void xenfb_update(void *opaque)
 
     /* resize if needed */
     if (xenfb->do_resize) {
+        pixman_format_code_t format;
+
         xenfb->do_resize = 0;
         switch (xenfb->depth) {
         case 16:
         case 32:
             /* console.c supported depth -> buffer can be used directly */
+            format = qemu_default_pixman_format(xenfb->depth, true);
             surface = qemu_create_displaysurface_from
-                (xenfb->width, xenfb->height, xenfb->depth,
-                 xenfb->row_stride, xenfb->pixels + xenfb->offset,
-                 false);
+                (xenfb->width, xenfb->height, format,
+                 xenfb->row_stride, xenfb->pixels + xenfb->offset);
             break;
         default:
             /* we must convert stuff */
diff --git a/include/ui/console.h b/include/ui/console.h
index 845526e..68ac362 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -119,8 +119,6 @@ struct DisplaySurface {
     pixman_format_code_t format;
     pixman_image_t *image;
     uint8_t flags;
-
-    struct PixelFormat pf;
 };
 
 typedef struct QemuUIInfo {
@@ -188,9 +186,9 @@ struct DisplayChangeListener {
 };
 
 DisplayState *init_displaystate(void);
-DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
-                                                int linesize, uint8_t *data,
-                                                bool byteswap);
+DisplaySurface *qemu_create_displaysurface_from(int width, int height,
+                                                pixman_format_code_t format,
+                                                int linesize, uint8_t *data);
 PixelFormat qemu_different_endianness_pixelformat(int bpp);
 PixelFormat qemu_default_pixelformat(int bpp);
 
@@ -199,10 +197,12 @@ void qemu_free_displaysurface(DisplaySurface *surface);
 
 static inline int is_surface_bgr(DisplaySurface *surface)
 {
-    if (surface->pf.bits_per_pixel == 32 && surface->pf.rshift == 0)
+    if (PIXMAN_FORMAT_BPP(surface->format) == 32 &&
+        PIXMAN_FORMAT_TYPE(surface->format) == PIXMAN_TYPE_ABGR) {
         return 1;
-    else
+    } else {
         return 0;
+    }
 }
 
 static inline int is_buffer_shared(DisplaySurface *surface)
diff --git a/trace-events b/trace-events
index 03ac5d2..fb58963 100644
--- a/trace-events
+++ b/trace-events
@@ -1045,7 +1045,7 @@ console_txt_new(int w, int h) "%dx%d"
 console_select(int nr) "%d"
 console_refresh(int interval) "interval %d ms"
 displaysurface_create(void *display_surface, int w, int h) "surface=%p, %dx%d"
-displaysurface_create_from(void *display_surface, int w, int h, int bpp, int swap) "surface=%p, %dx%d, bpp %d, bswap %d"
+displaysurface_create_from(void *display_surface, int w, int h, uint32_t format) "surface=%p, %dx%d, format 0x%x"
 displaysurface_free(void *display_surface) "surface=%p"
 displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]"
 displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
diff --git a/ui/console.c b/ui/console.c
index 28711a4..968aaaf 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1224,22 +1224,18 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
     return s;
 }
 
-static void qemu_alloc_display(DisplaySurface *surface, int width, int height,
-                               int linesize, PixelFormat pf, int newflags)
+static void qemu_alloc_display(DisplaySurface *surface, int width, int height)
 {
-    surface->pf = pf;
-
     qemu_pixman_image_unref(surface->image);
     surface->image = NULL;
 
-    surface->format = qemu_pixman_get_format(&pf);
-    assert(surface->format != 0);
+    surface->format = PIXMAN_x8r8g8b8;
     surface->image = pixman_image_create_bits(surface->format,
                                               width, height,
-                                              NULL, linesize);
+                                              NULL, width * 4);
     assert(surface->image != NULL);
 
-    surface->flags = newflags | QEMU_ALLOCATED_FLAG;
+    surface->flags = QEMU_ALLOCATED_FLAG;
 #ifdef HOST_WORDS_BIGENDIAN
     surface->flags |= QEMU_BIG_ENDIAN_FLAG;
 #endif
@@ -1248,29 +1244,20 @@ static void qemu_alloc_display(DisplaySurface *surface, int width, int height,
 DisplaySurface *qemu_create_displaysurface(int width, int height)
 {
     DisplaySurface *surface = g_new0(DisplaySurface, 1);
-    int linesize = width * 4;
 
     trace_displaysurface_create(surface, width, height);
-    qemu_alloc_display(surface, width, height, linesize,
-                       qemu_default_pixelformat(32), 0);
+    qemu_alloc_display(surface, width, height);
     return surface;
 }
 
-DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
-                                                int linesize, uint8_t *data,
-                                                bool byteswap)
+DisplaySurface *qemu_create_displaysurface_from(int width, int height,
+                                                pixman_format_code_t format,
+                                                int linesize, uint8_t *data)
 {
     DisplaySurface *surface = g_new0(DisplaySurface, 1);
 
-    trace_displaysurface_create_from(surface, width, height, bpp, byteswap);
-    if (byteswap) {
-        surface->pf = qemu_different_endianness_pixelformat(bpp);
-    } else {
-        surface->pf = qemu_default_pixelformat(bpp);
-    }
-
-    surface->format = qemu_pixman_get_format(&surface->pf);
-    assert(surface->format != 0);
+    trace_displaysurface_create_from(surface, width, height, format);
+    surface->format = format;
     surface->image = pixman_image_create_bits(surface->format,
                                               width, height,
                                               (void *)data, linesize);
diff --git a/ui/sdl.c b/ui/sdl.c
index 4e7f920..94c1d9d 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -127,6 +127,7 @@ static void do_sdl_resize(int width, int height, int bpp)
 static void sdl_switch(DisplayChangeListener *dcl,
                        DisplaySurface *new_surface)
 {
+    PixelFormat pf = qemu_pixelformat_from_pixman(new_surface->format);
 
     /* temporary hack: allows to call sdl_switch to handle scaling changes */
     if (new_surface) {
@@ -148,8 +149,8 @@ static void sdl_switch(DisplayChangeListener *dcl,
         (surface_data(surface),
          surface_width(surface), surface_height(surface),
          surface_bits_per_pixel(surface), surface_stride(surface),
-         surface->pf.rmask, surface->pf.gmask,
-         surface->pf.bmask, surface->pf.amask);
+         pf.rmask, pf.gmask,
+         pf.bmask, pf.amask);
 }
 
 /* generic keyboard conversion */
commit 56bd9ea1a37395012adecca8b9c4762da15b01e7
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 18 11:07:50 2014 +0200

    console: reimplement qemu_default_pixelformat
    
    Use the new qemu_pixelformat_from_pixman and qemu_default_pixman_format
    functions to reimplement qemu_default_pixelformat
    (qemu_different_endianness_pixelformat too).
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/console.c b/ui/console.c
index ab84549..28711a4 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1902,124 +1902,15 @@ DisplayState *qemu_console_displaystate(QemuConsole *console)
 
 PixelFormat qemu_different_endianness_pixelformat(int bpp)
 {
-    PixelFormat pf;
-
-    memset(&pf, 0x00, sizeof(PixelFormat));
-
-    pf.bits_per_pixel = bpp;
-    pf.bytes_per_pixel = DIV_ROUND_UP(bpp, 8);
-    pf.depth = bpp == 32 ? 24 : bpp;
-
-    switch (bpp) {
-        case 24:
-            pf.rmask = 0x000000FF;
-            pf.gmask = 0x0000FF00;
-            pf.bmask = 0x00FF0000;
-            pf.rmax = 255;
-            pf.gmax = 255;
-            pf.bmax = 255;
-            pf.rshift = 0;
-            pf.gshift = 8;
-            pf.bshift = 16;
-            pf.rbits = 8;
-            pf.gbits = 8;
-            pf.bbits = 8;
-            break;
-        case 32:
-            pf.rmask = 0x0000FF00;
-            pf.gmask = 0x00FF0000;
-            pf.bmask = 0xFF000000;
-            pf.amask = 0x00000000;
-            pf.amax = 255;
-            pf.rmax = 255;
-            pf.gmax = 255;
-            pf.bmax = 255;
-            pf.ashift = 0;
-            pf.rshift = 8;
-            pf.gshift = 16;
-            pf.bshift = 24;
-            pf.rbits = 8;
-            pf.gbits = 8;
-            pf.bbits = 8;
-            pf.abits = 8;
-            break;
-        default:
-            break;
-    }
+    pixman_format_code_t fmt = qemu_default_pixman_format(bpp, false);
+    PixelFormat pf = qemu_pixelformat_from_pixman(fmt);
     return pf;
 }
 
 PixelFormat qemu_default_pixelformat(int bpp)
 {
-    PixelFormat pf;
-
-    memset(&pf, 0x00, sizeof(PixelFormat));
-
-    pf.bits_per_pixel = bpp;
-    pf.bytes_per_pixel = DIV_ROUND_UP(bpp, 8);
-    pf.depth = bpp == 32 ? 24 : bpp;
-
-    switch (bpp) {
-        case 15:
-            pf.bits_per_pixel = 16;
-            pf.rmask = 0x00007c00;
-            pf.gmask = 0x000003E0;
-            pf.bmask = 0x0000001F;
-            pf.rmax = 31;
-            pf.gmax = 31;
-            pf.bmax = 31;
-            pf.rshift = 10;
-            pf.gshift = 5;
-            pf.bshift = 0;
-            pf.rbits = 5;
-            pf.gbits = 5;
-            pf.bbits = 5;
-            break;
-        case 16:
-            pf.rmask = 0x0000F800;
-            pf.gmask = 0x000007E0;
-            pf.bmask = 0x0000001F;
-            pf.rmax = 31;
-            pf.gmax = 63;
-            pf.bmax = 31;
-            pf.rshift = 11;
-            pf.gshift = 5;
-            pf.bshift = 0;
-            pf.rbits = 5;
-            pf.gbits = 6;
-            pf.bbits = 5;
-            break;
-        case 24:
-            pf.rmask = 0x00FF0000;
-            pf.gmask = 0x0000FF00;
-            pf.bmask = 0x000000FF;
-            pf.rmax = 255;
-            pf.gmax = 255;
-            pf.bmax = 255;
-            pf.rshift = 16;
-            pf.gshift = 8;
-            pf.bshift = 0;
-            pf.rbits = 8;
-            pf.gbits = 8;
-            pf.bbits = 8;
-            break;
-        case 32:
-            pf.rmask = 0x00FF0000;
-            pf.gmask = 0x0000FF00;
-            pf.bmask = 0x000000FF;
-            pf.rmax = 255;
-            pf.gmax = 255;
-            pf.bmax = 255;
-            pf.rshift = 16;
-            pf.gshift = 8;
-            pf.bshift = 0;
-            pf.rbits = 8;
-            pf.gbits = 8;
-            pf.bbits = 8;
-            break;
-        default:
-            break;
-    }
+    pixman_format_code_t fmt = qemu_default_pixman_format(bpp, true);
+    PixelFormat pf = qemu_pixelformat_from_pixman(fmt);
     return pf;
 }
 
commit 1527a25ec90f34693fbe24c81c1107e78cead1d7
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 18 11:31:42 2014 +0200

    console: add qemu_default_pixman_format
    
    Function returning the default pixman format for a given depth.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h
index 090a3e2..80ed94a 100644
--- a/include/ui/qemu-pixman.h
+++ b/include/ui/qemu-pixman.h
@@ -34,6 +34,7 @@
 /* -------------------------------------------------------------------- */
 
 PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format);
+pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian);
 int qemu_pixman_get_type(int rshift, int gshift, int bshift);
 pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf);
 
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index bdc1439..5d8bd46 100644
--- a/ui/qemu-pixman.c
+++ b/ui/qemu-pixman.c
@@ -62,6 +62,31 @@ PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format)
     return pf;
 }
 
+pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian)
+{
+    if (native_endian) {
+        switch (bpp) {
+        case 15:
+            return PIXMAN_x1r5g5b5;
+        case 16:
+            return PIXMAN_r5g6b5;
+        case 24:
+            return PIXMAN_r8g8b8;
+        case 32:
+            return PIXMAN_x8r8g8b8;
+        }
+    } else {
+        switch (bpp) {
+        case 24:
+            return PIXMAN_b8g8r8;
+        case 32:
+            return PIXMAN_b8g8r8a8;
+        break;
+        }
+    }
+    g_assert_not_reached();
+}
+
 int qemu_pixman_get_type(int rshift, int gshift, int bshift)
 {
     int type = PIXMAN_TYPE_OTHER;
commit a93a3af9ec44710b2f7de8eb1c36f93ee3ec0d10
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 18 09:00:00 2014 +0200

    console: add qemu_pixelformat_from_pixman
    
    Function to convert pixman format codes to qemu PixelFormat.
    
    [ Benjamin Herrenschmidt: fix BGRA+RGBA shifts ]
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h
index ba970f8..090a3e2 100644
--- a/include/ui/qemu-pixman.h
+++ b/include/ui/qemu-pixman.h
@@ -33,6 +33,7 @@
 
 /* -------------------------------------------------------------------- */
 
+PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format);
 int qemu_pixman_get_type(int rshift, int gshift, int bshift);
 pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf);
 
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index 254bd8c..bdc1439 100644
--- a/ui/qemu-pixman.c
+++ b/ui/qemu-pixman.c
@@ -6,6 +6,62 @@
 #include "qemu-common.h"
 #include "ui/console.h"
 
+PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format)
+{
+    PixelFormat pf;
+    uint8_t bpp;
+
+    bpp = pf.bits_per_pixel = PIXMAN_FORMAT_BPP(format);
+    pf.bytes_per_pixel = PIXMAN_FORMAT_BPP(format) / 8;
+    pf.depth = PIXMAN_FORMAT_DEPTH(format);
+
+    pf.abits = PIXMAN_FORMAT_A(format);
+    pf.rbits = PIXMAN_FORMAT_R(format);
+    pf.gbits = PIXMAN_FORMAT_G(format);
+    pf.bbits = PIXMAN_FORMAT_B(format);
+
+    switch (PIXMAN_FORMAT_TYPE(format)) {
+    case PIXMAN_TYPE_ARGB:
+        pf.ashift = pf.bbits + pf.gbits + pf.rbits;
+        pf.rshift = pf.bbits + pf.gbits;
+        pf.gshift = pf.bbits;
+        pf.bshift = 0;
+        break;
+    case PIXMAN_TYPE_ABGR:
+        pf.ashift = pf.rbits + pf.gbits + pf.bbits;
+        pf.bshift = pf.rbits + pf.gbits;
+        pf.gshift = pf.rbits;
+        pf.rshift = 0;
+        break;
+    case PIXMAN_TYPE_BGRA:
+	pf.bshift = bpp - pf.bbits;
+        pf.gshift = bpp - (pf.bbits + pf.gbits);
+        pf.rshift = bpp - (pf.bbits + pf.gbits + pf.rbits);
+        pf.ashift = 0;
+        break;
+    case PIXMAN_TYPE_RGBA:
+        pf.rshift = bpp - pf.rbits;
+        pf.gshift = bpp - (pf.rbits + pf.gbits);
+        pf.bshift = bpp - (pf.rbits + pf.gbits + pf.bbits);
+        pf.ashift = 0;
+        break;
+    default:
+        g_assert_not_reached();
+        break;
+    }
+
+    pf.amax = (1 << pf.abits) - 1;
+    pf.rmax = (1 << pf.rbits) - 1;
+    pf.gmax = (1 << pf.gbits) - 1;
+    pf.bmax = (1 << pf.bbits) - 1;
+    pf.amask = pf.amax << pf.ashift;
+    pf.rmask = pf.rmax << pf.rshift;
+    pf.gmask = pf.gmax << pf.gshift;
+    pf.bmask = pf.bmax << pf.bshift;
+
+    return pf;
+}
+
 int qemu_pixman_get_type(int rshift, int gshift, int bshift)
 {
     int type = PIXMAN_TYPE_OTHER;


More information about the Spice-commits mailing list