From 87e487a14bd9f3fb4a2b27179377e011bdda7c51 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 4 Jun 2010 11:46:35 +0200 Subject: [PATCH 01/22] console: QLIST-ify display change listeners. Signed-off-by: Gerd Hoffmann --- console.h | 72 ++++++++++++++++++++++++++++-------------------------- hw/xenfb.c | 2 +- vl.c | 9 +++---- 3 files changed, 42 insertions(+), 41 deletions(-) diff --git a/console.h b/console.h index 6099d8d710..4239eb346c 100644 --- a/console.h +++ b/console.h @@ -164,7 +164,7 @@ struct DisplayChangeListener { int w, int h, uint32_t c); void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); - struct DisplayChangeListener *next; + QLIST_ENTRY(DisplayChangeListener) next; }; struct DisplayAllocator { @@ -179,7 +179,7 @@ struct DisplayState { struct QEMUTimer *gui_timer; struct DisplayAllocator* allocator; - struct DisplayChangeListener* listeners; + QLIST_HEAD(, DisplayChangeListener) listeners; void (*mouse_set)(int x, int y, int on); void (*cursor_define)(QEMUCursor *cursor); @@ -231,72 +231,76 @@ static inline int is_buffer_shared(DisplaySurface *surface) static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) { - dcl->next = ds->listeners; - ds->listeners = dcl; + QLIST_INSERT_HEAD(&ds->listeners, dcl, next); } static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { dcl->dpy_update(s, x, y, w, h); - dcl = dcl->next; } } static inline void dpy_resize(DisplayState *s) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { dcl->dpy_resize(s); - dcl = dcl->next; } } static inline void dpy_setdata(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_setdata) { + dcl->dpy_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) + int dst_x, int dst_y, int w, int h) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_copy) { dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h); - else /* TODO */ + } else { /* TODO */ dcl->dpy_update(s, dst_x, dst_y, w, h); - dcl = dcl->next; + } } } 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; + int w, int h, uint32_t c) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_fill) { + dcl->dpy_fill(s, x, y, w, h, c); + } } } -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_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); + } } } diff --git a/hw/xenfb.c b/hw/xenfb.c index 338800a4d9..ef24c3315c 100644 --- a/hw/xenfb.c +++ b/hw/xenfb.c @@ -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; diff --git a/vl.c b/vl.c index 5513d1518e..427e8a2d40 100644 --- a/vl.c +++ b/vl.c @@ -1359,15 +1359,14 @@ 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)); } @@ -3846,14 +3845,12 @@ int main(int argc, char **argv, char **envp) /* display setup */ dpy_resize(ds); - dcl = ds->listeners; - while (dcl != NULL) { + QLIST_FOREACH(dcl, &ds->listeners, next) { 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); From 35c9e0a5c2804b94d1a452a0a9a12d7a893b5318 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 4 Jun 2010 11:51:31 +0200 Subject: [PATCH 02/22] console: add unregister_displaychangelistener Also change the way the gui_timer is initialized: each time a displaychangelistener is registered or unregistered we'll check whether we need a timer (due to dpy_refresh callback being present) and if so setup a timer, otherwise zap it. This way the gui timer works correctly with displaychangelisteners coming and going. Signed-off-by: Gerd Hoffmann --- console.h | 10 ++++++++++ vl.c | 31 +++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/console.h b/console.h index 4239eb346c..f476ac810d 100644 --- a/console.h +++ b/console.h @@ -229,9 +229,19 @@ static inline int is_buffer_shared(DisplaySurface *surface) !(surface->flags & QEMU_REALPIXELS_FLAG)); } +void gui_setup_refresh(DisplayState *ds); + static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) { QLIST_INSERT_HEAD(&ds->listeners, dcl, next); + gui_setup_refresh(ds); +} + +static inline void unregister_displaychangelistener(DisplayState *ds, + DisplayChangeListener *dcl) +{ + QLIST_REMOVE(dcl, next); + gui_setup_refresh(ds); } static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) diff --git a/vl.c b/vl.c index 427e8a2d40..4c45b02f05 100644 --- a/vl.c +++ b/vl.c @@ -1371,6 +1371,29 @@ static void gui_update(void *opaque) 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; + + QLIST_FOREACH(dcl, &ds->listeners, next) { + if (dcl->dpy_refresh != NULL) { + need_timer = true; + break; + } + } + + 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; + } +} + struct vm_change_state_entry { VMChangeStateHandler *cb; void *opaque; @@ -2454,7 +2477,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; @@ -3845,13 +3867,6 @@ int main(int argc, char **argv, char **envp) /* display setup */ dpy_resize(ds); - QLIST_FOREACH(dcl, &ds->listeners, next) { - 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; - } - } text_consoles_set_display(ds); if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { From bf2fde70fea6b3245dab44253deafba95f2979e5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 12 Sep 2012 07:56:45 +0200 Subject: [PATCH 03/22] console: move set_mouse + cursor_define callbacks When adding DisplayChangeListeners the set_mouse and cursor_define callbacks have been left in DisplayState for some reason. Fix it. Signed-off-by: Gerd Hoffmann --- console.c | 2 +- console.h | 39 +++++++++++++++++++++++++++++++++++---- hw/jazz_led.c | 2 +- hw/qxl-render.c | 2 +- hw/vga.c | 10 +++++----- hw/vmware_vga.c | 11 ++++++----- ui/sdl.c | 8 ++++---- ui/spice-display.c | 4 ++-- ui/vnc.c | 8 ++++---- 9 files changed, 59 insertions(+), 27 deletions(-) diff --git a/console.c b/console.c index 3f3d2547bf..260a029246 100644 --- a/console.c +++ b/console.c @@ -1242,7 +1242,7 @@ 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; } } diff --git a/console.h b/console.h index f476ac810d..fb38ce9060 100644 --- a/console.h +++ b/console.h @@ -164,6 +164,9 @@ struct DisplayChangeListener { int w, int h, uint32_t c); void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); + void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on); + void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor); + QLIST_ENTRY(DisplayChangeListener) next; }; @@ -181,9 +184,6 @@ struct DisplayState { struct DisplayAllocator* allocator; QLIST_HEAD(, DisplayChangeListener) listeners; - void (*mouse_set)(int x, int y, int on); - void (*cursor_define)(QEMUCursor *cursor); - struct DisplayState *next; }; @@ -304,7 +304,7 @@ static inline void dpy_fill(struct DisplayState *s, int x, int y, } } -static inline void dpy_cursor(struct DisplayState *s, int x, int y) +static inline void dpy_text_cursor(struct DisplayState *s, int x, int y) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { @@ -314,6 +314,37 @@ static inline void dpy_cursor(struct DisplayState *s, int x, int y) } } +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; diff --git a/hw/jazz_led.c b/hw/jazz_led.c index a6a90ab283..853bf6d4c1 100644 --- a/hw/jazz_led.c +++ b/hw/jazz_led.c @@ -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 */ diff --git a/hw/qxl-render.c b/hw/qxl-render.c index b66c168ef6..e8cf29e62a 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -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; } diff --git a/hw/vga.c b/hw/vga.c index e4220df25e..f3256cb6c7 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2070,11 +2070,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, - TEXTMODE_X(cursor_offset), - TEXTMODE_Y(cursor_offset)); + 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]; @@ -2135,7 +2135,7 @@ 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); + dpy_text_cursor(s->ds, -1, -1); s->ds->surface->width = s->last_width; s->ds->surface->height = height; dpy_resize(s->ds); diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index badaf7cef4..dc9279064c 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -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; diff --git a/ui/sdl.c b/ui/sdl.c index f6f711c1bb..f8ead930ae 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -905,7 +905,7 @@ static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c) 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 +921,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; @@ -1025,8 +1025,8 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) 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_mouse_set = sdl_mouse_warp; + dcl->dpy_cursor_define = sdl_mouse_define; register_displaychangelistener(ds, dcl); da = g_malloc0(sizeof(DisplayAllocator)); diff --git a/ui/spice-display.c b/ui/spice-display.c index b61764f381..5779fa8ba6 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -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; } diff --git a/ui/vnc.c b/ui/vnc.c index d0ffcc54af..1b70db7e05 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -802,7 +802,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 ??? */ } @@ -829,7 +829,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; @@ -2757,9 +2757,9 @@ void vnc_display_init(DisplayState *ds) dcl->dpy_update = vnc_dpy_update; dcl->dpy_resize = vnc_dpy_resize; dcl->dpy_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; } From 76ffb0b4d048aac18b54f8555c60b6d3b0e2bc37 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 28 Sep 2012 13:24:17 +0200 Subject: [PATCH 04/22] console: s/TextConsole/QemuConsole/ Signed-off-by: Gerd Hoffmann --- console.c | 72 +++++++++++++++++++++++++-------------------------- qemu-common.h | 3 +-- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/console.c b/console.c index 260a029246..b53dc1b6f3 100644 --- a/console.c +++ b/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,7 +631,7 @@ 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; @@ -666,7 +666,7 @@ static void console_refresh(TextConsole *s) static void console_scroll(int ydelta) { - TextConsole *s; + QemuConsole *s; int i, y1; s = active_console; @@ -698,7 +698,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 +749,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 +842,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 +852,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 +871,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 +1078,7 @@ static void console_putchar(TextConsole *s, int ch) void console_select(unsigned int index) { - TextConsole *s; + QemuConsole *s; if (index >= MAX_CONSOLES) return; @@ -1111,7 +1111,7 @@ void console_select(unsigned int index) 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; @@ -1133,7 +1133,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 +1156,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 +1211,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 +1222,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]) { @@ -1247,10 +1247,10 @@ static void text_console_update(void *opaque, console_ch_t *chardata) } } -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 +1259,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; @@ -1417,7 +1417,7 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update, vga_hw_text_update_ptr text_update, void *opaque) { - TextConsole *s; + QemuConsole *s; DisplayState *ds; ds = (DisplayState *) g_malloc0(sizeof(DisplayState)); @@ -1463,14 +1463,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 +1480,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 +1543,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,7 +1589,7 @@ 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; diff --git a/qemu-common.h b/qemu-common.h index b54612b1a5..fdd0dbcf64 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -264,8 +264,7 @@ 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; From a93a4a226a2afba147ba5df688b85d844f537c68 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 28 Sep 2012 15:02:08 +0200 Subject: [PATCH 05/22] console: untangle gfx & txt updates Stop abusing displaysurface fields for text mode displays. (bpp = 0, width = cols, height = lines). Add flags to displaystate indicating whenever text mode display (curses) or gfx mode displays (sdl, vnc, ...) are present. Add separate displaychangelistener callbacks for text / gfx mode resize & updates. This allows to enable gfx and txt diplays at the same time and also paves the way for more cleanups in the future. Signed-off-by: Gerd Hoffmann --- console.c | 59 ++++++++++++++++++----------------- console.h | 74 +++++++++++++++++++++++++++++++------------- hw/blizzard.c | 4 +-- hw/exynos4210_fimd.c | 2 +- hw/g364fb.c | 7 +++-- hw/jazz_led.c | 4 +-- hw/milkymist-vgafb.c | 2 +- hw/musicpal.c | 2 +- hw/nseries.c | 2 +- hw/omap_lcdc.c | 2 +- hw/palm.c | 2 +- hw/pl110.c | 2 +- hw/pxa2xx_lcd.c | 8 ++--- hw/qxl-render.c | 10 +++--- hw/qxl.c | 4 +-- hw/sm501.c | 4 +-- hw/ssd0303.c | 2 +- hw/ssd0323.c | 2 +- hw/tc6393xb.c | 4 +-- hw/tcx.c | 16 +++++----- hw/vga.c | 34 +++++++++----------- hw/vmware_vga.c | 4 +-- ui/curses.c | 21 +++++-------- ui/sdl.c | 12 +++---- ui/spice-display.c | 4 +-- ui/vnc.c | 8 ++--- vl.c | 14 +++++++-- 27 files changed, 171 insertions(+), 138 deletions(-) diff --git a/console.c b/console.c index b53dc1b6f3..61812c7c7f 100644 --- a/console.c +++ b/console.c @@ -638,30 +638,33 @@ static void console_refresh(QemuConsole *s) 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; } - 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++) { - c = s->cells + y1 * s->width; - for(x = 0; x < s->width; x++) { - vga_putcharxy(s->ds, x, y, c->ch, - &(c->t_attrib)); - c++; + 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++) { + c = s->cells + y1 * s->width; + for (x = 0; x < s->width; x++) { + vga_putcharxy(s->ds, x, y, c->ch, + &(c->t_attrib)); + c++; + } + if (++y1 == s->total_height) { + y1 = 0; + } } - if (++y1 == s->total_height) - y1 = 0; + console_show_cursor(s, 1); + dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds)); } - console_show_cursor(s, 1); - dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds)); } static void console_scroll(int ydelta) @@ -1094,17 +1097,17 @@ 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(); } } @@ -1123,10 +1126,10 @@ 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, - s->update_x1 - s->update_x0, - s->update_y1 - 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); } return len; } @@ -1234,8 +1237,8 @@ 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], - s->text_x[1] - s->text_x[0], i - 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; s->text_x[1] = 0; @@ -1596,7 +1599,7 @@ void qemu_console_resize(DisplayState *ds, int width, int height) 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 +1607,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); } } diff --git a/console.h b/console.h index fb38ce9060..00e2f03424 100644 --- a/console.h +++ b/console.h @@ -154,15 +154,19 @@ 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, - 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_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_gfx_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); void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on); void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor); @@ -180,6 +184,8 @@ struct DisplayState { struct DisplaySurface *surface; void *opaque; struct QEMUTimer *gui_timer; + bool have_gfx; + bool have_text; struct DisplayAllocator* allocator; QLIST_HEAD(, DisplayChangeListener) listeners; @@ -244,28 +250,32 @@ static inline void unregister_displaychangelistener(DisplayState *ds, gui_setup_refresh(ds); } -static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) +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) { - dcl->dpy_update(s, x, y, w, h); + if (dcl->dpy_gfx_update) { + dcl->dpy_gfx_update(s, x, y, w, h); + } } } -static inline void dpy_resize(DisplayState *s) +static inline void dpy_gfx_resize(DisplayState *s) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { - dcl->dpy_resize(s); + if (dcl->dpy_gfx_resize) { + dcl->dpy_gfx_resize(s); + } } } -static inline void dpy_setdata(DisplayState *s) +static inline void dpy_gfx_setdata(DisplayState *s) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_setdata) { - dcl->dpy_setdata(s); + if (dcl->dpy_gfx_setdata) { + dcl->dpy_gfx_setdata(s); } } } @@ -280,26 +290,26 @@ static inline void dpy_refresh(DisplayState *s) } } -static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y, +static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_copy) { - dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h); + if (dcl->dpy_gfx_copy) { + dcl->dpy_gfx_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->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) +static inline void dpy_gfx_fill(struct DisplayState *s, int x, int y, + int w, int h, uint32_t c) { struct DisplayChangeListener *dcl; QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_fill) { - dcl->dpy_fill(s, x, y, w, h, c); + if (dcl->dpy_gfx_fill) { + dcl->dpy_gfx_fill(s, x, y, w, h, c); } } } @@ -314,6 +324,26 @@ static inline void dpy_text_cursor(struct DisplayState *s, int x, int y) } } +static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h) +{ + struct DisplayChangeListener *dcl; + 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; diff --git a/hw/blizzard.c b/hw/blizzard.c index 06e19b364b..1b57eb5396 100644 --- a/hw/blizzard.c +++ b/hw/blizzard.c @@ -921,8 +921,8 @@ 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], - s->mx[1] - s->mx[0], y - 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; s->mx[1] = 0; diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c index 7cb2c31bee..f2443ca4af 100644 --- a/hw/exynos4210_fimd.c +++ b/hw/exynos4210_fimd.c @@ -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; diff --git a/hw/g364fb.c b/hw/g364fb.c index f7b4bf5ae2..8192baf1c8 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -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; } diff --git a/hw/jazz_led.c b/hw/jazz_led.c index 853bf6d4c1..640e75ef2f 100644 --- a/hw/jazz_led.c +++ b/hw/jazz_led.c @@ -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) @@ -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) diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c index 8d36bc10f6..833881cc6a 100644 --- a/hw/milkymist-vgafb.c +++ b/hw/milkymist-vgafb.c @@ -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; } diff --git a/hw/musicpal.c b/hw/musicpal.c index beec76bf38..e0c57c84eb 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -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) diff --git a/hw/nseries.c b/hw/nseries.c index 9306aa15a7..26d5e3507f 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -1376,7 +1376,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device, 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 = { diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index bf177c22dd..d7ae3032be 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -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; } diff --git a/hw/palm.c b/hw/palm.c index d26305159d..6f6f414e6e 100644 --- a/hw/palm.c +++ b/hw/palm.c @@ -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 = { diff --git a/hw/pl110.c b/hw/pl110.c index 82486b0c14..79a3f82ddf 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -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; } diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index 38c38890c9..b53dfaf3cf 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -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; } } diff --git a/hw/qxl-render.c b/hw/qxl-render.c index e8cf29e62a..47eb8b4154 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -123,17 +123,17 @@ 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, - qxl->dirty[i].left, qxl->dirty[i].top, - qxl->dirty[i].right - qxl->dirty[i].left, - qxl->dirty[i].bottom - qxl->dirty[i].top); + 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); } qxl->num_dirty_rects = 0; } diff --git a/hw/qxl.c b/hw/qxl.c index d54daf6d3b..1f56fcd169 100644 --- a/hw/qxl.c +++ b/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, }; diff --git a/hw/sm501.c b/hw/sm501.c index 4aafe49cce..50324cda53 100644 --- a/hw/sm501.c +++ b/hw/sm501.c @@ -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) { diff --git a/hw/ssd0303.c b/hw/ssd0303.c index 4e1ee6e12b..d7fd828c65 100644 --- a/hw/ssd0303.c +++ b/hw/ssd0303.c @@ -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) diff --git a/hw/ssd0323.c b/hw/ssd0323.c index 9c42d648e2..4098830c2b 100644 --- a/hw/ssd0323.c +++ b/hw/ssd0323.c @@ -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) diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c index 31d4f26629..f0320271d4 100644 --- a/hw/tc6393xb.c +++ b/hw/tc6393xb.c @@ -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) diff --git a/hw/tcx.c b/hw/tcx.c index 7abe865e3f..7aee2a9bd3 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -268,8 +268,8 @@ static void tcx_update_display(void *opaque) } else { if (y_start >= 0) { /* flush to display */ - dpy_update(ts->ds, 0, y_start, - ts->width, y - y_start); + dpy_gfx_update(ts->ds, 0, y_start, + ts->width, y - y_start); y_start = -1; } d += dd * 4; @@ -278,8 +278,8 @@ static void tcx_update_display(void *opaque) } if (y_start >= 0) { /* flush to display */ - dpy_update(ts->ds, 0, y_start, - ts->width, y - y_start); + dpy_gfx_update(ts->ds, 0, y_start, + ts->width, y - y_start); } /* reset modified pages */ if (page_max >= page_min) { @@ -344,8 +344,8 @@ static void tcx24_update_display(void *opaque) } else { if (y_start >= 0) { /* flush to display */ - dpy_update(ts->ds, 0, y_start, - ts->width, y - y_start); + dpy_gfx_update(ts->ds, 0, y_start, + ts->width, y - y_start); y_start = -1; } d += dd * 4; @@ -356,8 +356,8 @@ static void tcx24_update_display(void *opaque) } if (y_start >= 0) { /* flush to display */ - dpy_update(ts->ds, 0, y_start, - ts->width, y - y_start); + dpy_gfx_update(ts->ds, 0, y_start, + ts->width, y - y_start); } /* reset modified pages */ if (page_max >= page_min) { diff --git a/hw/vga.c b/hw/vga.c index f3256cb6c7..dc8dddec80 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1456,8 +1456,8 @@ 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, - (cx_max - cx_min + 1) * cw, cheight); + dpy_gfx_update(s->ds, cx_min * cw, cy * cheight, + (cx_max - cx_min + 1) * cw, cheight); } dest += linesize * cheight; line1 = line + cheight; @@ -1688,7 +1688,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); } @@ -1702,7 +1702,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) } 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); + dpy_gfx_setdata(s->ds); } s->rgb_to_pixel = @@ -1807,8 +1807,8 @@ 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, - disp_width, y - y_start); + dpy_gfx_update(s->ds, 0, y_start, + disp_width, y - y_start); y_start = -1; } } @@ -1828,8 +1828,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) } if (y_start >= 0) { /* flush to display */ - dpy_update(s->ds, 0, y_start, - disp_width, y - y_start); + dpy_gfx_update(s->ds, 0, y_start, + disp_width, y - y_start); } /* reset modified pages */ if (page_max >= page_min) { @@ -1863,8 +1863,8 @@ 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, - s->last_scr_width, s->last_scr_height); + dpy_gfx_update(s->ds, 0, 0, + s->last_scr_width, s->last_scr_height); } #define GMODE_TEXT 0 @@ -2052,9 +2052,7 @@ 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); + dpy_text_resize(s->ds, width, height); s->last_width = width; s->last_height = height; s->last_ch = cheight; @@ -2087,7 +2085,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 +2108,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); } } @@ -2136,9 +2134,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) s->last_width = 60; s->last_height = height = 3; dpy_text_cursor(s->ds, -1, -1); - s->ds->surface->width = s->last_width; - s->ds->surface->height = height; - dpy_resize(s->ds); + 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 +2145,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, diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index dc9279064c..34532e5c3a 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -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, diff --git a/ui/curses.c b/ui/curses.c index c2be2c641a..b40b22307d 100644 --- a/ui/curses.c +++ b/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; } diff --git a/ui/sdl.c b/ui/sdl.c index f8ead930ae..fac1a4740d 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -553,7 +553,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); } } @@ -1020,11 +1020,11 @@ 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; + dcl->dpy_gfx_setdata = sdl_setdata; + dcl->dpy_gfx_fill = sdl_fill; dcl->dpy_mouse_set = sdl_mouse_warp; dcl->dpy_cursor_define = sdl_mouse_define; register_displaychangelistener(ds, dcl); @@ -1034,7 +1034,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) da->resize_displaysurface = sdl_resize_displaysurface; da->free_displaysurface = sdl_free_displaysurface; if (register_displayallocator(ds, da) == da) { - dpy_resize(ds); + dpy_gfx_resize(ds); } mouse_mode_notifier.notify = sdl_mouse_mode_change; diff --git a/ui/spice-display.c b/ui/spice-display.c index 5779fa8ba6..fb99148349 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -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, }; diff --git a/ui/vnc.c b/ui/vnc.c index 1b70db7e05..0ae1c74984 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2753,10 +2753,10 @@ 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); diff --git a/vl.c b/vl.c index 4c45b02f05..8716fc0a6c 100644 --- a/vl.c +++ b/vl.c @@ -1375,11 +1375,18 @@ 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; - break; + } + if (dcl->dpy_gfx_update != NULL) { + have_gfx = true; + } + if (dcl->dpy_text_update != NULL) { + have_text = true; } } @@ -1392,6 +1399,9 @@ void gui_setup_refresh(DisplayState *ds) 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 { @@ -3866,7 +3876,7 @@ int main(int argc, char **argv, char **envp) #endif /* display setup */ - dpy_resize(ds); + dpy_gfx_resize(ds); text_consoles_set_display(ds); if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { From e250d949feb1334828f27f0d145c35f29c4b7639 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 28 Sep 2012 15:30:07 +0200 Subject: [PATCH 06/22] console: init displaychangelisteners on register Signed-off-by: Gerd Hoffmann --- console.h | 3 +++ vl.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/console.h b/console.h index 00e2f03424..7e0ac760e3 100644 --- a/console.h +++ b/console.h @@ -241,6 +241,9 @@ static inline void register_displaychangelistener(DisplayState *ds, DisplayChang { QLIST_INSERT_HEAD(&ds->listeners, dcl, next); gui_setup_refresh(ds); + if (dcl->dpy_gfx_resize) { + dcl->dpy_gfx_resize(ds); + } } static inline void unregister_displaychangelistener(DisplayState *ds, diff --git a/vl.c b/vl.c index 8716fc0a6c..df776e91ad 100644 --- a/vl.c +++ b/vl.c @@ -3876,7 +3876,6 @@ int main(int argc, char **argv, char **envp) #endif /* display setup */ - dpy_gfx_resize(ds); text_consoles_set_display(ds); if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { From 9678aedd8e76978465698b9edeb069ccee15e975 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 9 Oct 2012 17:10:13 +0200 Subject: [PATCH 07/22] vga: fix text mode updating With both text (curses) and graphics (vnc/sdl/spice/...) display active vga text mode emulation fails to update both correctly. Depending on whenever vga_update_text() or vga_draw_text() happens to be called first only the text display or only the graphics display will see display resolution changes and full redraws. Fix it by calling both text/gfx resize functions in both code paths and keep track of full screen redraws needed in VGACommonState fields. Signed-off-by: Gerd Hoffmann --- hw/vga.c | 19 +++++++++++++++++++ hw/vga_int.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/hw/vga.c b/hw/vga.c index dc8dddec80..f31dbdd652 100644 --- a/hw/vga.c +++ b/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 || @@ -2052,7 +2061,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; + 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; @@ -2060,6 +2071,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; diff --git a/hw/vga_int.h b/hw/vga_int.h index 22f1706adf..d4da777e62 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -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); From 4dc6a39bbd1a03f86797e0df2db285318f086aee Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 28 Sep 2012 15:31:33 +0200 Subject: [PATCH 08/22] console: remove dpy_gfx_fill Unused code. 'nuff said. Signed-off-by: Gerd Hoffmann --- console.h | 13 ------------- ui/sdl.c | 7 ------- 2 files changed, 20 deletions(-) diff --git a/console.h b/console.h index 7e0ac760e3..6492e67bd2 100644 --- a/console.h +++ b/console.h @@ -161,8 +161,6 @@ struct DisplayChangeListener { 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_gfx_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); @@ -306,17 +304,6 @@ static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, } } -static inline void dpy_gfx_fill(struct DisplayState *s, int x, int y, - int w, int h, uint32_t c) -{ - struct DisplayChangeListener *dcl; - QLIST_FOREACH(dcl, &s->listeners, next) { - if (dcl->dpy_gfx_fill) { - dcl->dpy_gfx_fill(s, x, y, w, h, c); - } - } -} - static inline void dpy_text_cursor(struct DisplayState *s, int x, int y) { struct DisplayChangeListener *dcl; diff --git a/ui/sdl.c b/ui/sdl.c index fac1a4740d..c3ba79fe43 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -899,12 +899,6 @@ 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(DisplayState *ds, int x, int y, int on) { if (on) { @@ -1024,7 +1018,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) dcl->dpy_gfx_resize = sdl_resize; dcl->dpy_refresh = sdl_refresh; dcl->dpy_gfx_setdata = sdl_setdata; - dcl->dpy_gfx_fill = sdl_fill; dcl->dpy_mouse_set = sdl_mouse_warp; dcl->dpy_cursor_define = sdl_mouse_define; register_displaychangelistener(ds, dcl); From 187cd1d9f30d13f0d0ef682e4d91cfa3e4cbd472 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 26 Sep 2012 07:46:20 +0200 Subject: [PATCH 09/22] console: remove DisplayAllocator Causes [temporary] preformance regression with 24bpp vga modes @ sdl. Signed-off-by: Gerd Hoffmann --- console.c | 52 ++++++++-------------- console.h | 34 +++------------ qemu-common.h | 1 - ui/sdl.c | 117 +++----------------------------------------------- 4 files changed, 31 insertions(+), 173 deletions(-) diff --git a/console.c b/console.c index 61812c7c7f..71cc543b7b 100644 --- a/console.c +++ b/console.c @@ -1294,9 +1294,10 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type) return s; } -static DisplaySurface* defaultallocator_create_displaysurface(int width, int height) +DisplaySurface *qemu_create_displaysurface(DisplayState *ds, + int width, int height) { - DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface)); + DisplaySurface *surface = g_new0(DisplaySurface, 1); int linesize = width * 4; qemu_alloc_display(surface, width, height, linesize, @@ -1304,13 +1305,15 @@ static DisplaySurface* defaultallocator_create_displaysurface(int width, int hei return surface; } -static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface, - int width, int height) +DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, + int width, int height) { int linesize = width * 4; - qemu_alloc_display(surface, width, height, linesize, + + trace_displaysurface_resize(ds, ds->surface, width, height); + qemu_alloc_display(ds->surface, width, height, linesize, qemu_default_pixelformat(32), 0); - return surface; + return ds->surface; } void qemu_alloc_display(DisplaySurface *surface, int width, int height, @@ -1323,7 +1326,7 @@ void qemu_alloc_display(DisplaySurface *surface, int width, int height, surface->pf = pf; if (surface->flags & QEMU_ALLOCATED_FLAG) { data = g_realloc(surface->data, - surface->linesize * surface->height); + surface->linesize * surface->height); } else { data = g_malloc(surface->linesize * surface->height); } @@ -1334,7 +1337,7 @@ void qemu_alloc_display(DisplaySurface *surface, int width, int height, #endif } -DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, +DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, int linesize, uint8_t *data) { DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface)); @@ -1351,28 +1354,24 @@ DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, 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); + } + if (ds->surface->flags & QEMU_ALLOCATED_FLAG) { + g_free(ds->surface->data); + } + 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; @@ -1402,18 +1401,6 @@ 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, @@ -1424,7 +1411,6 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update, 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); diff --git a/console.h b/console.h index 6492e67bd2..6be880a554 100644 --- a/console.h +++ b/console.h @@ -107,7 +107,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; @@ -172,12 +171,6 @@ struct DisplayChangeListener { QLIST_ENTRY(DisplayChangeListener) next; }; -struct DisplayAllocator { - DisplaySurface* (*create_displaysurface)(int width, int height); - DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height); - void (*free_displaysurface)(DisplaySurface *surface); -}; - struct DisplayState { struct DisplaySurface *surface; void *opaque; @@ -185,7 +178,6 @@ struct DisplayState { bool have_gfx; bool have_text; - struct DisplayAllocator* allocator; QLIST_HEAD(, DisplayChangeListener) listeners; struct DisplayState *next; @@ -200,24 +192,11 @@ void qemu_alloc_display(DisplaySurface *surface, int width, int height, 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) { @@ -229,8 +208,7 @@ 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); diff --git a/qemu-common.h b/qemu-common.h index fdd0dbcf64..89cec1d817 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -262,7 +262,6 @@ 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 QemuConsole QemuConsole; typedef struct CharDriverState CharDriverState; diff --git a/ui/sdl.c b/ui/sdl.c index c3ba79fe43..37f01b217d 100644 --- a/ui/sdl.c +++ b/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) - 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)); - sdl_setdata(ds); - } else { - if (guest_screen != NULL) { - SDL_FreeSurface(guest_screen); - guest_screen = NULL; - } + 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)); } -} - -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); + sdl_setdata(ds); } /* generic keyboard conversion */ @@ -949,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; @@ -1022,14 +925,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) 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_gfx_resize(ds); - } - mouse_mode_notifier.notify = sdl_mouse_mode_change; qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier); From 9f2c7d7d67c228ae6a02f50082f0c6d10703f483 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 27 Sep 2012 09:52:35 +0200 Subject: [PATCH 10/22] pixman: add submodule Add pixman submodule as fallback for old distros. Picking version 0.18.4. This is shipped by rhel6 and also the minimum version needed by spice so this should serve well as baseline. Signed-off-by: Gerd Hoffmann --- .gitmodules | 3 +++ pixman | 1 + 2 files changed, 4 insertions(+) create mode 160000 pixman diff --git a/.gitmodules b/.gitmodules index eca876f85d..cfa2af9f7a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/pixman b/pixman new file mode 160000 index 0000000000..97336fad32 --- /dev/null +++ b/pixman @@ -0,0 +1 @@ +Subproject commit 97336fad32acf802003855cd8bd6477fa49a12e3 From e2134eb9223edac82cc7aa2281779c92c920d579 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2012 16:04:58 +0200 Subject: [PATCH 11/22] pixman: windup in configure & makefiles Signed-off-by: Gerd Hoffmann --- Makefile | 9 +++++++++ configure | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/Makefile b/Makefile index b522b10195..e4866d9bd3 100644 --- a/Makefile +++ b/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 diff --git a/configure b/configure index 9c6ac875a5..79701ea27b 100755 --- a/configure +++ b/configure @@ -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" From d2ec7e24a270ba72a151b506ac57c6cd21e3c587 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2012 16:23:24 +0200 Subject: [PATCH 12/22] pixman: helper functions Add some helper functions which will be put into use by following patches. Signed-off-by: Gerd Hoffmann --- Makefile.objs | 1 + qemu-pixman.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-pixman.h | 32 +++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 qemu-pixman.c create mode 100644 qemu-pixman.h diff --git a/Makefile.objs b/Makefile.objs index 9eca179903..acca2854d1 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -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 diff --git a/qemu-pixman.c b/qemu-pixman.c new file mode 100644 index 0000000000..7547ed74c1 --- /dev/null +++ b/qemu-pixman.c @@ -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); +} diff --git a/qemu-pixman.h b/qemu-pixman.h new file mode 100644 index 0000000000..7652c41277 --- /dev/null +++ b/qemu-pixman.h @@ -0,0 +1,32 @@ +#ifndef QEMU_PIXMAN_H +#define QEMU_PIXMAN_H + +#include + +#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 */ From 69c7777720c18d8afca7d9685c6dced1aae3a056 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 26 Sep 2012 15:20:05 +0200 Subject: [PATCH 13/22] pixman: add pixman image to DisplaySurface Surfaces are now allocated using pixman. DisplaySurface gets new struct fields with pixman image and data. DisplayChangeListeners can easily start using pixman now. Signed-off-by: Gerd Hoffmann --- console.c | 37 ++++++++++++++++++++++++------------- console.h | 3 +++ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/console.c b/console.c index 71cc543b7b..5e1c5f560d 100644 --- a/console.c +++ b/console.c @@ -1319,18 +1319,23 @@ DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, 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->data = 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->data = (uint8_t *)pixman_image_get_data(surface->image); surface->flags = newflags | QEMU_ALLOCATED_FLAG; #ifdef HOST_WORDS_BIGENDIAN surface->flags |= QEMU_BIG_ENDIAN_FLAG; @@ -1338,14 +1343,22 @@ void qemu_alloc_display(DisplaySurface *surface, int width, int height, } DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, - int linesize, uint8_t *data) + 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 @@ -1360,9 +1373,7 @@ void qemu_free_displaysurface(DisplayState *ds) if (ds->surface == NULL) { return; } - if (ds->surface->flags & QEMU_ALLOCATED_FLAG) { - g_free(ds->surface->data); - } + qemu_pixman_image_unref(ds->surface->image); g_free(ds->surface); } diff --git a/console.h b/console.h index 6be880a554..f19e6a443b 100644 --- a/console.h +++ b/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" @@ -119,6 +120,8 @@ struct PixelFormat { }; struct DisplaySurface { + pixman_format_code_t format; + pixman_image_t *image; uint8_t flags; int width; int height; From 537a43913c19973adc4153d30498591f92a90359 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 27 Sep 2012 11:06:36 +0200 Subject: [PATCH 14/22] console: make qemu_alloc_display static Signed-off-by: Gerd Hoffmann --- console.c | 48 ++++++++++++++++++++++++------------------------ console.h | 2 -- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/console.c b/console.c index 5e1c5f560d..48d88e43ce 100644 --- a/console.c +++ b/console.c @@ -1294,30 +1294,8 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type) return s; } -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; -} - -void qemu_alloc_display(DisplaySurface *surface, int width, int height, - int linesize, PixelFormat pf, int newflags) +static void qemu_alloc_display(DisplaySurface *surface, int width, int height, + int linesize, PixelFormat pf, int newflags) { surface->width = width; surface->height = height; @@ -1342,6 +1320,28 @@ void qemu_alloc_display(DisplaySurface *surface, int width, int height, #endif } +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) { diff --git a/console.h b/console.h index f19e6a443b..21bd957d95 100644 --- a/console.h +++ b/console.h @@ -190,8 +190,6 @@ 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); From 09bbb0ae8226c71aba440bdfa6fca300acd9e5d4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 11:16:26 +0200 Subject: [PATCH 15/22] console: don't set PixelFormat alpha fields for 32bpp Currently it is inconstent, PixelFormat->amask is left unset whereas abits and amax and ashift are filled. As an alpha channel doesn't make sense for the vga framebuffer leave all alpha fields clear. Signed-off-by: Gerd Hoffmann --- console.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/console.c b/console.c index 48d88e43ce..d28b75ec7d 100644 --- a/console.c +++ b/console.c @@ -1715,18 +1715,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; From b6e9f63711ea19b110574e384477bad4ea74f4a2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 13:02:14 +0200 Subject: [PATCH 16/22] qxl: stop direct access to DisplaySurface fields. Signed-off-by: Gerd Hoffmann --- hw/qxl-render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index 47eb8b4154..98ecb21405 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -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)) { From 1fd2510a3786fb557919cdd71e8e65c504439ddc Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 13:05:05 +0200 Subject: [PATCH 17/22] vga: stop direct access to DisplaySurface fields. Signed-off-by: Gerd Hoffmann --- hw/vga.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/vga.c b/hw/vga.c index f31dbdd652..1188463208 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1709,8 +1709,13 @@ 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); + (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); } From b12f32c408ef8cb9b3a4dfcb3710b382fd24a3ee Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 13:12:58 +0200 Subject: [PATCH 18/22] pixman: switch screendump function. Signed-off-by: Gerd Hoffmann --- hw/vga.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/hw/vga.c b/hw/vga.c index 1188463208..023134ef68 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2393,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"); @@ -2408,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; @@ -2442,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; From 9f64916da20eea67121d544698676295bbb105a7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 13:29:43 +0200 Subject: [PATCH 19/22] pixman/vnc: use pixman images in vnc. The vnc code uses *three* DisplaySurfaces: First is the surface of the actual QemuConsole, usually the guest screen, but could also be a text console (monitor/serial reachable via Ctrl-Alt- keys). This is left as-is. Second is the current server's view of the screen content. The vnc code uses this to figure which parts of the guest screen did _really_ change to reduce the amount of updates sent to the vnc clients. It is also used as data source when sending out the updates to the clients. This surface gets replaced by a pixman image. The format changes too, instead of using the guest screen format we'll use fixed 32bit rgb framebuffer and convert the pixels on the fly when comparing and updating the server framebuffer. Third surface carries the format expected by the vnc client. That isn't used to store image data. This surface is switched to PixelFormat and a boolean for bigendian byte order. Signed-off-by: Gerd Hoffmann --- ui/vnc-enc-hextile-template.h | 23 ++-- ui/vnc-enc-hextile.c | 45 ++++--- ui/vnc-enc-tight.c | 144 ++++++++++----------- ui/vnc-enc-zrle.c | 18 +-- ui/vnc-jobs.c | 3 +- ui/vnc.c | 235 +++++++++++++++++++--------------- ui/vnc.h | 19 ++- 7 files changed, 259 insertions(+), 228 deletions(-) diff --git a/ui/vnc-enc-hextile-template.h b/ui/vnc-enc-hextile-template.h index a7310e1947..d868d75720 100644 --- a/ui/vnc-enc-hextile-template.h +++ b/ui/vnc-enc-hextile-template.h @@ -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); } } } diff --git a/ui/vnc-enc-hextile.c b/ui/vnc-enc-hextile.c index c860dbb2e5..263a0ce9d2 100644 --- a/ui/vnc-enc-hextile.c +++ b/ui/vnc-enc-hextile.c @@ -68,10 +68,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,28 +88,28 @@ 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; - case 32: - vs->hextile.send_tile = send_hextile_tile_32; - break; + switch (VNC_SERVER_FB_BITS) { + case 8: + vs->hextile.send_tile = send_hextile_tile_8; + break; + case 16: + vs->hextile.send_tile = send_hextile_tile_16; + break; + 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; - case 32: - vs->hextile.send_tile = send_hextile_tile_generic_32; - break; + switch (VNC_SERVER_FB_BITS) { + case 8: + vs->hextile.send_tile = send_hextile_tile_generic_8; + break; + case 16: + vs->hextile.send_tile = send_hextile_tile_generic_16; + break; + case 32: + vs->hextile.send_tile = send_hextile_tile_generic_32; + break; } } } diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 5d492abe92..8013c5c6dd 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -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++) { \ @@ -682,9 +682,7 @@ DEFINE_GRADIENT_FILTER_FUNCTION(32) 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)); \ + fbptr = vnc_server_fb_ptr(vd, x, y); \ \ c = *fbptr; \ if (samecolor && (uint32_t)c != *color) { \ @@ -698,7 +696,7 @@ DEFINE_GRADIENT_FILTER_FUNCTION(32) } \ } \ fbptr = (uint##bpp##_t *) \ - ((uint8_t *)fbptr + ds_get_linesize(vs->ds)); \ + ((uint8_t *)fbptr + vnc_server_fb_stride(vd)); \ } \ \ *color = (uint32_t)c; \ @@ -712,9 +710,7 @@ DEFINE_CHECK_SOLID_FUNCTION(8) 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: @@ -906,15 +902,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 +942,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 +962,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 +979,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 +996,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 +1039,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 +1054,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 +1066,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 +1104,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; @@ -1156,8 +1153,7 @@ static void rgb_prepare_row24(VncState *vs, uint8_t *dst, int x, int y, 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)); + fbptr = vnc_server_fb_ptr(vd, x, y); while (count--) { pix = *fbptr++; @@ -1178,9 +1174,7 @@ static void rgb_prepare_row24(VncState *vs, uint8_t *dst, int x, int y, 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)); \ + fbptr = vnc_server_fb_ptr(vd, x, y); \ \ while (count--) { \ pix = *fbptr++; \ @@ -1207,10 +1201,8 @@ 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) { + if (VNC_SERVER_FB_BYTES == 4) { + if (1) { rgb_prepare_row24(vs, dst, x, y, count); } else { rgb_prepare_row32(vs, dst, x, y, count); @@ -1326,23 +1318,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); } } @@ -1422,7 +1414,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); @@ -1713,8 +1705,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; diff --git a/ui/vnc-enc-zrle.c b/ui/vnc-enc-zrle.c index 917d384f57..ed3b48465d 100644 --- a/ui/vnc-enc-zrle.c +++ b/ui/vnc-enc-zrle.c @@ -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) { diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 3c592b3f3d..04f139b56f 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -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; diff --git a/ui/vnc.c b/ui/vnc.c index 0ae1c74984..15aef86047 100644 --- a/ui/vnc.c +++ b/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,37 @@ 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) { + } else if (VNC_SERVER_FB_BYTES == 2) { uint16_t *pixels = pixels1; int n, i; n = size >> 1; - 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 == 1) { + } else if (VNC_SERVER_FB_BYTES == 1) { uint8_t *pixels = pixels1; int n, i; n = size; - 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 { - fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n"); + fprintf(stderr, "%s: VncState color depth not supported\n", __func__); } } @@ -676,10 +693,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 +753,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 +766,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 +796,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 +806,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; } @@ -810,7 +826,6 @@ static void vnc_mouse_set(DisplayState *ds, 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 +835,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; @@ -898,8 +913,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 +1876,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 +1898,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 +1924,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 +1935,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 +2457,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 +2478,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 +2548,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 +2570,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; - guest_ptr = guest_row; + if (vd->guest.format != VNC_SERVER_FB_FORMAT) { + qemu_pixman_linebuf_fill(tmpbuf, vd->guest.fb, width, y); + guest_ptr = (uint8_t *)pixman_image_get_data(tmpbuf); + } else { + guest_ptr = guest_row; + } server_ptr = server_row; - 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 +2609,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; } diff --git a/ui/vnc.h b/ui/vnc.h index 068c2fcda5..d003afbbfd 100644 --- a/ui/vnc.h +++ b/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); From 47683d669f993308c2b84bed4ce64aafb5d7ced4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 11 Oct 2012 12:04:33 +0200 Subject: [PATCH 20/22] pixman/vnc: remove rgb_prepare_row* functions Let pixman do it instead. Signed-off-by: Gerd Hoffmann --- ui/vnc-enc-tight.c | 84 ++++++---------------------------------------- 1 file changed, 10 insertions(+), 74 deletions(-) diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 8013c5c6dd..9fd255650e 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -1145,74 +1145,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 = vnc_server_fb_ptr(vd, x, y); - - 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 = vnc_server_fb_ptr(vd, x, y); \ - \ - 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 (VNC_SERVER_FB_BYTES == 4) { - if (1) { - 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. */ @@ -1257,6 +1189,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; @@ -1285,13 +1218,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); @@ -1370,6 +1304,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; @@ -1424,17 +1359,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); From 94362682d31eb7c9bfd6bf74cd615d0616a09361 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 11 Oct 2012 12:11:27 +0200 Subject: [PATCH 21/22] pixman/vnc: remove dead code. Switching the vnc server framebuffer to use 32bpp unconditionally turns the code bits which handle 8 and 16 bpp into dead code. Remove them. Signed-off-by: Gerd Hoffmann --- ui/vnc-enc-hextile.c | 32 ---------------------- ui/vnc-enc-tight.c | 64 +++++++++++++++++++------------------------- ui/vnc.c | 18 ------------- 3 files changed, 27 insertions(+), 87 deletions(-) diff --git a/ui/vnc-enc-hextile.c b/ui/vnc-enc-hextile.c index 263a0ce9d2..2e768fd899 100644 --- a/ui/vnc-enc-hextile.c +++ b/ui/vnc-enc-hextile.c @@ -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" @@ -89,24 +69,12 @@ void vnc_hextile_set_pixel_conversion(VncState *vs, int generic) { if (!generic) { switch (VNC_SERVER_FB_BITS) { - case 8: - vs->hextile.send_tile = send_hextile_tile_8; - break; - case 16: - vs->hextile.send_tile = send_hextile_tile_16; - break; case 32: vs->hextile.send_tile = send_hextile_tile_32; break; } } else { switch (VNC_SERVER_FB_BITS) { - case 8: - vs->hextile.send_tile = send_hextile_tile_generic_8; - break; - case 16: - vs->hextile.send_tile = send_hextile_tile_generic_16; - break; case 32: vs->hextile.send_tile = send_hextile_tile_generic_32; break; diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 9fd255650e..9ae4cabffc 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -671,41 +671,35 @@ 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 = vnc_server_fb_ptr(vd, x, y); \ - \ - 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 + vnc_server_fb_stride(vd)); \ - } \ - \ - *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) @@ -713,10 +707,6 @@ static bool check_solid_tile(VncState *vs, int x, int y, int w, int h, 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); } } diff --git a/ui/vnc.c b/ui/vnc.c index 15aef86047..7c120e6f06 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -666,24 +666,6 @@ static void vnc_write_pixels_generic(VncState *vs, vnc_convert_pixel(vs, buf, pixels[i]); vnc_write(vs, buf, vs->client_pf.bytes_per_pixel); } - } else if (VNC_SERVER_FB_BYTES == 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->client_pf.bytes_per_pixel); - } - } else if (VNC_SERVER_FB_BYTES == 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->client_pf.bytes_per_pixel); - } - } else { - fprintf(stderr, "%s: VncState color depth not supported\n", __func__); } } From 64f735920ad319aee860e56bb9bad6cfccf4ad40 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 10 Oct 2012 11:15:52 +0200 Subject: [PATCH 22/22] pixman: drop obsolete fields from DisplaySurface Signed-off-by: Gerd Hoffmann --- console.c | 9 --------- console.h | 23 +++++++++++++---------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/console.c b/console.c index d28b75ec7d..048b48e721 100644 --- a/console.c +++ b/console.c @@ -1297,14 +1297,10 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type) static void qemu_alloc_display(DisplaySurface *surface, int width, int height, int linesize, PixelFormat pf, int newflags) { - surface->width = width; - surface->height = height; - surface->linesize = linesize; surface->pf = pf; qemu_pixman_image_unref(surface->image); surface->image = NULL; - surface->data = NULL; surface->format = qemu_pixman_get_format(&pf); assert(surface->format != 0); @@ -1313,7 +1309,6 @@ static void qemu_alloc_display(DisplaySurface *surface, int width, int height, NULL, linesize); assert(surface->image != NULL); - surface->data = (uint8_t *)pixman_image_get_data(surface->image); surface->flags = newflags | QEMU_ALLOCATED_FLAG; #ifdef HOST_WORDS_BIGENDIAN surface->flags |= QEMU_BIG_ENDIAN_FLAG; @@ -1347,9 +1342,6 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, { 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); @@ -1362,7 +1354,6 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, #ifdef HOST_WORDS_BIGENDIAN surface->flags = QEMU_BIG_ENDIAN_FLAG; #endif - surface->data = data; return surface; } diff --git a/console.h b/console.h index 21bd957d95..33ad69b48c 100644 --- a/console.h +++ b/console.h @@ -123,10 +123,6 @@ 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; }; @@ -346,32 +342,39 @@ static inline bool dpy_cursor_define_supported(struct DisplayState *s) 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