From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KYjjI-0005T1-NL for qemu-devel@nongnu.org; Thu, 28 Aug 2008 11:48:12 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KYjjH-0005S3-Q3 for qemu-devel@nongnu.org; Thu, 28 Aug 2008 11:48:12 -0400 Received: from [199.232.76.173] (port=47092 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KYjjH-0005Rj-8N for qemu-devel@nongnu.org; Thu, 28 Aug 2008 11:48:11 -0400 Received: from smtp.ctxuk.citrix.com ([62.200.22.115]:32480 helo=SMTP.EU.CITRIX.COM) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KYjjG-0004Jm-Hd for qemu-devel@nongnu.org; Thu, 28 Aug 2008 11:48:11 -0400 Message-ID: <48B6C90D.9020002@eu.citrix.com> Date: Thu, 28 Aug 2008 16:49:33 +0100 From: Stefano Stabellini MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH 3 of 3] vga shared buffer Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This patch implements sharing of the display pixel buffer between vnc.c and vga.c, in order to save a lot of memcpy's. Signed-off-by: Stefano Stabellini --- diff --git a/console.c b/console.c index cb85272..b5d7d86 100644 --- a/console.c +++ b/console.c @@ -1327,12 +1327,20 @@ CharDriverState *text_console_init(DisplayState *ds, const char *p) void qemu_console_resize(QEMUConsole *console, int width, int height) { - if (console->g_width != width || console->g_height != height - || !console->ds->data) { - console->g_width = width; - console->g_height = height; - if (active_console == console) { - dpy_resize(console->ds, width, height); - } + console->g_width = width; + console->g_height = height; + if (active_console == console) { + dpy_resize(console->ds, width, height); + } +} + +void qemu_console_resize_shared(QEMUConsole *console, int width, int height, + int depth, int linesize, void *pixels) +{ + console->g_width = width; + console->g_height = height; + if (active_console == console) { + dpy_resize_shared(console->ds, width, height, depth, linesize, pixels); } } + diff --git a/console.h b/console.h index fcac1eb..a054d97 100644 --- a/console.h +++ b/console.h @@ -84,9 +84,12 @@ struct DisplayState { struct QEMUTimer *gui_timer; uint64_t gui_timer_interval; int idle; /* there is nothing to update (window invisible), set by vnc/sdl */ + int shared_buf; void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); void (*dpy_resize)(struct DisplayState *s, int w, int h); + void (*dpy_resize_shared)(struct DisplayState *s, int w, int h, int depth, int linesize, void *pixels); + void (*dpy_setdata)(DisplayState *s, void *pixels); 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); @@ -108,6 +111,11 @@ static inline void dpy_resize(DisplayState *s, int w, int h) s->dpy_resize(s, w, h); } +static inline void dpy_resize_shared(DisplayState *s, int w, int h, int depth, int linesize, void *pixels) +{ + s->dpy_resize_shared(s, w, h, depth, linesize, pixels); +} + static inline void dpy_cursor(DisplayState *s, int x, int y) { if (s->dpy_text_cursor) @@ -140,6 +148,8 @@ CharDriverState *text_console_init(DisplayState *ds, const char *p); void console_select(unsigned int index); void console_color_init(DisplayState *ds); void qemu_console_resize(QEMUConsole *console, int width, int height); +void qemu_console_resize_shared(QEMUConsole *console, int width, int height, + int depth, int linesize, void *pixels); /* sdl.c */ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame); diff --git a/hw/vga.c b/hw/vga.c index eb0bae8..157f3e0 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1099,9 +1099,6 @@ static void vga_draw_text(VGAState *s, int full_update) vga_draw_glyph8_func *vga_draw_glyph8; vga_draw_glyph9_func *vga_draw_glyph9; - full_update |= update_palette16(s); - palette = s->last_palette; - /* compute font data address (in plane 2) */ v = s->sr[3]; offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2; @@ -1135,7 +1132,6 @@ static void vga_draw_text(VGAState *s, int full_update) cw = 9; if (s->sr[1] & 0x08) cw = 16; /* NOTE: no 18 pixel wide */ - x_incr = cw * ((s->ds->depth + 7) >> 3); width = (s->cr[0x01] + 1); if (s->cr[0x06] == 100) { /* ugly hack for CGA 160x100x16 - explain me the logic */ @@ -1152,16 +1148,21 @@ static void vga_draw_text(VGAState *s, int full_update) } if (width != s->last_width || height != s->last_height || - cw != s->last_cw || cheight != s->last_ch) { + cw != s->last_cw || cheight != s->last_ch || s->last_depth) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height); + s->last_depth = 0; s->last_width = width; s->last_height = height; s->last_ch = cheight; s->last_cw = cw; full_update = 1; } + full_update |= update_palette16(s); + palette = s->last_palette; + x_incr = cw * ((s->ds->depth + 7) >> 3); + cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr; if (cursor_offset != s->cursor_offset || s->cr[0xa] != s->cursor_start || @@ -1419,6 +1420,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) { int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask; int width, height, shift_control, line_offset, page0, page1, bwidth, bits; + int ds_depth, depth; int disp_width, multi_scan, multi_run; uint8_t *d; uint32_t v, addr1, addr; @@ -1446,6 +1448,35 @@ static void vga_draw_graphic(VGAState *s, int full_update) s->double_scan = double_scan; } + ds_depth = s->ds->depth; + depth = s->get_bpp(s); + if (s->ds->dpy_resize_shared) { + if (s->line_offset != s->last_line_offset || + disp_width != s->last_width || + height != s->last_height || + s->last_depth != depth) { + qemu_console_resize_shared(s->console, disp_width, height, + depth, s->line_offset, s->vram_ptr + (s->start_addr * 4)); + s->last_scr_width = disp_width; + s->last_scr_height = height; + s->last_width = disp_width; + s->last_height = height; + s->last_line_offset = s->line_offset; + s->last_depth = depth; + full_update = 1; + } else if (s->ds->shared_buf && + (full_update || s->ds->data != s->vram_ptr + (s->start_addr * 4))) + s->ds->dpy_setdata(s->ds, s->vram_ptr + (s->start_addr * 4)); + } else if (disp_width != s->last_width || + height != s->last_height) { + qemu_console_resize(s->console, disp_width, height); + s->last_scr_width = disp_width; + s->last_scr_height = height; + s->last_width = disp_width; + s->last_height = height; + full_update = 1; + } + if (shift_control == 0) { full_update |= update_palette16(s); if (s->sr[0x01] & 8) { @@ -1496,17 +1527,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) } } vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)]; - - if (disp_width != s->last_width || - height != s->last_height) { - qemu_console_resize(s->console, disp_width, height); - s->last_scr_width = disp_width; - s->last_scr_height = height; - s->last_width = disp_width; - s->last_height = height; - full_update = 1; - } - if (s->cursor_invalidate) + if (!s->ds->shared_buf && s->cursor_invalidate) s->cursor_invalidate(s); line_offset = s->line_offset; @@ -1552,9 +1573,11 @@ static void vga_draw_graphic(VGAState *s, int full_update) page_min = page0; if (page1 > page_max) page_max = page1; - vga_draw_line(s, d, s->vram_ptr + addr, width); - if (s->cursor_draw_line) - s->cursor_draw_line(s, d, y); + if (!s->ds->shared_buf) { + vga_draw_line(s, d, s->vram_ptr + addr, width); + if (s->cursor_draw_line) + s->cursor_draw_line(s, d, y); + } } else { if (y_start >= 0) { /* flush to display */ diff --git a/hw/vga_int.h b/hw/vga_int.h index 343da34..d187f1b 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -130,9 +130,11 @@ uint32_t line_compare; \ uint32_t start_addr; \ uint32_t plane_updated; \ + uint32_t last_line_offset; \ uint8_t last_cw, last_ch; \ uint32_t last_width, last_height; /* in chars or pixels */ \ uint32_t last_scr_width, last_scr_height; /* in pixels */ \ + uint32_t last_depth; /* in bits */ \ uint8_t cursor_start, cursor_end; \ uint32_t cursor_offset; \ unsigned int (*rgb_to_pixel)(unsigned int r, \ diff --git a/vnc.c b/vnc.c index d021b50..7793392 100644 --- a/vnc.c +++ b/vnc.c @@ -289,13 +289,28 @@ static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h, vnc_write_s32(vs, encoding); } -static void vnc_dpy_resize(DisplayState *ds, int w, int h) +static void vnc_dpy_resize_shared(DisplayState *ds, int w, int h, int depth, int linesize, void *pixels) { + static int allocated; int size_changed; VncState *vs = ds->opaque; - ds->data = qemu_realloc(ds->data, w * h * vs->depth); - vs->old_data = qemu_realloc(vs->old_data, w * h * vs->depth); + vnc_colourdepth(ds, depth); + if (!ds->shared_buf) { + ds->linesize = w * vs->depth; + if (allocated) + ds->data = realloc(ds->data, h * ds->linesize); + else + ds->data = malloc(h * ds->linesize); + allocated = 1; + } else { + ds->linesize = linesize; + if (allocated) { + free(ds->data); + allocated = 0; + } + } + vs->old_data = qemu_realloc(vs->old_data, h * ds->linesize); if (ds->data == NULL || vs->old_data == NULL) { fprintf(stderr, "vnc: memory allocation failed\n"); @@ -309,7 +324,6 @@ static void vnc_dpy_resize(DisplayState *ds, int w, int h) size_changed = ds->width != w || ds->height != h; ds->width = w; ds->height = h; - ds->linesize = w * vs->depth; if (size_changed) { vs->width = ds->width; vs->height = ds->height; @@ -324,6 +338,12 @@ static void vnc_dpy_resize(DisplayState *ds, int w, int h) memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); memset(vs->old_data, 42, vs->ds->linesize * vs->ds->height); + if (ds->shared_buf) ds->data = pixels; +} + +static void vnc_dpy_resize(DisplayState *ds, int w, int h) +{ + vnc_dpy_resize_shared(ds, w, h, 0, w * (ds->depth / 8), NULL); } /* fastest code */ @@ -496,6 +516,9 @@ static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_ int pitch = ds->linesize; VncState *vs = ds->opaque; + if (ds->shared_buf) + return; + vnc_update_client(vs); if (dst_y > src_y) { @@ -1247,9 +1270,6 @@ static void set_pixel_format(VncState *vs, vs->blue_shift = blue_shift; vs->blue_max = blue_max; vs->pix_bpp = bits_per_pixel / 8; - - vga_hw_invalidate(); - vga_hw_update(); } static void pixel_format_message (VncState *vs) { @@ -1303,6 +1323,11 @@ static void pixel_format_message (VncState *vs) { vnc_write(vs, pad, 3); /* padding */ } +static void vnc_dpy_setdata(DisplayState *ds, void *pixels) +{ + ds->data = pixels; +} + static void vnc_colourdepth(DisplayState *ds, int depth) { int host_big_endian_flag; @@ -1310,13 +1335,16 @@ static void vnc_colourdepth(DisplayState *ds, int depth) switch (depth) { case 24: + ds->shared_buf = 0; if (ds->depth == 32) return; depth = 32; break; case 8: case 0: + ds->shared_buf = 0; return; default: + ds->shared_buf = 1; break; } @@ -2172,9 +2200,14 @@ void vnc_display_init(DisplayState *ds) vs->ds->data = NULL; vs->ds->dpy_update = vnc_dpy_update; vs->ds->dpy_resize = vnc_dpy_resize; + vs->ds->dpy_setdata = vnc_dpy_setdata; + vs->ds->dpy_resize_shared = vnc_dpy_resize_shared; vs->ds->dpy_refresh = NULL; - vnc_dpy_resize(vs->ds, 640, 400); + vs->ds->width = 640; + vs->ds->height = 400; + vs->ds->linesize = 640 * 4; + vnc_dpy_resize_shared(ds, ds->width, ds->height, 24, ds->linesize, NULL); } #if CONFIG_VNC_TLS