aboutsummaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-09-11 11:44:16 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-09-11 11:44:17 +0100
commit0dfa7e30126364c434a48cb37a1a41119e536c2a (patch)
treee3f10541a2c2ab6fe43b65dbe6943b8e2c05e347 /ui
parentfc3b9aa876901ab2317923ce1ab09043eee7f2a4 (diff)
parent77bfcf28f1ee92bbc9e077abb9a494b12406846f (diff)
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@redhat.com>" # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" # gpg: aka "Gerd Hoffmann (private) <kraxel@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@linaro.org>
Diffstat (limited to 'ui')
-rw-r--r--ui/console.c253
-rw-r--r--ui/qemu-pixman.c90
-rw-r--r--ui/sdl.c5
-rw-r--r--ui/vnc-enc-tight.c12
4 files changed, 208 insertions, 152 deletions
diff --git a/ui/console.c b/ui/console.c
index ab8454903c..5d73d811c0 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
@@ -1224,61 +1225,77 @@ 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;
-#ifdef HOST_WORDS_BIGENDIAN
- surface->flags |= QEMU_BIG_ENDIAN_FLAG;
-#endif
+ surface->flags = QEMU_ALLOCATED_FLAG;
}
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);
assert(surface->image != NULL);
-#ifdef HOST_WORDS_BIGENDIAN
- surface->flags = QEMU_BIG_ENDIAN_FLAG;
-#endif
+ 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;
}
@@ -1557,6 +1574,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 */
@@ -1902,124 +1980,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;
}
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index 254bd8ce10..30c7fdd011 100644
--- a/ui/qemu-pixman.c
+++ b/ui/qemu-pixman.c
@@ -6,6 +6,87 @@
#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;
+}
+
+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;
@@ -52,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)
{
@@ -59,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)
{
diff --git a/ui/sdl.c b/ui/sdl.c
index 4e7f920e37..94c1d9dc3a 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 */
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index f02352cc46..3d1b5cd066 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;