qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PATCH 09/14] pl110: add framebuffer_update_display_swap_pixman
Date: Tue,  2 Sep 2014 10:00:22 +0200	[thread overview]
Message-ID: <1409644827-26317-10-git-send-email-kraxel@redhat.com> (raw)
In-Reply-To: <1409644827-26317-1-git-send-email-kraxel@redhat.com>

Works like framebuffer_update_display, but accepts a (newly introduced)
swapmode and a pixman format instead of a callback function.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/display/framebuffer.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++
 hw/display/framebuffer.h |  17 +++++++
 2 files changed, 146 insertions(+)

diff --git a/hw/display/framebuffer.c b/hw/display/framebuffer.c
index 4546e42..d3a2c70 100644
--- a/hw/display/framebuffer.c
+++ b/hw/display/framebuffer.c
@@ -111,3 +111,132 @@ void framebuffer_update_display(
 out:
     memory_region_unref(mem);
 }
+
+static void framebuffer_swap(enum framebuffer_swapmode swapmode,
+                             pixman_image_t *dest, void *src)
+{
+    int swaps;
+    uint32_t *s32, *d32;
+    uint16_t *s16, *d16;
+
+    switch (swapmode) {
+    case FB_SWAP_NONE:
+        memcpy(pixman_image_get_data(dest),
+               src,
+               pixman_image_get_stride(dest));
+        break;
+    case FB_SWAP_16_BYTES:
+        swaps = pixman_image_get_stride(dest) / 2;
+        s16 = src;
+        d16 = (void*)pixman_image_get_data(dest);
+        while (swaps) {
+            *d16 = bswap16(*s16);
+            s16++; d16++; swaps--;
+        }
+        break;
+    case FB_SWAP_32_BYTES:
+        swaps = pixman_image_get_stride(dest) / 4;
+        s32 = src;
+        d32 = pixman_image_get_data(dest);
+        while (swaps) {
+            *d32 = bswap32(*s32);
+            s32++; d32++; swaps--;
+        }
+        break;
+    case FB_SWAP_32_WORDS:
+        swaps = pixman_image_get_stride(dest) / 4;
+        s32 = src;
+        d32 = pixman_image_get_data(dest);
+        while (swaps) {
+            *d32 = (((*s32 & 0x0000ffff) << 16) |
+                    ((*s32 & 0xffff0000) >> 16));
+            s32++; d32++; swaps--;
+        }
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+void framebuffer_update_display_swap_pixman(
+    DisplaySurface *ds,
+    MemoryRegion *address_space,
+    hwaddr base,
+    enum framebuffer_swapmode swapmode,
+    pixman_format_code_t format,
+    int invalidate, /* nonzero to redraw the whole image.  */
+    int *first_row, /* Input and output.  */
+    int *last_row /* Output only */)
+{
+    int cols = surface_width(ds);
+    int rows = surface_height(ds);
+    int src_width = cols * PIXMAN_FORMAT_BPP(format) / 8;
+    pixman_image_t *linebuf;
+    hwaddr src_len;
+    uint8_t *src;
+    uint8_t *src_base;
+    int first, last = 0;
+    int dirty;
+    int i;
+    ram_addr_t addr;
+    MemoryRegionSection mem_section;
+    MemoryRegion *mem;
+
+    i = *first_row;
+    *first_row = -1;
+    src_len = src_width * rows;
+
+    mem_section = memory_region_find(address_space, base, src_len);
+    mem = mem_section.mr;
+    if (int128_get64(mem_section.size) != src_len ||
+        !memory_region_is_ram(mem_section.mr)) {
+        goto out;
+    }
+    assert(mem);
+    assert(mem_section.offset_within_address_space == base);
+
+    memory_region_sync_dirty_bitmap(mem);
+    src_base = cpu_physical_memory_map(base, &src_len, 0);
+    /* If we can't map the framebuffer then bail.  We could try harder,
+       but it's not really worth it as dirty flag tracking will probably
+       already have failed above.  */
+    if (!src_base)
+        goto out;
+    if (src_len != src_width * rows) {
+        cpu_physical_memory_unmap(src_base, src_len, 0, 0);
+        goto out;
+    }
+    src = src_base;
+    first = -1;
+    addr = mem_section.offset_within_region;
+
+    addr += i * src_width;
+    src += i * src_width;
+
+    linebuf = qemu_pixman_linebuf_create(format, cols);
+    for (; i < rows; i++) {
+        dirty = memory_region_get_dirty(mem, addr, src_width,
+                                        DIRTY_MEMORY_VGA);
+        if (dirty || invalidate) {
+            framebuffer_swap(swapmode, linebuf, src);
+            qemu_pixman_linebuf_copy(ds->image, cols, 0, i, linebuf);
+            if (first == -1)
+                first = i;
+            last = i;
+        }
+        addr += src_width;
+        src += src_width;
+    }
+    qemu_pixman_image_unref(linebuf);
+
+    cpu_physical_memory_unmap(src_base, src_len, 0, 0);
+    if (first < 0) {
+        goto out;
+    }
+    memory_region_reset_dirty(mem, mem_section.offset_within_region, src_len,
+                              DIRTY_MEMORY_VGA);
+    *first_row = first;
+    *last_row = last;
+out:
+    memory_region_unref(mem);
+}
diff --git a/hw/display/framebuffer.h b/hw/display/framebuffer.h
index 6eae035..6ee6df5 100644
--- a/hw/display/framebuffer.h
+++ b/hw/display/framebuffer.h
@@ -22,4 +22,21 @@ void framebuffer_update_display(
     int *first_row,
     int *last_row);
 
+enum framebuffer_swapmode {
+    FB_SWAP_NONE = 0,
+    FB_SWAP_16_BYTES,
+    FB_SWAP_32_BYTES,
+    FB_SWAP_32_WORDS,
+};
+
+void framebuffer_update_display_swap_pixman(
+    DisplaySurface *ds,
+    MemoryRegion *address_space,
+    hwaddr base,
+    enum framebuffer_swapmode,
+    pixman_format_code_t format,
+    int invalidate, /* nonzero to redraw the whole image.  */
+    int *first_row, /* Input and output.  */
+    int *last_row /* Output only */);
+
 #endif
-- 
1.8.3.1

  parent reply	other threads:[~2014-09-02  8:01 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-02  8:00 [Qemu-devel] [PATCH 00/14] console/pl110: pixman conversion continued Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 01/14] console: add qemu_pixelformat_from_pixman Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 02/14] console: add qemu_default_pixman_format Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 03/14] console: reimplement qemu_default_pixelformat Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 04/14] console: stop using PixelFormat Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 05/14] console: add qemu_create_displaysurface_guestmem Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 06/14] console: add dpy_gfx_update_dirty Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 07/14] console: add qemu_pixman_linebuf_copy Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 08/14] console: Remove unused QEMU_BIG_ENDIAN_FLAG Gerd Hoffmann
2014-09-02  8:00 ` Gerd Hoffmann [this message]
2014-09-02  8:00 ` [Qemu-devel] [PATCH 10/14] pl100: Drop support for depths other than 32bpp Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 11/14] pl110: move resize Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 12/14] [wip] pl110: start using pixman Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 13/14] [wip] pl110: switch some conversions to swap+pixman mode Gerd Hoffmann
2014-09-02  8:00 ` [Qemu-devel] [PATCH 14/14] [wip] pl110: start handling paletted images via pixman Gerd Hoffmann

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=1409644827-26317-10-git-send-email-kraxel@redhat.com \
    --to=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).