mirror of https://gitee.com/openkylin/qemu.git
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-<nr> 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 <kraxel@redhat.com>
This commit is contained in:
parent
b12f32c408
commit
9f64916da2
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -255,7 +255,7 @@ static void zrle_write_u8(VncState *vs, uint8_t value)
|
|||
static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
|
||||
int w, int h)
|
||||
{
|
||||
bool be = !!(vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG);
|
||||
bool be = vs->client_be;
|
||||
size_t bytes;
|
||||
int zywrle_level;
|
||||
|
||||
|
@ -277,13 +277,13 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
|
|||
|
||||
vnc_zrle_start(vs);
|
||||
|
||||
switch(vs->clientds.pf.bytes_per_pixel) {
|
||||
switch (vs->client_pf.bytes_per_pixel) {
|
||||
case 1:
|
||||
zrle_encode_8ne(vs, x, y, w, h, zywrle_level);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (vs->clientds.pf.gmax > 0x1F) {
|
||||
if (vs->client_pf.gmax > 0x1F) {
|
||||
if (be) {
|
||||
zrle_encode_16be(vs, x, y, w, h, zywrle_level);
|
||||
} else {
|
||||
|
@ -304,13 +304,13 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y,
|
|||
bool fits_in_ms3bytes;
|
||||
|
||||
fits_in_ls3bytes =
|
||||
((vs->clientds.pf.rmax << vs->clientds.pf.rshift) < (1 << 24) &&
|
||||
(vs->clientds.pf.gmax << vs->clientds.pf.gshift) < (1 << 24) &&
|
||||
(vs->clientds.pf.bmax << vs->clientds.pf.bshift) < (1 << 24));
|
||||
((vs->client_pf.rmax << vs->client_pf.rshift) < (1 << 24) &&
|
||||
(vs->client_pf.gmax << vs->client_pf.gshift) < (1 << 24) &&
|
||||
(vs->client_pf.bmax << vs->client_pf.bshift) < (1 << 24));
|
||||
|
||||
fits_in_ms3bytes = (vs->clientds.pf.rshift > 7 &&
|
||||
vs->clientds.pf.gshift > 7 &&
|
||||
vs->clientds.pf.bshift > 7);
|
||||
fits_in_ms3bytes = (vs->client_pf.rshift > 7 &&
|
||||
vs->client_pf.gshift > 7 &&
|
||||
vs->client_pf.bshift > 7);
|
||||
|
||||
if ((fits_in_ls3bytes && !be) || (fits_in_ms3bytes && be)) {
|
||||
if (be) {
|
||||
|
|
|
@ -187,7 +187,8 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
|
|||
local->vd = orig->vd;
|
||||
local->lossy_rect = orig->lossy_rect;
|
||||
local->write_pixels = orig->write_pixels;
|
||||
local->clientds = orig->clientds;
|
||||
local->client_pf = orig->client_pf;
|
||||
local->client_be = orig->client_be;
|
||||
local->tight = orig->tight;
|
||||
local->zlib = orig->zlib;
|
||||
local->hextile = orig->hextile;
|
||||
|
|
235
ui/vnc.c
235
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;
|
||||
}
|
||||
|
||||
|
|
19
ui/vnc.h
19
ui/vnc.h
|
@ -69,7 +69,7 @@ typedef struct VncRectEntry VncRectEntry;
|
|||
|
||||
typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
|
||||
|
||||
typedef void VncWritePixels(VncState *vs, struct PixelFormat *pf, void *data, int size);
|
||||
typedef void VncWritePixels(VncState *vs, void *data, int size);
|
||||
|
||||
typedef void VncSendHextileTile(VncState *vs,
|
||||
int x, int y, int w, int h,
|
||||
|
@ -117,7 +117,8 @@ struct VncSurface
|
|||
struct timeval last_freq_check;
|
||||
DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_MAX_WIDTH / 16);
|
||||
VncRectStat stats[VNC_STAT_ROWS][VNC_STAT_COLS];
|
||||
DisplaySurface *ds;
|
||||
pixman_image_t *fb;
|
||||
pixman_format_code_t format;
|
||||
};
|
||||
|
||||
typedef enum VncShareMode {
|
||||
|
@ -151,7 +152,7 @@ struct VncDisplay
|
|||
uint8_t *cursor_mask;
|
||||
|
||||
struct VncSurface guest; /* guest visible surface (aka ds->surface) */
|
||||
DisplaySurface *server; /* vnc server surface */
|
||||
pixman_image_t *server; /* vnc server surface */
|
||||
|
||||
char *display;
|
||||
char *password;
|
||||
|
@ -275,7 +276,9 @@ struct VncState
|
|||
Buffer input;
|
||||
/* current output mode information */
|
||||
VncWritePixels *write_pixels;
|
||||
DisplaySurface clientds;
|
||||
PixelFormat client_pf;
|
||||
pixman_format_code_t client_format;
|
||||
bool client_be;
|
||||
|
||||
CaptureVoiceOut *audio_cap;
|
||||
struct audsettings as;
|
||||
|
@ -527,6 +530,14 @@ static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
|
|||
void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
|
||||
int32_t encoding);
|
||||
|
||||
/* server fb is in PIXMAN_x8r8g8b8 */
|
||||
#define VNC_SERVER_FB_FORMAT PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8)
|
||||
#define VNC_SERVER_FB_BITS (PIXMAN_FORMAT_BPP(VNC_SERVER_FB_FORMAT))
|
||||
#define VNC_SERVER_FB_BYTES ((VNC_SERVER_FB_BITS+7)/8)
|
||||
|
||||
void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y);
|
||||
int vnc_server_fb_stride(VncDisplay *vd);
|
||||
|
||||
void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v);
|
||||
double vnc_update_freq(VncState *vs, int x, int y, int w, int h);
|
||||
void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h);
|
||||
|
|
Loading…
Reference in New Issue