mirror of https://gitee.com/openkylin/qemu.git
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:
commit
4ba79505f4
|
@ -19,3 +19,6 @@
|
|||
[submodule "roms/sgabios"]
|
||||
path = roms/sgabios
|
||||
url = git://git.qemu.org/sgabios.git
|
||||
[submodule "pixman"]
|
||||
path = pixman
|
||||
url = git://anongit.freedesktop.org/pixman
|
||||
|
|
9
Makefile
9
Makefile
|
@ -118,6 +118,15 @@ endif
|
|||
|
||||
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 %-user,$(SUBDIR_RULES)): $(universal-obj-y) $(trace-obj-y) subdir-libdis-user subdir-libuser
|
||||
|
|
|
@ -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 += qom/
|
||||
common-obj-y += readline.o console.o cursor.o
|
||||
common-obj-y += qemu-pixman.o
|
||||
common-obj-y += $(oslib-obj-y)
|
||||
common-obj-$(CONFIG_WIN32) += os-win32.o
|
||||
common-obj-$(CONFIG_POSIX) += os-posix.o
|
||||
|
|
|
@ -147,6 +147,7 @@ curses=""
|
|||
docs=""
|
||||
fdt=""
|
||||
nptl=""
|
||||
pixman=""
|
||||
sdl=""
|
||||
virtfs=""
|
||||
vnc="yes"
|
||||
|
@ -642,6 +643,10 @@ for opt do
|
|||
# configure to be used by RPM and similar macros that set
|
||||
# lots of directory switches by default.
|
||||
;;
|
||||
--with-system-pixman) pixman="system"
|
||||
;;
|
||||
--without-system-pixman) pixman="internal"
|
||||
;;
|
||||
--disable-sdl) sdl="no"
|
||||
;;
|
||||
--enable-sdl) sdl="yes"
|
||||
|
@ -2094,6 +2099,34 @@ else
|
|||
exit 1
|
||||
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
|
||||
|
||||
|
@ -3142,6 +3175,7 @@ echo "-Werror enabled $werror"
|
|||
if test "$darwin" = "yes" ; then
|
||||
echo "Cocoa support $cocoa"
|
||||
fi
|
||||
echo "pixman $pixman"
|
||||
echo "SDL support $sdl"
|
||||
echo "curses support $curses"
|
||||
echo "curl support $curl"
|
||||
|
@ -3908,6 +3942,9 @@ if test "$target_softmmu" = "yes" ; then
|
|||
if test "$smartcard_nss" = "yes" ; then
|
||||
echo "subdir-$target: subdir-libcacard" >> $config_host_mak
|
||||
fi
|
||||
if test "$pixman" = "internal" ; then
|
||||
echo "subdir-$target: subdir-pixman" >> $config_host_mak
|
||||
fi
|
||||
case "$target_arch2" in
|
||||
i386|x86_64)
|
||||
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 qapi-generated"
|
||||
DIRS="$DIRS libcacard libcacard/libcacard libcacard/trace"
|
||||
DIRS="$DIRS pixman"
|
||||
FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
|
||||
FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
|
||||
FILES="$FILES tests/tcg/lm32/Makefile libcacard/Makefile"
|
||||
|
|
224
console.c
224
console.c
|
@ -114,20 +114,20 @@ typedef enum {
|
|||
TEXT_CONSOLE_FIXED_SIZE
|
||||
} console_type_t;
|
||||
|
||||
/* ??? This is mis-named.
|
||||
It is used for both text and graphical consoles. */
|
||||
struct TextConsole {
|
||||
struct QemuConsole {
|
||||
int index;
|
||||
console_type_t console_type;
|
||||
DisplayState *ds;
|
||||
|
||||
/* Graphic console state. */
|
||||
vga_hw_update_ptr hw_update;
|
||||
vga_hw_invalidate_ptr hw_invalidate;
|
||||
vga_hw_screen_dump_ptr hw_screen_dump;
|
||||
vga_hw_text_update_ptr hw_text_update;
|
||||
void *hw;
|
||||
|
||||
int g_width, g_height;
|
||||
|
||||
/* Text console state */
|
||||
int width;
|
||||
int height;
|
||||
int total_height;
|
||||
|
@ -161,8 +161,8 @@ struct TextConsole {
|
|||
};
|
||||
|
||||
static DisplayState *display_state;
|
||||
static TextConsole *active_console;
|
||||
static TextConsole *consoles[MAX_CONSOLES];
|
||||
static QemuConsole *active_console;
|
||||
static QemuConsole *consoles[MAX_CONSOLES];
|
||||
static int nb_consoles = 0;
|
||||
|
||||
void vga_hw_update(void)
|
||||
|
@ -179,7 +179,7 @@ void vga_hw_invalidate(void)
|
|||
|
||||
void qmp_screendump(const char *filename, Error **errp)
|
||||
{
|
||||
TextConsole *previous_active_console;
|
||||
QemuConsole *previous_active_console;
|
||||
bool cswitch;
|
||||
|
||||
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;
|
||||
int w1, x, y, last_width;
|
||||
|
@ -553,7 +553,7 @@ static void text_console_resize(TextConsole *s)
|
|||
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[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);
|
||||
}
|
||||
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
static void update_xy(TextConsole *s, int x, int y)
|
||||
static void update_xy(QemuConsole *s, int x, int y)
|
||||
{
|
||||
TextCell *c;
|
||||
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;
|
||||
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;
|
||||
int x, y, y1;
|
||||
|
||||
if (s != active_console)
|
||||
return;
|
||||
if (!ds_get_bits_per_pixel(s->ds)) {
|
||||
|
||||
if (s->ds->have_text) {
|
||||
s->text_x[0] = 0;
|
||||
s->text_y[0] = 0;
|
||||
s->text_x[1] = s->width - 1;
|
||||
s->text_y[1] = s->height - 1;
|
||||
s->cursor_invalidate = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->ds->have_gfx) {
|
||||
vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
|
||||
color_table[0][COLOR_BLACK]);
|
||||
y1 = s->y_displayed;
|
||||
for(y = 0; y < s->height; y++) {
|
||||
for (y = 0; y < s->height; y++) {
|
||||
c = s->cells + y1 * s->width;
|
||||
for(x = 0; x < s->width; x++) {
|
||||
for (x = 0; x < s->width; x++) {
|
||||
vga_putcharxy(s->ds, x, y, c->ch,
|
||||
&(c->t_attrib));
|
||||
c++;
|
||||
}
|
||||
if (++y1 == s->total_height)
|
||||
if (++y1 == s->total_height) {
|
||||
y1 = 0;
|
||||
}
|
||||
}
|
||||
console_show_cursor(s, 1);
|
||||
dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
|
||||
dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
|
||||
}
|
||||
}
|
||||
|
||||
static void console_scroll(int ydelta)
|
||||
{
|
||||
TextConsole *s;
|
||||
QemuConsole *s;
|
||||
int i, y1;
|
||||
|
||||
s = active_console;
|
||||
|
@ -698,7 +701,7 @@ static void console_scroll(int ydelta)
|
|||
console_refresh(s);
|
||||
}
|
||||
|
||||
static void console_put_lf(TextConsole *s)
|
||||
static void console_put_lf(QemuConsole *s)
|
||||
{
|
||||
TextCell *c;
|
||||
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
|
||||
* 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;
|
||||
|
||||
|
@ -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;
|
||||
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 */
|
||||
static void set_cursor(TextConsole *s, int x, int y)
|
||||
static void set_cursor(QemuConsole *s, int x, int y)
|
||||
{
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
|
@ -871,7 +874,7 @@ static void set_cursor(TextConsole *s, int x, int y)
|
|||
s->y = y;
|
||||
}
|
||||
|
||||
static void console_putchar(TextConsole *s, int ch)
|
||||
static void console_putchar(QemuConsole *s, int ch)
|
||||
{
|
||||
TextCell *c;
|
||||
int y1, i;
|
||||
|
@ -1078,7 +1081,7 @@ static void console_putchar(TextConsole *s, int ch)
|
|||
|
||||
void console_select(unsigned int index)
|
||||
{
|
||||
TextConsole *s;
|
||||
QemuConsole *s;
|
||||
|
||||
if (index >= MAX_CONSOLES)
|
||||
return;
|
||||
|
@ -1094,24 +1097,24 @@ void console_select(unsigned int index)
|
|||
qemu_del_timer(active_console->cursor_timer);
|
||||
}
|
||||
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);
|
||||
} else {
|
||||
s->ds->surface->width = s->width;
|
||||
s->ds->surface->height = s->height;
|
||||
dpy_gfx_resize(ds);
|
||||
}
|
||||
if (ds->have_text) {
|
||||
dpy_text_resize(ds, s->width, s->height);
|
||||
}
|
||||
if (s->cursor_timer) {
|
||||
qemu_mod_timer(s->cursor_timer,
|
||||
qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
|
||||
}
|
||||
dpy_resize(s->ds);
|
||||
vga_hw_invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
TextConsole *s = chr->opaque;
|
||||
QemuConsole *s = chr->opaque;
|
||||
int i;
|
||||
|
||||
s->update_x0 = s->width * FONT_WIDTH;
|
||||
|
@ -1123,8 +1126,8 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
|
|||
console_putchar(s, buf[i]);
|
||||
}
|
||||
console_show_cursor(s, 1);
|
||||
if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) {
|
||||
dpy_update(s->ds, s->update_x0, s->update_y0,
|
||||
if (s->ds->have_gfx && s->update_x0 < s->update_x1) {
|
||||
dpy_gfx_update(s->ds, s->update_x0, s->update_y0,
|
||||
s->update_x1 - s->update_x0,
|
||||
s->update_y1 - s->update_y0);
|
||||
}
|
||||
|
@ -1133,7 +1136,7 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
|
|||
|
||||
static void kbd_send_chars(void *opaque)
|
||||
{
|
||||
TextConsole *s = opaque;
|
||||
QemuConsole *s = opaque;
|
||||
int len;
|
||||
uint8_t buf[16];
|
||||
|
||||
|
@ -1156,7 +1159,7 @@ static void kbd_send_chars(void *opaque)
|
|||
/* called when an ascii key is pressed */
|
||||
void kbd_put_keysym(int keysym)
|
||||
{
|
||||
TextConsole *s;
|
||||
QemuConsole *s;
|
||||
uint8_t buf[16], *q;
|
||||
int c;
|
||||
|
||||
|
@ -1211,7 +1214,7 @@ void kbd_put_keysym(int keysym)
|
|||
|
||||
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) {
|
||||
s->g_width = ds_get_width(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)
|
||||
{
|
||||
TextConsole *s = (TextConsole *) opaque;
|
||||
QemuConsole *s = (QemuConsole *) opaque;
|
||||
int i, j, src;
|
||||
|
||||
if (s->text_x[0] <= s->text_x[1]) {
|
||||
|
@ -1234,7 +1237,7 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
|
|||
(s->cells[src].t_attrib.fgcol << 12) |
|
||||
(s->cells[src].t_attrib.bgcol << 8) |
|
||||
(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[0] = s->width;
|
||||
s->text_y[0] = s->height;
|
||||
|
@ -1242,15 +1245,15 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
|
|||
s->text_y[1] = 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static TextConsole *get_graphic_console(DisplayState *ds)
|
||||
static QemuConsole *get_graphic_console(DisplayState *ds)
|
||||
{
|
||||
int i;
|
||||
TextConsole *s;
|
||||
QemuConsole *s;
|
||||
for (i = 0; i < nb_consoles; i++) {
|
||||
s = consoles[i];
|
||||
if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
|
||||
|
@ -1259,14 +1262,14 @@ static TextConsole *get_graphic_console(DisplayState *ds)
|
|||
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;
|
||||
|
||||
if (nb_consoles >= MAX_CONSOLES)
|
||||
return NULL;
|
||||
s = g_malloc0(sizeof(TextConsole));
|
||||
s = g_malloc0(sizeof(QemuConsole));
|
||||
if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
|
||||
(console_type == GRAPHIC_CONSOLE))) {
|
||||
active_console = s;
|
||||
|
@ -1291,85 +1294,86 @@ static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
|
|||
return s;
|
||||
}
|
||||
|
||||
static DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
|
||||
{
|
||||
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,
|
||||
static 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;
|
||||
if (surface->flags & QEMU_ALLOCATED_FLAG) {
|
||||
data = g_realloc(surface->data,
|
||||
surface->linesize * surface->height);
|
||||
} else {
|
||||
data = g_malloc(surface->linesize * surface->height);
|
||||
}
|
||||
surface->data = (uint8_t *)data;
|
||||
|
||||
qemu_pixman_image_unref(surface->image);
|
||||
surface->image = NULL;
|
||||
|
||||
surface->format = qemu_pixman_get_format(&pf);
|
||||
assert(surface->format != 0);
|
||||
surface->image = pixman_image_create_bits(surface->format,
|
||||
width, height,
|
||||
NULL, linesize);
|
||||
assert(surface->image != NULL);
|
||||
|
||||
surface->flags = newflags | QEMU_ALLOCATED_FLAG;
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
surface->flags |= QEMU_BIG_ENDIAN_FLAG;
|
||||
#endif
|
||||
}
|
||||
|
||||
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
|
||||
DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
|
||||
int width, int height)
|
||||
{
|
||||
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 = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
|
||||
DisplaySurface *surface = g_new0(DisplaySurface, 1);
|
||||
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->linesize = linesize;
|
||||
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
|
||||
surface->flags = QEMU_BIG_ENDIAN_FLAG;
|
||||
#endif
|
||||
surface->data = data;
|
||||
|
||||
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;
|
||||
if (surface->flags & QEMU_ALLOCATED_FLAG)
|
||||
g_free(surface->data);
|
||||
g_free(surface);
|
||||
}
|
||||
qemu_pixman_image_unref(ds->surface->image);
|
||||
g_free(ds->surface);
|
||||
}
|
||||
|
||||
static struct DisplayAllocator default_allocator = {
|
||||
defaultallocator_create_displaysurface,
|
||||
defaultallocator_resize_displaysurface,
|
||||
defaultallocator_free_displaysurface
|
||||
};
|
||||
|
||||
static void dumb_display_init(void)
|
||||
{
|
||||
DisplayState *ds = g_malloc0(sizeof(DisplayState));
|
||||
int width = 640;
|
||||
int height = 480;
|
||||
|
||||
ds->allocator = &default_allocator;
|
||||
if (is_fixedsize_console()) {
|
||||
width = active_console->g_width;
|
||||
height = active_console->g_height;
|
||||
|
@ -1399,29 +1403,16 @@ DisplayState *get_displaystate(void)
|
|||
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,
|
||||
vga_hw_invalidate_ptr invalidate,
|
||||
vga_hw_screen_dump_ptr screen_dump,
|
||||
vga_hw_text_update_ptr text_update,
|
||||
void *opaque)
|
||||
{
|
||||
TextConsole *s;
|
||||
QemuConsole *s;
|
||||
DisplayState *ds;
|
||||
|
||||
ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
|
||||
ds->allocator = &default_allocator;
|
||||
ds->surface = qemu_create_displaysurface(ds, 640, 480);
|
||||
|
||||
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)
|
||||
{
|
||||
TextConsole *s = chr->opaque;
|
||||
QemuConsole *s = chr->opaque;
|
||||
|
||||
s->echo = echo;
|
||||
}
|
||||
|
||||
static void text_console_update_cursor(void *opaque)
|
||||
{
|
||||
TextConsole *s = opaque;
|
||||
QemuConsole *s = opaque;
|
||||
|
||||
s->cursor_visible_phase = !s->cursor_visible_phase;
|
||||
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)
|
||||
{
|
||||
TextConsole *s;
|
||||
QemuConsole *s;
|
||||
static int color_inited;
|
||||
|
||||
s = chr->opaque;
|
||||
|
@ -1543,7 +1534,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
|
|||
CharDriverState *text_console_init(QemuOpts *opts)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
TextConsole *s;
|
||||
QemuConsole *s;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
|
||||
|
@ -1589,14 +1580,14 @@ void text_consoles_set_display(DisplayState *ds)
|
|||
|
||||
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;
|
||||
|
||||
s->g_width = width;
|
||||
s->g_height = height;
|
||||
if (is_graphic_console()) {
|
||||
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)
|
||||
{
|
||||
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.gmask = 0x0000FF00;
|
||||
pf.bmask = 0x000000FF;
|
||||
pf.amax = 255;
|
||||
pf.rmax = 255;
|
||||
pf.gmax = 255;
|
||||
pf.bmax = 255;
|
||||
pf.ashift = 24;
|
||||
pf.rshift = 16;
|
||||
pf.gshift = 8;
|
||||
pf.bshift = 0;
|
||||
pf.rbits = 8;
|
||||
pf.gbits = 8;
|
||||
pf.bbits = 8;
|
||||
pf.abits = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
235
console.h
235
console.h
|
@ -2,6 +2,7 @@
|
|||
#define CONSOLE_H
|
||||
|
||||
#include "qemu-char.h"
|
||||
#include "qemu-pixman.h"
|
||||
#include "qdict.h"
|
||||
#include "notify.h"
|
||||
#include "monitor.h"
|
||||
|
@ -107,7 +108,6 @@ void kbd_put_keysym(int keysym);
|
|||
|
||||
#define QEMU_BIG_ENDIAN_FLAG 0x01
|
||||
#define QEMU_ALLOCATED_FLAG 0x02
|
||||
#define QEMU_REALPIXELS_FLAG 0x04
|
||||
|
||||
struct PixelFormat {
|
||||
uint8_t bits_per_pixel;
|
||||
|
@ -120,11 +120,9 @@ struct PixelFormat {
|
|||
};
|
||||
|
||||
struct DisplaySurface {
|
||||
pixman_format_code_t format;
|
||||
pixman_image_t *image;
|
||||
uint8_t flags;
|
||||
int width;
|
||||
int height;
|
||||
int linesize; /* bytes per line */
|
||||
uint8_t *data;
|
||||
|
||||
struct PixelFormat pf;
|
||||
};
|
||||
|
@ -154,35 +152,32 @@ struct DisplayChangeListener {
|
|||
int idle;
|
||||
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_copy)(struct DisplayState *s, int src_x, int src_y,
|
||||
|
||||
void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h);
|
||||
void (*dpy_gfx_resize)(struct DisplayState *s);
|
||||
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_fill)(struct DisplayState *s, int x, int y,
|
||||
int w, int h, uint32_t c);
|
||||
|
||||
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 {
|
||||
DisplaySurface* (*create_displaysurface)(int width, int height);
|
||||
DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height);
|
||||
void (*free_displaysurface)(DisplaySurface *surface);
|
||||
QLIST_ENTRY(DisplayChangeListener) next;
|
||||
};
|
||||
|
||||
struct DisplayState {
|
||||
struct DisplaySurface *surface;
|
||||
void *opaque;
|
||||
struct QEMUTimer *gui_timer;
|
||||
bool have_gfx;
|
||||
bool have_text;
|
||||
|
||||
struct DisplayAllocator* allocator;
|
||||
struct DisplayChangeListener* listeners;
|
||||
|
||||
void (*mouse_set)(int x, int y, int on);
|
||||
void (*cursor_define)(QEMUCursor *cursor);
|
||||
QLIST_HEAD(, DisplayChangeListener) listeners;
|
||||
|
||||
struct DisplayState *next;
|
||||
};
|
||||
|
@ -191,29 +186,14 @@ void register_displaystate(DisplayState *ds);
|
|||
DisplayState *get_displaystate(void);
|
||||
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
|
||||
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_default_pixelformat(int bpp);
|
||||
|
||||
DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da);
|
||||
|
||||
static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height)
|
||||
{
|
||||
return ds->allocator->create_displaysurface(width, height);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
|
||||
int width, int height);
|
||||
DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
|
||||
int width, int height);
|
||||
void qemu_free_displaysurface(DisplayState *ds);
|
||||
|
||||
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)
|
||||
{
|
||||
return (!(surface->flags & QEMU_ALLOCATED_FLAG) &&
|
||||
!(surface->flags & QEMU_REALPIXELS_FLAG));
|
||||
return !(surface->flags & QEMU_ALLOCATED_FLAG);
|
||||
}
|
||||
|
||||
void gui_setup_refresh(DisplayState *ds);
|
||||
|
||||
static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
|
||||
{
|
||||
dcl->next = ds->listeners;
|
||||
ds->listeners = dcl;
|
||||
}
|
||||
|
||||
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;
|
||||
QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
|
||||
gui_setup_refresh(ds);
|
||||
if (dcl->dpy_gfx_resize) {
|
||||
dcl->dpy_gfx_resize(ds);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dpy_resize(DisplayState *s)
|
||||
static inline void unregister_displaychangelistener(DisplayState *ds,
|
||||
DisplayChangeListener *dcl)
|
||||
{
|
||||
struct DisplayChangeListener *dcl = s->listeners;
|
||||
while (dcl != NULL) {
|
||||
dcl->dpy_resize(s);
|
||||
dcl = dcl->next;
|
||||
QLIST_REMOVE(dcl, next);
|
||||
gui_setup_refresh(ds);
|
||||
}
|
||||
|
||||
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;
|
||||
while (dcl != NULL) {
|
||||
if (dcl->dpy_setdata) dcl->dpy_setdata(s);
|
||||
dcl = dcl->next;
|
||||
struct DisplayChangeListener *dcl;
|
||||
QLIST_FOREACH(dcl, &s->listeners, next) {
|
||||
if (dcl->dpy_gfx_resize) {
|
||||
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)
|
||||
{
|
||||
struct DisplayChangeListener *dcl = s->listeners;
|
||||
while (dcl != NULL) {
|
||||
if (dcl->dpy_refresh) dcl->dpy_refresh(s);
|
||||
dcl = dcl->next;
|
||||
struct DisplayChangeListener *dcl;
|
||||
QLIST_FOREACH(dcl, &s->listeners, next) {
|
||||
if (dcl->dpy_refresh) {
|
||||
dcl->dpy_refresh(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y,
|
||||
int dst_x, int dst_y, int w, int h) {
|
||||
struct DisplayChangeListener *dcl = s->listeners;
|
||||
while (dcl != NULL) {
|
||||
if (dcl->dpy_copy)
|
||||
dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h);
|
||||
else /* TODO */
|
||||
dcl->dpy_update(s, dst_x, dst_y, w, h);
|
||||
dcl = dcl->next;
|
||||
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)
|
||||
{
|
||||
struct DisplayChangeListener *dcl;
|
||||
QLIST_FOREACH(dcl, &s->listeners, next) {
|
||||
if (dcl->dpy_gfx_copy) {
|
||||
dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h);
|
||||
} else { /* TODO */
|
||||
dcl->dpy_gfx_update(s, dst_x, dst_y, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dpy_fill(struct DisplayState *s, int x, int y,
|
||||
int w, int h, uint32_t c) {
|
||||
struct DisplayChangeListener *dcl = s->listeners;
|
||||
while (dcl != NULL) {
|
||||
if (dcl->dpy_fill) dcl->dpy_fill(s, x, y, w, h, c);
|
||||
dcl = dcl->next;
|
||||
static inline void dpy_text_cursor(struct DisplayState *s, int x, int y)
|
||||
{
|
||||
struct DisplayChangeListener *dcl;
|
||||
QLIST_FOREACH(dcl, &s->listeners, next) {
|
||||
if (dcl->dpy_text_cursor) {
|
||||
dcl->dpy_text_cursor(s, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dpy_cursor(struct DisplayState *s, int x, int y) {
|
||||
struct DisplayChangeListener *dcl = s->listeners;
|
||||
while (dcl != NULL) {
|
||||
if (dcl->dpy_text_cursor) dcl->dpy_text_cursor(s, x, y);
|
||||
dcl = dcl->next;
|
||||
static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
|
||||
{
|
||||
struct DisplayChangeListener *dcl;
|
||||
QLIST_FOREACH(dcl, &s->listeners, 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)
|
||||
{
|
||||
return ds->surface->linesize;
|
||||
return pixman_image_get_stride(ds->surface->image);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return ds->surface->width;
|
||||
return pixman_image_get_width(ds->surface->image);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -921,7 +921,7 @@ static void blizzard_update_display(void *opaque)
|
|||
for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
|
||||
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[0] = s->x;
|
||||
|
|
|
@ -1307,7 +1307,7 @@ static void exynos4210_fimd_update(void *opaque)
|
|||
fimd_copy_line_toqemu(global_width, s->ifb + global_width * line *
|
||||
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->vidintcon[1] |= FIMD_VIDINT_INTFRMPEND;
|
||||
|
|
|
@ -197,7 +197,8 @@ static void g364fb_draw_graphic8(G364State *s)
|
|||
reset_dirty(s, page_min, page_max);
|
||||
page_min = (ram_addr_t)-1;
|
||||
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;
|
||||
xmax = 0;
|
||||
ymin = s->height;
|
||||
|
@ -216,7 +217,7 @@ static void g364fb_draw_graphic8(G364State *s)
|
|||
|
||||
done:
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -238,7 +239,7 @@ static void g364fb_draw_blank(G364State *s)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ static void jazz_led_update_display(void *opaque)
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -210,7 +210,7 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
|
|||
LedState *s = opaque;
|
||||
char buf[2];
|
||||
|
||||
dpy_cursor(s->ds, -1, -1);
|
||||
dpy_text_cursor(s->ds, -1, -1);
|
||||
qemu_console_resize(s->ds, 2, 1);
|
||||
|
||||
/* 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[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)
|
||||
|
|
|
@ -134,7 +134,7 @@ static void vgafb_update_display(void *opaque)
|
|||
&first, &last);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -526,7 +526,7 @@ static void lcd_refresh(void *opaque)
|
|||
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)
|
||||
|
|
|
@ -1375,7 +1375,7 @@ static void n8x0_init(QEMUMachineInitArgs *args,
|
|||
size until the guest activates the display. */
|
||||
ds = get_displaystate();
|
||||
ds->surface = qemu_resize_displaysurface(ds, 800, 480);
|
||||
dpy_resize(ds);
|
||||
dpy_gfx_resize(ds);
|
||||
}
|
||||
|
||||
static struct arm_boot_info n800_binfo = {
|
||||
|
|
|
@ -219,7 +219,7 @@ static void omap_update_display(void *opaque)
|
|||
draw_line, omap_lcd->palette,
|
||||
&first, &last);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -273,7 +273,7 @@ static void palmte_init(QEMUMachineInitArgs *args)
|
|||
will set the size once configured, so this just sets an initial
|
||||
size until the guest activates the display. */
|
||||
ds->surface = qemu_resize_displaysurface(ds, 320, 320);
|
||||
dpy_resize(ds);
|
||||
dpy_gfx_resize(ds);
|
||||
}
|
||||
|
||||
static QEMUMachine palmte_machine = {
|
||||
|
|
|
@ -239,7 +239,7 @@ static void pl110_update_display(void *opaque)
|
|||
fn, s->palette,
|
||||
&first, &last);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -871,20 +871,20 @@ static void pxa2xx_update_display(void *opaque)
|
|||
if (miny >= 0) {
|
||||
switch (s->orientation) {
|
||||
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;
|
||||
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;
|
||||
case 180:
|
||||
maxy = s->yres - maxy - 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;
|
||||
case 270:
|
||||
maxy = s->yres - maxy - 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
|
||||
{
|
||||
uint8_t *src;
|
||||
uint8_t *dst = qxl->vga.ds->surface->data;
|
||||
uint8_t *dst = ds_get_data(qxl->vga.ds);
|
||||
int len, i;
|
||||
|
||||
if (is_buffer_shared(qxl->vga.ds->surface)) {
|
||||
|
@ -123,14 +123,14 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
|
|||
qxl->guest_primary.surface.width,
|
||||
qxl->guest_primary.surface.height);
|
||||
}
|
||||
dpy_resize(vga->ds);
|
||||
dpy_gfx_resize(vga->ds);
|
||||
}
|
||||
for (i = 0; i < qxl->num_dirty_rects; i++) {
|
||||
if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
|
||||
break;
|
||||
}
|
||||
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].right - qxl->dirty[i].left,
|
||||
qxl->dirty[i].bottom - qxl->dirty[i].top);
|
||||
|
@ -234,7 +234,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!qxl->ssd.ds->mouse_set || !qxl->ssd.ds->cursor_define) {
|
||||
if (!dpy_cursor_define_supported(qxl->ssd.ds)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
4
hw/qxl.c
4
hw/qxl.c
|
@ -1864,8 +1864,8 @@ static void display_refresh(struct DisplayState *ds)
|
|||
}
|
||||
|
||||
static DisplayChangeListener display_listener = {
|
||||
.dpy_update = display_update,
|
||||
.dpy_resize = display_resize,
|
||||
.dpy_gfx_update = display_update,
|
||||
.dpy_gfx_resize = display_resize,
|
||||
.dpy_refresh = display_refresh,
|
||||
};
|
||||
|
||||
|
|
|
@ -1351,7 +1351,7 @@ static void sm501_draw_crt(SM501State * s)
|
|||
} else {
|
||||
if (y_start >= 0) {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
@ -1362,7 +1362,7 @@ static void sm501_draw_crt(SM501State * s)
|
|||
|
||||
/* complete flush to display */
|
||||
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 */
|
||||
if (page_min != ~0l) {
|
||||
|
|
|
@ -252,7 +252,7 @@ static void ssd0303_update_display(void *opaque)
|
|||
}
|
||||
}
|
||||
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)
|
||||
|
|
|
@ -260,7 +260,7 @@ static void ssd0323_update_display(void *opaque)
|
|||
}
|
||||
}
|
||||
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)
|
||||
|
|
|
@ -454,7 +454,7 @@ static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
|
|||
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)
|
||||
|
@ -472,7 +472,7 @@ static void tc6393xb_draw_blank(TC6393xbState *s, int full_update)
|
|||
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)
|
||||
|
|
8
hw/tcx.c
8
hw/tcx.c
|
@ -268,7 +268,7 @@ static void tcx_update_display(void *opaque)
|
|||
} else {
|
||||
if (y_start >= 0) {
|
||||
/* flush to display */
|
||||
dpy_update(ts->ds, 0, y_start,
|
||||
dpy_gfx_update(ts->ds, 0, y_start,
|
||||
ts->width, y - y_start);
|
||||
y_start = -1;
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ static void tcx_update_display(void *opaque)
|
|||
}
|
||||
if (y_start >= 0) {
|
||||
/* flush to display */
|
||||
dpy_update(ts->ds, 0, y_start,
|
||||
dpy_gfx_update(ts->ds, 0, y_start,
|
||||
ts->width, y - y_start);
|
||||
}
|
||||
/* reset modified pages */
|
||||
|
@ -344,7 +344,7 @@ static void tcx24_update_display(void *opaque)
|
|||
} else {
|
||||
if (y_start >= 0) {
|
||||
/* flush to display */
|
||||
dpy_update(ts->ds, 0, y_start,
|
||||
dpy_gfx_update(ts->ds, 0, y_start,
|
||||
ts->width, y - y_start);
|
||||
y_start = -1;
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ static void tcx24_update_display(void *opaque)
|
|||
}
|
||||
if (y_start >= 0) {
|
||||
/* flush to display */
|
||||
dpy_update(ts->ds, 0, y_start,
|
||||
dpy_gfx_update(ts->ds, 0, y_start,
|
||||
ts->width, y - y_start);
|
||||
}
|
||||
/* reset modified pages */
|
||||
|
|
99
hw/vga.c
99
hw/vga.c
|
@ -1346,6 +1346,7 @@ static void vga_draw_text(VGACommonState *s, int full_update)
|
|||
s->last_scr_width = width * cw;
|
||||
s->last_scr_height = height * cheight;
|
||||
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_width = width;
|
||||
s->last_height = height;
|
||||
|
@ -1359,6 +1360,14 @@ static void vga_draw_text(VGACommonState *s, int full_update)
|
|||
palette = s->last_palette;
|
||||
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) |
|
||||
s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
|
||||
if (cursor_offset != s->cursor_offset ||
|
||||
|
@ -1456,7 +1465,7 @@ static void vga_draw_text(VGACommonState *s, int full_update)
|
|||
ch_attr_ptr++;
|
||||
}
|
||||
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);
|
||||
}
|
||||
dest += linesize * cheight;
|
||||
|
@ -1688,7 +1697,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
|||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||
s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
|
||||
#endif
|
||||
dpy_resize(s->ds);
|
||||
dpy_gfx_resize(s->ds);
|
||||
} else {
|
||||
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;
|
||||
full_update = 1;
|
||||
} else if (is_buffer_shared(s->ds->surface) &&
|
||||
(full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
|
||||
s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
|
||||
dpy_setdata(s->ds);
|
||||
(full_update || ds_get_data(s->ds) != s->vram_ptr
|
||||
+ (s->start_addr * 4))) {
|
||||
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 =
|
||||
|
@ -1807,7 +1821,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
|||
} else {
|
||||
if (y_start >= 0) {
|
||||
/* flush to display */
|
||||
dpy_update(s->ds, 0, y_start,
|
||||
dpy_gfx_update(s->ds, 0, y_start,
|
||||
disp_width, y - y_start);
|
||||
y_start = -1;
|
||||
}
|
||||
|
@ -1828,7 +1842,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
|||
}
|
||||
if (y_start >= 0) {
|
||||
/* flush to display */
|
||||
dpy_update(s->ds, 0, y_start,
|
||||
dpy_gfx_update(s->ds, 0, y_start,
|
||||
disp_width, y - y_start);
|
||||
}
|
||||
/* reset modified pages */
|
||||
|
@ -1863,7 +1877,7 @@ static void vga_draw_blank(VGACommonState *s, int full_update)
|
|||
memset(d, val, w);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2052,9 +2066,9 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
|
|||
cw != s->last_cw || cheight != s->last_ch) {
|
||||
s->last_scr_width = width * cw;
|
||||
s->last_scr_height = height * cheight;
|
||||
s->ds->surface->width = width;
|
||||
s->ds->surface->height = height;
|
||||
dpy_resize(s->ds);
|
||||
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_width = width;
|
||||
s->last_height = height;
|
||||
s->last_ch = cheight;
|
||||
|
@ -2062,6 +2076,14 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
|
|||
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 */
|
||||
cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
|
||||
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) {
|
||||
cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
|
||||
if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
|
||||
dpy_cursor(s->ds,
|
||||
dpy_text_cursor(s->ds,
|
||||
TEXTMODE_X(cursor_offset),
|
||||
TEXTMODE_Y(cursor_offset));
|
||||
else
|
||||
dpy_cursor(s->ds, -1, -1);
|
||||
dpy_text_cursor(s->ds, -1, -1);
|
||||
s->cursor_offset = cursor_offset;
|
||||
s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
|
||||
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 ++)
|
||||
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 {
|
||||
c_max = 0;
|
||||
|
||||
|
@ -2110,7 +2132,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
|
|||
|
||||
if (c_min <= c_max) {
|
||||
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 */
|
||||
s->last_width = 60;
|
||||
s->last_height = height = 3;
|
||||
dpy_cursor(s->ds, -1, -1);
|
||||
s->ds->surface->width = s->last_width;
|
||||
s->ds->surface->height = height;
|
||||
dpy_resize(s->ds);
|
||||
dpy_text_cursor(s->ds, -1, -1);
|
||||
dpy_text_resize(s->ds, s->last_width, height);
|
||||
|
||||
for (dst = chardata, i = 0; i < s->last_width * height; i ++)
|
||||
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 ++)
|
||||
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,
|
||||
|
@ -2373,13 +2393,12 @@ void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
|
|||
|
||||
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;
|
||||
uint8_t *d, *d1;
|
||||
uint32_t v;
|
||||
int y, x;
|
||||
uint8_t r, g, b;
|
||||
int y;
|
||||
int ret;
|
||||
char *linebuf, *pbuf;
|
||||
pixman_image_t *linebuf;
|
||||
|
||||
trace_ppm_save(filename, ds);
|
||||
f = fopen(filename, "wb");
|
||||
|
@ -2388,33 +2407,17 @@ void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp)
|
|||
strerror(errno));
|
||||
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) {
|
||||
linebuf = NULL;
|
||||
goto write_err;
|
||||
}
|
||||
linebuf = g_malloc(ds->width * 3);
|
||||
d1 = ds->data;
|
||||
for(y = 0; y < ds->height; 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;
|
||||
linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
|
||||
for (y = 0; y < height; y++) {
|
||||
qemu_pixman_linebuf_fill(linebuf, ds->image, width, y);
|
||||
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;
|
||||
if (ferror(f)) {
|
||||
goto write_err;
|
||||
|
@ -2422,7 +2425,7 @@ void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp)
|
|||
}
|
||||
|
||||
out:
|
||||
g_free(linebuf);
|
||||
qemu_pixman_image_unref(linebuf);
|
||||
fclose(f);
|
||||
return;
|
||||
|
||||
|
|
|
@ -154,6 +154,8 @@ typedef struct VGACommonState {
|
|||
vga_hw_invalidate_ptr invalidate;
|
||||
vga_hw_screen_dump_ptr screen_dump;
|
||||
vga_hw_text_update_ptr text_update;
|
||||
bool full_update_text;
|
||||
bool full_update_gfx;
|
||||
/* hardware mouse cursor support */
|
||||
uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32];
|
||||
void (*cursor_invalidate)(struct VGACommonState *s);
|
||||
|
|
|
@ -321,14 +321,14 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
|
|||
for (; line > 0; line --, src += bypl, dst += bypl)
|
||||
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)
|
||||
{
|
||||
memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr,
|
||||
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,
|
||||
|
@ -478,8 +478,7 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
|
|||
qc = cursor_builtin_left_ptr();
|
||||
}
|
||||
|
||||
if (s->vga.ds->cursor_define)
|
||||
s->vga.ds->cursor_define(qc);
|
||||
dpy_cursor_define(s->vga.ds, qc);
|
||||
cursor_put(qc);
|
||||
}
|
||||
#endif
|
||||
|
@ -754,9 +753,10 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
|
|||
caps |= SVGA_CAP_RECT_FILL;
|
||||
#endif
|
||||
#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 |
|
||||
SVGA_CAP_CURSOR_BYPASS;
|
||||
}
|
||||
#endif
|
||||
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_HIDE);
|
||||
#ifdef HW_MOUSE_ACCEL
|
||||
if (s->vga.ds->mouse_set && value <= SVGA_CURSOR_ON_SHOW)
|
||||
s->vga.ds->mouse_set(s->cursor.x, s->cursor.y, s->cursor.on);
|
||||
if (value <= SVGA_CURSOR_ON_SHOW) {
|
||||
dpy_mouse_set(s->vga.ds, s->cursor.x, s->cursor.y, s->cursor.on);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
|
|
@ -717,7 +717,7 @@ static void xenfb_update(void *opaque)
|
|||
if (xenfb_queue_full(xenfb))
|
||||
return;
|
||||
|
||||
for (l = xenfb->c.ds->listeners; l != NULL; l = l->next) {
|
||||
QLIST_FOREACH(l, &xenfb->c.ds->listeners, next) {
|
||||
if (l->idle)
|
||||
continue;
|
||||
idle = 0;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 97336fad32acf802003855cd8bd6477fa49a12e3
|
|
@ -261,10 +261,8 @@ typedef struct DriveInfo DriveInfo;
|
|||
typedef struct DisplayState DisplayState;
|
||||
typedef struct DisplayChangeListener DisplayChangeListener;
|
||||
typedef struct DisplaySurface DisplaySurface;
|
||||
typedef struct DisplayAllocator DisplayAllocator;
|
||||
typedef struct PixelFormat PixelFormat;
|
||||
typedef struct TextConsole TextConsole;
|
||||
typedef TextConsole QEMUConsole;
|
||||
typedef struct QemuConsole QemuConsole;
|
||||
typedef struct CharDriverState CharDriverState;
|
||||
typedef struct MACAddr MACAddr;
|
||||
typedef struct NetClientState NetClientState;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
21
ui/curses.c
21
ui/curses.c
|
@ -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;
|
||||
}
|
||||
|
||||
gwidth = ds_get_width(ds);
|
||||
gheight = ds_get_height(ds);
|
||||
gwidth = width;
|
||||
gheight = height;
|
||||
|
||||
curses_calc_pad();
|
||||
ds->surface->width = width * FONT_WIDTH;
|
||||
ds->surface->height = height * FONT_HEIGHT;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -167,8 +166,6 @@ static void curses_refresh(DisplayState *ds)
|
|||
clear();
|
||||
refresh();
|
||||
curses_calc_pad();
|
||||
ds->surface->width = FONT_WIDTH * width;
|
||||
ds->surface->height = FONT_HEIGHT * height;
|
||||
vga_hw_invalidate();
|
||||
invalidate = 0;
|
||||
}
|
||||
|
@ -195,8 +192,6 @@ static void curses_refresh(DisplayState *ds)
|
|||
refresh();
|
||||
curses_calc_pad();
|
||||
curses_update(ds, 0, 0, width, height);
|
||||
ds->surface->width = FONT_WIDTH * width;
|
||||
ds->surface->height = FONT_HEIGHT * height;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
@ -355,13 +350,11 @@ void curses_display_init(DisplayState *ds, int full_screen)
|
|||
#endif
|
||||
|
||||
dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener));
|
||||
dcl->dpy_update = curses_update;
|
||||
dcl->dpy_resize = curses_resize;
|
||||
dcl->dpy_text_update = curses_update;
|
||||
dcl->dpy_text_resize = curses_resize;
|
||||
dcl->dpy_refresh = curses_refresh;
|
||||
dcl->dpy_text_cursor = curses_cursor_position;
|
||||
register_displaychangelistener(ds, dcl);
|
||||
qemu_free_displaysurface(ds);
|
||||
ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen);
|
||||
|
||||
invalidate = 1;
|
||||
}
|
||||
|
|
138
ui/sdl.c
138
ui/sdl.c
|
@ -55,7 +55,6 @@ static int absolute_enabled = 0;
|
|||
static int guest_cursor = 0;
|
||||
static int guest_x, guest_y;
|
||||
static SDL_Cursor *guest_sprite = NULL;
|
||||
static uint8_t allocator;
|
||||
static SDL_PixelFormat host_format;
|
||||
static int scaling_active = 0;
|
||||
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)
|
||||
{
|
||||
if (!allocator) {
|
||||
if (!scaling_active)
|
||||
if (!scaling_active) {
|
||||
do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
|
||||
else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds))
|
||||
do_sdl_resize(real_screen->w, real_screen->h, 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,
|
||||
ds_get_bits_per_pixel(ds));
|
||||
}
|
||||
sdl_setdata(ds);
|
||||
} else {
|
||||
if (guest_screen != NULL) {
|
||||
SDL_FreeSurface(guest_screen);
|
||||
guest_screen = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
|
@ -553,7 +457,7 @@ static void sdl_scale(DisplayState *ds, int width, int height)
|
|||
if (!is_buffer_shared(ds->surface)) {
|
||||
ds->surface = qemu_resize_displaysurface(ds, ds_get_width(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)
|
||||
{
|
||||
SDL_Rect dst = { x, y, w, h };
|
||||
SDL_FillRect(real_screen, &dst, c);
|
||||
}
|
||||
|
||||
static void sdl_mouse_warp(int x, int y, int on)
|
||||
static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on)
|
||||
{
|
||||
if (on) {
|
||||
if (!guest_cursor)
|
||||
|
@ -921,7 +819,7 @@ static void sdl_mouse_warp(int x, int y, int on)
|
|||
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;
|
||||
int bpl;
|
||||
|
@ -955,7 +853,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
|
|||
{
|
||||
int flags;
|
||||
uint8_t data = 0;
|
||||
DisplayAllocator *da;
|
||||
const SDL_VideoInfo *vi;
|
||||
char *filename;
|
||||
|
||||
|
@ -1020,23 +917,14 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
|
|||
}
|
||||
|
||||
dcl = g_malloc0(sizeof(DisplayChangeListener));
|
||||
dcl->dpy_update = sdl_update;
|
||||
dcl->dpy_resize = sdl_resize;
|
||||
dcl->dpy_gfx_update = sdl_update;
|
||||
dcl->dpy_gfx_resize = sdl_resize;
|
||||
dcl->dpy_refresh = sdl_refresh;
|
||||
dcl->dpy_setdata = sdl_setdata;
|
||||
dcl->dpy_fill = sdl_fill;
|
||||
ds->mouse_set = sdl_mouse_warp;
|
||||
ds->cursor_define = sdl_mouse_define;
|
||||
dcl->dpy_gfx_setdata = sdl_setdata;
|
||||
dcl->dpy_mouse_set = sdl_mouse_warp;
|
||||
dcl->dpy_cursor_define = sdl_mouse_define;
|
||||
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;
|
||||
qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier);
|
||||
|
||||
|
|
|
@ -404,12 +404,12 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
|
|||
void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
|
||||
{
|
||||
if (ssd->cursor) {
|
||||
ssd->ds->cursor_define(ssd->cursor);
|
||||
dpy_cursor_define(ssd->ds, ssd->cursor);
|
||||
cursor_put(ssd->cursor);
|
||||
ssd->cursor = NULL;
|
||||
}
|
||||
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_y = -1;
|
||||
}
|
||||
|
@ -571,8 +571,8 @@ static void display_refresh(struct DisplayState *ds)
|
|||
}
|
||||
|
||||
static DisplayChangeListener display_listener = {
|
||||
.dpy_update = display_update,
|
||||
.dpy_resize = display_resize,
|
||||
.dpy_gfx_update = display_update,
|
||||
.dpy_gfx_resize = display_resize,
|
||||
.dpy_refresh = display_refresh,
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
|
|||
int *has_bg, int *has_fg)
|
||||
{
|
||||
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;
|
||||
int j, i;
|
||||
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 fg_count = 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_subtiles = 0;
|
||||
|
||||
|
@ -58,7 +58,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
|
|||
}
|
||||
if (n_colors > 2)
|
||||
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) {
|
||||
|
@ -106,7 +106,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
|
|||
n_data += 2;
|
||||
n_subtiles++;
|
||||
}
|
||||
irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
|
||||
irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
|
@ -133,7 +133,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
|
|||
has_color = 0;
|
||||
#ifdef GENERIC
|
||||
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
|
||||
memcpy(data + n_data, &color, sizeof(color));
|
||||
n_data += sizeof(pixel_t);
|
||||
|
@ -153,7 +153,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
|
|||
if (has_color) {
|
||||
#ifdef GENERIC
|
||||
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
|
||||
memcpy(data + n_data, &color, sizeof(color));
|
||||
n_data += sizeof(pixel_t);
|
||||
|
@ -162,7 +162,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
|
|||
n_data += 2;
|
||||
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 */
|
||||
|
@ -190,18 +190,17 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
|
|||
vnc_write_u8(vs, flags);
|
||||
if (n_colors < 4) {
|
||||
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)
|
||||
vs->write_pixels(vs, &vd->server->pf, last_fg, sizeof(pixel_t));
|
||||
vs->write_pixels(vs, last_fg, sizeof(pixel_t));
|
||||
if (n_subtiles) {
|
||||
vnc_write_u8(vs, n_subtiles);
|
||||
vnc_write(vs, data, n_data);
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < h; j++) {
|
||||
vs->write_pixels(vs, &vd->server->pf, row,
|
||||
w * ds_get_bytes_per_pixel(vs->ds));
|
||||
row += ds_get_linesize(vs->ds);
|
||||
vs->write_pixels(vs, row, w * 4);
|
||||
row += vnc_server_fb_stride(vd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
#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
|
||||
#include "vnc-enc-hextile-template.h"
|
||||
#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 BPP 32
|
||||
#include "vnc-enc-hextile-template.h"
|
||||
|
@ -68,10 +48,9 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
|
|||
int i, j;
|
||||
int has_fg, has_bg;
|
||||
uint8_t *last_fg, *last_bg;
|
||||
VncDisplay *vd = vs->vd;
|
||||
|
||||
last_fg = (uint8_t *) g_malloc(vd->server->pf.bytes_per_pixel);
|
||||
last_bg = (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(VNC_SERVER_FB_BYTES);
|
||||
has_fg = has_bg = 0;
|
||||
for (j = y; j < (y + h); j += 16) {
|
||||
for (i = x; i < (x + w); i += 16) {
|
||||
|
@ -89,25 +68,13 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
|
|||
void vnc_hextile_set_pixel_conversion(VncState *vs, int generic)
|
||||
{
|
||||
if (!generic) {
|
||||
switch (vs->ds->surface->pf.bits_per_pixel) {
|
||||
case 8:
|
||||
vs->hextile.send_tile = send_hextile_tile_8;
|
||||
break;
|
||||
case 16:
|
||||
vs->hextile.send_tile = send_hextile_tile_16;
|
||||
break;
|
||||
switch (VNC_SERVER_FB_BITS) {
|
||||
case 32:
|
||||
vs->hextile.send_tile = send_hextile_tile_32;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (vs->ds->surface->pf.bits_per_pixel) {
|
||||
case 8:
|
||||
vs->hextile.send_tile = send_hextile_tile_generic_8;
|
||||
break;
|
||||
case 16:
|
||||
vs->hextile.send_tile = send_hextile_tile_generic_16;
|
||||
break;
|
||||
switch (VNC_SERVER_FB_BITS) {
|
||||
case 32:
|
||||
vs->hextile.send_tile = send_hextile_tile_generic_32;
|
||||
break;
|
||||
|
|
|
@ -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 ||
|
||||
vs->clientds.pf.bytes_per_pixel == 1) {
|
||||
vs->client_pf.bytes_per_pixel == 1) {
|
||||
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
|
||||
* 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));
|
||||
|
||||
|
@ -216,16 +216,16 @@ tight_detect_smooth_image24(VncState *vs, int w, int h)
|
|||
unsigned int errors; \
|
||||
unsigned char *buf = vs->tight.tight.buffer; \
|
||||
\
|
||||
endian = ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
|
||||
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); \
|
||||
endian = 0; /* FIXME: ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
|
||||
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); */ \
|
||||
\
|
||||
\
|
||||
max[0] = vs->clientds.pf.rmax; \
|
||||
max[1] = vs->clientds.pf.gmax; \
|
||||
max[2] = vs->clientds.pf.bmax; \
|
||||
shift[0] = vs->clientds.pf.rshift; \
|
||||
shift[1] = vs->clientds.pf.gshift; \
|
||||
shift[2] = vs->clientds.pf.bshift; \
|
||||
max[0] = vs->client_pf.rmax; \
|
||||
max[1] = vs->client_pf.gmax; \
|
||||
max[2] = vs->client_pf.bmax; \
|
||||
shift[0] = vs->client_pf.rshift; \
|
||||
shift[1] = vs->client_pf.gshift; \
|
||||
shift[2] = vs->client_pf.bshift; \
|
||||
\
|
||||
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 ||
|
||||
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) {
|
||||
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) {
|
||||
errors = tight_detect_smooth_image24(vs, w, h);
|
||||
if (vs->tight.quality != (uint8_t)-1) {
|
||||
|
@ -430,7 +430,7 @@ static int tight_fill_palette(VncState *vs, int x, int y,
|
|||
max = 256;
|
||||
}
|
||||
|
||||
switch(vs->clientds.pf.bytes_per_pixel) {
|
||||
switch (vs->client_pf.bytes_per_pixel) {
|
||||
case 4:
|
||||
return tight_fill_palette32(vs, x, y, max, count, bg, fg, palette);
|
||||
case 2:
|
||||
|
@ -557,15 +557,15 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h)
|
|||
buf32 = (uint32_t *)buf;
|
||||
memset(vs->tight.gradient.buffer, 0, w * 3 * sizeof(int));
|
||||
|
||||
if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
|
||||
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)) {
|
||||
shift[0] = vs->clientds.pf.rshift;
|
||||
shift[1] = vs->clientds.pf.gshift;
|
||||
shift[2] = vs->clientds.pf.bshift;
|
||||
if (1 /* FIXME: (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
|
||||
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) */) {
|
||||
shift[0] = vs->client_pf.rshift;
|
||||
shift[1] = vs->client_pf.gshift;
|
||||
shift[2] = vs->client_pf.bshift;
|
||||
} else {
|
||||
shift[0] = 24 - vs->clientds.pf.rshift;
|
||||
shift[1] = 24 - vs->clientds.pf.gshift;
|
||||
shift[2] = 24 - vs->clientds.pf.bshift;
|
||||
shift[0] = 24 - vs->client_pf.rshift;
|
||||
shift[1] = 24 - vs->client_pf.gshift;
|
||||
shift[2] = 24 - vs->client_pf.bshift;
|
||||
}
|
||||
|
||||
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)); \
|
||||
\
|
||||
endian = ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
|
||||
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); \
|
||||
endian = 0; /* FIXME: ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
|
||||
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); */ \
|
||||
\
|
||||
max[0] = vs->clientds.pf.rmax; \
|
||||
max[1] = vs->clientds.pf.gmax; \
|
||||
max[2] = vs->clientds.pf.bmax; \
|
||||
shift[0] = vs->clientds.pf.rshift; \
|
||||
shift[1] = vs->clientds.pf.gshift; \
|
||||
shift[2] = vs->clientds.pf.bshift; \
|
||||
max[0] = vs->client_pf.rmax; \
|
||||
max[1] = vs->client_pf.gmax; \
|
||||
max[2] = vs->client_pf.bmax; \
|
||||
shift[0] = vs->client_pf.rshift; \
|
||||
shift[1] = vs->client_pf.gshift; \
|
||||
shift[2] = vs->client_pf.bshift; \
|
||||
\
|
||||
for (y = 0; y < h; y++) { \
|
||||
for (c = 0; c < 3; c++) { \
|
||||
|
@ -671,56 +671,42 @@ DEFINE_GRADIENT_FILTER_FUNCTION(32)
|
|||
* that case new color will be stored in *colorPtr.
|
||||
*/
|
||||
|
||||
#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \
|
||||
\
|
||||
static bool \
|
||||
check_solid_tile##bpp(VncState *vs, int x, int y, int w, int h, \
|
||||
uint32_t* color, bool samecolor) \
|
||||
{ \
|
||||
VncDisplay *vd = vs->vd; \
|
||||
uint##bpp##_t *fbptr; \
|
||||
uint##bpp##_t c; \
|
||||
int dx, dy; \
|
||||
\
|
||||
fbptr = (uint##bpp##_t *) \
|
||||
(vd->server->data + y * ds_get_linesize(vs->ds) + \
|
||||
x * ds_get_bytes_per_pixel(vs->ds)); \
|
||||
\
|
||||
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; \
|
||||
static bool
|
||||
check_solid_tile32(VncState *vs, int x, int y, int w, int h,
|
||||
uint32_t *color, bool samecolor)
|
||||
{
|
||||
VncDisplay *vd = vs->vd;
|
||||
uint32_t *fbptr;
|
||||
uint32_t c;
|
||||
int dx, dy;
|
||||
|
||||
fbptr = vnc_server_fb_ptr(vd, x, y);
|
||||
|
||||
c = *fbptr;
|
||||
if (samecolor && (uint32_t)c != *color) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_CHECK_SOLID_FUNCTION(32)
|
||||
DEFINE_CHECK_SOLID_FUNCTION(16)
|
||||
DEFINE_CHECK_SOLID_FUNCTION(8)
|
||||
for (dy = 0; dy < h; dy++) {
|
||||
for (dx = 0; dx < w; dx++) {
|
||||
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,
|
||||
uint32_t* color, bool samecolor)
|
||||
{
|
||||
VncDisplay *vd = vs->vd;
|
||||
|
||||
switch(vd->server->pf.bytes_per_pixel) {
|
||||
switch (VNC_SERVER_FB_BYTES) {
|
||||
case 4:
|
||||
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;
|
||||
|
||||
if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
|
||||
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)) {
|
||||
rshift = vs->clientds.pf.rshift;
|
||||
gshift = vs->clientds.pf.gshift;
|
||||
bshift = vs->clientds.pf.bshift;
|
||||
if (1 /* FIXME: (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
|
||||
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) */) {
|
||||
rshift = vs->client_pf.rshift;
|
||||
gshift = vs->client_pf.gshift;
|
||||
bshift = vs->client_pf.bshift;
|
||||
} else {
|
||||
rshift = 24 - vs->clientds.pf.rshift;
|
||||
gshift = 24 - vs->clientds.pf.gshift;
|
||||
bshift = 24 - vs->clientds.pf.bshift;
|
||||
rshift = 24 - vs->client_pf.rshift;
|
||||
gshift = 24 - vs->client_pf.gshift;
|
||||
bshift = 24 - vs->client_pf.bshift;
|
||||
}
|
||||
|
||||
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);
|
||||
bytes = 3;
|
||||
} else {
|
||||
bytes = vs->clientds.pf.bytes_per_pixel;
|
||||
bytes = vs->client_pf.bytes_per_pixel;
|
||||
}
|
||||
|
||||
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);
|
||||
bytes = 3;
|
||||
} else {
|
||||
bytes = vs->clientds.pf.bytes_per_pixel;
|
||||
bytes = vs->client_pf.bytes_per_pixel;
|
||||
}
|
||||
|
||||
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
|
||||
if (tight_can_send_png_rect(vs, w, h)) {
|
||||
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);
|
||||
|
||||
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, 1);
|
||||
|
||||
switch(vs->clientds.pf.bytes_per_pixel) {
|
||||
switch (vs->client_pf.bytes_per_pixel) {
|
||||
case 4:
|
||||
{
|
||||
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;
|
||||
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) {
|
||||
((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;
|
||||
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);
|
||||
}
|
||||
|
||||
vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4);
|
||||
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) {
|
||||
tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h);
|
||||
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);
|
||||
bytes = 4;
|
||||
} 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, colors - 1);
|
||||
|
||||
switch(vs->clientds.pf.bytes_per_pixel) {
|
||||
switch (vs->client_pf.bytes_per_pixel) {
|
||||
case 4:
|
||||
{
|
||||
size_t old_offset, offset;
|
||||
|
@ -1148,79 +1135,6 @@ static int send_palette_rect(VncState *vs, int x, int y,
|
|||
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.
|
||||
*/
|
||||
|
@ -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_error_mgr jerr;
|
||||
struct jpeg_destination_mgr manager;
|
||||
pixman_image_t *linebuf;
|
||||
JSAMPROW row[1];
|
||||
uint8_t *buf;
|
||||
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);
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
g_free(buf);
|
||||
qemu_pixman_image_unref(linebuf);
|
||||
|
||||
jpeg_finish_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)
|
||||
{
|
||||
color->red = (pix >> vs->clientds.pf.rshift) & vs->clientds.pf.rmax;
|
||||
color->green = (pix >> vs->clientds.pf.gshift) & vs->clientds.pf.gmax;
|
||||
color->blue = (pix >> vs->clientds.pf.bshift) & vs->clientds.pf.bmax;
|
||||
color->red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax;
|
||||
color->green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax;
|
||||
color->blue = (pix >> vs->client_pf.bshift) & vs->client_pf.bmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
int red, green, blue;
|
||||
|
||||
red = (pix >> vs->clientds.pf.rshift) & vs->clientds.pf.rmax;
|
||||
green = (pix >> vs->clientds.pf.gshift) & vs->clientds.pf.gmax;
|
||||
blue = (pix >> vs->clientds.pf.bshift) & vs->clientds.pf.bmax;
|
||||
color->red = ((red * 255 + vs->clientds.pf.rmax / 2) /
|
||||
vs->clientds.pf.rmax);
|
||||
color->green = ((green * 255 + vs->clientds.pf.gmax / 2) /
|
||||
vs->clientds.pf.gmax);
|
||||
color->blue = ((blue * 255 + vs->clientds.pf.bmax / 2) /
|
||||
vs->clientds.pf.bmax);
|
||||
red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax;
|
||||
green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax;
|
||||
blue = (pix >> vs->client_pf.bshift) & vs->client_pf.bmax;
|
||||
color->red = ((red * 255 + vs->client_pf.rmax / 2) /
|
||||
vs->client_pf.rmax);
|
||||
color->green = ((green * 255 + vs->client_pf.gmax / 2) /
|
||||
vs->client_pf.gmax);
|
||||
color->blue = ((blue * 255 + vs->client_pf.bmax / 2) /
|
||||
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_infop info_ptr;
|
||||
png_colorp png_palette = NULL;
|
||||
pixman_image_t *linebuf;
|
||||
int level = tight_png_conf[vs->tight.compression].png_zlib_level;
|
||||
int filters = tight_png_conf[vs->tight.compression].png_filters;
|
||||
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));
|
||||
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
|
||||
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++)
|
||||
{
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
memcpy(buf, vs->tight.tight.buffer + (dy * w), w);
|
||||
} 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);
|
||||
}
|
||||
g_free(buf);
|
||||
qemu_pixman_image_unref(linebuf);
|
||||
|
||||
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;
|
||||
|
||||
if (vs->clientds.pf.bytes_per_pixel == 4 && vs->clientds.pf.rmax == 0xFF &&
|
||||
vs->clientds.pf.bmax == 0xFF && vs->clientds.pf.gmax == 0xFF) {
|
||||
if (vs->client_pf.bytes_per_pixel == 4 && vs->client_pf.rmax == 0xFF &&
|
||||
vs->client_pf.bmax == 0xFF && vs->client_pf.gmax == 0xFF) {
|
||||
vs->tight.pixel24 = true;
|
||||
} else {
|
||||
vs->tight.pixel24 = false;
|
||||
|
|
|
@ -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,
|
||||
int w, int h)
|
||||
{
|
||||
bool be = !!(vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG);
|
||||
bool be = vs->client_be;
|
||||
size_t bytes;
|
||||
int zywrle_level;
|
||||
|
||||
|
@ -277,13 +277,13 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
|
|||
|
||||
vnc_zrle_start(vs);
|
||||
|
||||
switch(vs->clientds.pf.bytes_per_pixel) {
|
||||
switch (vs->client_pf.bytes_per_pixel) {
|
||||
case 1:
|
||||
zrle_encode_8ne(vs, x, y, w, h, zywrle_level);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (vs->clientds.pf.gmax > 0x1F) {
|
||||
if (vs->client_pf.gmax > 0x1F) {
|
||||
if (be) {
|
||||
zrle_encode_16be(vs, x, y, w, h, zywrle_level);
|
||||
} else {
|
||||
|
@ -304,13 +304,13 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
|
|||
bool fits_in_ms3bytes;
|
||||
|
||||
fits_in_ls3bytes =
|
||||
((vs->clientds.pf.rmax << vs->clientds.pf.rshift) < (1 << 24) &&
|
||||
(vs->clientds.pf.gmax << vs->clientds.pf.gshift) < (1 << 24) &&
|
||||
(vs->clientds.pf.bmax << vs->clientds.pf.bshift) < (1 << 24));
|
||||
((vs->client_pf.rmax << vs->client_pf.rshift) < (1 << 24) &&
|
||||
(vs->client_pf.gmax << vs->client_pf.gshift) < (1 << 24) &&
|
||||
(vs->client_pf.bmax << vs->client_pf.bshift) < (1 << 24));
|
||||
|
||||
fits_in_ms3bytes = (vs->clientds.pf.rshift > 7 &&
|
||||
vs->clientds.pf.gshift > 7 &&
|
||||
vs->clientds.pf.bshift > 7);
|
||||
fits_in_ms3bytes = (vs->client_pf.rshift > 7 &&
|
||||
vs->client_pf.gshift > 7 &&
|
||||
vs->client_pf.bshift > 7);
|
||||
|
||||
if ((fits_in_ls3bytes && !be) || (fits_in_ms3bytes && be)) {
|
||||
if (be) {
|
||||
|
|
|
@ -187,7 +187,8 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
|
|||
local->vd = orig->vd;
|
||||
local->lossy_rect = orig->lossy_rect;
|
||||
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->zlib = orig->zlib;
|
||||
local->hextile = orig->hextile;
|
||||
|
|
253
ui/vnc.c
253
ui/vnc.c
|
@ -436,6 +436,8 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
|
|||
int i;
|
||||
VncDisplay *vd = ds->opaque;
|
||||
struct VncSurface *s = &vd->guest;
|
||||
int width = ds_get_width(ds);
|
||||
int height = ds_get_height(ds);
|
||||
|
||||
h += y;
|
||||
|
||||
|
@ -446,10 +448,10 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
|
|||
w += (x % 16);
|
||||
x -= (x % 16);
|
||||
|
||||
x = MIN(x, s->ds->width);
|
||||
y = MIN(y, s->ds->height);
|
||||
w = MIN(x + w, s->ds->width) - x;
|
||||
h = MIN(h, s->ds->height);
|
||||
x = MIN(x, width);
|
||||
y = MIN(y, height);
|
||||
w = MIN(x + w, width) - x;
|
||||
h = MIN(h, height);
|
||||
|
||||
for (; y < h; y++)
|
||||
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)
|
||||
{
|
||||
VncDisplay *vd = ds->opaque;
|
||||
|
@ -558,20 +575,20 @@ static void vnc_dpy_resize(DisplayState *ds)
|
|||
vnc_abort_display_jobs(vd);
|
||||
|
||||
/* server surface */
|
||||
if (!vd->server)
|
||||
vd->server = g_malloc0(sizeof(*vd->server));
|
||||
if (vd->server->data)
|
||||
g_free(vd->server->data);
|
||||
*(vd->server) = *(ds->surface);
|
||||
vd->server->data = g_malloc0(vd->server->linesize *
|
||||
vd->server->height);
|
||||
qemu_pixman_image_unref(vd->server);
|
||||
vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT,
|
||||
ds_get_width(ds),
|
||||
ds_get_height(ds),
|
||||
NULL, 0);
|
||||
|
||||
/* guest surface */
|
||||
if (!vd->guest.ds)
|
||||
vd->guest.ds = g_malloc0(sizeof(*vd->guest.ds));
|
||||
#if 0 /* FIXME */
|
||||
if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel)
|
||||
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));
|
||||
|
||||
QTAILQ_FOREACH(vs, &vd->clients, next) {
|
||||
|
@ -585,7 +602,7 @@ static void vnc_dpy_resize(DisplayState *ds)
|
|||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
uint8_t r, g, b;
|
||||
VncDisplay *vd = vs->vd;
|
||||
|
||||
r = ((((v & vd->server->pf.rmask) >> vd->server->pf.rshift) << vs->clientds.pf.rbits) >>
|
||||
vd->server->pf.rbits);
|
||||
g = ((((v & vd->server->pf.gmask) >> vd->server->pf.gshift) << vs->clientds.pf.gbits) >>
|
||||
vd->server->pf.gbits);
|
||||
b = ((((v & vd->server->pf.bmask) >> vd->server->pf.bshift) << vs->clientds.pf.bbits) >>
|
||||
vd->server->pf.bbits);
|
||||
v = (r << vs->clientds.pf.rshift) |
|
||||
(g << vs->clientds.pf.gshift) |
|
||||
(b << vs->clientds.pf.bshift);
|
||||
switch(vs->clientds.pf.bytes_per_pixel) {
|
||||
#if VNC_SERVER_FB_FORMAT == PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8)
|
||||
r = (((v & 0x00ff0000) >> 16) << vs->client_pf.rbits) >> 8;
|
||||
g = (((v & 0x0000ff00) >> 8) << vs->client_pf.gbits) >> 8;
|
||||
b = (((v & 0x000000ff) >> 0) << vs->client_pf.bbits) >> 8;
|
||||
#else
|
||||
# error need some bits here if you change VNC_SERVER_FB_FORMAT
|
||||
#endif
|
||||
v = (r << vs->client_pf.rshift) |
|
||||
(g << vs->client_pf.gshift) |
|
||||
(b << vs->client_pf.bshift);
|
||||
switch (vs->client_pf.bytes_per_pixel) {
|
||||
case 1:
|
||||
buf[0] = v;
|
||||
break;
|
||||
case 2:
|
||||
if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) {
|
||||
if (vs->client_be) {
|
||||
buf[0] = v >> 8;
|
||||
buf[1] = v;
|
||||
} else {
|
||||
|
@ -621,7 +638,7 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
|
|||
break;
|
||||
default:
|
||||
case 4:
|
||||
if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) {
|
||||
if (vs->client_be) {
|
||||
buf[0] = v >> 24;
|
||||
buf[1] = v >> 16;
|
||||
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)
|
||||
{
|
||||
uint8_t buf[4];
|
||||
|
||||
if (pf->bytes_per_pixel == 4) {
|
||||
if (VNC_SERVER_FB_BYTES == 4) {
|
||||
uint32_t *pixels = pixels1;
|
||||
int n, i;
|
||||
n = size >> 2;
|
||||
for(i = 0; i < n; i++) {
|
||||
for (i = 0; i < n; 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;
|
||||
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++) {
|
||||
vs->write_pixels(vs, &vd->server->pf, row, w * ds_get_bytes_per_pixel(vs->ds));
|
||||
row += ds_get_linesize(vs->ds);
|
||||
vs->write_pixels(vs, row, w * VNC_SERVER_FB_BYTES);
|
||||
row += vnc_server_fb_stride(vd);
|
||||
}
|
||||
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;
|
||||
uint8_t *src_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;
|
||||
|
||||
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 */
|
||||
pitch = ds_get_linesize(vd->ds);
|
||||
depth = ds_get_bytes_per_pixel(vd->ds);
|
||||
src_row = vd->server->data + pitch * src_y + depth * src_x;
|
||||
dst_row = vd->server->data + pitch * dst_y + depth * dst_x;
|
||||
pitch = vnc_server_fb_stride(vd);
|
||||
src_row = vnc_server_fb_ptr(vd, src_x, src_y);
|
||||
dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y);
|
||||
y = dst_y;
|
||||
inc = 1;
|
||||
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 {
|
||||
s = 16;
|
||||
}
|
||||
cmp_bytes = s * depth;
|
||||
cmp_bytes = s * VNC_SERVER_FB_BYTES;
|
||||
if (memcmp(src_row, dst_row, cmp_bytes) == 0)
|
||||
continue;
|
||||
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;
|
||||
dst_row += pitch - w * depth;
|
||||
src_row += pitch - w * VNC_SERVER_FB_BYTES;
|
||||
dst_row += pitch - w * VNC_SERVER_FB_BYTES;
|
||||
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 ??? */
|
||||
}
|
||||
|
@ -810,7 +808,6 @@ static void vnc_mouse_set(int x, int y, int visible)
|
|||
static int vnc_cursor_define(VncState *vs)
|
||||
{
|
||||
QEMUCursor *c = vs->vd->cursor;
|
||||
PixelFormat pf = qemu_default_pixelformat(32);
|
||||
int isize;
|
||||
|
||||
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_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height,
|
||||
VNC_ENCODING_RICH_CURSOR);
|
||||
isize = c->width * c->height * vs->clientds.pf.bytes_per_pixel;
|
||||
vnc_write_pixels_generic(vs, &pf, c->data, isize);
|
||||
isize = c->width * c->height * vs->client_pf.bytes_per_pixel;
|
||||
vnc_write_pixels_generic(vs, c->data, isize);
|
||||
vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize);
|
||||
vnc_unlock_output(vs);
|
||||
return 0;
|
||||
|
@ -829,7 +826,7 @@ static int vnc_cursor_define(VncState *vs)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void vnc_dpy_cursor_define(QEMUCursor *c)
|
||||
static void vnc_dpy_cursor_define(DisplayState *ds, QEMUCursor *c)
|
||||
{
|
||||
VncDisplay *vd = vnc_display;
|
||||
VncState *vs;
|
||||
|
@ -898,8 +895,8 @@ static int vnc_update_client(VncState *vs, int has_dirty)
|
|||
*/
|
||||
job = vnc_job_new(vs);
|
||||
|
||||
width = MIN(vd->server->width, vs->client_width);
|
||||
height = MIN(vd->server->height, vs->client_height);
|
||||
width = MIN(pixman_image_get_width(vd->server), vs->client_width);
|
||||
height = MIN(pixman_image_get_height(vd->server), vs->client_height);
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
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)
|
||||
{
|
||||
if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
|
||||
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
|
||||
!memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
|
||||
pixman_format_code_t fmt = qemu_pixman_get_format(&vs->client_pf);
|
||||
|
||||
if (fmt == VNC_SERVER_FB_FORMAT) {
|
||||
vs->write_pixels = vnc_write_pixels_copy;
|
||||
vnc_hextile_set_pixel_conversion(vs, 0);
|
||||
} else {
|
||||
|
@ -1883,23 +1880,22 @@ static void set_pixel_format(VncState *vs,
|
|||
return;
|
||||
}
|
||||
|
||||
vs->clientds = *(vs->vd->guest.ds);
|
||||
vs->clientds.pf.rmax = red_max;
|
||||
vs->clientds.pf.rbits = hweight_long(red_max);
|
||||
vs->clientds.pf.rshift = red_shift;
|
||||
vs->clientds.pf.rmask = red_max << red_shift;
|
||||
vs->clientds.pf.gmax = green_max;
|
||||
vs->clientds.pf.gbits = hweight_long(green_max);
|
||||
vs->clientds.pf.gshift = green_shift;
|
||||
vs->clientds.pf.gmask = green_max << green_shift;
|
||||
vs->clientds.pf.bmax = blue_max;
|
||||
vs->clientds.pf.bbits = hweight_long(blue_max);
|
||||
vs->clientds.pf.bshift = blue_shift;
|
||||
vs->clientds.pf.bmask = blue_max << blue_shift;
|
||||
vs->clientds.pf.bits_per_pixel = bits_per_pixel;
|
||||
vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8;
|
||||
vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
|
||||
vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00;
|
||||
vs->client_pf.rmax = red_max;
|
||||
vs->client_pf.rbits = hweight_long(red_max);
|
||||
vs->client_pf.rshift = red_shift;
|
||||
vs->client_pf.rmask = red_max << red_shift;
|
||||
vs->client_pf.gmax = green_max;
|
||||
vs->client_pf.gbits = hweight_long(green_max);
|
||||
vs->client_pf.gshift = green_shift;
|
||||
vs->client_pf.gmask = green_max << green_shift;
|
||||
vs->client_pf.bmax = blue_max;
|
||||
vs->client_pf.bbits = hweight_long(blue_max);
|
||||
vs->client_pf.bshift = blue_shift;
|
||||
vs->client_pf.bmask = blue_max << blue_shift;
|
||||
vs->client_pf.bits_per_pixel = bits_per_pixel;
|
||||
vs->client_pf.bytes_per_pixel = bits_per_pixel / 8;
|
||||
vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
|
||||
vs->client_be = big_endian_flag;
|
||||
|
||||
set_pixel_conversion(vs);
|
||||
|
||||
|
@ -1910,8 +1906,10 @@ static void set_pixel_format(VncState *vs,
|
|||
static void pixel_format_message (VncState *vs) {
|
||||
char pad[3] = { 0, 0, 0 };
|
||||
|
||||
vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */
|
||||
vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */
|
||||
vs->client_pf = qemu_default_pixelformat(32);
|
||||
|
||||
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
|
||||
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 */
|
||||
#endif
|
||||
vnc_write_u8(vs, 1); /* true-color-flag */
|
||||
vnc_write_u16(vs, vs->ds->surface->pf.rmax); /* red-max */
|
||||
vnc_write_u16(vs, vs->ds->surface->pf.gmax); /* green-max */
|
||||
vnc_write_u16(vs, vs->ds->surface->pf.bmax); /* blue-max */
|
||||
vnc_write_u8(vs, vs->ds->surface->pf.rshift); /* red-shift */
|
||||
vnc_write_u8(vs, vs->ds->surface->pf.gshift); /* green-shift */
|
||||
vnc_write_u8(vs, vs->ds->surface->pf.bshift); /* blue-shift */
|
||||
vnc_write_u16(vs, vs->client_pf.rmax); /* red-max */
|
||||
vnc_write_u16(vs, vs->client_pf.gmax); /* green-max */
|
||||
vnc_write_u16(vs, vs->client_pf.bmax); /* blue-max */
|
||||
vnc_write_u8(vs, vs->client_pf.rshift); /* red-shift */
|
||||
vnc_write_u8(vs, vs->client_pf.gshift); /* green-shift */
|
||||
vnc_write_u8(vs, vs->client_pf.bshift); /* blue-shift */
|
||||
vnc_write(vs, pad, 3); /* padding */
|
||||
|
||||
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;
|
||||
|
||||
vnc_write(vs, pad, 3); /* padding */
|
||||
}
|
||||
|
||||
static void vnc_dpy_setdata(DisplayState *ds)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
int width = pixman_image_get_width(vd->guest.fb);
|
||||
int height = pixman_image_get_height(vd->guest.fb);
|
||||
int x, y;
|
||||
struct timeval res;
|
||||
int has_dirty = 0;
|
||||
|
||||
for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) {
|
||||
for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) {
|
||||
for (y = 0; y < height; y += VNC_STAT_RECT) {
|
||||
for (x = 0; x < width; x += VNC_STAT_RECT) {
|
||||
VncRectStat *rect = vnc_stat_rect(vd, x, y);
|
||||
|
||||
rect->updated = false;
|
||||
|
@ -2462,8 +2460,8 @@ static int vnc_update_stats(VncDisplay *vd, struct timeval * tv)
|
|||
}
|
||||
vd->guest.last_freq_check = *tv;
|
||||
|
||||
for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) {
|
||||
for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) {
|
||||
for (y = 0; y < height; y += VNC_STAT_RECT) {
|
||||
for (x = 0; x < width; x += VNC_STAT_RECT) {
|
||||
VncRectStat *rect= vnc_stat_rect(vd, x, y);
|
||||
int count = ARRAY_SIZE(rect->times);
|
||||
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)
|
||||
{
|
||||
int width = pixman_image_get_width(vd->guest.fb);
|
||||
int height = pixman_image_get_height(vd->guest.fb);
|
||||
int y;
|
||||
uint8_t *guest_row;
|
||||
uint8_t *server_row;
|
||||
int cmp_bytes;
|
||||
VncState *vs;
|
||||
int has_dirty = 0;
|
||||
pixman_image_t *tmpbuf = NULL;
|
||||
|
||||
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.
|
||||
* Update server dirty map.
|
||||
*/
|
||||
cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds);
|
||||
if (cmp_bytes > vd->ds->surface->linesize) {
|
||||
cmp_bytes = vd->ds->surface->linesize;
|
||||
cmp_bytes = 64;
|
||||
if (cmp_bytes > vnc_server_fb_stride(vd)) {
|
||||
cmp_bytes = vnc_server_fb_stride(vd);
|
||||
}
|
||||
guest_row = vd->guest.ds->data;
|
||||
server_row = vd->server->data;
|
||||
for (y = 0; y < vd->guest.ds->height; y++) {
|
||||
if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
|
||||
int width = pixman_image_get_width(vd->server);
|
||||
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)) {
|
||||
int x;
|
||||
uint8_t *guest_ptr;
|
||||
uint8_t *server_ptr;
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
if (!test_and_clear_bit((x / 16), vd->guest.dirty[y]))
|
||||
continue;
|
||||
|
@ -2581,9 +2591,10 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
|
|||
has_dirty++;
|
||||
}
|
||||
}
|
||||
guest_row += ds_get_linesize(vd->ds);
|
||||
server_row += ds_get_linesize(vd->ds);
|
||||
guest_row += pixman_image_get_stride(vd->guest.fb);
|
||||
server_row += pixman_image_get_stride(vd->server);
|
||||
}
|
||||
qemu_pixman_image_unref(tmpbuf);
|
||||
return has_dirty;
|
||||
}
|
||||
|
||||
|
@ -2753,13 +2764,13 @@ void vnc_display_init(DisplayState *ds)
|
|||
qemu_mutex_init(&vs->mutex);
|
||||
vnc_start_worker_thread();
|
||||
|
||||
dcl->dpy_copy = vnc_dpy_copy;
|
||||
dcl->dpy_update = vnc_dpy_update;
|
||||
dcl->dpy_resize = vnc_dpy_resize;
|
||||
dcl->dpy_setdata = vnc_dpy_setdata;
|
||||
dcl->dpy_gfx_copy = vnc_dpy_copy;
|
||||
dcl->dpy_gfx_update = vnc_dpy_update;
|
||||
dcl->dpy_gfx_resize = vnc_dpy_resize;
|
||||
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);
|
||||
ds->mouse_set = vnc_mouse_set;
|
||||
ds->cursor_define = vnc_dpy_cursor_define;
|
||||
}
|
||||
|
||||
|
||||
|
|
19
ui/vnc.h
19
ui/vnc.h
|
@ -69,7 +69,7 @@ typedef struct VncRectEntry VncRectEntry;
|
|||
|
||||
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,
|
||||
int x, int y, int w, int h,
|
||||
|
@ -117,7 +117,8 @@ struct VncSurface
|
|||
struct timeval last_freq_check;
|
||||
DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_MAX_WIDTH / 16);
|
||||
VncRectStat stats[VNC_STAT_ROWS][VNC_STAT_COLS];
|
||||
DisplaySurface *ds;
|
||||
pixman_image_t *fb;
|
||||
pixman_format_code_t format;
|
||||
};
|
||||
|
||||
typedef enum VncShareMode {
|
||||
|
@ -151,7 +152,7 @@ struct VncDisplay
|
|||
uint8_t *cursor_mask;
|
||||
|
||||
struct VncSurface guest; /* guest visible surface (aka ds->surface) */
|
||||
DisplaySurface *server; /* vnc server surface */
|
||||
pixman_image_t *server; /* vnc server surface */
|
||||
|
||||
char *display;
|
||||
char *password;
|
||||
|
@ -275,7 +276,9 @@ struct VncState
|
|||
Buffer input;
|
||||
/* current output mode information */
|
||||
VncWritePixels *write_pixels;
|
||||
DisplaySurface clientds;
|
||||
PixelFormat client_pf;
|
||||
pixman_format_code_t client_format;
|
||||
bool client_be;
|
||||
|
||||
CaptureVoiceOut *audio_cap;
|
||||
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,
|
||||
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);
|
||||
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);
|
||||
|
|
49
vl.c
49
vl.c
|
@ -1359,19 +1359,51 @@ static void gui_update(void *opaque)
|
|||
{
|
||||
uint64_t interval = GUI_REFRESH_INTERVAL;
|
||||
DisplayState *ds = opaque;
|
||||
DisplayChangeListener *dcl = ds->listeners;
|
||||
DisplayChangeListener *dcl;
|
||||
|
||||
dpy_refresh(ds);
|
||||
|
||||
while (dcl != NULL) {
|
||||
QLIST_FOREACH(dcl, &ds->listeners, next) {
|
||||
if (dcl->gui_timer_interval &&
|
||||
dcl->gui_timer_interval < interval)
|
||||
interval = dcl->gui_timer_interval;
|
||||
dcl = dcl->next;
|
||||
}
|
||||
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 {
|
||||
VMChangeStateHandler *cb;
|
||||
void *opaque;
|
||||
|
@ -2450,7 +2482,6 @@ int main(int argc, char **argv, char **envp)
|
|||
const char *kernel_filename, *kernel_cmdline;
|
||||
char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */
|
||||
DisplayState *ds;
|
||||
DisplayChangeListener *dcl;
|
||||
int cyls, heads, secs, translation;
|
||||
QemuOpts *hda_opts = NULL, *opts, *machine_opts;
|
||||
QemuOptsList *olist;
|
||||
|
@ -3873,16 +3904,6 @@ int main(int argc, char **argv, char **envp)
|
|||
#endif
|
||||
|
||||
/* 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);
|
||||
|
||||
if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
|
||||
|
|
Loading…
Reference in New Issue