Merge remote-tracking branch 'kraxel/pixman.v3' into staging

* kraxel/pixman.v3: (22 commits)
  pixman: drop obsolete fields from DisplaySurface
  pixman/vnc: remove dead code.
  pixman/vnc: remove rgb_prepare_row* functions
  pixman/vnc: use pixman images in vnc.
  pixman: switch screendump function.
  vga: stop direct access to DisplaySurface fields.
  qxl: stop direct access to DisplaySurface fields.
  console: don't set PixelFormat alpha fields for 32bpp
  console: make qemu_alloc_display static
  pixman: add pixman image to DisplaySurface
  pixman: helper functions
  pixman: windup in configure & makefiles
  pixman: add submodule
  console: remove DisplayAllocator
  console: remove dpy_gfx_fill
  vga: fix text mode updating
  console: init displaychangelisteners on register
  console: untangle gfx & txt updates
  console: s/TextConsole/QemuConsole/
  console: move set_mouse + cursor_define callbacks
  ...

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Anthony Liguori 2012-11-01 11:14:39 -05:00
commit 4ba79505f4
43 changed files with 857 additions and 864 deletions

3
.gitmodules vendored
View File

@ -19,3 +19,6 @@
[submodule "roms/sgabios"] [submodule "roms/sgabios"]
path = roms/sgabios path = roms/sgabios
url = git://git.qemu.org/sgabios.git url = git://git.qemu.org/sgabios.git
[submodule "pixman"]
path = pixman
url = git://anongit.freedesktop.org/pixman

View File

@ -118,6 +118,15 @@ endif
subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o
subdir-pixman: pixman/Makefile
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pixman V="$(V)" all,)
pixman/Makefile: $(SRC_PATH)/pixman/configure
(cd pixman; $(SRC_PATH)/pixman/configure --disable-shared --enable-static)
$(SRC_PATH)/pixman/configure:
(cd $(SRC_PATH)/pixman; autoreconf -v --install)
$(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) subdir-libdis $(filter %-softmmu,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) $(common-obj-y) $(extra-obj-y) subdir-libdis
$(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser $(filter %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser

View File

@ -65,6 +65,7 @@ common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/
common-obj-y += net.o net/ common-obj-y += net.o net/
common-obj-y += qom/ common-obj-y += qom/
common-obj-y += readline.o console.o cursor.o common-obj-y += readline.o console.o cursor.o
common-obj-y += qemu-pixman.o
common-obj-y += $(oslib-obj-y) common-obj-y += $(oslib-obj-y)
common-obj-$(CONFIG_WIN32) += os-win32.o common-obj-$(CONFIG_WIN32) += os-win32.o
common-obj-$(CONFIG_POSIX) += os-posix.o common-obj-$(CONFIG_POSIX) += os-posix.o

38
configure vendored
View File

@ -147,6 +147,7 @@ curses=""
docs="" docs=""
fdt="" fdt=""
nptl="" nptl=""
pixman=""
sdl="" sdl=""
virtfs="" virtfs=""
vnc="yes" vnc="yes"
@ -642,6 +643,10 @@ for opt do
# configure to be used by RPM and similar macros that set # configure to be used by RPM and similar macros that set
# lots of directory switches by default. # lots of directory switches by default.
;; ;;
--with-system-pixman) pixman="system"
;;
--without-system-pixman) pixman="internal"
;;
--disable-sdl) sdl="no" --disable-sdl) sdl="no"
;; ;;
--enable-sdl) sdl="yes" --enable-sdl) sdl="yes"
@ -2094,6 +2099,34 @@ else
exit 1 exit 1
fi fi
##########################################
# pixman support probe
if test "$pixman" = ""; then
if $pkg_config pixman-1 > /dev/null 2>&1; then
pixman="system"
else
pixman="internal"
fi
fi
if test "$pixman" = "system"; then
pixman_cflags=`$pkg_config --cflags pixman-1 2>/dev/null`
pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null`
else
if test ! -d ${source_path}/pixman/pixman; then
echo "ERROR: pixman not present. Your options:"
echo " (1) Prefered: Install the pixman devel package (any recent"
echo " distro should have packages as Xorg needs pixman too)."
echo " (2) Fetch the pixman submodule, using:"
echo " git submodule update --init pixman"
exit 1
fi
pixman_cflags="-I${source_path}/pixman/pixman"
pixman_libs="-Lpixman/pixman/.libs -lpixman-1"
fi
QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags"
libs_softmmu="$libs_softmmu $pixman_libs"
########################################## ##########################################
# libcap probe # libcap probe
@ -3142,6 +3175,7 @@ echo "-Werror enabled $werror"
if test "$darwin" = "yes" ; then if test "$darwin" = "yes" ; then
echo "Cocoa support $cocoa" echo "Cocoa support $cocoa"
fi fi
echo "pixman $pixman"
echo "SDL support $sdl" echo "SDL support $sdl"
echo "curses support $curses" echo "curses support $curses"
echo "curl support $curl" echo "curl support $curl"
@ -3908,6 +3942,9 @@ if test "$target_softmmu" = "yes" ; then
if test "$smartcard_nss" = "yes" ; then if test "$smartcard_nss" = "yes" ; then
echo "subdir-$target: subdir-libcacard" >> $config_host_mak echo "subdir-$target: subdir-libcacard" >> $config_host_mak
fi fi
if test "$pixman" = "internal" ; then
echo "subdir-$target: subdir-pixman" >> $config_host_mak
fi
case "$target_arch2" in case "$target_arch2" in
i386|x86_64) i386|x86_64)
echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak
@ -4111,6 +4148,7 @@ DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas"
DIRS="$DIRS roms/seabios roms/vgabios" DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS qapi-generated" DIRS="$DIRS qapi-generated"
DIRS="$DIRS libcacard libcacard/libcacard libcacard/trace" DIRS="$DIRS libcacard libcacard/libcacard libcacard/trace"
DIRS="$DIRS pixman"
FILES="Makefile tests/tcg/Makefile qdict-test-data.txt" FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit" FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
FILES="$FILES tests/tcg/lm32/Makefile libcacard/Makefile" FILES="$FILES tests/tcg/lm32/Makefile libcacard/Makefile"

252
console.c
View File

@ -114,20 +114,20 @@ typedef enum {
TEXT_CONSOLE_FIXED_SIZE TEXT_CONSOLE_FIXED_SIZE
} console_type_t; } console_type_t;
/* ??? This is mis-named. struct QemuConsole {
It is used for both text and graphical consoles. */
struct TextConsole {
int index; int index;
console_type_t console_type; console_type_t console_type;
DisplayState *ds; DisplayState *ds;
/* Graphic console state. */ /* Graphic console state. */
vga_hw_update_ptr hw_update; vga_hw_update_ptr hw_update;
vga_hw_invalidate_ptr hw_invalidate; vga_hw_invalidate_ptr hw_invalidate;
vga_hw_screen_dump_ptr hw_screen_dump; vga_hw_screen_dump_ptr hw_screen_dump;
vga_hw_text_update_ptr hw_text_update; vga_hw_text_update_ptr hw_text_update;
void *hw; void *hw;
int g_width, g_height; int g_width, g_height;
/* Text console state */
int width; int width;
int height; int height;
int total_height; int total_height;
@ -161,8 +161,8 @@ struct TextConsole {
}; };
static DisplayState *display_state; static DisplayState *display_state;
static TextConsole *active_console; static QemuConsole *active_console;
static TextConsole *consoles[MAX_CONSOLES]; static QemuConsole *consoles[MAX_CONSOLES];
static int nb_consoles = 0; static int nb_consoles = 0;
void vga_hw_update(void) void vga_hw_update(void)
@ -179,7 +179,7 @@ void vga_hw_invalidate(void)
void qmp_screendump(const char *filename, Error **errp) void qmp_screendump(const char *filename, Error **errp)
{ {
TextConsole *previous_active_console; QemuConsole *previous_active_console;
bool cswitch; bool cswitch;
previous_active_console = active_console; previous_active_console = active_console;
@ -521,7 +521,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
} }
} }
static void text_console_resize(TextConsole *s) static void text_console_resize(QemuConsole *s)
{ {
TextCell *cells, *c, *c1; TextCell *cells, *c, *c1;
int w1, x, y, last_width; int w1, x, y, last_width;
@ -553,7 +553,7 @@ static void text_console_resize(TextConsole *s)
s->cells = cells; s->cells = cells;
} }
static inline void text_update_xy(TextConsole *s, int x, int y) static inline void text_update_xy(QemuConsole *s, int x, int y)
{ {
s->text_x[0] = MIN(s->text_x[0], x); s->text_x[0] = MIN(s->text_x[0], x);
s->text_x[1] = MAX(s->text_x[1], x); s->text_x[1] = MAX(s->text_x[1], x);
@ -561,7 +561,7 @@ static inline void text_update_xy(TextConsole *s, int x, int y)
s->text_y[1] = MAX(s->text_y[1], y); s->text_y[1] = MAX(s->text_y[1], y);
} }
static void invalidate_xy(TextConsole *s, int x, int y) static void invalidate_xy(QemuConsole *s, int x, int y)
{ {
if (s->update_x0 > x * FONT_WIDTH) if (s->update_x0 > x * FONT_WIDTH)
s->update_x0 = x * FONT_WIDTH; s->update_x0 = x * FONT_WIDTH;
@ -573,7 +573,7 @@ static void invalidate_xy(TextConsole *s, int x, int y)
s->update_y1 = (y + 1) * FONT_HEIGHT; s->update_y1 = (y + 1) * FONT_HEIGHT;
} }
static void update_xy(TextConsole *s, int x, int y) static void update_xy(QemuConsole *s, int x, int y)
{ {
TextCell *c; TextCell *c;
int y1, y2; int y1, y2;
@ -597,7 +597,7 @@ static void update_xy(TextConsole *s, int x, int y)
} }
} }
static void console_show_cursor(TextConsole *s, int show) static void console_show_cursor(QemuConsole *s, int show)
{ {
TextCell *c; TextCell *c;
int y, y1; int y, y1;
@ -631,42 +631,45 @@ static void console_show_cursor(TextConsole *s, int show)
} }
} }
static void console_refresh(TextConsole *s) static void console_refresh(QemuConsole *s)
{ {
TextCell *c; TextCell *c;
int x, y, y1; int x, y, y1;
if (s != active_console) if (s != active_console)
return; return;
if (!ds_get_bits_per_pixel(s->ds)) {
if (s->ds->have_text) {
s->text_x[0] = 0; s->text_x[0] = 0;
s->text_y[0] = 0; s->text_y[0] = 0;
s->text_x[1] = s->width - 1; s->text_x[1] = s->width - 1;
s->text_y[1] = s->height - 1; s->text_y[1] = s->height - 1;
s->cursor_invalidate = 1; s->cursor_invalidate = 1;
return;
} }
vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds), if (s->ds->have_gfx) {
color_table[0][COLOR_BLACK]); vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
y1 = s->y_displayed; color_table[0][COLOR_BLACK]);
for(y = 0; y < s->height; y++) { y1 = s->y_displayed;
c = s->cells + y1 * s->width; for (y = 0; y < s->height; y++) {
for(x = 0; x < s->width; x++) { c = s->cells + y1 * s->width;
vga_putcharxy(s->ds, x, y, c->ch, for (x = 0; x < s->width; x++) {
&(c->t_attrib)); vga_putcharxy(s->ds, x, y, c->ch,
c++; &(c->t_attrib));
c++;
}
if (++y1 == s->total_height) {
y1 = 0;
}
} }
if (++y1 == s->total_height) console_show_cursor(s, 1);
y1 = 0; dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
} }
console_show_cursor(s, 1);
dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
} }
static void console_scroll(int ydelta) static void console_scroll(int ydelta)
{ {
TextConsole *s; QemuConsole *s;
int i, y1; int i, y1;
s = active_console; s = active_console;
@ -698,7 +701,7 @@ static void console_scroll(int ydelta)
console_refresh(s); console_refresh(s);
} }
static void console_put_lf(TextConsole *s) static void console_put_lf(QemuConsole *s)
{ {
TextCell *c; TextCell *c;
int x, y1; int x, y1;
@ -749,7 +752,7 @@ static void console_put_lf(TextConsole *s)
* NOTE: I know this code is not very efficient (checking every color for it * NOTE: I know this code is not very efficient (checking every color for it
* self) but it is more readable and better maintainable. * self) but it is more readable and better maintainable.
*/ */
static void console_handle_escape(TextConsole *s) static void console_handle_escape(QemuConsole *s)
{ {
int i; int i;
@ -842,7 +845,7 @@ static void console_handle_escape(TextConsole *s)
} }
} }
static void console_clear_xy(TextConsole *s, int x, int y) static void console_clear_xy(QemuConsole *s, int x, int y)
{ {
int y1 = (s->y_base + y) % s->total_height; int y1 = (s->y_base + y) % s->total_height;
TextCell *c = &s->cells[y1 * s->width + x]; TextCell *c = &s->cells[y1 * s->width + x];
@ -852,7 +855,7 @@ static void console_clear_xy(TextConsole *s, int x, int y)
} }
/* set cursor, checking bounds */ /* set cursor, checking bounds */
static void set_cursor(TextConsole *s, int x, int y) static void set_cursor(QemuConsole *s, int x, int y)
{ {
if (x < 0) { if (x < 0) {
x = 0; x = 0;
@ -871,7 +874,7 @@ static void set_cursor(TextConsole *s, int x, int y)
s->y = y; s->y = y;
} }
static void console_putchar(TextConsole *s, int ch) static void console_putchar(QemuConsole *s, int ch)
{ {
TextCell *c; TextCell *c;
int y1, i; int y1, i;
@ -1078,7 +1081,7 @@ static void console_putchar(TextConsole *s, int ch)
void console_select(unsigned int index) void console_select(unsigned int index)
{ {
TextConsole *s; QemuConsole *s;
if (index >= MAX_CONSOLES) if (index >= MAX_CONSOLES)
return; return;
@ -1094,24 +1097,24 @@ void console_select(unsigned int index)
qemu_del_timer(active_console->cursor_timer); qemu_del_timer(active_console->cursor_timer);
} }
active_console = s; active_console = s;
if (ds_get_bits_per_pixel(s->ds)) { if (ds->have_gfx) {
ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height); ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
} else { dpy_gfx_resize(ds);
s->ds->surface->width = s->width; }
s->ds->surface->height = s->height; if (ds->have_text) {
dpy_text_resize(ds, s->width, s->height);
} }
if (s->cursor_timer) { if (s->cursor_timer) {
qemu_mod_timer(s->cursor_timer, qemu_mod_timer(s->cursor_timer,
qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2); qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
} }
dpy_resize(s->ds);
vga_hw_invalidate(); vga_hw_invalidate();
} }
} }
static int console_puts(CharDriverState *chr, const uint8_t *buf, int len) static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
{ {
TextConsole *s = chr->opaque; QemuConsole *s = chr->opaque;
int i; int i;
s->update_x0 = s->width * FONT_WIDTH; s->update_x0 = s->width * FONT_WIDTH;
@ -1123,17 +1126,17 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
console_putchar(s, buf[i]); console_putchar(s, buf[i]);
} }
console_show_cursor(s, 1); console_show_cursor(s, 1);
if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) { if (s->ds->have_gfx && s->update_x0 < s->update_x1) {
dpy_update(s->ds, s->update_x0, s->update_y0, dpy_gfx_update(s->ds, s->update_x0, s->update_y0,
s->update_x1 - s->update_x0, s->update_x1 - s->update_x0,
s->update_y1 - s->update_y0); s->update_y1 - s->update_y0);
} }
return len; return len;
} }
static void kbd_send_chars(void *opaque) static void kbd_send_chars(void *opaque)
{ {
TextConsole *s = opaque; QemuConsole *s = opaque;
int len; int len;
uint8_t buf[16]; uint8_t buf[16];
@ -1156,7 +1159,7 @@ static void kbd_send_chars(void *opaque)
/* called when an ascii key is pressed */ /* called when an ascii key is pressed */
void kbd_put_keysym(int keysym) void kbd_put_keysym(int keysym)
{ {
TextConsole *s; QemuConsole *s;
uint8_t buf[16], *q; uint8_t buf[16], *q;
int c; int c;
@ -1211,7 +1214,7 @@ void kbd_put_keysym(int keysym)
static void text_console_invalidate(void *opaque) static void text_console_invalidate(void *opaque)
{ {
TextConsole *s = (TextConsole *) opaque; QemuConsole *s = (QemuConsole *) opaque;
if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) { if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
s->g_width = ds_get_width(s->ds); s->g_width = ds_get_width(s->ds);
s->g_height = ds_get_height(s->ds); s->g_height = ds_get_height(s->ds);
@ -1222,7 +1225,7 @@ static void text_console_invalidate(void *opaque)
static void text_console_update(void *opaque, console_ch_t *chardata) static void text_console_update(void *opaque, console_ch_t *chardata)
{ {
TextConsole *s = (TextConsole *) opaque; QemuConsole *s = (QemuConsole *) opaque;
int i, j, src; int i, j, src;
if (s->text_x[0] <= s->text_x[1]) { if (s->text_x[0] <= s->text_x[1]) {
@ -1234,23 +1237,23 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
(s->cells[src].t_attrib.fgcol << 12) | (s->cells[src].t_attrib.fgcol << 12) |
(s->cells[src].t_attrib.bgcol << 8) | (s->cells[src].t_attrib.bgcol << 8) |
(s->cells[src].t_attrib.bold << 21)); (s->cells[src].t_attrib.bold << 21));
dpy_update(s->ds, s->text_x[0], s->text_y[0], dpy_text_update(s->ds, s->text_x[0], s->text_y[0],
s->text_x[1] - s->text_x[0], i - s->text_y[0]); s->text_x[1] - s->text_x[0], i - s->text_y[0]);
s->text_x[0] = s->width; s->text_x[0] = s->width;
s->text_y[0] = s->height; s->text_y[0] = s->height;
s->text_x[1] = 0; s->text_x[1] = 0;
s->text_y[1] = 0; s->text_y[1] = 0;
} }
if (s->cursor_invalidate) { if (s->cursor_invalidate) {
dpy_cursor(s->ds, s->x, s->y); dpy_text_cursor(s->ds, s->x, s->y);
s->cursor_invalidate = 0; s->cursor_invalidate = 0;
} }
} }
static TextConsole *get_graphic_console(DisplayState *ds) static QemuConsole *get_graphic_console(DisplayState *ds)
{ {
int i; int i;
TextConsole *s; QemuConsole *s;
for (i = 0; i < nb_consoles; i++) { for (i = 0; i < nb_consoles; i++) {
s = consoles[i]; s = consoles[i];
if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds) if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
@ -1259,14 +1262,14 @@ static TextConsole *get_graphic_console(DisplayState *ds)
return NULL; return NULL;
} }
static TextConsole *new_console(DisplayState *ds, console_type_t console_type) static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
{ {
TextConsole *s; QemuConsole *s;
int i; int i;
if (nb_consoles >= MAX_CONSOLES) if (nb_consoles >= MAX_CONSOLES)
return NULL; return NULL;
s = g_malloc0(sizeof(TextConsole)); s = g_malloc0(sizeof(QemuConsole));
if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) && if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
(console_type == GRAPHIC_CONSOLE))) { (console_type == GRAPHIC_CONSOLE))) {
active_console = s; active_console = s;
@ -1291,85 +1294,86 @@ static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
return s; return s;
} }
static DisplaySurface* defaultallocator_create_displaysurface(int width, int height) static void qemu_alloc_display(DisplaySurface *surface, int width, int height,
int linesize, PixelFormat pf, int newflags)
{ {
DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
int linesize = width * 4;
qemu_alloc_display(surface, width, height, linesize,
qemu_default_pixelformat(32), 0);
return surface;
}
static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
int width, int height)
{
int linesize = width * 4;
qemu_alloc_display(surface, width, height, linesize,
qemu_default_pixelformat(32), 0);
return surface;
}
void qemu_alloc_display(DisplaySurface *surface, int width, int height,
int linesize, PixelFormat pf, int newflags)
{
void *data;
surface->width = width;
surface->height = height;
surface->linesize = linesize;
surface->pf = pf; surface->pf = pf;
if (surface->flags & QEMU_ALLOCATED_FLAG) {
data = g_realloc(surface->data, qemu_pixman_image_unref(surface->image);
surface->linesize * surface->height); surface->image = NULL;
} else {
data = g_malloc(surface->linesize * surface->height); surface->format = qemu_pixman_get_format(&pf);
} assert(surface->format != 0);
surface->data = (uint8_t *)data; surface->image = pixman_image_create_bits(surface->format,
width, height,
NULL, linesize);
assert(surface->image != NULL);
surface->flags = newflags | QEMU_ALLOCATED_FLAG; surface->flags = newflags | QEMU_ALLOCATED_FLAG;
#ifdef HOST_WORDS_BIGENDIAN #ifdef HOST_WORDS_BIGENDIAN
surface->flags |= QEMU_BIG_ENDIAN_FLAG; surface->flags |= QEMU_BIG_ENDIAN_FLAG;
#endif #endif
} }
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
int linesize, uint8_t *data) int width, int height)
{ {
DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface)); DisplaySurface *surface = g_new0(DisplaySurface, 1);
int linesize = width * 4;
qemu_alloc_display(surface, width, height, linesize,
qemu_default_pixelformat(32), 0);
return surface;
}
DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
int width, int height)
{
int linesize = width * 4;
trace_displaysurface_resize(ds, ds->surface, width, height);
qemu_alloc_display(ds->surface, width, height, linesize,
qemu_default_pixelformat(32), 0);
return ds->surface;
}
DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
int linesize, uint8_t *data)
{
DisplaySurface *surface = g_new0(DisplaySurface, 1);
surface->width = width;
surface->height = height;
surface->linesize = linesize;
surface->pf = qemu_default_pixelformat(bpp); surface->pf = qemu_default_pixelformat(bpp);
surface->format = qemu_pixman_get_format(&surface->pf);
assert(surface->format != 0);
surface->image = pixman_image_create_bits(surface->format,
width, height,
(void *)data, linesize);
assert(surface->image != NULL);
#ifdef HOST_WORDS_BIGENDIAN #ifdef HOST_WORDS_BIGENDIAN
surface->flags = QEMU_BIG_ENDIAN_FLAG; surface->flags = QEMU_BIG_ENDIAN_FLAG;
#endif #endif
surface->data = data;
return surface; return surface;
} }
static void defaultallocator_free_displaysurface(DisplaySurface *surface) void qemu_free_displaysurface(DisplayState *ds)
{ {
if (surface == NULL) trace_displaysurface_free(ds, ds->surface);
if (ds->surface == NULL) {
return; return;
if (surface->flags & QEMU_ALLOCATED_FLAG) }
g_free(surface->data); qemu_pixman_image_unref(ds->surface->image);
g_free(surface); g_free(ds->surface);
} }
static struct DisplayAllocator default_allocator = {
defaultallocator_create_displaysurface,
defaultallocator_resize_displaysurface,
defaultallocator_free_displaysurface
};
static void dumb_display_init(void) static void dumb_display_init(void)
{ {
DisplayState *ds = g_malloc0(sizeof(DisplayState)); DisplayState *ds = g_malloc0(sizeof(DisplayState));
int width = 640; int width = 640;
int height = 480; int height = 480;
ds->allocator = &default_allocator;
if (is_fixedsize_console()) { if (is_fixedsize_console()) {
width = active_console->g_width; width = active_console->g_width;
height = active_console->g_height; height = active_console->g_height;
@ -1399,29 +1403,16 @@ DisplayState *get_displaystate(void)
return display_state; return display_state;
} }
DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
{
if(ds->allocator == &default_allocator) {
DisplaySurface *surf;
surf = da->create_displaysurface(ds_get_width(ds), ds_get_height(ds));
defaultallocator_free_displaysurface(ds->surface);
ds->surface = surf;
ds->allocator = da;
}
return ds->allocator;
}
DisplayState *graphic_console_init(vga_hw_update_ptr update, DisplayState *graphic_console_init(vga_hw_update_ptr update,
vga_hw_invalidate_ptr invalidate, vga_hw_invalidate_ptr invalidate,
vga_hw_screen_dump_ptr screen_dump, vga_hw_screen_dump_ptr screen_dump,
vga_hw_text_update_ptr text_update, vga_hw_text_update_ptr text_update,
void *opaque) void *opaque)
{ {
TextConsole *s; QemuConsole *s;
DisplayState *ds; DisplayState *ds;
ds = (DisplayState *) g_malloc0(sizeof(DisplayState)); ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
ds->allocator = &default_allocator;
ds->surface = qemu_create_displaysurface(ds, 640, 480); ds->surface = qemu_create_displaysurface(ds, 640, 480);
s = new_console(ds, GRAPHIC_CONSOLE); s = new_console(ds, GRAPHIC_CONSOLE);
@ -1463,14 +1454,14 @@ void console_color_init(DisplayState *ds)
static void text_console_set_echo(CharDriverState *chr, bool echo) static void text_console_set_echo(CharDriverState *chr, bool echo)
{ {
TextConsole *s = chr->opaque; QemuConsole *s = chr->opaque;
s->echo = echo; s->echo = echo;
} }
static void text_console_update_cursor(void *opaque) static void text_console_update_cursor(void *opaque)
{ {
TextConsole *s = opaque; QemuConsole *s = opaque;
s->cursor_visible_phase = !s->cursor_visible_phase; s->cursor_visible_phase = !s->cursor_visible_phase;
vga_hw_invalidate(); vga_hw_invalidate();
@ -1480,7 +1471,7 @@ static void text_console_update_cursor(void *opaque)
static void text_console_do_init(CharDriverState *chr, DisplayState *ds) static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
{ {
TextConsole *s; QemuConsole *s;
static int color_inited; static int color_inited;
s = chr->opaque; s = chr->opaque;
@ -1543,7 +1534,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
CharDriverState *text_console_init(QemuOpts *opts) CharDriverState *text_console_init(QemuOpts *opts)
{ {
CharDriverState *chr; CharDriverState *chr;
TextConsole *s; QemuConsole *s;
unsigned width; unsigned width;
unsigned height; unsigned height;
@ -1589,14 +1580,14 @@ void text_consoles_set_display(DisplayState *ds)
void qemu_console_resize(DisplayState *ds, int width, int height) void qemu_console_resize(DisplayState *ds, int width, int height)
{ {
TextConsole *s = get_graphic_console(ds); QemuConsole *s = get_graphic_console(ds);
if (!s) return; if (!s) return;
s->g_width = width; s->g_width = width;
s->g_height = height; s->g_height = height;
if (is_graphic_console()) { if (is_graphic_console()) {
ds->surface = qemu_resize_displaysurface(ds, width, height); ds->surface = qemu_resize_displaysurface(ds, width, height);
dpy_resize(ds); dpy_gfx_resize(ds);
} }
} }
@ -1604,7 +1595,7 @@ void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
int dst_x, int dst_y, int w, int h) int dst_x, int dst_y, int w, int h)
{ {
if (is_graphic_console()) { if (is_graphic_console()) {
dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h); dpy_gfx_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
} }
} }
@ -1715,18 +1706,15 @@ PixelFormat qemu_default_pixelformat(int bpp)
pf.rmask = 0x00FF0000; pf.rmask = 0x00FF0000;
pf.gmask = 0x0000FF00; pf.gmask = 0x0000FF00;
pf.bmask = 0x000000FF; pf.bmask = 0x000000FF;
pf.amax = 255;
pf.rmax = 255; pf.rmax = 255;
pf.gmax = 255; pf.gmax = 255;
pf.bmax = 255; pf.bmax = 255;
pf.ashift = 24;
pf.rshift = 16; pf.rshift = 16;
pf.gshift = 8; pf.gshift = 8;
pf.bshift = 0; pf.bshift = 0;
pf.rbits = 8; pf.rbits = 8;
pf.gbits = 8; pf.gbits = 8;
pf.bbits = 8; pf.bbits = 8;
pf.abits = 8;
break; break;
default: default:
break; break;

237
console.h
View File

@ -2,6 +2,7 @@
#define CONSOLE_H #define CONSOLE_H
#include "qemu-char.h" #include "qemu-char.h"
#include "qemu-pixman.h"
#include "qdict.h" #include "qdict.h"
#include "notify.h" #include "notify.h"
#include "monitor.h" #include "monitor.h"
@ -107,7 +108,6 @@ void kbd_put_keysym(int keysym);
#define QEMU_BIG_ENDIAN_FLAG 0x01 #define QEMU_BIG_ENDIAN_FLAG 0x01
#define QEMU_ALLOCATED_FLAG 0x02 #define QEMU_ALLOCATED_FLAG 0x02
#define QEMU_REALPIXELS_FLAG 0x04
struct PixelFormat { struct PixelFormat {
uint8_t bits_per_pixel; uint8_t bits_per_pixel;
@ -120,11 +120,9 @@ struct PixelFormat {
}; };
struct DisplaySurface { struct DisplaySurface {
pixman_format_code_t format;
pixman_image_t *image;
uint8_t flags; uint8_t flags;
int width;
int height;
int linesize; /* bytes per line */
uint8_t *data;
struct PixelFormat pf; struct PixelFormat pf;
}; };
@ -154,35 +152,32 @@ struct DisplayChangeListener {
int idle; int idle;
uint64_t gui_timer_interval; uint64_t gui_timer_interval;
void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_resize)(struct DisplayState *s);
void (*dpy_setdata)(struct DisplayState *s);
void (*dpy_refresh)(struct DisplayState *s); void (*dpy_refresh)(struct DisplayState *s);
void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h); void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_fill)(struct DisplayState *s, int x, int y, void (*dpy_gfx_resize)(struct DisplayState *s);
int w, int h, uint32_t c); void (*dpy_gfx_setdata)(struct DisplayState *s);
void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h);
void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
void (*dpy_text_resize)(struct DisplayState *s, int w, int h);
void (*dpy_text_update)(struct DisplayState *s, int x, int y, int w, int h);
struct DisplayChangeListener *next; void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on);
}; void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor);
struct DisplayAllocator { QLIST_ENTRY(DisplayChangeListener) next;
DisplaySurface* (*create_displaysurface)(int width, int height);
DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height);
void (*free_displaysurface)(DisplaySurface *surface);
}; };
struct DisplayState { struct DisplayState {
struct DisplaySurface *surface; struct DisplaySurface *surface;
void *opaque; void *opaque;
struct QEMUTimer *gui_timer; struct QEMUTimer *gui_timer;
bool have_gfx;
bool have_text;
struct DisplayAllocator* allocator; QLIST_HEAD(, DisplayChangeListener) listeners;
struct DisplayChangeListener* listeners;
void (*mouse_set)(int x, int y, int on);
void (*cursor_define)(QEMUCursor *cursor);
struct DisplayState *next; struct DisplayState *next;
}; };
@ -191,29 +186,14 @@ void register_displaystate(DisplayState *ds);
DisplayState *get_displaystate(void); DisplayState *get_displaystate(void);
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
int linesize, uint8_t *data); int linesize, uint8_t *data);
void qemu_alloc_display(DisplaySurface *surface, int width, int height,
int linesize, PixelFormat pf, int newflags);
PixelFormat qemu_different_endianness_pixelformat(int bpp); PixelFormat qemu_different_endianness_pixelformat(int bpp);
PixelFormat qemu_default_pixelformat(int bpp); PixelFormat qemu_default_pixelformat(int bpp);
DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da); DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
int width, int height);
static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height) DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
{ int width, int height);
return ds->allocator->create_displaysurface(width, height); void qemu_free_displaysurface(DisplayState *ds);
}
static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height)
{
trace_displaysurface_resize(ds, ds->surface, width, height);
return ds->allocator->resize_displaysurface(ds->surface, width, height);
}
static inline void qemu_free_displaysurface(DisplayState *ds)
{
trace_displaysurface_free(ds, ds->surface);
ds->allocator->free_displaysurface(ds->surface);
}
static inline int is_surface_bgr(DisplaySurface *surface) static inline int is_surface_bgr(DisplaySurface *surface)
{ {
@ -225,109 +205,176 @@ static inline int is_surface_bgr(DisplaySurface *surface)
static inline int is_buffer_shared(DisplaySurface *surface) static inline int is_buffer_shared(DisplaySurface *surface)
{ {
return (!(surface->flags & QEMU_ALLOCATED_FLAG) && return !(surface->flags & QEMU_ALLOCATED_FLAG);
!(surface->flags & QEMU_REALPIXELS_FLAG));
} }
void gui_setup_refresh(DisplayState *ds);
static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
{ {
dcl->next = ds->listeners; QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
ds->listeners = dcl; gui_setup_refresh(ds);
} if (dcl->dpy_gfx_resize) {
dcl->dpy_gfx_resize(ds);
static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
{
struct DisplayChangeListener *dcl = s->listeners;
while (dcl != NULL) {
dcl->dpy_update(s, x, y, w, h);
dcl = dcl->next;
} }
} }
static inline void dpy_resize(DisplayState *s) static inline void unregister_displaychangelistener(DisplayState *ds,
DisplayChangeListener *dcl)
{ {
struct DisplayChangeListener *dcl = s->listeners; QLIST_REMOVE(dcl, next);
while (dcl != NULL) { gui_setup_refresh(ds);
dcl->dpy_resize(s); }
dcl = dcl->next;
static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_gfx_update) {
dcl->dpy_gfx_update(s, x, y, w, h);
}
} }
} }
static inline void dpy_setdata(DisplayState *s) static inline void dpy_gfx_resize(DisplayState *s)
{ {
struct DisplayChangeListener *dcl = s->listeners; struct DisplayChangeListener *dcl;
while (dcl != NULL) { QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_setdata) dcl->dpy_setdata(s); if (dcl->dpy_gfx_resize) {
dcl = dcl->next; dcl->dpy_gfx_resize(s);
}
}
}
static inline void dpy_gfx_setdata(DisplayState *s)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_gfx_setdata) {
dcl->dpy_gfx_setdata(s);
}
} }
} }
static inline void dpy_refresh(DisplayState *s) static inline void dpy_refresh(DisplayState *s)
{ {
struct DisplayChangeListener *dcl = s->listeners; struct DisplayChangeListener *dcl;
while (dcl != NULL) { QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_refresh) dcl->dpy_refresh(s); if (dcl->dpy_refresh) {
dcl = dcl->next; dcl->dpy_refresh(s);
}
} }
} }
static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y, static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
int dst_x, int dst_y, int w, int h) { int dst_x, int dst_y, int w, int h)
struct DisplayChangeListener *dcl = s->listeners; {
while (dcl != NULL) { struct DisplayChangeListener *dcl;
if (dcl->dpy_copy) QLIST_FOREACH(dcl, &s->listeners, next) {
dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h); if (dcl->dpy_gfx_copy) {
else /* TODO */ dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h);
dcl->dpy_update(s, dst_x, dst_y, w, h); } else { /* TODO */
dcl = dcl->next; dcl->dpy_gfx_update(s, dst_x, dst_y, w, h);
}
} }
} }
static inline void dpy_fill(struct DisplayState *s, int x, int y, static inline void dpy_text_cursor(struct DisplayState *s, int x, int y)
int w, int h, uint32_t c) { {
struct DisplayChangeListener *dcl = s->listeners; struct DisplayChangeListener *dcl;
while (dcl != NULL) { QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_fill) dcl->dpy_fill(s, x, y, w, h, c); if (dcl->dpy_text_cursor) {
dcl = dcl->next; dcl->dpy_text_cursor(s, x, y);
}
} }
} }
static inline void dpy_cursor(struct DisplayState *s, int x, int y) { static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
struct DisplayChangeListener *dcl = s->listeners; {
while (dcl != NULL) { struct DisplayChangeListener *dcl;
if (dcl->dpy_text_cursor) dcl->dpy_text_cursor(s, x, y); QLIST_FOREACH(dcl, &s->listeners, next) {
dcl = dcl->next; if (dcl->dpy_text_update) {
dcl->dpy_text_update(s, x, y, w, h);
}
} }
} }
static inline void dpy_text_resize(DisplayState *s, int w, int h)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_text_resize) {
dcl->dpy_text_resize(s, w, h);
}
}
}
static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_mouse_set) {
dcl->dpy_mouse_set(s, x, y, on);
}
}
}
static inline void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_cursor_define) {
dcl->dpy_cursor_define(s, cursor);
}
}
}
static inline bool dpy_cursor_define_supported(struct DisplayState *s)
{
struct DisplayChangeListener *dcl;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (dcl->dpy_cursor_define) {
return true;
}
}
return false;
}
static inline int ds_get_linesize(DisplayState *ds) static inline int ds_get_linesize(DisplayState *ds)
{ {
return ds->surface->linesize; return pixman_image_get_stride(ds->surface->image);
} }
static inline uint8_t* ds_get_data(DisplayState *ds) static inline uint8_t* ds_get_data(DisplayState *ds)
{ {
return ds->surface->data; return (void *)pixman_image_get_data(ds->surface->image);
} }
static inline int ds_get_width(DisplayState *ds) static inline int ds_get_width(DisplayState *ds)
{ {
return ds->surface->width; return pixman_image_get_width(ds->surface->image);
} }
static inline int ds_get_height(DisplayState *ds) static inline int ds_get_height(DisplayState *ds)
{ {
return ds->surface->height; return pixman_image_get_height(ds->surface->image);
} }
static inline int ds_get_bits_per_pixel(DisplayState *ds) static inline int ds_get_bits_per_pixel(DisplayState *ds)
{ {
return ds->surface->pf.bits_per_pixel; int bits = PIXMAN_FORMAT_BPP(ds->surface->format);
return bits;
} }
static inline int ds_get_bytes_per_pixel(DisplayState *ds) static inline int ds_get_bytes_per_pixel(DisplayState *ds)
{ {
return ds->surface->pf.bytes_per_pixel; int bits = PIXMAN_FORMAT_BPP(ds->surface->format);
return (bits + 7) / 8;
}
static inline pixman_format_code_t ds_get_format(DisplayState *ds)
{
return ds->surface->format;
} }
#ifdef CONFIG_CURSES #ifdef CONFIG_CURSES

View File

@ -921,8 +921,8 @@ static void blizzard_update_display(void *opaque)
for (; y < s->my[1]; y ++, src += bypl, dst += bypl) for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
memcpy(dst, src, bwidth); memcpy(dst, src, bwidth);
dpy_update(s->state, s->mx[0], s->my[0], dpy_gfx_update(s->state, s->mx[0], s->my[0],
s->mx[1] - s->mx[0], y - s->my[0]); s->mx[1] - s->mx[0], y - s->my[0]);
s->mx[0] = s->x; s->mx[0] = s->x;
s->mx[1] = 0; s->mx[1] = 0;

View File

@ -1307,7 +1307,7 @@ static void exynos4210_fimd_update(void *opaque)
fimd_copy_line_toqemu(global_width, s->ifb + global_width * line * fimd_copy_line_toqemu(global_width, s->ifb + global_width * line *
RGBA_SIZE, d + global_width * line * bpp); RGBA_SIZE, d + global_width * line * bpp);
} }
dpy_update(s->console, 0, 0, global_width, global_height); dpy_gfx_update(s->console, 0, 0, global_width, global_height);
} }
s->invalidate = false; s->invalidate = false;
s->vidintcon[1] |= FIMD_VIDINT_INTFRMPEND; s->vidintcon[1] |= FIMD_VIDINT_INTFRMPEND;

View File

@ -197,7 +197,8 @@ static void g364fb_draw_graphic8(G364State *s)
reset_dirty(s, page_min, page_max); reset_dirty(s, page_min, page_max);
page_min = (ram_addr_t)-1; page_min = (ram_addr_t)-1;
page_max = 0; page_max = 0;
dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); dpy_gfx_update(s->ds, xmin, ymin,
xmax - xmin + 1, ymax - ymin + 1);
xmin = s->width; xmin = s->width;
xmax = 0; xmax = 0;
ymin = s->height; ymin = s->height;
@ -216,7 +217,7 @@ static void g364fb_draw_graphic8(G364State *s)
done: done:
if (page_min != (ram_addr_t)-1) { if (page_min != (ram_addr_t)-1) {
dpy_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); dpy_gfx_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
reset_dirty(s, page_min, page_max); reset_dirty(s, page_min, page_max);
} }
} }
@ -238,7 +239,7 @@ static void g364fb_draw_blank(G364State *s)
d += ds_get_linesize(s->ds); d += ds_get_linesize(s->ds);
} }
dpy_update(s->ds, 0, 0, s->width, s->height); dpy_gfx_update(s->ds, 0, 0, s->width, s->height);
s->blanked = 1; s->blanked = 1;
} }

View File

@ -196,7 +196,7 @@ static void jazz_led_update_display(void *opaque)
} }
s->state = REDRAW_NONE; s->state = REDRAW_NONE;
dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); dpy_gfx_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
} }
static void jazz_led_invalidate_display(void *opaque) static void jazz_led_invalidate_display(void *opaque)
@ -210,7 +210,7 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
LedState *s = opaque; LedState *s = opaque;
char buf[2]; char buf[2];
dpy_cursor(s->ds, -1, -1); dpy_text_cursor(s->ds, -1, -1);
qemu_console_resize(s->ds, 2, 1); qemu_console_resize(s->ds, 2, 1);
/* TODO: draw the segments */ /* TODO: draw the segments */
@ -218,7 +218,7 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
console_write_ch(chardata++, 0x00200100 | buf[0]); console_write_ch(chardata++, 0x00200100 | buf[0]);
console_write_ch(chardata++, 0x00200100 | buf[1]); console_write_ch(chardata++, 0x00200100 | buf[1]);
dpy_update(s->ds, 0, 0, 2, 1); dpy_text_update(s->ds, 0, 0, 2, 1);
} }
static int jazz_led_post_load(void *opaque, int version_id) static int jazz_led_post_load(void *opaque, int version_id)

View File

@ -134,7 +134,7 @@ static void vgafb_update_display(void *opaque)
&first, &last); &first, &last);
if (first >= 0) { if (first >= 0) {
dpy_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1); dpy_gfx_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
} }
s->invalidate = 0; s->invalidate = 0;
} }

View File

@ -526,7 +526,7 @@ static void lcd_refresh(void *opaque)
ds_get_bits_per_pixel(s->ds)); ds_get_bits_per_pixel(s->ds));
} }
dpy_update(s->ds, 0, 0, 128*3, 64*3); dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3);
} }
static void lcd_invalidate(void *opaque) static void lcd_invalidate(void *opaque)

View File

@ -1375,7 +1375,7 @@ static void n8x0_init(QEMUMachineInitArgs *args,
size until the guest activates the display. */ size until the guest activates the display. */
ds = get_displaystate(); ds = get_displaystate();
ds->surface = qemu_resize_displaysurface(ds, 800, 480); ds->surface = qemu_resize_displaysurface(ds, 800, 480);
dpy_resize(ds); dpy_gfx_resize(ds);
} }
static struct arm_boot_info n800_binfo = { static struct arm_boot_info n800_binfo = {

View File

@ -219,7 +219,7 @@ static void omap_update_display(void *opaque)
draw_line, omap_lcd->palette, draw_line, omap_lcd->palette,
&first, &last); &first, &last);
if (first >= 0) { if (first >= 0) {
dpy_update(omap_lcd->state, 0, first, width, last - first + 1); dpy_gfx_update(omap_lcd->state, 0, first, width, last - first + 1);
} }
omap_lcd->invalidate = 0; omap_lcd->invalidate = 0;
} }

View File

@ -273,7 +273,7 @@ static void palmte_init(QEMUMachineInitArgs *args)
will set the size once configured, so this just sets an initial will set the size once configured, so this just sets an initial
size until the guest activates the display. */ size until the guest activates the display. */
ds->surface = qemu_resize_displaysurface(ds, 320, 320); ds->surface = qemu_resize_displaysurface(ds, 320, 320);
dpy_resize(ds); dpy_gfx_resize(ds);
} }
static QEMUMachine palmte_machine = { static QEMUMachine palmte_machine = {

View File

@ -239,7 +239,7 @@ static void pl110_update_display(void *opaque)
fn, s->palette, fn, s->palette,
&first, &last); &first, &last);
if (first >= 0) { if (first >= 0) {
dpy_update(s->ds, 0, first, s->cols, last - first + 1); dpy_gfx_update(s->ds, 0, first, s->cols, last - first + 1);
} }
s->invalidate = 0; s->invalidate = 0;
} }

View File

@ -871,20 +871,20 @@ static void pxa2xx_update_display(void *opaque)
if (miny >= 0) { if (miny >= 0) {
switch (s->orientation) { switch (s->orientation) {
case 0: case 0:
dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1); dpy_gfx_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
break; break;
case 90: case 90:
dpy_update(s->ds, miny, 0, maxy - miny + 1, s->xres); dpy_gfx_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
break; break;
case 180: case 180:
maxy = s->yres - maxy - 1; maxy = s->yres - maxy - 1;
miny = s->yres - miny - 1; miny = s->yres - miny - 1;
dpy_update(s->ds, 0, maxy, s->xres, miny - maxy + 1); dpy_gfx_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
break; break;
case 270: case 270:
maxy = s->yres - maxy - 1; maxy = s->yres - maxy - 1;
miny = s->yres - miny - 1; miny = s->yres - miny - 1;
dpy_update(s->ds, maxy, 0, miny - maxy + 1, s->xres); dpy_gfx_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
break; break;
} }
} }

View File

@ -24,7 +24,7 @@
static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect) static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
{ {
uint8_t *src; uint8_t *src;
uint8_t *dst = qxl->vga.ds->surface->data; uint8_t *dst = ds_get_data(qxl->vga.ds);
int len, i; int len, i;
if (is_buffer_shared(qxl->vga.ds->surface)) { if (is_buffer_shared(qxl->vga.ds->surface)) {
@ -123,17 +123,17 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.surface.width, qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height); qxl->guest_primary.surface.height);
} }
dpy_resize(vga->ds); dpy_gfx_resize(vga->ds);
} }
for (i = 0; i < qxl->num_dirty_rects; i++) { for (i = 0; i < qxl->num_dirty_rects; i++) {
if (qemu_spice_rect_is_empty(qxl->dirty+i)) { if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
break; break;
} }
qxl_blit(qxl, qxl->dirty+i); qxl_blit(qxl, qxl->dirty+i);
dpy_update(vga->ds, dpy_gfx_update(vga->ds,
qxl->dirty[i].left, qxl->dirty[i].top, qxl->dirty[i].left, qxl->dirty[i].top,
qxl->dirty[i].right - qxl->dirty[i].left, qxl->dirty[i].right - qxl->dirty[i].left,
qxl->dirty[i].bottom - qxl->dirty[i].top); qxl->dirty[i].bottom - qxl->dirty[i].top);
} }
qxl->num_dirty_rects = 0; qxl->num_dirty_rects = 0;
} }
@ -234,7 +234,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
return 1; return 1;
} }
if (!qxl->ssd.ds->mouse_set || !qxl->ssd.ds->cursor_define) { if (!dpy_cursor_define_supported(qxl->ssd.ds)) {
return 0; return 0;
} }

View File

@ -1864,8 +1864,8 @@ static void display_refresh(struct DisplayState *ds)
} }
static DisplayChangeListener display_listener = { static DisplayChangeListener display_listener = {
.dpy_update = display_update, .dpy_gfx_update = display_update,
.dpy_resize = display_resize, .dpy_gfx_resize = display_resize,
.dpy_refresh = display_refresh, .dpy_refresh = display_refresh,
}; };

View File

@ -1351,7 +1351,7 @@ static void sm501_draw_crt(SM501State * s)
} else { } else {
if (y_start >= 0) { if (y_start >= 0) {
/* flush to display */ /* flush to display */
dpy_update(s->ds, 0, y_start, width, y - y_start); dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
y_start = -1; y_start = -1;
} }
} }
@ -1362,7 +1362,7 @@ static void sm501_draw_crt(SM501State * s)
/* complete flush to display */ /* complete flush to display */
if (y_start >= 0) if (y_start >= 0)
dpy_update(s->ds, 0, y_start, width, y - y_start); dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
/* clear dirty flags */ /* clear dirty flags */
if (page_min != ~0l) { if (page_min != ~0l) {

View File

@ -252,7 +252,7 @@ static void ssd0303_update_display(void *opaque)
} }
} }
s->redraw = 0; s->redraw = 0;
dpy_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY); dpy_gfx_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
} }
static void ssd0303_invalidate_display(void * opaque) static void ssd0303_invalidate_display(void * opaque)

View File

@ -260,7 +260,7 @@ static void ssd0323_update_display(void *opaque)
} }
} }
s->redraw = 0; s->redraw = 0;
dpy_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY); dpy_gfx_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
} }
static void ssd0323_invalidate_display(void * opaque) static void ssd0323_invalidate_display(void * opaque)

View File

@ -454,7 +454,7 @@ static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
return; return;
} }
dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height);
} }
static void tc6393xb_draw_blank(TC6393xbState *s, int full_update) static void tc6393xb_draw_blank(TC6393xbState *s, int full_update)
@ -472,7 +472,7 @@ static void tc6393xb_draw_blank(TC6393xbState *s, int full_update)
d += ds_get_linesize(s->ds); d += ds_get_linesize(s->ds);
} }
dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height);
} }
static void tc6393xb_update_display(void *opaque) static void tc6393xb_update_display(void *opaque)

View File

@ -268,8 +268,8 @@ static void tcx_update_display(void *opaque)
} else { } else {
if (y_start >= 0) { if (y_start >= 0) {
/* flush to display */ /* flush to display */
dpy_update(ts->ds, 0, y_start, dpy_gfx_update(ts->ds, 0, y_start,
ts->width, y - y_start); ts->width, y - y_start);
y_start = -1; y_start = -1;
} }
d += dd * 4; d += dd * 4;
@ -278,8 +278,8 @@ static void tcx_update_display(void *opaque)
} }
if (y_start >= 0) { if (y_start >= 0) {
/* flush to display */ /* flush to display */
dpy_update(ts->ds, 0, y_start, dpy_gfx_update(ts->ds, 0, y_start,
ts->width, y - y_start); ts->width, y - y_start);
} }
/* reset modified pages */ /* reset modified pages */
if (page_max >= page_min) { if (page_max >= page_min) {
@ -344,8 +344,8 @@ static void tcx24_update_display(void *opaque)
} else { } else {
if (y_start >= 0) { if (y_start >= 0) {
/* flush to display */ /* flush to display */
dpy_update(ts->ds, 0, y_start, dpy_gfx_update(ts->ds, 0, y_start,
ts->width, y - y_start); ts->width, y - y_start);
y_start = -1; y_start = -1;
} }
d += dd * 4; d += dd * 4;
@ -356,8 +356,8 @@ static void tcx24_update_display(void *opaque)
} }
if (y_start >= 0) { if (y_start >= 0) {
/* flush to display */ /* flush to display */
dpy_update(ts->ds, 0, y_start, dpy_gfx_update(ts->ds, 0, y_start,
ts->width, y - y_start); ts->width, y - y_start);
} }
/* reset modified pages */ /* reset modified pages */
if (page_max >= page_min) { if (page_max >= page_min) {

111
hw/vga.c
View File

@ -1346,6 +1346,7 @@ static void vga_draw_text(VGACommonState *s, int full_update)
s->last_scr_width = width * cw; s->last_scr_width = width * cw;
s->last_scr_height = height * cheight; s->last_scr_height = height * cheight;
qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height); qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
dpy_text_resize(s->ds, width, height);
s->last_depth = 0; s->last_depth = 0;
s->last_width = width; s->last_width = width;
s->last_height = height; s->last_height = height;
@ -1359,6 +1360,14 @@ static void vga_draw_text(VGACommonState *s, int full_update)
palette = s->last_palette; palette = s->last_palette;
x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
if (full_update) {
s->full_update_text = 1;
}
if (s->full_update_gfx) {
s->full_update_gfx = 0;
full_update |= 1;
}
cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) | cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr; s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
if (cursor_offset != s->cursor_offset || if (cursor_offset != s->cursor_offset ||
@ -1456,8 +1465,8 @@ static void vga_draw_text(VGACommonState *s, int full_update)
ch_attr_ptr++; ch_attr_ptr++;
} }
if (cx_max != -1) { if (cx_max != -1) {
dpy_update(s->ds, cx_min * cw, cy * cheight, dpy_gfx_update(s->ds, cx_min * cw, cy * cheight,
(cx_max - cx_min + 1) * cw, cheight); (cx_max - cx_min + 1) * cw, cheight);
} }
dest += linesize * cheight; dest += linesize * cheight;
line1 = line + cheight; line1 = line + cheight;
@ -1688,7 +1697,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
s->ds->surface->pf = qemu_different_endianness_pixelformat(depth); s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
#endif #endif
dpy_resize(s->ds); dpy_gfx_resize(s->ds);
} else { } else {
qemu_console_resize(s->ds, disp_width, height); qemu_console_resize(s->ds, disp_width, height);
} }
@ -1700,9 +1709,14 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
s->last_depth = depth; s->last_depth = depth;
full_update = 1; full_update = 1;
} else if (is_buffer_shared(s->ds->surface) && } else if (is_buffer_shared(s->ds->surface) &&
(full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) { (full_update || ds_get_data(s->ds) != s->vram_ptr
s->ds->surface->data = s->vram_ptr + (s->start_addr * 4); + (s->start_addr * 4))) {
dpy_setdata(s->ds); qemu_free_displaysurface(s->ds);
s->ds->surface = qemu_create_displaysurface_from(disp_width,
height, depth,
s->line_offset,
s->vram_ptr + (s->start_addr * 4));
dpy_gfx_setdata(s->ds);
} }
s->rgb_to_pixel = s->rgb_to_pixel =
@ -1807,8 +1821,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
} else { } else {
if (y_start >= 0) { if (y_start >= 0) {
/* flush to display */ /* flush to display */
dpy_update(s->ds, 0, y_start, dpy_gfx_update(s->ds, 0, y_start,
disp_width, y - y_start); disp_width, y - y_start);
y_start = -1; y_start = -1;
} }
} }
@ -1828,8 +1842,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
} }
if (y_start >= 0) { if (y_start >= 0) {
/* flush to display */ /* flush to display */
dpy_update(s->ds, 0, y_start, dpy_gfx_update(s->ds, 0, y_start,
disp_width, y - y_start); disp_width, y - y_start);
} }
/* reset modified pages */ /* reset modified pages */
if (page_max >= page_min) { if (page_max >= page_min) {
@ -1863,8 +1877,8 @@ static void vga_draw_blank(VGACommonState *s, int full_update)
memset(d, val, w); memset(d, val, w);
d += ds_get_linesize(s->ds); d += ds_get_linesize(s->ds);
} }
dpy_update(s->ds, 0, 0, dpy_gfx_update(s->ds, 0, 0,
s->last_scr_width, s->last_scr_height); s->last_scr_width, s->last_scr_height);
} }
#define GMODE_TEXT 0 #define GMODE_TEXT 0
@ -2052,9 +2066,9 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
cw != s->last_cw || cheight != s->last_ch) { cw != s->last_cw || cheight != s->last_ch) {
s->last_scr_width = width * cw; s->last_scr_width = width * cw;
s->last_scr_height = height * cheight; s->last_scr_height = height * cheight;
s->ds->surface->width = width; qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
s->ds->surface->height = height; dpy_text_resize(s->ds, width, height);
dpy_resize(s->ds); s->last_depth = 0;
s->last_width = width; s->last_width = width;
s->last_height = height; s->last_height = height;
s->last_ch = cheight; s->last_ch = cheight;
@ -2062,6 +2076,14 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
full_update = 1; full_update = 1;
} }
if (full_update) {
s->full_update_gfx = 1;
}
if (s->full_update_text) {
s->full_update_text = 0;
full_update |= 1;
}
/* Update "hardware" cursor */ /* Update "hardware" cursor */
cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) | cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr; s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
@ -2070,11 +2092,11 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) { s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20); cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
if (cursor_visible && cursor_offset < size && cursor_offset >= 0) if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
dpy_cursor(s->ds, dpy_text_cursor(s->ds,
TEXTMODE_X(cursor_offset), TEXTMODE_X(cursor_offset),
TEXTMODE_Y(cursor_offset)); TEXTMODE_Y(cursor_offset));
else else
dpy_cursor(s->ds, -1, -1); dpy_text_cursor(s->ds, -1, -1);
s->cursor_offset = cursor_offset; s->cursor_offset = cursor_offset;
s->cursor_start = s->cr[VGA_CRTC_CURSOR_START]; s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
s->cursor_end = s->cr[VGA_CRTC_CURSOR_END]; s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
@ -2087,7 +2109,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
for (i = 0; i < size; src ++, dst ++, i ++) for (i = 0; i < size; src ++, dst ++, i ++)
console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src))); console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
dpy_update(s->ds, 0, 0, width, height); dpy_text_update(s->ds, 0, 0, width, height);
} else { } else {
c_max = 0; c_max = 0;
@ -2110,7 +2132,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
if (c_min <= c_max) { if (c_min <= c_max) {
i = TEXTMODE_Y(c_min); i = TEXTMODE_Y(c_min);
dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1); dpy_text_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
} }
} }
@ -2135,10 +2157,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
/* Display a message */ /* Display a message */
s->last_width = 60; s->last_width = 60;
s->last_height = height = 3; s->last_height = height = 3;
dpy_cursor(s->ds, -1, -1); dpy_text_cursor(s->ds, -1, -1);
s->ds->surface->width = s->last_width; dpy_text_resize(s->ds, s->last_width, height);
s->ds->surface->height = height;
dpy_resize(s->ds);
for (dst = chardata, i = 0; i < s->last_width * height; i ++) for (dst = chardata, i = 0; i < s->last_width * height; i ++)
console_write_ch(dst ++, ' '); console_write_ch(dst ++, ' ');
@ -2149,7 +2169,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
for (i = 0; i < size; i ++) for (i = 0; i < size; i ++)
console_write_ch(dst ++, 0x00200100 | msg_buffer[i]); console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
dpy_update(s->ds, 0, 0, s->last_width, height); dpy_text_update(s->ds, 0, 0, s->last_width, height);
} }
static uint64_t vga_mem_read(void *opaque, hwaddr addr, static uint64_t vga_mem_read(void *opaque, hwaddr addr,
@ -2373,13 +2393,12 @@ void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp) void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp)
{ {
int width = pixman_image_get_width(ds->image);
int height = pixman_image_get_height(ds->image);
FILE *f; FILE *f;
uint8_t *d, *d1; int y;
uint32_t v;
int y, x;
uint8_t r, g, b;
int ret; int ret;
char *linebuf, *pbuf; pixman_image_t *linebuf;
trace_ppm_save(filename, ds); trace_ppm_save(filename, ds);
f = fopen(filename, "wb"); f = fopen(filename, "wb");
@ -2388,33 +2407,17 @@ void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp)
strerror(errno)); strerror(errno));
return; return;
} }
ret = fprintf(f, "P6\n%d %d\n%d\n", ds->width, ds->height, 255); ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255);
if (ret < 0) { if (ret < 0) {
linebuf = NULL; linebuf = NULL;
goto write_err; goto write_err;
} }
linebuf = g_malloc(ds->width * 3); linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
d1 = ds->data; for (y = 0; y < height; y++) {
for(y = 0; y < ds->height; y++) { qemu_pixman_linebuf_fill(linebuf, ds->image, width, y);
d = d1;
pbuf = linebuf;
for(x = 0; x < ds->width; x++) {
if (ds->pf.bits_per_pixel == 32)
v = *(uint32_t *)d;
else
v = (uint32_t) (*(uint16_t *)d);
/* Limited to 8 or fewer bits per channel: */
r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits);
g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits);
b = ((v >> ds->pf.bshift) & ds->pf.bmax) << (8 - ds->pf.bbits);
*pbuf++ = r;
*pbuf++ = g;
*pbuf++ = b;
d += ds->pf.bytes_per_pixel;
}
d1 += ds->linesize;
clearerr(f); clearerr(f);
ret = fwrite(linebuf, 1, pbuf - linebuf, f); ret = fwrite(pixman_image_get_data(linebuf), 1,
pixman_image_get_stride(linebuf), f);
(void)ret; (void)ret;
if (ferror(f)) { if (ferror(f)) {
goto write_err; goto write_err;
@ -2422,7 +2425,7 @@ void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp)
} }
out: out:
g_free(linebuf); qemu_pixman_image_unref(linebuf);
fclose(f); fclose(f);
return; return;

View File

@ -154,6 +154,8 @@ typedef struct VGACommonState {
vga_hw_invalidate_ptr invalidate; vga_hw_invalidate_ptr invalidate;
vga_hw_screen_dump_ptr screen_dump; vga_hw_screen_dump_ptr screen_dump;
vga_hw_text_update_ptr text_update; vga_hw_text_update_ptr text_update;
bool full_update_text;
bool full_update_gfx;
/* hardware mouse cursor support */ /* hardware mouse cursor support */
uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32];
void (*cursor_invalidate)(struct VGACommonState *s); void (*cursor_invalidate)(struct VGACommonState *s);

View File

@ -321,14 +321,14 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
for (; line > 0; line --, src += bypl, dst += bypl) for (; line > 0; line --, src += bypl, dst += bypl)
memcpy(dst, src, width); memcpy(dst, src, width);
dpy_update(s->vga.ds, x, y, w, h); dpy_gfx_update(s->vga.ds, x, y, w, h);
} }
static inline void vmsvga_update_screen(struct vmsvga_state_s *s) static inline void vmsvga_update_screen(struct vmsvga_state_s *s)
{ {
memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr, memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr,
s->bypp * s->width * s->height); s->bypp * s->width * s->height);
dpy_update(s->vga.ds, 0, 0, s->width, s->height); dpy_gfx_update(s->vga.ds, 0, 0, s->width, s->height);
} }
static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s, static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
@ -478,8 +478,7 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
qc = cursor_builtin_left_ptr(); qc = cursor_builtin_left_ptr();
} }
if (s->vga.ds->cursor_define) dpy_cursor_define(s->vga.ds, qc);
s->vga.ds->cursor_define(qc);
cursor_put(qc); cursor_put(qc);
} }
#endif #endif
@ -754,9 +753,10 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
caps |= SVGA_CAP_RECT_FILL; caps |= SVGA_CAP_RECT_FILL;
#endif #endif
#ifdef HW_MOUSE_ACCEL #ifdef HW_MOUSE_ACCEL
if (s->vga.ds->mouse_set) if (dpy_cursor_define_supported(s->vga.ds)) {
caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 | caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 |
SVGA_CAP_CURSOR_BYPASS; SVGA_CAP_CURSOR_BYPASS;
}
#endif #endif
return caps; return caps;
@ -903,8 +903,9 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
s->cursor.on |= (value == SVGA_CURSOR_ON_SHOW); s->cursor.on |= (value == SVGA_CURSOR_ON_SHOW);
s->cursor.on &= (value != SVGA_CURSOR_ON_HIDE); s->cursor.on &= (value != SVGA_CURSOR_ON_HIDE);
#ifdef HW_MOUSE_ACCEL #ifdef HW_MOUSE_ACCEL
if (s->vga.ds->mouse_set && value <= SVGA_CURSOR_ON_SHOW) if (value <= SVGA_CURSOR_ON_SHOW) {
s->vga.ds->mouse_set(s->cursor.x, s->cursor.y, s->cursor.on); dpy_mouse_set(s->vga.ds, s->cursor.x, s->cursor.y, s->cursor.on);
}
#endif #endif
break; break;

View File

@ -717,7 +717,7 @@ static void xenfb_update(void *opaque)
if (xenfb_queue_full(xenfb)) if (xenfb_queue_full(xenfb))
return; return;
for (l = xenfb->c.ds->listeners; l != NULL; l = l->next) { QLIST_FOREACH(l, &xenfb->c.ds->listeners, next) {
if (l->idle) if (l->idle)
continue; continue;
idle = 0; idle = 0;

1
pixman Submodule

@ -0,0 +1 @@
Subproject commit 97336fad32acf802003855cd8bd6477fa49a12e3

View File

@ -261,10 +261,8 @@ typedef struct DriveInfo DriveInfo;
typedef struct DisplayState DisplayState; typedef struct DisplayState DisplayState;
typedef struct DisplayChangeListener DisplayChangeListener; typedef struct DisplayChangeListener DisplayChangeListener;
typedef struct DisplaySurface DisplaySurface; typedef struct DisplaySurface DisplaySurface;
typedef struct DisplayAllocator DisplayAllocator;
typedef struct PixelFormat PixelFormat; typedef struct PixelFormat PixelFormat;
typedef struct TextConsole TextConsole; typedef struct QemuConsole QemuConsole;
typedef TextConsole QEMUConsole;
typedef struct CharDriverState CharDriverState; typedef struct CharDriverState CharDriverState;
typedef struct MACAddr MACAddr; typedef struct MACAddr MACAddr;
typedef struct NetClientState NetClientState; typedef struct NetClientState NetClientState;

60
qemu-pixman.c Normal file
View File

@ -0,0 +1,60 @@
#include "qemu-pixman.h"
int qemu_pixman_get_type(int rshift, int gshift, int bshift)
{
int type = PIXMAN_TYPE_OTHER;
if (rshift > gshift && gshift > bshift) {
if (bshift == 0) {
type = PIXMAN_TYPE_ARGB;
} else {
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0, 21, 8)
type = PIXMAN_TYPE_RGBA;
#endif
}
} else if (rshift < gshift && gshift < bshift) {
if (rshift == 0) {
type = PIXMAN_TYPE_ABGR;
} else {
type = PIXMAN_TYPE_BGRA;
}
}
return type;
}
pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf)
{
pixman_format_code_t format;
int type;
type = qemu_pixman_get_type(pf->rshift, pf->gshift, pf->bshift);
format = PIXMAN_FORMAT(pf->bits_per_pixel, type,
pf->abits, pf->rbits, pf->gbits, pf->bbits);
if (!pixman_format_supported_source(format)) {
return 0;
}
return format;
}
pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format,
int width)
{
pixman_image_t *image = pixman_image_create_bits(format, width, 1, NULL, 0);
assert(image != NULL);
return image;
}
void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb,
int width, int y)
{
pixman_image_composite(PIXMAN_OP_SRC, fb, NULL, linebuf,
0, y, 0, 0, 0, 0, width, 1);
}
void qemu_pixman_image_unref(pixman_image_t *image)
{
if (image == NULL) {
return;
}
pixman_image_unref(image);
}

32
qemu-pixman.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef QEMU_PIXMAN_H
#define QEMU_PIXMAN_H
#include <pixman.h>
#include "console.h"
/*
* pixman image formats are defined to be native endian,
* that means host byte order on qemu. So we go define
* fixed formats here for cases where it is needed, like
* feeding libjpeg / libpng and writing screenshots.
*/
#ifdef HOST_WORDS_BIGENDIAN
# define PIXMAN_BE_r8g8b8 PIXMAN_r8g8b8
#else
# define PIXMAN_BE_r8g8b8 PIXMAN_b8g8r8
#endif
/* -------------------------------------------------------------------- */
int qemu_pixman_get_type(int rshift, int gshift, int bshift);
pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf);
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 y);
void qemu_pixman_image_unref(pixman_image_t *image);
#endif /* QEMU_PIXMAN_H */

View File

@ -95,17 +95,16 @@ static void curses_calc_pad(void)
} }
} }
static void curses_resize(DisplayState *ds) static void curses_resize(DisplayState *ds, int width, int height)
{ {
if (ds_get_width(ds) == gwidth && ds_get_height(ds) == gheight) if (width == gwidth && height == gheight) {
return; return;
}
gwidth = ds_get_width(ds); gwidth = width;
gheight = ds_get_height(ds); gheight = height;
curses_calc_pad(); curses_calc_pad();
ds->surface->width = width * FONT_WIDTH;
ds->surface->height = height * FONT_HEIGHT;
} }
#ifndef _WIN32 #ifndef _WIN32
@ -167,8 +166,6 @@ static void curses_refresh(DisplayState *ds)
clear(); clear();
refresh(); refresh();
curses_calc_pad(); curses_calc_pad();
ds->surface->width = FONT_WIDTH * width;
ds->surface->height = FONT_HEIGHT * height;
vga_hw_invalidate(); vga_hw_invalidate();
invalidate = 0; invalidate = 0;
} }
@ -195,8 +192,6 @@ static void curses_refresh(DisplayState *ds)
refresh(); refresh();
curses_calc_pad(); curses_calc_pad();
curses_update(ds, 0, 0, width, height); curses_update(ds, 0, 0, width, height);
ds->surface->width = FONT_WIDTH * width;
ds->surface->height = FONT_HEIGHT * height;
continue; continue;
} }
#endif #endif
@ -355,13 +350,11 @@ void curses_display_init(DisplayState *ds, int full_screen)
#endif #endif
dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener)); dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener));
dcl->dpy_update = curses_update; dcl->dpy_text_update = curses_update;
dcl->dpy_resize = curses_resize; dcl->dpy_text_resize = curses_resize;
dcl->dpy_refresh = curses_refresh; dcl->dpy_refresh = curses_refresh;
dcl->dpy_text_cursor = curses_cursor_position; dcl->dpy_text_cursor = curses_cursor_position;
register_displaychangelistener(ds, dcl); register_displaychangelistener(ds, dcl);
qemu_free_displaysurface(ds);
ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen);
invalidate = 1; invalidate = 1;
} }

140
ui/sdl.c
View File

@ -55,7 +55,6 @@ static int absolute_enabled = 0;
static int guest_cursor = 0; static int guest_cursor = 0;
static int guest_x, guest_y; static int guest_x, guest_y;
static SDL_Cursor *guest_sprite = NULL; static SDL_Cursor *guest_sprite = NULL;
static uint8_t allocator;
static SDL_PixelFormat host_format; static SDL_PixelFormat host_format;
static int scaling_active = 0; static int scaling_active = 0;
static Notifier mouse_mode_notifier; static Notifier mouse_mode_notifier;
@ -117,108 +116,13 @@ static void do_sdl_resize(int width, int height, int bpp)
static void sdl_resize(DisplayState *ds) static void sdl_resize(DisplayState *ds)
{ {
if (!allocator) { if (!scaling_active) {
if (!scaling_active) do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); } else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds)) {
else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds)) do_sdl_resize(real_screen->w, real_screen->h,
do_sdl_resize(real_screen->w, real_screen->h, ds_get_bits_per_pixel(ds)); ds_get_bits_per_pixel(ds));
sdl_setdata(ds);
} else {
if (guest_screen != NULL) {
SDL_FreeSurface(guest_screen);
guest_screen = NULL;
}
} }
} sdl_setdata(ds);
static PixelFormat sdl_to_qemu_pixelformat(SDL_PixelFormat *sdl_pf)
{
PixelFormat qemu_pf;
memset(&qemu_pf, 0x00, sizeof(PixelFormat));
qemu_pf.bits_per_pixel = sdl_pf->BitsPerPixel;
qemu_pf.bytes_per_pixel = sdl_pf->BytesPerPixel;
qemu_pf.depth = (qemu_pf.bits_per_pixel) == 32 ? 24 : (qemu_pf.bits_per_pixel);
qemu_pf.rmask = sdl_pf->Rmask;
qemu_pf.gmask = sdl_pf->Gmask;
qemu_pf.bmask = sdl_pf->Bmask;
qemu_pf.amask = sdl_pf->Amask;
qemu_pf.rshift = sdl_pf->Rshift;
qemu_pf.gshift = sdl_pf->Gshift;
qemu_pf.bshift = sdl_pf->Bshift;
qemu_pf.ashift = sdl_pf->Ashift;
qemu_pf.rbits = 8 - sdl_pf->Rloss;
qemu_pf.gbits = 8 - sdl_pf->Gloss;
qemu_pf.bbits = 8 - sdl_pf->Bloss;
qemu_pf.abits = 8 - sdl_pf->Aloss;
qemu_pf.rmax = ((1 << qemu_pf.rbits) - 1);
qemu_pf.gmax = ((1 << qemu_pf.gbits) - 1);
qemu_pf.bmax = ((1 << qemu_pf.bbits) - 1);
qemu_pf.amax = ((1 << qemu_pf.abits) - 1);
return qemu_pf;
}
static DisplaySurface* sdl_create_displaysurface(int width, int height)
{
DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
surface->width = width;
surface->height = height;
if (scaling_active) {
int linesize;
PixelFormat pf;
if (host_format.BytesPerPixel != 2 && host_format.BytesPerPixel != 4) {
linesize = width * 4;
pf = qemu_default_pixelformat(32);
} else {
linesize = width * host_format.BytesPerPixel;
pf = sdl_to_qemu_pixelformat(&host_format);
}
qemu_alloc_display(surface, width, height, linesize, pf, 0);
return surface;
}
if (host_format.BitsPerPixel == 16)
do_sdl_resize(width, height, 16);
else
do_sdl_resize(width, height, 32);
surface->pf = sdl_to_qemu_pixelformat(real_screen->format);
surface->linesize = real_screen->pitch;
surface->data = real_screen->pixels;
#ifdef HOST_WORDS_BIGENDIAN
surface->flags = QEMU_REALPIXELS_FLAG | QEMU_BIG_ENDIAN_FLAG;
#else
surface->flags = QEMU_REALPIXELS_FLAG;
#endif
allocator = 1;
return surface;
}
static void sdl_free_displaysurface(DisplaySurface *surface)
{
allocator = 0;
if (surface == NULL)
return;
if (surface->flags & QEMU_ALLOCATED_FLAG)
g_free(surface->data);
g_free(surface);
}
static DisplaySurface* sdl_resize_displaysurface(DisplaySurface *surface, int width, int height)
{
sdl_free_displaysurface(surface);
return sdl_create_displaysurface(width, height);
} }
/* generic keyboard conversion */ /* generic keyboard conversion */
@ -553,7 +457,7 @@ static void sdl_scale(DisplayState *ds, int width, int height)
if (!is_buffer_shared(ds->surface)) { if (!is_buffer_shared(ds->surface)) {
ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds), ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds),
ds_get_height(ds)); ds_get_height(ds));
dpy_resize(ds); dpy_gfx_resize(ds);
} }
} }
@ -899,13 +803,7 @@ static void sdl_refresh(DisplayState *ds)
} }
} }
static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c) static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on)
{
SDL_Rect dst = { x, y, w, h };
SDL_FillRect(real_screen, &dst, c);
}
static void sdl_mouse_warp(int x, int y, int on)
{ {
if (on) { if (on) {
if (!guest_cursor) if (!guest_cursor)
@ -921,7 +819,7 @@ static void sdl_mouse_warp(int x, int y, int on)
guest_x = x, guest_y = y; guest_x = x, guest_y = y;
} }
static void sdl_mouse_define(QEMUCursor *c) static void sdl_mouse_define(DisplayState *ds, QEMUCursor *c)
{ {
uint8_t *image, *mask; uint8_t *image, *mask;
int bpl; int bpl;
@ -955,7 +853,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
{ {
int flags; int flags;
uint8_t data = 0; uint8_t data = 0;
DisplayAllocator *da;
const SDL_VideoInfo *vi; const SDL_VideoInfo *vi;
char *filename; char *filename;
@ -1020,23 +917,14 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
} }
dcl = g_malloc0(sizeof(DisplayChangeListener)); dcl = g_malloc0(sizeof(DisplayChangeListener));
dcl->dpy_update = sdl_update; dcl->dpy_gfx_update = sdl_update;
dcl->dpy_resize = sdl_resize; dcl->dpy_gfx_resize = sdl_resize;
dcl->dpy_refresh = sdl_refresh; dcl->dpy_refresh = sdl_refresh;
dcl->dpy_setdata = sdl_setdata; dcl->dpy_gfx_setdata = sdl_setdata;
dcl->dpy_fill = sdl_fill; dcl->dpy_mouse_set = sdl_mouse_warp;
ds->mouse_set = sdl_mouse_warp; dcl->dpy_cursor_define = sdl_mouse_define;
ds->cursor_define = sdl_mouse_define;
register_displaychangelistener(ds, dcl); register_displaychangelistener(ds, dcl);
da = g_malloc0(sizeof(DisplayAllocator));
da->create_displaysurface = sdl_create_displaysurface;
da->resize_displaysurface = sdl_resize_displaysurface;
da->free_displaysurface = sdl_free_displaysurface;
if (register_displayallocator(ds, da) == da) {
dpy_resize(ds);
}
mouse_mode_notifier.notify = sdl_mouse_mode_change; mouse_mode_notifier.notify = sdl_mouse_mode_change;
qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier); qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier);

View File

@ -404,12 +404,12 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd) void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
{ {
if (ssd->cursor) { if (ssd->cursor) {
ssd->ds->cursor_define(ssd->cursor); dpy_cursor_define(ssd->ds, ssd->cursor);
cursor_put(ssd->cursor); cursor_put(ssd->cursor);
ssd->cursor = NULL; ssd->cursor = NULL;
} }
if (ssd->mouse_x != -1 && ssd->mouse_y != -1) { if (ssd->mouse_x != -1 && ssd->mouse_y != -1) {
ssd->ds->mouse_set(ssd->mouse_x, ssd->mouse_y, 1); dpy_mouse_set(ssd->ds, ssd->mouse_x, ssd->mouse_y, 1);
ssd->mouse_x = -1; ssd->mouse_x = -1;
ssd->mouse_y = -1; ssd->mouse_y = -1;
} }
@ -571,8 +571,8 @@ static void display_refresh(struct DisplayState *ds)
} }
static DisplayChangeListener display_listener = { static DisplayChangeListener display_listener = {
.dpy_update = display_update, .dpy_gfx_update = display_update,
.dpy_resize = display_resize, .dpy_gfx_resize = display_resize,
.dpy_refresh = display_refresh, .dpy_refresh = display_refresh,
}; };

View File

@ -14,7 +14,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
int *has_bg, int *has_fg) int *has_bg, int *has_fg)
{ {
VncDisplay *vd = vs->vd; VncDisplay *vd = vs->vd;
uint8_t *row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds); uint8_t *row = vnc_server_fb_ptr(vd, x, y);
pixel_t *irow = (pixel_t *)row; pixel_t *irow = (pixel_t *)row;
int j, i; int j, i;
pixel_t *last_bg = (pixel_t *)last_bg_; pixel_t *last_bg = (pixel_t *)last_bg_;
@ -25,7 +25,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
int bg_count = 0; int bg_count = 0;
int fg_count = 0; int fg_count = 0;
int flags = 0; int flags = 0;
uint8_t data[(vs->clientds.pf.bytes_per_pixel + 2) * 16 * 16]; uint8_t data[(vs->client_pf.bytes_per_pixel + 2) * 16 * 16];
int n_data = 0; int n_data = 0;
int n_subtiles = 0; int n_subtiles = 0;
@ -58,7 +58,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
} }
if (n_colors > 2) if (n_colors > 2)
break; break;
irow += ds_get_linesize(vs->ds) / sizeof(pixel_t); irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
} }
if (n_colors > 1 && fg_count > bg_count) { if (n_colors > 1 && fg_count > bg_count) {
@ -106,7 +106,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
n_data += 2; n_data += 2;
n_subtiles++; n_subtiles++;
} }
irow += ds_get_linesize(vs->ds) / sizeof(pixel_t); irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
} }
break; break;
case 3: case 3:
@ -133,7 +133,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
has_color = 0; has_color = 0;
#ifdef GENERIC #ifdef GENERIC
vnc_convert_pixel(vs, data + n_data, color); vnc_convert_pixel(vs, data + n_data, color);
n_data += vs->clientds.pf.bytes_per_pixel; n_data += vs->client_pf.bytes_per_pixel;
#else #else
memcpy(data + n_data, &color, sizeof(color)); memcpy(data + n_data, &color, sizeof(color));
n_data += sizeof(pixel_t); n_data += sizeof(pixel_t);
@ -153,7 +153,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
if (has_color) { if (has_color) {
#ifdef GENERIC #ifdef GENERIC
vnc_convert_pixel(vs, data + n_data, color); vnc_convert_pixel(vs, data + n_data, color);
n_data += vs->clientds.pf.bytes_per_pixel; n_data += vs->client_pf.bytes_per_pixel;
#else #else
memcpy(data + n_data, &color, sizeof(color)); memcpy(data + n_data, &color, sizeof(color));
n_data += sizeof(pixel_t); n_data += sizeof(pixel_t);
@ -162,7 +162,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
n_data += 2; n_data += 2;
n_subtiles++; n_subtiles++;
} }
irow += ds_get_linesize(vs->ds) / sizeof(pixel_t); irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
} }
/* A SubrectsColoured subtile invalidates the foreground color */ /* A SubrectsColoured subtile invalidates the foreground color */
@ -190,18 +190,17 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
vnc_write_u8(vs, flags); vnc_write_u8(vs, flags);
if (n_colors < 4) { if (n_colors < 4) {
if (flags & 0x02) if (flags & 0x02)
vs->write_pixels(vs, &vd->server->pf, last_bg, sizeof(pixel_t)); vs->write_pixels(vs, last_bg, sizeof(pixel_t));
if (flags & 0x04) if (flags & 0x04)
vs->write_pixels(vs, &vd->server->pf, last_fg, sizeof(pixel_t)); vs->write_pixels(vs, last_fg, sizeof(pixel_t));
if (n_subtiles) { if (n_subtiles) {
vnc_write_u8(vs, n_subtiles); vnc_write_u8(vs, n_subtiles);
vnc_write(vs, data, n_data); vnc_write(vs, data, n_data);
} }
} else { } else {
for (j = 0; j < h; j++) { for (j = 0; j < h; j++) {
vs->write_pixels(vs, &vd->server->pf, row, vs->write_pixels(vs, row, w * 4);
w * ds_get_bytes_per_pixel(vs->ds)); row += vnc_server_fb_stride(vd);
row += ds_get_linesize(vs->ds);
} }
} }
} }

View File

@ -32,30 +32,10 @@ static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F); ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
} }
#define BPP 8
#include "vnc-enc-hextile-template.h"
#undef BPP
#define BPP 16
#include "vnc-enc-hextile-template.h"
#undef BPP
#define BPP 32 #define BPP 32
#include "vnc-enc-hextile-template.h" #include "vnc-enc-hextile-template.h"
#undef BPP #undef BPP
#define GENERIC
#define BPP 8
#include "vnc-enc-hextile-template.h"
#undef BPP
#undef GENERIC
#define GENERIC
#define BPP 16
#include "vnc-enc-hextile-template.h"
#undef BPP
#undef GENERIC
#define GENERIC #define GENERIC
#define BPP 32 #define BPP 32
#include "vnc-enc-hextile-template.h" #include "vnc-enc-hextile-template.h"
@ -68,10 +48,9 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
int i, j; int i, j;
int has_fg, has_bg; int has_fg, has_bg;
uint8_t *last_fg, *last_bg; uint8_t *last_fg, *last_bg;
VncDisplay *vd = vs->vd;
last_fg = (uint8_t *) g_malloc(vd->server->pf.bytes_per_pixel); last_fg = (uint8_t *) g_malloc(VNC_SERVER_FB_BYTES);
last_bg = (uint8_t *) g_malloc(vd->server->pf.bytes_per_pixel); last_bg = (uint8_t *) g_malloc(VNC_SERVER_FB_BYTES);
has_fg = has_bg = 0; has_fg = has_bg = 0;
for (j = y; j < (y + h); j += 16) { for (j = y; j < (y + h); j += 16) {
for (i = x; i < (x + w); i += 16) { for (i = x; i < (x + w); i += 16) {
@ -89,28 +68,16 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
void vnc_hextile_set_pixel_conversion(VncState *vs, int generic) void vnc_hextile_set_pixel_conversion(VncState *vs, int generic)
{ {
if (!generic) { if (!generic) {
switch (vs->ds->surface->pf.bits_per_pixel) { switch (VNC_SERVER_FB_BITS) {
case 8: case 32:
vs->hextile.send_tile = send_hextile_tile_8; vs->hextile.send_tile = send_hextile_tile_32;
break; break;
case 16:
vs->hextile.send_tile = send_hextile_tile_16;
break;
case 32:
vs->hextile.send_tile = send_hextile_tile_32;
break;
} }
} else { } else {
switch (vs->ds->surface->pf.bits_per_pixel) { switch (VNC_SERVER_FB_BITS) {
case 8: case 32:
vs->hextile.send_tile = send_hextile_tile_generic_8; vs->hextile.send_tile = send_hextile_tile_generic_32;
break; break;
case 16:
vs->hextile.send_tile = send_hextile_tile_generic_16;
break;
case 32:
vs->hextile.send_tile = send_hextile_tile_generic_32;
break;
} }
} }
} }

View File

@ -124,7 +124,7 @@ static bool tight_can_send_png_rect(VncState *vs, int w, int h)
} }
if (ds_get_bytes_per_pixel(vs->ds) == 1 || if (ds_get_bytes_per_pixel(vs->ds) == 1 ||
vs->clientds.pf.bytes_per_pixel == 1) { vs->client_pf.bytes_per_pixel == 1) {
return false; return false;
} }
@ -153,7 +153,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
* If client is big-endian, color samples begin from the second * If client is big-endian, color samples begin from the second
* byte (offset 1) of a 32-bit pixel value. * byte (offset 1) of a 32-bit pixel value.
*/ */
off = !!(vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG); off = vs->client_be;
memset(stats, 0, sizeof (stats)); memset(stats, 0, sizeof (stats));
@ -216,16 +216,16 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
unsigned int errors; \ unsigned int errors; \
unsigned char *buf = vs->tight.tight.buffer; \ unsigned char *buf = vs->tight.tight.buffer; \
\ \
endian = ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \ endian = 0; /* FIXME: ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); \ (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); */ \
\ \
\ \
max[0] = vs->clientds.pf.rmax; \ max[0] = vs->client_pf.rmax; \
max[1] = vs->clientds.pf.gmax; \ max[1] = vs->client_pf.gmax; \
max[2] = vs->clientds.pf.bmax; \ max[2] = vs->client_pf.bmax; \
shift[0] = vs->clientds.pf.rshift; \ shift[0] = vs->client_pf.rshift; \
shift[1] = vs->clientds.pf.gshift; \ shift[1] = vs->client_pf.gshift; \
shift[2] = vs->clientds.pf.bshift; \ shift[2] = vs->client_pf.bshift; \
\ \
memset(stats, 0, sizeof(stats)); \ memset(stats, 0, sizeof(stats)); \
\ \
@ -302,7 +302,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h)
} }
if (ds_get_bytes_per_pixel(vs->ds) == 1 || if (ds_get_bytes_per_pixel(vs->ds) == 1 ||
vs->clientds.pf.bytes_per_pixel == 1 || vs->client_pf.bytes_per_pixel == 1 ||
w < VNC_TIGHT_DETECT_MIN_WIDTH || h < VNC_TIGHT_DETECT_MIN_HEIGHT) { w < VNC_TIGHT_DETECT_MIN_WIDTH || h < VNC_TIGHT_DETECT_MIN_HEIGHT) {
return 0; return 0;
} }
@ -317,7 +317,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h)
} }
} }
if (vs->clientds.pf.bytes_per_pixel == 4) { if (vs->client_pf.bytes_per_pixel == 4) {
if (vs->tight.pixel24) { if (vs->tight.pixel24) {
errors = tight_detect_smooth_image24(vs, w, h); errors = tight_detect_smooth_image24(vs, w, h);
if (vs->tight.quality != (uint8_t)-1) { if (vs->tight.quality != (uint8_t)-1) {
@ -430,7 +430,7 @@ static int tight_fill_palette(VncState *vs, int x, int y,
max = 256; max = 256;
} }
switch(vs->clientds.pf.bytes_per_pixel) { switch (vs->client_pf.bytes_per_pixel) {
case 4: case 4:
return tight_fill_palette32(vs, x, y, max, count, bg, fg, palette); return tight_fill_palette32(vs, x, y, max, count, bg, fg, palette);
case 2: case 2:
@ -557,15 +557,15 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
buf32 = (uint32_t *)buf; buf32 = (uint32_t *)buf;
memset(vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); memset(vs->tight.gradient.buffer, 0, w * 3 * sizeof(int));
if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == if (1 /* FIXME: (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)) { (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) */) {
shift[0] = vs->clientds.pf.rshift; shift[0] = vs->client_pf.rshift;
shift[1] = vs->clientds.pf.gshift; shift[1] = vs->client_pf.gshift;
shift[2] = vs->clientds.pf.bshift; shift[2] = vs->client_pf.bshift;
} else { } else {
shift[0] = 24 - vs->clientds.pf.rshift; shift[0] = 24 - vs->client_pf.rshift;
shift[1] = 24 - vs->clientds.pf.gshift; shift[1] = 24 - vs->client_pf.gshift;
shift[2] = 24 - vs->clientds.pf.bshift; shift[2] = 24 - vs->client_pf.bshift;
} }
for (y = 0; y < h; y++) { for (y = 0; y < h; y++) {
@ -615,15 +615,15 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
\ \
memset (vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); \ memset (vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); \
\ \
endian = ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \ endian = 0; /* FIXME: ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); \ (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); */ \
\ \
max[0] = vs->clientds.pf.rmax; \ max[0] = vs->client_pf.rmax; \
max[1] = vs->clientds.pf.gmax; \ max[1] = vs->client_pf.gmax; \
max[2] = vs->clientds.pf.bmax; \ max[2] = vs->client_pf.bmax; \
shift[0] = vs->clientds.pf.rshift; \ shift[0] = vs->client_pf.rshift; \
shift[1] = vs->clientds.pf.gshift; \ shift[1] = vs->client_pf.gshift; \
shift[2] = vs->clientds.pf.bshift; \ shift[2] = vs->client_pf.bshift; \
\ \
for (y = 0; y < h; y++) { \ for (y = 0; y < h; y++) { \
for (c = 0; c < 3; c++) { \ for (c = 0; c < 3; c++) { \
@ -671,56 +671,42 @@ DEFINE_GRADIENT_FILTER_FUNCTION(32)
* that case new color will be stored in *colorPtr. * that case new color will be stored in *colorPtr.
*/ */
#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ static bool
\ check_solid_tile32(VncState *vs, int x, int y, int w, int h,
static bool \ uint32_t *color, bool samecolor)
check_solid_tile##bpp(VncState *vs, int x, int y, int w, int h, \ {
uint32_t* color, bool samecolor) \ VncDisplay *vd = vs->vd;
{ \ uint32_t *fbptr;
VncDisplay *vd = vs->vd; \ uint32_t c;
uint##bpp##_t *fbptr; \ int dx, dy;
uint##bpp##_t c; \
int dx, dy; \ fbptr = vnc_server_fb_ptr(vd, x, y);
\
fbptr = (uint##bpp##_t *) \ c = *fbptr;
(vd->server->data + y * ds_get_linesize(vs->ds) + \ if (samecolor && (uint32_t)c != *color) {
x * ds_get_bytes_per_pixel(vs->ds)); \ return false;
\
c = *fbptr; \
if (samecolor && (uint32_t)c != *color) { \
return false; \
} \
\
for (dy = 0; dy < h; dy++) { \
for (dx = 0; dx < w; dx++) { \
if (c != fbptr[dx]) { \
return false; \
} \
} \
fbptr = (uint##bpp##_t *) \
((uint8_t *)fbptr + ds_get_linesize(vs->ds)); \
} \
\
*color = (uint32_t)c; \
return true; \
} }
DEFINE_CHECK_SOLID_FUNCTION(32) for (dy = 0; dy < h; dy++) {
DEFINE_CHECK_SOLID_FUNCTION(16) for (dx = 0; dx < w; dx++) {
DEFINE_CHECK_SOLID_FUNCTION(8) if (c != fbptr[dx]) {
return false;
}
}
fbptr = (uint32_t *)
((uint8_t *)fbptr + vnc_server_fb_stride(vd));
}
*color = (uint32_t)c;
return true;
}
static bool check_solid_tile(VncState *vs, int x, int y, int w, int h, static bool check_solid_tile(VncState *vs, int x, int y, int w, int h,
uint32_t* color, bool samecolor) uint32_t* color, bool samecolor)
{ {
VncDisplay *vd = vs->vd; switch (VNC_SERVER_FB_BYTES) {
switch(vd->server->pf.bytes_per_pixel) {
case 4: case 4:
return check_solid_tile32(vs, x, y, w, h, color, samecolor); return check_solid_tile32(vs, x, y, w, h, color, samecolor);
case 2:
return check_solid_tile16(vs, x, y, w, h, color, samecolor);
default:
return check_solid_tile8(vs, x, y, w, h, color, samecolor);
} }
} }
@ -906,15 +892,15 @@ static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret)
buf32 = (uint32_t *)buf; buf32 = (uint32_t *)buf;
if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == if (1 /* FIXME: (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)) { (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) */) {
rshift = vs->clientds.pf.rshift; rshift = vs->client_pf.rshift;
gshift = vs->clientds.pf.gshift; gshift = vs->client_pf.gshift;
bshift = vs->clientds.pf.bshift; bshift = vs->client_pf.bshift;
} else { } else {
rshift = 24 - vs->clientds.pf.rshift; rshift = 24 - vs->client_pf.rshift;
gshift = 24 - vs->clientds.pf.gshift; gshift = 24 - vs->client_pf.gshift;
bshift = 24 - vs->clientds.pf.bshift; bshift = 24 - vs->client_pf.bshift;
} }
if (ret) { if (ret) {
@ -946,7 +932,7 @@ static int send_full_color_rect(VncState *vs, int x, int y, int w, int h)
tight_pack24(vs, vs->tight.tight.buffer, w * h, &vs->tight.tight.offset); tight_pack24(vs, vs->tight.tight.buffer, w * h, &vs->tight.tight.offset);
bytes = 3; bytes = 3;
} else { } else {
bytes = vs->clientds.pf.bytes_per_pixel; bytes = vs->client_pf.bytes_per_pixel;
} }
bytes = tight_compress_data(vs, stream, w * h * bytes, bytes = tight_compress_data(vs, stream, w * h * bytes,
@ -966,7 +952,7 @@ static int send_solid_rect(VncState *vs)
tight_pack24(vs, vs->tight.tight.buffer, 1, &vs->tight.tight.offset); tight_pack24(vs, vs->tight.tight.buffer, 1, &vs->tight.tight.offset);
bytes = 3; bytes = 3;
} else { } else {
bytes = vs->clientds.pf.bytes_per_pixel; bytes = vs->client_pf.bytes_per_pixel;
} }
vnc_write(vs, vs->tight.tight.buffer, bytes); vnc_write(vs, vs->tight.tight.buffer, bytes);
@ -983,7 +969,7 @@ static int send_mono_rect(VncState *vs, int x, int y,
#ifdef CONFIG_VNC_PNG #ifdef CONFIG_VNC_PNG
if (tight_can_send_png_rect(vs, w, h)) { if (tight_can_send_png_rect(vs, w, h)) {
int ret; int ret;
int bpp = vs->clientds.pf.bytes_per_pixel * 8; int bpp = vs->client_pf.bytes_per_pixel * 8;
VncPalette *palette = palette_new(2, bpp); VncPalette *palette = palette_new(2, bpp);
palette_put(palette, bg); palette_put(palette, bg);
@ -1000,7 +986,7 @@ static int send_mono_rect(VncState *vs, int x, int y,
vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE); vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE);
vnc_write_u8(vs, 1); vnc_write_u8(vs, 1);
switch(vs->clientds.pf.bytes_per_pixel) { switch (vs->client_pf.bytes_per_pixel) {
case 4: case 4:
{ {
uint32_t buf[2] = {bg, fg}; uint32_t buf[2] = {bg, fg};
@ -1043,7 +1029,7 @@ static void write_palette(int idx, uint32_t color, void *opaque)
{ {
struct palette_cb_priv *priv = opaque; struct palette_cb_priv *priv = opaque;
VncState *vs = priv->vs; VncState *vs = priv->vs;
uint32_t bytes = vs->clientds.pf.bytes_per_pixel; uint32_t bytes = vs->client_pf.bytes_per_pixel;
if (bytes == 4) { if (bytes == 4) {
((uint32_t*)priv->header)[idx] = color; ((uint32_t*)priv->header)[idx] = color;
@ -1058,8 +1044,9 @@ static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h)
int level = tight_conf[vs->tight.compression].gradient_zlib_level; int level = tight_conf[vs->tight.compression].gradient_zlib_level;
ssize_t bytes; ssize_t bytes;
if (vs->clientds.pf.bytes_per_pixel == 1) if (vs->client_pf.bytes_per_pixel == 1) {
return send_full_color_rect(vs, x, y, w, h); return send_full_color_rect(vs, x, y, w, h);
}
vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4); vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4);
vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT); vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT);
@ -1069,7 +1056,7 @@ static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h)
if (vs->tight.pixel24) { if (vs->tight.pixel24) {
tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h); tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h);
bytes = 3; bytes = 3;
} else if (vs->clientds.pf.bytes_per_pixel == 4) { } else if (vs->client_pf.bytes_per_pixel == 4) {
tight_filter_gradient32(vs, (uint32_t *)vs->tight.tight.buffer, w, h); tight_filter_gradient32(vs, (uint32_t *)vs->tight.tight.buffer, w, h);
bytes = 4; bytes = 4;
} else { } else {
@ -1107,7 +1094,7 @@ static int send_palette_rect(VncState *vs, int x, int y,
vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE); vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE);
vnc_write_u8(vs, colors - 1); vnc_write_u8(vs, colors - 1);
switch(vs->clientds.pf.bytes_per_pixel) { switch (vs->client_pf.bytes_per_pixel) {
case 4: case 4:
{ {
size_t old_offset, offset; size_t old_offset, offset;
@ -1148,79 +1135,6 @@ static int send_palette_rect(VncState *vs, int x, int y,
return (bytes >= 0); return (bytes >= 0);
} }
#if defined(CONFIG_VNC_JPEG) || defined(CONFIG_VNC_PNG)
static void rgb_prepare_row24(VncState *vs, uint8_t *dst, int x, int y,
int count)
{
VncDisplay *vd = vs->vd;
uint32_t *fbptr;
uint32_t pix;
fbptr = (uint32_t *)(vd->server->data + y * ds_get_linesize(vs->ds) +
x * ds_get_bytes_per_pixel(vs->ds));
while (count--) {
pix = *fbptr++;
*dst++ = (uint8_t)(pix >> vs->ds->surface->pf.rshift);
*dst++ = (uint8_t)(pix >> vs->ds->surface->pf.gshift);
*dst++ = (uint8_t)(pix >> vs->ds->surface->pf.bshift);
}
}
#define DEFINE_RGB_GET_ROW_FUNCTION(bpp) \
\
static void \
rgb_prepare_row##bpp(VncState *vs, uint8_t *dst, \
int x, int y, int count) \
{ \
VncDisplay *vd = vs->vd; \
uint##bpp##_t *fbptr; \
uint##bpp##_t pix; \
int r, g, b; \
\
fbptr = (uint##bpp##_t *) \
(vd->server->data + y * ds_get_linesize(vs->ds) + \
x * ds_get_bytes_per_pixel(vs->ds)); \
\
while (count--) { \
pix = *fbptr++; \
\
r = (int)((pix >> vs->ds->surface->pf.rshift) \
& vs->ds->surface->pf.rmax); \
g = (int)((pix >> vs->ds->surface->pf.gshift) \
& vs->ds->surface->pf.gmax); \
b = (int)((pix >> vs->ds->surface->pf.bshift) \
& vs->ds->surface->pf.bmax); \
\
*dst++ = (uint8_t)((r * 255 + vs->ds->surface->pf.rmax / 2) \
/ vs->ds->surface->pf.rmax); \
*dst++ = (uint8_t)((g * 255 + vs->ds->surface->pf.gmax / 2) \
/ vs->ds->surface->pf.gmax); \
*dst++ = (uint8_t)((b * 255 + vs->ds->surface->pf.bmax / 2) \
/ vs->ds->surface->pf.bmax); \
} \
}
DEFINE_RGB_GET_ROW_FUNCTION(16)
DEFINE_RGB_GET_ROW_FUNCTION(32)
static void rgb_prepare_row(VncState *vs, uint8_t *dst, int x, int y,
int count)
{
if (ds_get_bytes_per_pixel(vs->ds) == 4) {
if (vs->ds->surface->pf.rmax == 0xFF &&
vs->ds->surface->pf.gmax == 0xFF &&
vs->ds->surface->pf.bmax == 0xFF) {
rgb_prepare_row24(vs, dst, x, y, count);
} else {
rgb_prepare_row32(vs, dst, x, y, count);
}
} else {
rgb_prepare_row16(vs, dst, x, y, count);
}
}
#endif /* CONFIG_VNC_JPEG or CONFIG_VNC_PNG */
/* /*
* JPEG compression stuff. * JPEG compression stuff.
*/ */
@ -1265,6 +1179,7 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality)
struct jpeg_compress_struct cinfo; struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr; struct jpeg_error_mgr jerr;
struct jpeg_destination_mgr manager; struct jpeg_destination_mgr manager;
pixman_image_t *linebuf;
JSAMPROW row[1]; JSAMPROW row[1];
uint8_t *buf; uint8_t *buf;
int dy; int dy;
@ -1293,13 +1208,14 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality)
jpeg_start_compress(&cinfo, true); jpeg_start_compress(&cinfo, true);
buf = g_malloc(w * 3); linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w);
buf = (uint8_t *)pixman_image_get_data(linebuf);
row[0] = buf; row[0] = buf;
for (dy = 0; dy < h; dy++) { for (dy = 0; dy < h; dy++) {
rgb_prepare_row(vs, buf, x, y + dy, w); qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, dy);
jpeg_write_scanlines(&cinfo, row, 1); jpeg_write_scanlines(&cinfo, row, 1);
} }
g_free(buf); qemu_pixman_image_unref(linebuf);
jpeg_finish_compress(&cinfo); jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo); jpeg_destroy_compress(&cinfo);
@ -1326,23 +1242,23 @@ static void write_png_palette(int idx, uint32_t pix, void *opaque)
if (vs->tight.pixel24) if (vs->tight.pixel24)
{ {
color->red = (pix >> vs->clientds.pf.rshift) & vs->clientds.pf.rmax; color->red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax;
color->green = (pix >> vs->clientds.pf.gshift) & vs->clientds.pf.gmax; color->green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax;
color->blue = (pix >> vs->clientds.pf.bshift) & vs->clientds.pf.bmax; color->blue = (pix >> vs->client_pf.bshift) & vs->client_pf.bmax;
} }
else else
{ {
int red, green, blue; int red, green, blue;
red = (pix >> vs->clientds.pf.rshift) & vs->clientds.pf.rmax; red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax;
green = (pix >> vs->clientds.pf.gshift) & vs->clientds.pf.gmax; green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax;
blue = (pix >> vs->clientds.pf.bshift) & vs->clientds.pf.bmax; blue = (pix >> vs->client_pf.bshift) & vs->client_pf.bmax;
color->red = ((red * 255 + vs->clientds.pf.rmax / 2) / color->red = ((red * 255 + vs->client_pf.rmax / 2) /
vs->clientds.pf.rmax); vs->client_pf.rmax);
color->green = ((green * 255 + vs->clientds.pf.gmax / 2) / color->green = ((green * 255 + vs->client_pf.gmax / 2) /
vs->clientds.pf.gmax); vs->client_pf.gmax);
color->blue = ((blue * 255 + vs->clientds.pf.bmax / 2) / color->blue = ((blue * 255 + vs->client_pf.bmax / 2) /
vs->clientds.pf.bmax); vs->client_pf.bmax);
} }
} }
@ -1378,6 +1294,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h,
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
png_colorp png_palette = NULL; png_colorp png_palette = NULL;
pixman_image_t *linebuf;
int level = tight_png_conf[vs->tight.compression].png_zlib_level; int level = tight_png_conf[vs->tight.compression].png_zlib_level;
int filters = tight_png_conf[vs->tight.compression].png_filters; int filters = tight_png_conf[vs->tight.compression].png_filters;
uint8_t *buf; uint8_t *buf;
@ -1422,7 +1339,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h,
png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette));
if (vs->clientds.pf.bytes_per_pixel == 4) { if (vs->client_pf.bytes_per_pixel == 4) {
tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette);
} else { } else {
tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette);
@ -1432,17 +1349,18 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h,
png_write_info(png_ptr, info_ptr); png_write_info(png_ptr, info_ptr);
buffer_reserve(&vs->tight.png, 2048); buffer_reserve(&vs->tight.png, 2048);
buf = g_malloc(w * 3); linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w);
buf = (uint8_t *)pixman_image_get_data(linebuf);
for (dy = 0; dy < h; dy++) for (dy = 0; dy < h; dy++)
{ {
if (color_type == PNG_COLOR_TYPE_PALETTE) { if (color_type == PNG_COLOR_TYPE_PALETTE) {
memcpy(buf, vs->tight.tight.buffer + (dy * w), w); memcpy(buf, vs->tight.tight.buffer + (dy * w), w);
} else { } else {
rgb_prepare_row(vs, buf, x, y + dy, w); qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, dy);
} }
png_write_row(png_ptr, buf); png_write_row(png_ptr, buf);
} }
g_free(buf); qemu_pixman_image_unref(linebuf);
png_write_end(png_ptr, NULL); png_write_end(png_ptr, NULL);
@ -1713,8 +1631,8 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y,
{ {
int max_rows; int max_rows;
if (vs->clientds.pf.bytes_per_pixel == 4 && vs->clientds.pf.rmax == 0xFF && if (vs->client_pf.bytes_per_pixel == 4 && vs->client_pf.rmax == 0xFF &&
vs->clientds.pf.bmax == 0xFF && vs->clientds.pf.gmax == 0xFF) { vs->client_pf.bmax == 0xFF && vs->client_pf.gmax == 0xFF) {
vs->tight.pixel24 = true; vs->tight.pixel24 = true;
} else { } else {
vs->tight.pixel24 = false; vs->tight.pixel24 = false;

View File

@ -255,7 +255,7 @@ static void zrle_write_u8(VncState *vs, uint8_t value)
static int zrle_send_framebuffer_update(VncState *vs, int x, int y, static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
int w, int h) int w, int h)
{ {
bool be = !!(vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG); bool be = vs->client_be;
size_t bytes; size_t bytes;
int zywrle_level; int zywrle_level;
@ -277,13 +277,13 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
vnc_zrle_start(vs); vnc_zrle_start(vs);
switch(vs->clientds.pf.bytes_per_pixel) { switch (vs->client_pf.bytes_per_pixel) {
case 1: case 1:
zrle_encode_8ne(vs, x, y, w, h, zywrle_level); zrle_encode_8ne(vs, x, y, w, h, zywrle_level);
break; break;
case 2: case 2:
if (vs->clientds.pf.gmax > 0x1F) { if (vs->client_pf.gmax > 0x1F) {
if (be) { if (be) {
zrle_encode_16be(vs, x, y, w, h, zywrle_level); zrle_encode_16be(vs, x, y, w, h, zywrle_level);
} else { } else {
@ -304,13 +304,13 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
bool fits_in_ms3bytes; bool fits_in_ms3bytes;
fits_in_ls3bytes = fits_in_ls3bytes =
((vs->clientds.pf.rmax << vs->clientds.pf.rshift) < (1 << 24) && ((vs->client_pf.rmax << vs->client_pf.rshift) < (1 << 24) &&
(vs->clientds.pf.gmax << vs->clientds.pf.gshift) < (1 << 24) && (vs->client_pf.gmax << vs->client_pf.gshift) < (1 << 24) &&
(vs->clientds.pf.bmax << vs->clientds.pf.bshift) < (1 << 24)); (vs->client_pf.bmax << vs->client_pf.bshift) < (1 << 24));
fits_in_ms3bytes = (vs->clientds.pf.rshift > 7 && fits_in_ms3bytes = (vs->client_pf.rshift > 7 &&
vs->clientds.pf.gshift > 7 && vs->client_pf.gshift > 7 &&
vs->clientds.pf.bshift > 7); vs->client_pf.bshift > 7);
if ((fits_in_ls3bytes && !be) || (fits_in_ms3bytes && be)) { if ((fits_in_ls3bytes && !be) || (fits_in_ms3bytes && be)) {
if (be) { if (be) {

View File

@ -187,7 +187,8 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
local->vd = orig->vd; local->vd = orig->vd;
local->lossy_rect = orig->lossy_rect; local->lossy_rect = orig->lossy_rect;
local->write_pixels = orig->write_pixels; local->write_pixels = orig->write_pixels;
local->clientds = orig->clientds; local->client_pf = orig->client_pf;
local->client_be = orig->client_be;
local->tight = orig->tight; local->tight = orig->tight;
local->zlib = orig->zlib; local->zlib = orig->zlib;
local->hextile = orig->hextile; local->hextile = orig->hextile;

255
ui/vnc.c
View File

@ -436,6 +436,8 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
int i; int i;
VncDisplay *vd = ds->opaque; VncDisplay *vd = ds->opaque;
struct VncSurface *s = &vd->guest; struct VncSurface *s = &vd->guest;
int width = ds_get_width(ds);
int height = ds_get_height(ds);
h += y; h += y;
@ -446,10 +448,10 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
w += (x % 16); w += (x % 16);
x -= (x % 16); x -= (x % 16);
x = MIN(x, s->ds->width); x = MIN(x, width);
y = MIN(y, s->ds->height); y = MIN(y, height);
w = MIN(x + w, s->ds->width) - x; w = MIN(x + w, width) - x;
h = MIN(h, s->ds->height); h = MIN(h, height);
for (; y < h; y++) for (; y < h; y++)
for (i = 0; i < w; i += 16) for (i = 0; i < w; i += 16)
@ -550,6 +552,21 @@ static void vnc_abort_display_jobs(VncDisplay *vd)
} }
} }
int vnc_server_fb_stride(VncDisplay *vd)
{
return pixman_image_get_stride(vd->server);
}
void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
{
uint8_t *ptr;
ptr = (uint8_t *)pixman_image_get_data(vd->server);
ptr += y * vnc_server_fb_stride(vd);
ptr += x * VNC_SERVER_FB_BYTES;
return ptr;
}
static void vnc_dpy_resize(DisplayState *ds) static void vnc_dpy_resize(DisplayState *ds)
{ {
VncDisplay *vd = ds->opaque; VncDisplay *vd = ds->opaque;
@ -558,20 +575,20 @@ static void vnc_dpy_resize(DisplayState *ds)
vnc_abort_display_jobs(vd); vnc_abort_display_jobs(vd);
/* server surface */ /* server surface */
if (!vd->server) qemu_pixman_image_unref(vd->server);
vd->server = g_malloc0(sizeof(*vd->server)); vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT,
if (vd->server->data) ds_get_width(ds),
g_free(vd->server->data); ds_get_height(ds),
*(vd->server) = *(ds->surface); NULL, 0);
vd->server->data = g_malloc0(vd->server->linesize *
vd->server->height);
/* guest surface */ /* guest surface */
if (!vd->guest.ds) #if 0 /* FIXME */
vd->guest.ds = g_malloc0(sizeof(*vd->guest.ds));
if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel) if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel)
console_color_init(ds); console_color_init(ds);
*(vd->guest.ds) = *(ds->surface); #endif
qemu_pixman_image_unref(vd->guest.fb);
vd->guest.fb = pixman_image_ref(ds->surface->image);
vd->guest.format = ds->surface->format;
memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty)); memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty));
QTAILQ_FOREACH(vs, &vd->clients, next) { QTAILQ_FOREACH(vs, &vd->clients, next) {
@ -585,7 +602,7 @@ static void vnc_dpy_resize(DisplayState *ds)
} }
/* fastest code */ /* fastest code */
static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf, static void vnc_write_pixels_copy(VncState *vs,
void *pixels, int size) void *pixels, int size)
{ {
vnc_write(vs, pixels, size); vnc_write(vs, pixels, size);
@ -595,23 +612,23 @@ static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf,
void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
{ {
uint8_t r, g, b; uint8_t r, g, b;
VncDisplay *vd = vs->vd;
r = ((((v & vd->server->pf.rmask) >> vd->server->pf.rshift) << vs->clientds.pf.rbits) >> #if VNC_SERVER_FB_FORMAT == PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8)
vd->server->pf.rbits); r = (((v & 0x00ff0000) >> 16) << vs->client_pf.rbits) >> 8;
g = ((((v & vd->server->pf.gmask) >> vd->server->pf.gshift) << vs->clientds.pf.gbits) >> g = (((v & 0x0000ff00) >> 8) << vs->client_pf.gbits) >> 8;
vd->server->pf.gbits); b = (((v & 0x000000ff) >> 0) << vs->client_pf.bbits) >> 8;
b = ((((v & vd->server->pf.bmask) >> vd->server->pf.bshift) << vs->clientds.pf.bbits) >> #else
vd->server->pf.bbits); # error need some bits here if you change VNC_SERVER_FB_FORMAT
v = (r << vs->clientds.pf.rshift) | #endif
(g << vs->clientds.pf.gshift) | v = (r << vs->client_pf.rshift) |
(b << vs->clientds.pf.bshift); (g << vs->client_pf.gshift) |
switch(vs->clientds.pf.bytes_per_pixel) { (b << vs->client_pf.bshift);
switch (vs->client_pf.bytes_per_pixel) {
case 1: case 1:
buf[0] = v; buf[0] = v;
break; break;
case 2: case 2:
if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { if (vs->client_be) {
buf[0] = v >> 8; buf[0] = v >> 8;
buf[1] = v; buf[1] = v;
} else { } else {
@ -621,7 +638,7 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
break; break;
default: default:
case 4: case 4:
if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { if (vs->client_be) {
buf[0] = v >> 24; buf[0] = v >> 24;
buf[1] = v >> 16; buf[1] = v >> 16;
buf[2] = v >> 8; buf[2] = v >> 8;
@ -636,37 +653,19 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
} }
} }
static void vnc_write_pixels_generic(VncState *vs, struct PixelFormat *pf, static void vnc_write_pixels_generic(VncState *vs,
void *pixels1, int size) void *pixels1, int size)
{ {
uint8_t buf[4]; uint8_t buf[4];
if (pf->bytes_per_pixel == 4) { if (VNC_SERVER_FB_BYTES == 4) {
uint32_t *pixels = pixels1; uint32_t *pixels = pixels1;
int n, i; int n, i;
n = size >> 2; n = size >> 2;
for(i = 0; i < n; i++) { for (i = 0; i < n; i++) {
vnc_convert_pixel(vs, buf, pixels[i]); vnc_convert_pixel(vs, buf, pixels[i]);
vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); vnc_write(vs, buf, vs->client_pf.bytes_per_pixel);
} }
} else if (pf->bytes_per_pixel == 2) {
uint16_t *pixels = pixels1;
int n, i;
n = size >> 1;
for(i = 0; i < n; i++) {
vnc_convert_pixel(vs, buf, pixels[i]);
vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
}
} else if (pf->bytes_per_pixel == 1) {
uint8_t *pixels = pixels1;
int n, i;
n = size;
for(i = 0; i < n; i++) {
vnc_convert_pixel(vs, buf, pixels[i]);
vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
}
} else {
fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
} }
} }
@ -676,10 +675,10 @@ int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
uint8_t *row; uint8_t *row;
VncDisplay *vd = vs->vd; VncDisplay *vd = vs->vd;
row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds); row = vnc_server_fb_ptr(vd, x, y);
for (i = 0; i < h; i++) { for (i = 0; i < h; i++) {
vs->write_pixels(vs, &vd->server->pf, row, w * ds_get_bytes_per_pixel(vs->ds)); vs->write_pixels(vs, row, w * VNC_SERVER_FB_BYTES);
row += ds_get_linesize(vs->ds); row += vnc_server_fb_stride(vd);
} }
return 1; return 1;
} }
@ -736,7 +735,7 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int
VncState *vs, *vn; VncState *vs, *vn;
uint8_t *src_row; uint8_t *src_row;
uint8_t *dst_row; uint8_t *dst_row;
int i,x,y,pitch,depth,inc,w_lim,s; int i, x, y, pitch, inc, w_lim, s;
int cmp_bytes; int cmp_bytes;
vnc_refresh_server_surface(vd); vnc_refresh_server_surface(vd);
@ -749,10 +748,9 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int
} }
/* do bitblit op on the local surface too */ /* do bitblit op on the local surface too */
pitch = ds_get_linesize(vd->ds); pitch = vnc_server_fb_stride(vd);
depth = ds_get_bytes_per_pixel(vd->ds); src_row = vnc_server_fb_ptr(vd, src_x, src_y);
src_row = vd->server->data + pitch * src_y + depth * src_x; dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y);
dst_row = vd->server->data + pitch * dst_y + depth * dst_x;
y = dst_y; y = dst_y;
inc = 1; inc = 1;
if (dst_y > src_y) { if (dst_y > src_y) {
@ -780,7 +778,7 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int
} else { } else {
s = 16; s = 16;
} }
cmp_bytes = s * depth; cmp_bytes = s * VNC_SERVER_FB_BYTES;
if (memcmp(src_row, dst_row, cmp_bytes) == 0) if (memcmp(src_row, dst_row, cmp_bytes) == 0)
continue; continue;
memmove(dst_row, src_row, cmp_bytes); memmove(dst_row, src_row, cmp_bytes);
@ -790,8 +788,8 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int
} }
} }
} }
src_row += pitch - w * depth; src_row += pitch - w * VNC_SERVER_FB_BYTES;
dst_row += pitch - w * depth; dst_row += pitch - w * VNC_SERVER_FB_BYTES;
y += inc; y += inc;
} }
@ -802,7 +800,7 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int
} }
} }
static void vnc_mouse_set(int x, int y, int visible) static void vnc_mouse_set(DisplayState *ds, int x, int y, int visible)
{ {
/* can we ask the client(s) to move the pointer ??? */ /* can we ask the client(s) to move the pointer ??? */
} }
@ -810,7 +808,6 @@ static void vnc_mouse_set(int x, int y, int visible)
static int vnc_cursor_define(VncState *vs) static int vnc_cursor_define(VncState *vs)
{ {
QEMUCursor *c = vs->vd->cursor; QEMUCursor *c = vs->vd->cursor;
PixelFormat pf = qemu_default_pixelformat(32);
int isize; int isize;
if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) { if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) {
@ -820,8 +817,8 @@ static int vnc_cursor_define(VncState *vs)
vnc_write_u16(vs, 1); /* # of rects */ vnc_write_u16(vs, 1); /* # of rects */
vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height, vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height,
VNC_ENCODING_RICH_CURSOR); VNC_ENCODING_RICH_CURSOR);
isize = c->width * c->height * vs->clientds.pf.bytes_per_pixel; isize = c->width * c->height * vs->client_pf.bytes_per_pixel;
vnc_write_pixels_generic(vs, &pf, c->data, isize); vnc_write_pixels_generic(vs, c->data, isize);
vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize); vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize);
vnc_unlock_output(vs); vnc_unlock_output(vs);
return 0; return 0;
@ -829,7 +826,7 @@ static int vnc_cursor_define(VncState *vs)
return -1; return -1;
} }
static void vnc_dpy_cursor_define(QEMUCursor *c) static void vnc_dpy_cursor_define(DisplayState *ds, QEMUCursor *c)
{ {
VncDisplay *vd = vnc_display; VncDisplay *vd = vnc_display;
VncState *vs; VncState *vs;
@ -898,8 +895,8 @@ static int vnc_update_client(VncState *vs, int has_dirty)
*/ */
job = vnc_job_new(vs); job = vnc_job_new(vs);
width = MIN(vd->server->width, vs->client_width); width = MIN(pixman_image_get_width(vd->server), vs->client_width);
height = MIN(vd->server->height, vs->client_height); height = MIN(pixman_image_get_height(vd->server), vs->client_height);
for (y = 0; y < height; y++) { for (y = 0; y < height; y++) {
int x; int x;
@ -1861,9 +1858,9 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
static void set_pixel_conversion(VncState *vs) static void set_pixel_conversion(VncState *vs)
{ {
if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == pixman_format_code_t fmt = qemu_pixman_get_format(&vs->client_pf);
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
!memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) { if (fmt == VNC_SERVER_FB_FORMAT) {
vs->write_pixels = vnc_write_pixels_copy; vs->write_pixels = vnc_write_pixels_copy;
vnc_hextile_set_pixel_conversion(vs, 0); vnc_hextile_set_pixel_conversion(vs, 0);
} else { } else {
@ -1883,23 +1880,22 @@ static void set_pixel_format(VncState *vs,
return; return;
} }
vs->clientds = *(vs->vd->guest.ds); vs->client_pf.rmax = red_max;
vs->clientds.pf.rmax = red_max; vs->client_pf.rbits = hweight_long(red_max);
vs->clientds.pf.rbits = hweight_long(red_max); vs->client_pf.rshift = red_shift;
vs->clientds.pf.rshift = red_shift; vs->client_pf.rmask = red_max << red_shift;
vs->clientds.pf.rmask = red_max << red_shift; vs->client_pf.gmax = green_max;
vs->clientds.pf.gmax = green_max; vs->client_pf.gbits = hweight_long(green_max);
vs->clientds.pf.gbits = hweight_long(green_max); vs->client_pf.gshift = green_shift;
vs->clientds.pf.gshift = green_shift; vs->client_pf.gmask = green_max << green_shift;
vs->clientds.pf.gmask = green_max << green_shift; vs->client_pf.bmax = blue_max;
vs->clientds.pf.bmax = blue_max; vs->client_pf.bbits = hweight_long(blue_max);
vs->clientds.pf.bbits = hweight_long(blue_max); vs->client_pf.bshift = blue_shift;
vs->clientds.pf.bshift = blue_shift; vs->client_pf.bmask = blue_max << blue_shift;
vs->clientds.pf.bmask = blue_max << blue_shift; vs->client_pf.bits_per_pixel = bits_per_pixel;
vs->clientds.pf.bits_per_pixel = bits_per_pixel; vs->client_pf.bytes_per_pixel = bits_per_pixel / 8;
vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8; vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel; vs->client_be = big_endian_flag;
vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00;
set_pixel_conversion(vs); set_pixel_conversion(vs);
@ -1910,8 +1906,10 @@ static void set_pixel_format(VncState *vs,
static void pixel_format_message (VncState *vs) { static void pixel_format_message (VncState *vs) {
char pad[3] = { 0, 0, 0 }; char pad[3] = { 0, 0, 0 };
vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */ vs->client_pf = qemu_default_pixelformat(32);
vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */
vnc_write_u8(vs, vs->client_pf.bits_per_pixel); /* bits-per-pixel */
vnc_write_u8(vs, vs->client_pf.depth); /* depth */
#ifdef HOST_WORDS_BIGENDIAN #ifdef HOST_WORDS_BIGENDIAN
vnc_write_u8(vs, 1); /* big-endian-flag */ vnc_write_u8(vs, 1); /* big-endian-flag */
@ -1919,27 +1917,25 @@ static void pixel_format_message (VncState *vs) {
vnc_write_u8(vs, 0); /* big-endian-flag */ vnc_write_u8(vs, 0); /* big-endian-flag */
#endif #endif
vnc_write_u8(vs, 1); /* true-color-flag */ vnc_write_u8(vs, 1); /* true-color-flag */
vnc_write_u16(vs, vs->ds->surface->pf.rmax); /* red-max */ vnc_write_u16(vs, vs->client_pf.rmax); /* red-max */
vnc_write_u16(vs, vs->ds->surface->pf.gmax); /* green-max */ vnc_write_u16(vs, vs->client_pf.gmax); /* green-max */
vnc_write_u16(vs, vs->ds->surface->pf.bmax); /* blue-max */ vnc_write_u16(vs, vs->client_pf.bmax); /* blue-max */
vnc_write_u8(vs, vs->ds->surface->pf.rshift); /* red-shift */ vnc_write_u8(vs, vs->client_pf.rshift); /* red-shift */
vnc_write_u8(vs, vs->ds->surface->pf.gshift); /* green-shift */ vnc_write_u8(vs, vs->client_pf.gshift); /* green-shift */
vnc_write_u8(vs, vs->ds->surface->pf.bshift); /* blue-shift */ vnc_write_u8(vs, vs->client_pf.bshift); /* blue-shift */
vnc_write(vs, pad, 3); /* padding */
vnc_hextile_set_pixel_conversion(vs, 0); vnc_hextile_set_pixel_conversion(vs, 0);
vs->clientds = *(vs->ds->surface);
vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG;
vs->write_pixels = vnc_write_pixels_copy; vs->write_pixels = vnc_write_pixels_copy;
vnc_write(vs, pad, 3); /* padding */
} }
static void vnc_dpy_setdata(DisplayState *ds) static void vnc_dpy_setdata(DisplayState *ds)
{ {
VncDisplay *vd = ds->opaque; VncDisplay *vd = ds->opaque;
*(vd->guest.ds) = *(ds->surface); qemu_pixman_image_unref(vd->guest.fb);
vd->guest.fb = pixman_image_ref(ds->surface->image);
vd->guest.format = ds->surface->format;
vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
} }
@ -2443,12 +2439,14 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
static int vnc_update_stats(VncDisplay *vd, struct timeval * tv) static int vnc_update_stats(VncDisplay *vd, struct timeval * tv)
{ {
int width = pixman_image_get_width(vd->guest.fb);
int height = pixman_image_get_height(vd->guest.fb);
int x, y; int x, y;
struct timeval res; struct timeval res;
int has_dirty = 0; int has_dirty = 0;
for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) { for (y = 0; y < height; y += VNC_STAT_RECT) {
for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) { for (x = 0; x < width; x += VNC_STAT_RECT) {
VncRectStat *rect = vnc_stat_rect(vd, x, y); VncRectStat *rect = vnc_stat_rect(vd, x, y);
rect->updated = false; rect->updated = false;
@ -2462,8 +2460,8 @@ static int vnc_update_stats(VncDisplay *vd, struct timeval * tv)
} }
vd->guest.last_freq_check = *tv; vd->guest.last_freq_check = *tv;
for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) { for (y = 0; y < height; y += VNC_STAT_RECT) {
for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) { for (x = 0; x < width; x += VNC_STAT_RECT) {
VncRectStat *rect= vnc_stat_rect(vd, x, y); VncRectStat *rect= vnc_stat_rect(vd, x, y);
int count = ARRAY_SIZE(rect->times); int count = ARRAY_SIZE(rect->times);
struct timeval min, max; struct timeval min, max;
@ -2532,12 +2530,15 @@ static void vnc_rect_updated(VncDisplay *vd, int x, int y, struct timeval * tv)
static int vnc_refresh_server_surface(VncDisplay *vd) static int vnc_refresh_server_surface(VncDisplay *vd)
{ {
int width = pixman_image_get_width(vd->guest.fb);
int height = pixman_image_get_height(vd->guest.fb);
int y; int y;
uint8_t *guest_row; uint8_t *guest_row;
uint8_t *server_row; uint8_t *server_row;
int cmp_bytes; int cmp_bytes;
VncState *vs; VncState *vs;
int has_dirty = 0; int has_dirty = 0;
pixman_image_t *tmpbuf = NULL;
struct timeval tv = { 0, 0 }; struct timeval tv = { 0, 0 };
@ -2551,22 +2552,31 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
* Check and copy modified bits from guest to server surface. * Check and copy modified bits from guest to server surface.
* Update server dirty map. * Update server dirty map.
*/ */
cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds); cmp_bytes = 64;
if (cmp_bytes > vd->ds->surface->linesize) { if (cmp_bytes > vnc_server_fb_stride(vd)) {
cmp_bytes = vd->ds->surface->linesize; cmp_bytes = vnc_server_fb_stride(vd);
} }
guest_row = vd->guest.ds->data; if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
server_row = vd->server->data; int width = pixman_image_get_width(vd->server);
for (y = 0; y < vd->guest.ds->height; y++) { tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width);
}
guest_row = (uint8_t *)pixman_image_get_data(vd->guest.fb);
server_row = (uint8_t *)pixman_image_get_data(vd->server);
for (y = 0; y < height; y++) {
if (!bitmap_empty(vd->guest.dirty[y], VNC_DIRTY_BITS)) { if (!bitmap_empty(vd->guest.dirty[y], VNC_DIRTY_BITS)) {
int x; int x;
uint8_t *guest_ptr; uint8_t *guest_ptr;
uint8_t *server_ptr; uint8_t *server_ptr;
guest_ptr = guest_row; if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
qemu_pixman_linebuf_fill(tmpbuf, vd->guest.fb, width, y);
guest_ptr = (uint8_t *)pixman_image_get_data(tmpbuf);
} else {
guest_ptr = guest_row;
}
server_ptr = server_row; server_ptr = server_row;
for (x = 0; x + 15 < vd->guest.ds->width; for (x = 0; x + 15 < width;
x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) { x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
if (!test_and_clear_bit((x / 16), vd->guest.dirty[y])) if (!test_and_clear_bit((x / 16), vd->guest.dirty[y]))
continue; continue;
@ -2581,9 +2591,10 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
has_dirty++; has_dirty++;
} }
} }
guest_row += ds_get_linesize(vd->ds); guest_row += pixman_image_get_stride(vd->guest.fb);
server_row += ds_get_linesize(vd->ds); server_row += pixman_image_get_stride(vd->server);
} }
qemu_pixman_image_unref(tmpbuf);
return has_dirty; return has_dirty;
} }
@ -2753,13 +2764,13 @@ void vnc_display_init(DisplayState *ds)
qemu_mutex_init(&vs->mutex); qemu_mutex_init(&vs->mutex);
vnc_start_worker_thread(); vnc_start_worker_thread();
dcl->dpy_copy = vnc_dpy_copy; dcl->dpy_gfx_copy = vnc_dpy_copy;
dcl->dpy_update = vnc_dpy_update; dcl->dpy_gfx_update = vnc_dpy_update;
dcl->dpy_resize = vnc_dpy_resize; dcl->dpy_gfx_resize = vnc_dpy_resize;
dcl->dpy_setdata = vnc_dpy_setdata; dcl->dpy_gfx_setdata = vnc_dpy_setdata;
dcl->dpy_mouse_set = vnc_mouse_set;
dcl->dpy_cursor_define = vnc_dpy_cursor_define;
register_displaychangelistener(ds, dcl); register_displaychangelistener(ds, dcl);
ds->mouse_set = vnc_mouse_set;
ds->cursor_define = vnc_dpy_cursor_define;
} }

View File

@ -69,7 +69,7 @@ typedef struct VncRectEntry VncRectEntry;
typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len); typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
typedef void VncWritePixels(VncState *vs, struct PixelFormat *pf, void *data, int size); typedef void VncWritePixels(VncState *vs, void *data, int size);
typedef void VncSendHextileTile(VncState *vs, typedef void VncSendHextileTile(VncState *vs,
int x, int y, int w, int h, int x, int y, int w, int h,
@ -117,7 +117,8 @@ struct VncSurface
struct timeval last_freq_check; struct timeval last_freq_check;
DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_MAX_WIDTH / 16); DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_MAX_WIDTH / 16);
VncRectStat stats[VNC_STAT_ROWS][VNC_STAT_COLS]; VncRectStat stats[VNC_STAT_ROWS][VNC_STAT_COLS];
DisplaySurface *ds; pixman_image_t *fb;
pixman_format_code_t format;
}; };
typedef enum VncShareMode { typedef enum VncShareMode {
@ -151,7 +152,7 @@ struct VncDisplay
uint8_t *cursor_mask; uint8_t *cursor_mask;
struct VncSurface guest; /* guest visible surface (aka ds->surface) */ struct VncSurface guest; /* guest visible surface (aka ds->surface) */
DisplaySurface *server; /* vnc server surface */ pixman_image_t *server; /* vnc server surface */
char *display; char *display;
char *password; char *password;
@ -275,7 +276,9 @@ struct VncState
Buffer input; Buffer input;
/* current output mode information */ /* current output mode information */
VncWritePixels *write_pixels; VncWritePixels *write_pixels;
DisplaySurface clientds; PixelFormat client_pf;
pixman_format_code_t client_format;
bool client_be;
CaptureVoiceOut *audio_cap; CaptureVoiceOut *audio_cap;
struct audsettings as; struct audsettings as;
@ -527,6 +530,14 @@ static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h, void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
int32_t encoding); int32_t encoding);
/* server fb is in PIXMAN_x8r8g8b8 */
#define VNC_SERVER_FB_FORMAT PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8)
#define VNC_SERVER_FB_BITS (PIXMAN_FORMAT_BPP(VNC_SERVER_FB_FORMAT))
#define VNC_SERVER_FB_BYTES ((VNC_SERVER_FB_BITS+7)/8)
void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y);
int vnc_server_fb_stride(VncDisplay *vd);
void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v); void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v);
double vnc_update_freq(VncState *vs, int x, int y, int w, int h); double vnc_update_freq(VncState *vs, int x, int y, int w, int h);
void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h); void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h);

49
vl.c
View File

@ -1359,19 +1359,51 @@ static void gui_update(void *opaque)
{ {
uint64_t interval = GUI_REFRESH_INTERVAL; uint64_t interval = GUI_REFRESH_INTERVAL;
DisplayState *ds = opaque; DisplayState *ds = opaque;
DisplayChangeListener *dcl = ds->listeners; DisplayChangeListener *dcl;
dpy_refresh(ds); dpy_refresh(ds);
while (dcl != NULL) { QLIST_FOREACH(dcl, &ds->listeners, next) {
if (dcl->gui_timer_interval && if (dcl->gui_timer_interval &&
dcl->gui_timer_interval < interval) dcl->gui_timer_interval < interval)
interval = dcl->gui_timer_interval; interval = dcl->gui_timer_interval;
dcl = dcl->next;
} }
qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock)); qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock));
} }
void gui_setup_refresh(DisplayState *ds)
{
DisplayChangeListener *dcl;
bool need_timer = false;
bool have_gfx = false;
bool have_text = false;
QLIST_FOREACH(dcl, &ds->listeners, next) {
if (dcl->dpy_refresh != NULL) {
need_timer = true;
}
if (dcl->dpy_gfx_update != NULL) {
have_gfx = true;
}
if (dcl->dpy_text_update != NULL) {
have_text = true;
}
}
if (need_timer && ds->gui_timer == NULL) {
ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds);
qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock));
}
if (!need_timer && ds->gui_timer != NULL) {
qemu_del_timer(ds->gui_timer);
qemu_free_timer(ds->gui_timer);
ds->gui_timer = NULL;
}
ds->have_gfx = have_gfx;
ds->have_text = have_text;
}
struct vm_change_state_entry { struct vm_change_state_entry {
VMChangeStateHandler *cb; VMChangeStateHandler *cb;
void *opaque; void *opaque;
@ -2450,7 +2482,6 @@ int main(int argc, char **argv, char **envp)
const char *kernel_filename, *kernel_cmdline; const char *kernel_filename, *kernel_cmdline;
char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */ char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */
DisplayState *ds; DisplayState *ds;
DisplayChangeListener *dcl;
int cyls, heads, secs, translation; int cyls, heads, secs, translation;
QemuOpts *hda_opts = NULL, *opts, *machine_opts; QemuOpts *hda_opts = NULL, *opts, *machine_opts;
QemuOptsList *olist; QemuOptsList *olist;
@ -3873,16 +3904,6 @@ int main(int argc, char **argv, char **envp)
#endif #endif
/* display setup */ /* display setup */
dpy_resize(ds);
dcl = ds->listeners;
while (dcl != NULL) {
if (dcl->dpy_refresh != NULL) {
ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds);
qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock));
break;
}
dcl = dcl->next;
}
text_consoles_set_display(ds); text_consoles_set_display(ds);
if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {