qemu/vnchextile.h
aliguori 6cec548799 exploiting the new interface in vnc.c (Stefano Stabellini)
This patch exploits the new DisplaySurface and PixelFormat structures in
vnc, making the code easier to read allowing further improvements.

Compared to the last version I fixed a bug that prevented the hextile
encoding from working properly.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6337 c046a42c-6fe2-441c-8c8c-71466251a162
2009-01-15 22:17:38 +00:00

210 lines
4.5 KiB
C

#define CONCAT_I(a, b) a ## b
#define CONCAT(a, b) CONCAT_I(a, b)
#define pixel_t CONCAT(uint, CONCAT(BPP, _t))
#ifdef GENERIC
#define NAME CONCAT(generic_, BPP)
#else
#define NAME BPP
#endif
static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
int x, int y, int w, int h,
void *last_bg_,
void *last_fg_,
int *has_bg, int *has_fg)
{
uint8_t *row = (ds_get_data(vs->ds) + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds));
pixel_t *irow = (pixel_t *)row;
int j, i;
pixel_t *last_bg = (pixel_t *)last_bg_;
pixel_t *last_fg = (pixel_t *)last_fg_;
pixel_t bg = 0;
pixel_t fg = 0;
int n_colors = 0;
int bg_count = 0;
int fg_count = 0;
int flags = 0;
uint8_t data[(vs->clientds.pf.bytes_per_pixel + 2) * 16 * 16];
int n_data = 0;
int n_subtiles = 0;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
switch (n_colors) {
case 0:
bg = irow[i];
n_colors = 1;
break;
case 1:
if (irow[i] != bg) {
fg = irow[i];
n_colors = 2;
}
break;
case 2:
if (irow[i] != bg && irow[i] != fg) {
n_colors = 3;
} else {
if (irow[i] == bg)
bg_count++;
else if (irow[i] == fg)
fg_count++;
}
break;
default:
break;
}
}
if (n_colors > 2)
break;
irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
}
if (n_colors > 1 && fg_count > bg_count) {
pixel_t tmp = fg;
fg = bg;
bg = tmp;
}
if (!*has_bg || *last_bg != bg) {
flags |= 0x02;
*has_bg = 1;
*last_bg = bg;
}
if (!*has_fg || *last_fg != fg) {
flags |= 0x04;
*has_fg = 1;
*last_fg = fg;
}
switch (n_colors) {
case 1:
n_data = 0;
break;
case 2:
flags |= 0x08;
irow = (pixel_t *)row;
for (j = 0; j < h; j++) {
int min_x = -1;
for (i = 0; i < w; i++) {
if (irow[i] == fg) {
if (min_x == -1)
min_x = i;
} else if (min_x != -1) {
hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
n_data += 2;
n_subtiles++;
min_x = -1;
}
}
if (min_x != -1) {
hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
n_data += 2;
n_subtiles++;
}
irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
}
break;
case 3:
flags |= 0x18;
irow = (pixel_t *)row;
if (!*has_bg || *last_bg != bg)
flags |= 0x02;
for (j = 0; j < h; j++) {
int has_color = 0;
int min_x = -1;
pixel_t color = 0; /* shut up gcc */
for (i = 0; i < w; i++) {
if (!has_color) {
if (irow[i] == bg)
continue;
color = irow[i];
min_x = i;
has_color = 1;
} else if (irow[i] != color) {
has_color = 0;
#ifdef GENERIC
vnc_convert_pixel(vs, data + n_data, color);
n_data += vs->clientds.pf.bytes_per_pixel;
#else
memcpy(data + n_data, &color, sizeof(color));
n_data += sizeof(pixel_t);
#endif
hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
n_data += 2;
n_subtiles++;
min_x = -1;
if (irow[i] != bg) {
color = irow[i];
min_x = i;
has_color = 1;
}
}
}
if (has_color) {
#ifdef GENERIC
vnc_convert_pixel(vs, data + n_data, color);
n_data += vs->clientds.pf.bytes_per_pixel;
#else
memcpy(data + n_data, &color, sizeof(color));
n_data += sizeof(pixel_t);
#endif
hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
n_data += 2;
n_subtiles++;
}
irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
}
/* A SubrectsColoured subtile invalidates the foreground color */
*has_fg = 0;
if (n_data > (w * h * sizeof(pixel_t))) {
n_colors = 4;
flags = 0x01;
*has_bg = 0;
/* we really don't have to invalidate either the bg or fg
but we've lost the old values. oh well. */
}
default:
break;
}
if (n_colors > 3) {
flags = 0x01;
*has_fg = 0;
*has_bg = 0;
n_colors = 4;
}
vnc_write_u8(vs, flags);
if (n_colors < 4) {
if (flags & 0x02)
vs->write_pixels(vs, last_bg, sizeof(pixel_t));
if (flags & 0x04)
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, row, w * ds_get_bytes_per_pixel(vs->ds));
row += ds_get_linesize(vs->ds);
}
}
}
#undef NAME
#undef pixel_t
#undef CONCAT_I
#undef CONCAT