diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/cocoa.m | 4 | ||||
-rw-r--r-- | ui/curses.c | 21 | ||||
-rw-r--r-- | ui/sdl.c | 140 | ||||
-rw-r--r-- | ui/spice-display.c | 8 | ||||
-rw-r--r-- | ui/vnc-enc-hextile-template.h | 23 | ||||
-rw-r--r-- | ui/vnc-enc-hextile.c | 53 | ||||
-rw-r--r-- | ui/vnc-enc-tight.c | 280 | ||||
-rw-r--r-- | ui/vnc-enc-zrle.c | 18 | ||||
-rw-r--r-- | ui/vnc-jobs.c | 3 | ||||
-rw-r--r-- | ui/vnc.c | 255 | ||||
-rw-r--r-- | ui/vnc.h | 19 |
11 files changed, 306 insertions, 518 deletions
diff --git a/ui/cocoa.m b/ui/cocoa.m index 2383646dc0..87d2e44c69 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -1017,8 +1017,8 @@ void cocoa_display_init(DisplayState *ds, int full_screen) dcl = g_malloc0(sizeof(DisplayChangeListener)); // register vga output callbacks - dcl->dpy_update = cocoa_update; - dcl->dpy_resize = cocoa_resize; + dcl->dpy_gfx_update = cocoa_update; + dcl->dpy_gfx_resize = cocoa_resize; dcl->dpy_refresh = cocoa_refresh; register_displaychangelistener(ds, dcl); 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; } @@ -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; - } - } -} - -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 (!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)); } - - 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 */ @@ -553,7 +457,7 @@ static void sdl_scale(DisplayState *ds, int width, int height) if (!is_buffer_shared(ds->surface)) { ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds), ds_get_height(ds)); - dpy_resize(ds); + dpy_gfx_resize(ds); } } @@ -899,13 +803,7 @@ static void sdl_refresh(DisplayState *ds) } } -static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c) -{ - SDL_Rect dst = { x, y, w, h }; - SDL_FillRect(real_screen, &dst, c); -} - -static void sdl_mouse_warp(int x, int y, int on) +static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on) { if (on) { if (!guest_cursor) @@ -921,7 +819,7 @@ static void sdl_mouse_warp(int x, int y, int on) guest_x = x, guest_y = y; } -static void sdl_mouse_define(QEMUCursor *c) +static void sdl_mouse_define(DisplayState *ds, QEMUCursor *c) { uint8_t *image, *mask; int bpl; @@ -955,7 +853,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) { int flags; uint8_t data = 0; - DisplayAllocator *da; const SDL_VideoInfo *vi; char *filename; @@ -1020,23 +917,14 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) } dcl = g_malloc0(sizeof(DisplayChangeListener)); - dcl->dpy_update = sdl_update; - dcl->dpy_resize = sdl_resize; + dcl->dpy_gfx_update = sdl_update; + dcl->dpy_gfx_resize = sdl_resize; dcl->dpy_refresh = sdl_refresh; - dcl->dpy_setdata = sdl_setdata; - dcl->dpy_fill = sdl_fill; - ds->mouse_set = sdl_mouse_warp; - ds->cursor_define = sdl_mouse_define; + dcl->dpy_gfx_setdata = sdl_setdata; + dcl->dpy_mouse_set = sdl_mouse_warp; + dcl->dpy_cursor_define = sdl_mouse_define; register_displaychangelistener(ds, dcl); - da = g_malloc0(sizeof(DisplayAllocator)); - da->create_displaysurface = sdl_create_displaysurface; - da->resize_displaysurface = sdl_resize_displaysurface; - da->free_displaysurface = sdl_free_displaysurface; - if (register_displayallocator(ds, da) == da) { - dpy_resize(ds); - } - mouse_mode_notifier.notify = sdl_mouse_mode_change; qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier); diff --git a/ui/spice-display.c b/ui/spice-display.c index b61764f381..fb99148349 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; } @@ -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-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..2e768fd899 100644 --- a/ui/vnc-enc-hextile.c +++ b/ui/vnc-enc-hextile.c @@ -32,31 +32,11 @@ 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" #undef BPP @@ -68,10 +48,9 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x, int i, j; int has_fg, has_bg; uint8_t *last_fg, *last_bg; - VncDisplay *vd = vs->vd; - last_fg = (uint8_t *) g_malloc(vd->server->pf.bytes_per_pixel); - last_bg = (uint8_t *) g_malloc(vd->server->pf.bytes_per_pixel); + last_fg = (uint8_t *) g_malloc(VNC_SERVER_FB_BYTES); + last_bg = (uint8_t *) g_malloc(VNC_SERVER_FB_BYTES); has_fg = has_bg = 0; for (j = y; j < (y + h); j += 16) { for (i = x; i < (x + w); i += 16) { @@ -89,28 +68,16 @@ 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 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 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..9ae4cabffc 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++) { \ @@ -671,56 +671,42 @@ DEFINE_GRADIENT_FILTER_FUNCTION(32) * that case new color will be stored in *colorPtr. */ -#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ - \ - static bool \ - check_solid_tile##bpp(VncState *vs, int x, int y, int w, int h, \ - uint32_t* color, bool samecolor) \ - { \ - VncDisplay *vd = vs->vd; \ - uint##bpp##_t *fbptr; \ - uint##bpp##_t c; \ - int dx, dy; \ - \ - fbptr = (uint##bpp##_t *) \ - (vd->server->data + y * ds_get_linesize(vs->ds) + \ - x * ds_get_bytes_per_pixel(vs->ds)); \ - \ - c = *fbptr; \ - if (samecolor && (uint32_t)c != *color) { \ - return false; \ - } \ - \ - for (dy = 0; dy < h; dy++) { \ - for (dx = 0; dx < w; dx++) { \ - if (c != fbptr[dx]) { \ - return false; \ - } \ - } \ - fbptr = (uint##bpp##_t *) \ - ((uint8_t *)fbptr + ds_get_linesize(vs->ds)); \ - } \ - \ - *color = (uint32_t)c; \ - return true; \ +static bool +check_solid_tile32(VncState *vs, int x, int y, int w, int h, + uint32_t *color, bool samecolor) +{ + VncDisplay *vd = vs->vd; + uint32_t *fbptr; + uint32_t c; + int dx, dy; + + fbptr = vnc_server_fb_ptr(vd, x, y); + + c = *fbptr; + if (samecolor && (uint32_t)c != *color) { + return false; + } + + 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)); } -DEFINE_CHECK_SOLID_FUNCTION(32) -DEFINE_CHECK_SOLID_FUNCTION(16) -DEFINE_CHECK_SOLID_FUNCTION(8) + *color = (uint32_t)c; + return true; +} static bool check_solid_tile(VncState *vs, int x, int y, int w, int h, uint32_t* color, bool samecolor) { - VncDisplay *vd = vs->vd; - - switch(vd->server->pf.bytes_per_pixel) { + switch (VNC_SERVER_FB_BYTES) { case 4: return check_solid_tile32(vs, x, y, w, h, color, samecolor); - case 2: - return check_solid_tile16(vs, x, y, w, h, color, samecolor); - default: - return check_solid_tile8(vs, x, y, w, h, color, samecolor); } } @@ -906,15 +892,15 @@ static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret) buf32 = (uint32_t *)buf; - if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == - (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)) { - rshift = vs->clientds.pf.rshift; - gshift = vs->clientds.pf.gshift; - bshift = vs->clientds.pf.bshift; + if (1 /* FIXME: (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == + (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) */) { + rshift = vs->client_pf.rshift; + gshift = vs->client_pf.gshift; + bshift = vs->client_pf.bshift; } else { - rshift = 24 - vs->clientds.pf.rshift; - gshift = 24 - vs->clientds.pf.gshift; - bshift = 24 - vs->clientds.pf.bshift; + rshift = 24 - vs->client_pf.rshift; + gshift = 24 - vs->client_pf.gshift; + bshift = 24 - vs->client_pf.bshift; } if (ret) { @@ -946,7 +932,7 @@ static int send_full_color_rect(VncState *vs, int x, int y, int w, int h) tight_pack24(vs, vs->tight.tight.buffer, w * h, &vs->tight.tight.offset); bytes = 3; } else { - bytes = vs->clientds.pf.bytes_per_pixel; + bytes = vs->client_pf.bytes_per_pixel; } bytes = tight_compress_data(vs, stream, w * h * bytes, @@ -966,7 +952,7 @@ static int send_solid_rect(VncState *vs) tight_pack24(vs, vs->tight.tight.buffer, 1, &vs->tight.tight.offset); bytes = 3; } else { - bytes = vs->clientds.pf.bytes_per_pixel; + bytes = vs->client_pf.bytes_per_pixel; } vnc_write(vs, vs->tight.tight.buffer, bytes); @@ -983,7 +969,7 @@ static int send_mono_rect(VncState *vs, int x, int y, #ifdef CONFIG_VNC_PNG if (tight_can_send_png_rect(vs, w, h)) { int ret; - int bpp = vs->clientds.pf.bytes_per_pixel * 8; + int bpp = vs->client_pf.bytes_per_pixel * 8; VncPalette *palette = palette_new(2, bpp); palette_put(palette, bg); @@ -1000,7 +986,7 @@ static int send_mono_rect(VncState *vs, int x, int y, vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE); vnc_write_u8(vs, 1); - switch(vs->clientds.pf.bytes_per_pixel) { + switch (vs->client_pf.bytes_per_pixel) { case 4: { uint32_t buf[2] = {bg, fg}; @@ -1043,7 +1029,7 @@ static void write_palette(int idx, uint32_t color, void *opaque) { struct palette_cb_priv *priv = opaque; VncState *vs = priv->vs; - uint32_t bytes = vs->clientds.pf.bytes_per_pixel; + uint32_t bytes = vs->client_pf.bytes_per_pixel; if (bytes == 4) { ((uint32_t*)priv->header)[idx] = color; @@ -1058,8 +1044,9 @@ static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) int level = tight_conf[vs->tight.compression].gradient_zlib_level; ssize_t bytes; - if (vs->clientds.pf.bytes_per_pixel == 1) + if (vs->client_pf.bytes_per_pixel == 1) { return send_full_color_rect(vs, x, y, w, h); + } vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4); vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT); @@ -1069,7 +1056,7 @@ static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) if (vs->tight.pixel24) { tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h); bytes = 3; - } else if (vs->clientds.pf.bytes_per_pixel == 4) { + } else if (vs->client_pf.bytes_per_pixel == 4) { tight_filter_gradient32(vs, (uint32_t *)vs->tight.tight.buffer, w, h); bytes = 4; } else { @@ -1107,7 +1094,7 @@ static int send_palette_rect(VncState *vs, int x, int y, vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE); vnc_write_u8(vs, colors - 1); - switch(vs->clientds.pf.bytes_per_pixel) { + switch (vs->client_pf.bytes_per_pixel) { case 4: { size_t old_offset, offset; @@ -1148,79 +1135,6 @@ static int send_palette_rect(VncState *vs, int x, int y, return (bytes >= 0); } -#if defined(CONFIG_VNC_JPEG) || defined(CONFIG_VNC_PNG) -static void rgb_prepare_row24(VncState *vs, uint8_t *dst, int x, int y, - int count) -{ - VncDisplay *vd = vs->vd; - uint32_t *fbptr; - uint32_t pix; - - fbptr = (uint32_t *)(vd->server->data + y * ds_get_linesize(vs->ds) + - x * ds_get_bytes_per_pixel(vs->ds)); - - while (count--) { - pix = *fbptr++; - *dst++ = (uint8_t)(pix >> vs->ds->surface->pf.rshift); - *dst++ = (uint8_t)(pix >> vs->ds->surface->pf.gshift); - *dst++ = (uint8_t)(pix >> vs->ds->surface->pf.bshift); - } -} - -#define DEFINE_RGB_GET_ROW_FUNCTION(bpp) \ - \ - static void \ - rgb_prepare_row##bpp(VncState *vs, uint8_t *dst, \ - int x, int y, int count) \ - { \ - VncDisplay *vd = vs->vd; \ - uint##bpp##_t *fbptr; \ - uint##bpp##_t pix; \ - int r, g, b; \ - \ - fbptr = (uint##bpp##_t *) \ - (vd->server->data + y * ds_get_linesize(vs->ds) + \ - x * ds_get_bytes_per_pixel(vs->ds)); \ - \ - while (count--) { \ - pix = *fbptr++; \ - \ - r = (int)((pix >> vs->ds->surface->pf.rshift) \ - & vs->ds->surface->pf.rmax); \ - g = (int)((pix >> vs->ds->surface->pf.gshift) \ - & vs->ds->surface->pf.gmax); \ - b = (int)((pix >> vs->ds->surface->pf.bshift) \ - & vs->ds->surface->pf.bmax); \ - \ - *dst++ = (uint8_t)((r * 255 + vs->ds->surface->pf.rmax / 2) \ - / vs->ds->surface->pf.rmax); \ - *dst++ = (uint8_t)((g * 255 + vs->ds->surface->pf.gmax / 2) \ - / vs->ds->surface->pf.gmax); \ - *dst++ = (uint8_t)((b * 255 + vs->ds->surface->pf.bmax / 2) \ - / vs->ds->surface->pf.bmax); \ - } \ - } - -DEFINE_RGB_GET_ROW_FUNCTION(16) -DEFINE_RGB_GET_ROW_FUNCTION(32) - -static void rgb_prepare_row(VncState *vs, uint8_t *dst, int x, int y, - int count) -{ - if (ds_get_bytes_per_pixel(vs->ds) == 4) { - if (vs->ds->surface->pf.rmax == 0xFF && - vs->ds->surface->pf.gmax == 0xFF && - vs->ds->surface->pf.bmax == 0xFF) { - rgb_prepare_row24(vs, dst, x, y, count); - } else { - rgb_prepare_row32(vs, dst, x, y, count); - } - } else { - rgb_prepare_row16(vs, dst, x, y, count); - } -} -#endif /* CONFIG_VNC_JPEG or CONFIG_VNC_PNG */ - /* * JPEG compression stuff. */ @@ -1265,6 +1179,7 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; struct jpeg_destination_mgr manager; + pixman_image_t *linebuf; JSAMPROW row[1]; uint8_t *buf; int dy; @@ -1293,13 +1208,14 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) jpeg_start_compress(&cinfo, true); - buf = g_malloc(w * 3); + linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); + buf = (uint8_t *)pixman_image_get_data(linebuf); row[0] = buf; for (dy = 0; dy < h; dy++) { - rgb_prepare_row(vs, buf, x, y + dy, w); + qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, dy); jpeg_write_scanlines(&cinfo, row, 1); } - g_free(buf); + qemu_pixman_image_unref(linebuf); jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); @@ -1326,23 +1242,23 @@ static void write_png_palette(int idx, uint32_t pix, void *opaque) if (vs->tight.pixel24) { - color->red = (pix >> vs->clientds.pf.rshift) & vs->clientds.pf.rmax; - color->green = (pix >> vs->clientds.pf.gshift) & vs->clientds.pf.gmax; - color->blue = (pix >> vs->clientds.pf.bshift) & vs->clientds.pf.bmax; + color->red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax; + color->green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax; + color->blue = (pix >> vs->client_pf.bshift) & vs->client_pf.bmax; } else { int red, green, blue; - red = (pix >> vs->clientds.pf.rshift) & vs->clientds.pf.rmax; - green = (pix >> vs->clientds.pf.gshift) & vs->clientds.pf.gmax; - blue = (pix >> vs->clientds.pf.bshift) & vs->clientds.pf.bmax; - color->red = ((red * 255 + vs->clientds.pf.rmax / 2) / - vs->clientds.pf.rmax); - color->green = ((green * 255 + vs->clientds.pf.gmax / 2) / - vs->clientds.pf.gmax); - color->blue = ((blue * 255 + vs->clientds.pf.bmax / 2) / - vs->clientds.pf.bmax); + red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax; + green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax; + blue = (pix >> vs->client_pf.bshift) & vs->client_pf.bmax; + color->red = ((red * 255 + vs->client_pf.rmax / 2) / + vs->client_pf.rmax); + color->green = ((green * 255 + vs->client_pf.gmax / 2) / + vs->client_pf.gmax); + color->blue = ((blue * 255 + vs->client_pf.bmax / 2) / + vs->client_pf.bmax); } } @@ -1378,6 +1294,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, png_structp png_ptr; png_infop info_ptr; png_colorp png_palette = NULL; + pixman_image_t *linebuf; int level = tight_png_conf[vs->tight.compression].png_zlib_level; int filters = tight_png_conf[vs->tight.compression].png_filters; uint8_t *buf; @@ -1422,7 +1339,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); - if (vs->clientds.pf.bytes_per_pixel == 4) { + if (vs->client_pf.bytes_per_pixel == 4) { tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); } else { tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); @@ -1432,17 +1349,18 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, png_write_info(png_ptr, info_ptr); buffer_reserve(&vs->tight.png, 2048); - buf = g_malloc(w * 3); + linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); + buf = (uint8_t *)pixman_image_get_data(linebuf); for (dy = 0; dy < h; dy++) { if (color_type == PNG_COLOR_TYPE_PALETTE) { memcpy(buf, vs->tight.tight.buffer + (dy * w), w); } else { - rgb_prepare_row(vs, buf, x, y + dy, w); + qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, dy); } png_write_row(png_ptr, buf); } - g_free(buf); + qemu_pixman_image_unref(linebuf); png_write_end(png_ptr, NULL); @@ -1713,8 +1631,8 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y, { int max_rows; - if (vs->clientds.pf.bytes_per_pixel == 4 && vs->clientds.pf.rmax == 0xFF && - vs->clientds.pf.bmax == 0xFF && vs->clientds.pf.gmax == 0xFF) { + if (vs->client_pf.bytes_per_pixel == 4 && vs->client_pf.rmax == 0xFF && + vs->client_pf.bmax == 0xFF && vs->client_pf.gmax == 0xFF) { vs->tight.pixel24 = true; } else { vs->tight.pixel24 = false; 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 dfe482dc0f..57c091683b 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; @@ -436,6 +436,8 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) int i; VncDisplay *vd = ds->opaque; struct VncSurface *s = &vd->guest; + int width = ds_get_width(ds); + int height = ds_get_height(ds); h += y; @@ -446,10 +448,10 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) w += (x % 16); x -= (x % 16); - x = MIN(x, s->ds->width); - y = MIN(y, s->ds->height); - w = MIN(x + w, s->ds->width) - x; - h = MIN(h, s->ds->height); + x = MIN(x, width); + y = MIN(y, height); + w = MIN(x + w, width) - x; + h = MIN(h, height); for (; y < h; y++) for (i = 0; i < w; i += 16) @@ -550,6 +552,21 @@ static void vnc_abort_display_jobs(VncDisplay *vd) } } +int vnc_server_fb_stride(VncDisplay *vd) +{ + return pixman_image_get_stride(vd->server); +} + +void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y) +{ + uint8_t *ptr; + + ptr = (uint8_t *)pixman_image_get_data(vd->server); + ptr += y * vnc_server_fb_stride(vd); + ptr += x * VNC_SERVER_FB_BYTES; + return ptr; +} + static void vnc_dpy_resize(DisplayState *ds) { VncDisplay *vd = ds->opaque; @@ -558,20 +575,20 @@ static void vnc_dpy_resize(DisplayState *ds) vnc_abort_display_jobs(vd); /* server surface */ - if (!vd->server) - vd->server = g_malloc0(sizeof(*vd->server)); - if (vd->server->data) - g_free(vd->server->data); - *(vd->server) = *(ds->surface); - vd->server->data = g_malloc0(vd->server->linesize * - vd->server->height); + qemu_pixman_image_unref(vd->server); + vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT, + ds_get_width(ds), + ds_get_height(ds), + NULL, 0); /* guest surface */ - if (!vd->guest.ds) - vd->guest.ds = g_malloc0(sizeof(*vd->guest.ds)); +#if 0 /* FIXME */ if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel) console_color_init(ds); - *(vd->guest.ds) = *(ds->surface); +#endif + qemu_pixman_image_unref(vd->guest.fb); + vd->guest.fb = pixman_image_ref(ds->surface->image); + vd->guest.format = ds->surface->format; memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty)); QTAILQ_FOREACH(vs, &vd->clients, next) { @@ -585,7 +602,7 @@ static void vnc_dpy_resize(DisplayState *ds) } /* fastest code */ -static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf, +static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size) { vnc_write(vs, pixels, size); @@ -595,23 +612,23 @@ static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf, void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) { uint8_t r, g, b; - VncDisplay *vd = vs->vd; - r = ((((v & vd->server->pf.rmask) >> vd->server->pf.rshift) << vs->clientds.pf.rbits) >> - vd->server->pf.rbits); - g = ((((v & vd->server->pf.gmask) >> vd->server->pf.gshift) << vs->clientds.pf.gbits) >> - vd->server->pf.gbits); - b = ((((v & vd->server->pf.bmask) >> vd->server->pf.bshift) << vs->clientds.pf.bbits) >> - vd->server->pf.bbits); - v = (r << vs->clientds.pf.rshift) | - (g << vs->clientds.pf.gshift) | - (b << vs->clientds.pf.bshift); - switch(vs->clientds.pf.bytes_per_pixel) { +#if VNC_SERVER_FB_FORMAT == PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8) + r = (((v & 0x00ff0000) >> 16) << vs->client_pf.rbits) >> 8; + g = (((v & 0x0000ff00) >> 8) << vs->client_pf.gbits) >> 8; + b = (((v & 0x000000ff) >> 0) << vs->client_pf.bbits) >> 8; +#else +# error need some bits here if you change VNC_SERVER_FB_FORMAT +#endif + v = (r << vs->client_pf.rshift) | + (g << vs->client_pf.gshift) | + (b << vs->client_pf.bshift); + switch (vs->client_pf.bytes_per_pixel) { case 1: buf[0] = v; break; case 2: - if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { + if (vs->client_be) { buf[0] = v >> 8; buf[1] = v; } else { @@ -621,7 +638,7 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) break; default: case 4: - if (vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) { + if (vs->client_be) { buf[0] = v >> 24; buf[1] = v >> 16; buf[2] = v >> 8; @@ -636,37 +653,19 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) } } -static void vnc_write_pixels_generic(VncState *vs, struct PixelFormat *pf, +static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size) { uint8_t buf[4]; - if (pf->bytes_per_pixel == 4) { + if (VNC_SERVER_FB_BYTES == 4) { uint32_t *pixels = pixels1; int n, i; n = size >> 2; - for(i = 0; i < n; i++) { - vnc_convert_pixel(vs, buf, pixels[i]); - vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); - } - } else if (pf->bytes_per_pixel == 2) { - uint16_t *pixels = pixels1; - int n, i; - n = size >> 1; - for(i = 0; i < n; i++) { + 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) { - uint8_t *pixels = pixels1; - int n, i; - n = size; - for(i = 0; i < n; i++) { - vnc_convert_pixel(vs, buf, pixels[i]); - vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel); - } - } else { - fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n"); } } @@ -676,10 +675,10 @@ int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) uint8_t *row; VncDisplay *vd = vs->vd; - row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds); + row = vnc_server_fb_ptr(vd, x, y); for (i = 0; i < h; i++) { - vs->write_pixels(vs, &vd->server->pf, row, w * ds_get_bytes_per_pixel(vs->ds)); - row += ds_get_linesize(vs->ds); + vs->write_pixels(vs, row, w * VNC_SERVER_FB_BYTES); + row += vnc_server_fb_stride(vd); } return 1; } @@ -736,7 +735,7 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int VncState *vs, *vn; uint8_t *src_row; uint8_t *dst_row; - int i,x,y,pitch,depth,inc,w_lim,s; + int i, x, y, pitch, inc, w_lim, s; int cmp_bytes; vnc_refresh_server_surface(vd); @@ -749,10 +748,9 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } /* do bitblit op on the local surface too */ - pitch = ds_get_linesize(vd->ds); - depth = ds_get_bytes_per_pixel(vd->ds); - src_row = vd->server->data + pitch * src_y + depth * src_x; - dst_row = vd->server->data + pitch * dst_y + depth * dst_x; + pitch = vnc_server_fb_stride(vd); + src_row = vnc_server_fb_ptr(vd, src_x, src_y); + dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y); y = dst_y; inc = 1; if (dst_y > src_y) { @@ -780,7 +778,7 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } else { s = 16; } - cmp_bytes = s * depth; + cmp_bytes = s * VNC_SERVER_FB_BYTES; if (memcmp(src_row, dst_row, cmp_bytes) == 0) continue; memmove(dst_row, src_row, cmp_bytes); @@ -790,8 +788,8 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } } } - src_row += pitch - w * depth; - dst_row += pitch - w * depth; + src_row += pitch - w * VNC_SERVER_FB_BYTES; + dst_row += pitch - w * VNC_SERVER_FB_BYTES; y += inc; } @@ -802,7 +800,7 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } } -static void vnc_mouse_set(int x, int y, int visible) +static void vnc_mouse_set(DisplayState *ds, int x, int y, int visible) { /* can we ask the client(s) to move the pointer ??? */ } @@ -810,7 +808,6 @@ static void vnc_mouse_set(int x, int y, int visible) static int vnc_cursor_define(VncState *vs) { QEMUCursor *c = vs->vd->cursor; - PixelFormat pf = qemu_default_pixelformat(32); int isize; if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) { @@ -820,8 +817,8 @@ static int vnc_cursor_define(VncState *vs) vnc_write_u16(vs, 1); /* # of rects */ vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height, VNC_ENCODING_RICH_CURSOR); - isize = c->width * c->height * vs->clientds.pf.bytes_per_pixel; - vnc_write_pixels_generic(vs, &pf, c->data, isize); + isize = c->width * c->height * vs->client_pf.bytes_per_pixel; + vnc_write_pixels_generic(vs, c->data, isize); vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize); vnc_unlock_output(vs); return 0; @@ -829,7 +826,7 @@ static int vnc_cursor_define(VncState *vs) return -1; } -static void vnc_dpy_cursor_define(QEMUCursor *c) +static void vnc_dpy_cursor_define(DisplayState *ds, QEMUCursor *c) { VncDisplay *vd = vnc_display; VncState *vs; @@ -898,8 +895,8 @@ static int vnc_update_client(VncState *vs, int has_dirty) */ job = vnc_job_new(vs); - width = MIN(vd->server->width, vs->client_width); - height = MIN(vd->server->height, vs->client_height); + width = MIN(pixman_image_get_width(vd->server), vs->client_width); + height = MIN(pixman_image_get_height(vd->server), vs->client_height); for (y = 0; y < height; y++) { int x; @@ -1861,9 +1858,9 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) static void set_pixel_conversion(VncState *vs) { - if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) == - (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) && - !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) { + pixman_format_code_t fmt = qemu_pixman_get_format(&vs->client_pf); + + if (fmt == VNC_SERVER_FB_FORMAT) { vs->write_pixels = vnc_write_pixels_copy; vnc_hextile_set_pixel_conversion(vs, 0); } else { @@ -1883,23 +1880,22 @@ static void set_pixel_format(VncState *vs, return; } - vs->clientds = *(vs->vd->guest.ds); - vs->clientds.pf.rmax = red_max; - vs->clientds.pf.rbits = hweight_long(red_max); - vs->clientds.pf.rshift = red_shift; - vs->clientds.pf.rmask = red_max << red_shift; - vs->clientds.pf.gmax = green_max; - vs->clientds.pf.gbits = hweight_long(green_max); - vs->clientds.pf.gshift = green_shift; - vs->clientds.pf.gmask = green_max << green_shift; - vs->clientds.pf.bmax = blue_max; - vs->clientds.pf.bbits = hweight_long(blue_max); - vs->clientds.pf.bshift = blue_shift; - vs->clientds.pf.bmask = blue_max << blue_shift; - vs->clientds.pf.bits_per_pixel = bits_per_pixel; - vs->clientds.pf.bytes_per_pixel = bits_per_pixel / 8; - vs->clientds.pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel; - vs->clientds.flags = big_endian_flag ? QEMU_BIG_ENDIAN_FLAG : 0x00; + vs->client_pf.rmax = red_max; + vs->client_pf.rbits = hweight_long(red_max); + vs->client_pf.rshift = red_shift; + vs->client_pf.rmask = red_max << red_shift; + vs->client_pf.gmax = green_max; + vs->client_pf.gbits = hweight_long(green_max); + vs->client_pf.gshift = green_shift; + vs->client_pf.gmask = green_max << green_shift; + vs->client_pf.bmax = blue_max; + vs->client_pf.bbits = hweight_long(blue_max); + vs->client_pf.bshift = blue_shift; + vs->client_pf.bmask = blue_max << blue_shift; + vs->client_pf.bits_per_pixel = bits_per_pixel; + vs->client_pf.bytes_per_pixel = bits_per_pixel / 8; + vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel; + vs->client_be = big_endian_flag; set_pixel_conversion(vs); @@ -1910,8 +1906,10 @@ static void set_pixel_format(VncState *vs, static void pixel_format_message (VncState *vs) { char pad[3] = { 0, 0, 0 }; - vnc_write_u8(vs, vs->ds->surface->pf.bits_per_pixel); /* bits-per-pixel */ - vnc_write_u8(vs, vs->ds->surface->pf.depth); /* depth */ + vs->client_pf = qemu_default_pixelformat(32); + + vnc_write_u8(vs, vs->client_pf.bits_per_pixel); /* bits-per-pixel */ + vnc_write_u8(vs, vs->client_pf.depth); /* depth */ #ifdef HOST_WORDS_BIGENDIAN vnc_write_u8(vs, 1); /* big-endian-flag */ @@ -1919,27 +1917,25 @@ static void pixel_format_message (VncState *vs) { vnc_write_u8(vs, 0); /* big-endian-flag */ #endif vnc_write_u8(vs, 1); /* true-color-flag */ - vnc_write_u16(vs, vs->ds->surface->pf.rmax); /* red-max */ - vnc_write_u16(vs, vs->ds->surface->pf.gmax); /* green-max */ - vnc_write_u16(vs, vs->ds->surface->pf.bmax); /* blue-max */ - vnc_write_u8(vs, vs->ds->surface->pf.rshift); /* red-shift */ - vnc_write_u8(vs, vs->ds->surface->pf.gshift); /* green-shift */ - vnc_write_u8(vs, vs->ds->surface->pf.bshift); /* blue-shift */ + vnc_write_u16(vs, vs->client_pf.rmax); /* red-max */ + vnc_write_u16(vs, vs->client_pf.gmax); /* green-max */ + vnc_write_u16(vs, vs->client_pf.bmax); /* blue-max */ + vnc_write_u8(vs, vs->client_pf.rshift); /* red-shift */ + vnc_write_u8(vs, vs->client_pf.gshift); /* green-shift */ + vnc_write_u8(vs, vs->client_pf.bshift); /* blue-shift */ + vnc_write(vs, pad, 3); /* padding */ vnc_hextile_set_pixel_conversion(vs, 0); - - vs->clientds = *(vs->ds->surface); - vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG; vs->write_pixels = vnc_write_pixels_copy; - - vnc_write(vs, pad, 3); /* padding */ } static void vnc_dpy_setdata(DisplayState *ds) { VncDisplay *vd = ds->opaque; - *(vd->guest.ds) = *(ds->surface); + qemu_pixman_image_unref(vd->guest.fb); + vd->guest.fb = pixman_image_ref(ds->surface->image); + vd->guest.format = ds->surface->format; vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); } @@ -2443,12 +2439,14 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y) static int vnc_update_stats(VncDisplay *vd, struct timeval * tv) { + int width = pixman_image_get_width(vd->guest.fb); + int height = pixman_image_get_height(vd->guest.fb); int x, y; struct timeval res; int has_dirty = 0; - for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) { - for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) { + for (y = 0; y < height; y += VNC_STAT_RECT) { + for (x = 0; x < width; x += VNC_STAT_RECT) { VncRectStat *rect = vnc_stat_rect(vd, x, y); rect->updated = false; @@ -2462,8 +2460,8 @@ static int vnc_update_stats(VncDisplay *vd, struct timeval * tv) } vd->guest.last_freq_check = *tv; - for (y = 0; y < vd->guest.ds->height; y += VNC_STAT_RECT) { - for (x = 0; x < vd->guest.ds->width; x += VNC_STAT_RECT) { + for (y = 0; y < height; y += VNC_STAT_RECT) { + for (x = 0; x < width; x += VNC_STAT_RECT) { VncRectStat *rect= vnc_stat_rect(vd, x, y); int count = ARRAY_SIZE(rect->times); struct timeval min, max; @@ -2532,12 +2530,15 @@ static void vnc_rect_updated(VncDisplay *vd, int x, int y, struct timeval * tv) static int vnc_refresh_server_surface(VncDisplay *vd) { + int width = pixman_image_get_width(vd->guest.fb); + int height = pixman_image_get_height(vd->guest.fb); int y; uint8_t *guest_row; uint8_t *server_row; int cmp_bytes; VncState *vs; int has_dirty = 0; + pixman_image_t *tmpbuf = NULL; struct timeval tv = { 0, 0 }; @@ -2551,22 +2552,31 @@ static int vnc_refresh_server_surface(VncDisplay *vd) * Check and copy modified bits from guest to server surface. * Update server dirty map. */ - cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds); - if (cmp_bytes > vd->ds->surface->linesize) { - cmp_bytes = vd->ds->surface->linesize; + cmp_bytes = 64; + if (cmp_bytes > vnc_server_fb_stride(vd)) { + cmp_bytes = vnc_server_fb_stride(vd); } - guest_row = vd->guest.ds->data; - server_row = vd->server->data; - for (y = 0; y < vd->guest.ds->height; y++) { + if (vd->guest.format != VNC_SERVER_FB_FORMAT) { + int width = pixman_image_get_width(vd->server); + tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width); + } + guest_row = (uint8_t *)pixman_image_get_data(vd->guest.fb); + server_row = (uint8_t *)pixman_image_get_data(vd->server); + for (y = 0; y < height; y++) { if (!bitmap_empty(vd->guest.dirty[y], VNC_DIRTY_BITS)) { int x; uint8_t *guest_ptr; uint8_t *server_ptr; - 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 +2591,10 @@ static int vnc_refresh_server_surface(VncDisplay *vd) has_dirty++; } } - guest_row += ds_get_linesize(vd->ds); - server_row += ds_get_linesize(vd->ds); + guest_row += pixman_image_get_stride(vd->guest.fb); + server_row += pixman_image_get_stride(vd->server); } + qemu_pixman_image_unref(tmpbuf); return has_dirty; } @@ -2753,13 +2764,13 @@ void vnc_display_init(DisplayState *ds) qemu_mutex_init(&vs->mutex); vnc_start_worker_thread(); - dcl->dpy_copy = vnc_dpy_copy; - dcl->dpy_update = vnc_dpy_update; - dcl->dpy_resize = vnc_dpy_resize; - dcl->dpy_setdata = vnc_dpy_setdata; + dcl->dpy_gfx_copy = vnc_dpy_copy; + dcl->dpy_gfx_update = vnc_dpy_update; + dcl->dpy_gfx_resize = vnc_dpy_resize; + dcl->dpy_gfx_setdata = vnc_dpy_setdata; + dcl->dpy_mouse_set = vnc_mouse_set; + dcl->dpy_cursor_define = vnc_dpy_cursor_define; register_displaychangelistener(ds, dcl); - ds->mouse_set = vnc_mouse_set; - ds->cursor_define = vnc_dpy_cursor_define; } @@ -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; @@ -522,6 +525,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); |