71 |
71 |
|
72 |
72 |
typedef void VncSendHextileTile(VncState *vs,
|
73 |
73 |
int x, int y, int w, int h,
|
74 |
|
uint32_t *last_bg,
|
75 |
|
uint32_t *last_fg,
|
|
74 |
void *last_bg,
|
|
75 |
void *last_fg,
|
76 |
76 |
int *has_bg, int *has_fg);
|
77 |
77 |
|
78 |
78 |
#define VNC_MAX_WIDTH 2048
|
... | ... | |
164 |
164 |
VncWritePixels *write_pixels;
|
165 |
165 |
VncSendHextileTile *send_hextile_tile;
|
166 |
166 |
int pix_bpp, pix_big_endian;
|
167 |
|
int red_shift, red_max, red_shift1;
|
168 |
|
int green_shift, green_max, green_shift1;
|
169 |
|
int blue_shift, blue_max, blue_shift1;
|
|
167 |
int client_red_shift, client_red_max, server_red_shift, server_red_max;
|
|
168 |
int client_green_shift, client_green_max, server_green_shift, server_green_max;
|
|
169 |
int client_blue_shift, client_blue_max, server_blue_shift, server_blue_max;
|
170 |
170 |
|
171 |
171 |
VncReadEvent *read_handler;
|
172 |
172 |
size_t read_handler_expect;
|
... | ... | |
208 |
208 |
static void vnc_update_client(void *opaque);
|
209 |
209 |
static void vnc_client_read(void *opaque);
|
210 |
210 |
|
|
211 |
static void vnc_colordepth(DisplayState *ds, int depth);
|
|
212 |
|
211 |
213 |
static inline void vnc_set_bit(uint32_t *d, int k)
|
212 |
214 |
{
|
213 |
215 |
d[k >> 5] |= 1 << (k & 0x1f);
|
... | ... | |
330 |
332 |
/* slowest but generic code. */
|
331 |
333 |
static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
|
332 |
334 |
{
|
333 |
|
unsigned int r, g, b;
|
334 |
|
|
335 |
|
r = (v >> vs->red_shift1) & vs->red_max;
|
336 |
|
g = (v >> vs->green_shift1) & vs->green_max;
|
337 |
|
b = (v >> vs->blue_shift1) & vs->blue_max;
|
338 |
|
v = (r << vs->red_shift) |
|
339 |
|
(g << vs->green_shift) |
|
340 |
|
(b << vs->blue_shift);
|
|
335 |
uint8_t r, g, b;
|
|
336 |
|
|
337 |
r = ((v >> vs->server_red_shift) & vs->server_red_max) * (vs->client_red_max + 1) /
|
|
338 |
(vs->server_red_max + 1);
|
|
339 |
g = ((v >> vs->server_green_shift) & vs->server_green_max) * (vs->client_green_max + 1) /
|
|
340 |
(vs->server_green_max + 1);
|
|
341 |
b = ((v >> vs->server_blue_shift) & vs->server_blue_max) * (vs->client_blue_max + 1) /
|
|
342 |
(vs->server_blue_max + 1);
|
|
343 |
v = (r << vs->client_red_shift) |
|
|
344 |
(g << vs->client_green_shift) |
|
|
345 |
(b << vs->client_blue_shift);
|
341 |
346 |
switch(vs->pix_bpp) {
|
342 |
347 |
case 1:
|
343 |
348 |
buf[0] = v;
|
... | ... | |
370 |
375 |
|
371 |
376 |
static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
|
372 |
377 |
{
|
373 |
|
uint32_t *pixels = pixels1;
|
374 |
378 |
uint8_t buf[4];
|
375 |
|
int n, i;
|
376 |
379 |
|
377 |
|
n = size >> 2;
|
378 |
|
for(i = 0; i < n; i++) {
|
379 |
|
vnc_convert_pixel(vs, buf, pixels[i]);
|
380 |
|
vnc_write(vs, buf, vs->pix_bpp);
|
|
380 |
if (vs->depth == 4) {
|
|
381 |
uint32_t *pixels = pixels1;
|
|
382 |
int n, i;
|
|
383 |
n = size >> 2;
|
|
384 |
for(i = 0; i < n; i++) {
|
|
385 |
vnc_convert_pixel(vs, buf, pixels[i]);
|
|
386 |
vnc_write(vs, buf, vs->pix_bpp);
|
|
387 |
}
|
|
388 |
} else if (vs->depth == 2) {
|
|
389 |
uint16_t *pixels = pixels1;
|
|
390 |
int n, i;
|
|
391 |
n = size >> 1;
|
|
392 |
for(i = 0; i < n; i++) {
|
|
393 |
vnc_convert_pixel(vs, buf, pixels[i]);
|
|
394 |
vnc_write(vs, buf, vs->pix_bpp);
|
|
395 |
}
|
|
396 |
} else if (vs->depth == 1) {
|
|
397 |
uint8_t *pixels = pixels1;
|
|
398 |
int n, i;
|
|
399 |
n = size;
|
|
400 |
for(i = 0; i < n; i++) {
|
|
401 |
vnc_convert_pixel(vs, buf, pixels[i]);
|
|
402 |
vnc_write(vs, buf, vs->pix_bpp);
|
|
403 |
}
|
|
404 |
} else {
|
|
405 |
fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
|
381 |
406 |
}
|
382 |
407 |
}
|
383 |
408 |
|
... | ... | |
414 |
439 |
#undef BPP
|
415 |
440 |
|
416 |
441 |
#define GENERIC
|
|
442 |
#define BPP 8
|
|
443 |
#include "vnchextile.h"
|
|
444 |
#undef BPP
|
|
445 |
#undef GENERIC
|
|
446 |
|
|
447 |
#define GENERIC
|
|
448 |
#define BPP 16
|
|
449 |
#include "vnchextile.h"
|
|
450 |
#undef BPP
|
|
451 |
#undef GENERIC
|
|
452 |
|
|
453 |
#define GENERIC
|
417 |
454 |
#define BPP 32
|
418 |
455 |
#include "vnchextile.h"
|
419 |
456 |
#undef BPP
|
... | ... | |
423 |
460 |
{
|
424 |
461 |
int i, j;
|
425 |
462 |
int has_fg, has_bg;
|
426 |
|
uint32_t last_fg32, last_bg32;
|
|
463 |
uint8_t *last_fg, *last_bg;
|
427 |
464 |
|
428 |
465 |
vnc_framebuffer_update(vs, x, y, w, h, 5);
|
429 |
466 |
|
|
467 |
last_fg = (uint8_t *) malloc(vs->depth);
|
|
468 |
last_bg = (uint8_t *) malloc(vs->depth);
|
430 |
469 |
has_fg = has_bg = 0;
|
431 |
470 |
for (j = y; j < (y + h); j += 16) {
|
432 |
471 |
for (i = x; i < (x + w); i += 16) {
|
433 |
472 |
vs->send_hextile_tile(vs, i, j,
|
434 |
473 |
MIN(16, x + w - i), MIN(16, y + h - j),
|
435 |
|
&last_bg32, &last_fg32, &has_bg, &has_fg);
|
|
474 |
last_bg, last_fg, &has_bg, &has_fg);
|
436 |
475 |
}
|
437 |
476 |
}
|
|
477 |
free(last_fg);
|
|
478 |
free(last_bg);
|
|
479 |
|
438 |
480 |
}
|
439 |
481 |
|
440 |
482 |
static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
|
... | ... | |
1133 |
1175 |
check_pointer_type_change(vs, kbd_mouse_is_absolute());
|
1134 |
1176 |
}
|
1135 |
1177 |
|
1136 |
|
static int compute_nbits(unsigned int val)
|
1137 |
|
{
|
1138 |
|
int n;
|
1139 |
|
n = 0;
|
1140 |
|
while (val != 0) {
|
1141 |
|
n++;
|
1142 |
|
val >>= 1;
|
1143 |
|
}
|
1144 |
|
return n;
|
1145 |
|
}
|
1146 |
|
|
1147 |
1178 |
static void set_pixel_format(VncState *vs,
|
1148 |
1179 |
int bits_per_pixel, int depth,
|
1149 |
1180 |
int big_endian_flag, int true_color_flag,
|
... | ... | |
1163 |
1194 |
return;
|
1164 |
1195 |
}
|
1165 |
1196 |
if (bits_per_pixel == 32 &&
|
|
1197 |
bits_per_pixel == vs->depth * 8 &&
|
1166 |
1198 |
host_big_endian_flag == big_endian_flag &&
|
1167 |
1199 |
red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
|
1168 |
1200 |
red_shift == 16 && green_shift == 8 && blue_shift == 0) {
|
... | ... | |
1171 |
1203 |
vs->send_hextile_tile = send_hextile_tile_32;
|
1172 |
1204 |
} else
|
1173 |
1205 |
if (bits_per_pixel == 16 &&
|
|
1206 |
bits_per_pixel == vs->depth * 8 &&
|
1174 |
1207 |
host_big_endian_flag == big_endian_flag &&
|
1175 |
1208 |
red_max == 31 && green_max == 63 && blue_max == 31 &&
|
1176 |
1209 |
red_shift == 11 && green_shift == 5 && blue_shift == 0) {
|
... | ... | |
1179 |
1212 |
vs->send_hextile_tile = send_hextile_tile_16;
|
1180 |
1213 |
} else
|
1181 |
1214 |
if (bits_per_pixel == 8 &&
|
|
1215 |
bits_per_pixel == vs->depth * 8 &&
|
1182 |
1216 |
red_max == 7 && green_max == 7 && blue_max == 3 &&
|
1183 |
1217 |
red_shift == 5 && green_shift == 2 && blue_shift == 0) {
|
1184 |
1218 |
vs->depth = 1;
|
... | ... | |
1191 |
1225 |
bits_per_pixel != 16 &&
|
1192 |
1226 |
bits_per_pixel != 32)
|
1193 |
1227 |
goto fail;
|
1194 |
|
vs->depth = 4;
|
1195 |
|
vs->red_shift = red_shift;
|
1196 |
|
vs->red_max = red_max;
|
1197 |
|
vs->red_shift1 = 24 - compute_nbits(red_max);
|
1198 |
|
vs->green_shift = green_shift;
|
1199 |
|
vs->green_max = green_max;
|
1200 |
|
vs->green_shift1 = 16 - compute_nbits(green_max);
|
1201 |
|
vs->blue_shift = blue_shift;
|
1202 |
|
vs->blue_max = blue_max;
|
1203 |
|
vs->blue_shift1 = 8 - compute_nbits(blue_max);
|
1204 |
|
vs->pix_bpp = bits_per_pixel / 8;
|
|
1228 |
if (vs->depth == 4) {
|
|
1229 |
vs->send_hextile_tile = send_hextile_tile_generic_32;
|
|
1230 |
} else if (vs->depth == 2) {
|
|
1231 |
vs->send_hextile_tile = send_hextile_tile_generic_16;
|
|
1232 |
} else {
|
|
1233 |
vs->send_hextile_tile = send_hextile_tile_generic_8;
|
|
1234 |
}
|
|
1235 |
|
1205 |
1236 |
vs->pix_big_endian = big_endian_flag;
|
1206 |
1237 |
vs->write_pixels = vnc_write_pixels_generic;
|
1207 |
|
vs->send_hextile_tile = send_hextile_tile_generic;
|
1208 |
1238 |
}
|
1209 |
1239 |
|
1210 |
|
vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
|
|
1240 |
vs->client_red_shift = red_shift;
|
|
1241 |
vs->client_red_max = red_max;
|
|
1242 |
vs->client_green_shift = green_shift;
|
|
1243 |
vs->client_green_max = green_max;
|
|
1244 |
vs->client_blue_shift = blue_shift;
|
|
1245 |
vs->client_blue_max = blue_max;
|
|
1246 |
vs->pix_bpp = bits_per_pixel / 8;
|
1211 |
1247 |
|
1212 |
1248 |
vga_hw_invalidate();
|
1213 |
1249 |
vga_hw_update();
|
1214 |
1250 |
}
|
1215 |
1251 |
|
|
1252 |
static void vnc_colordepth(DisplayState *ds, int depth)
|
|
1253 |
{
|
|
1254 |
int host_big_endian_flag;
|
|
1255 |
struct VncState *vs = ds->opaque;
|
|
1256 |
|
|
1257 |
switch (depth) {
|
|
1258 |
case 24:
|
|
1259 |
if (ds->depth == 32) return;
|
|
1260 |
depth = 32;
|
|
1261 |
break;
|
|
1262 |
case 15:
|
|
1263 |
case 8:
|
|
1264 |
case 0:
|
|
1265 |
return;
|
|
1266 |
default:
|
|
1267 |
break;
|
|
1268 |
}
|
|
1269 |
|
|
1270 |
#ifdef WORDS_BIGENDIAN
|
|
1271 |
host_big_endian_flag = 1;
|
|
1272 |
#else
|
|
1273 |
host_big_endian_flag = 0;
|
|
1274 |
#endif
|
|
1275 |
|
|
1276 |
switch (depth) {
|
|
1277 |
case 8:
|
|
1278 |
vs->depth = depth / 8;
|
|
1279 |
vs->server_red_max = 7;
|
|
1280 |
vs->server_green_max = 7;
|
|
1281 |
vs->server_blue_max = 3;
|
|
1282 |
vs->server_red_shift = 5;
|
|
1283 |
vs->server_green_shift = 2;
|
|
1284 |
vs->server_blue_shift = 0;
|
|
1285 |
break;
|
|
1286 |
case 16:
|
|
1287 |
vs->depth = depth / 8;
|
|
1288 |
vs->server_red_max = 31;
|
|
1289 |
vs->server_green_max = 63;
|
|
1290 |
vs->server_blue_max = 31;
|
|
1291 |
vs->server_red_shift = 11;
|
|
1292 |
vs->server_green_shift = 5;
|
|
1293 |
vs->server_blue_shift = 0;
|
|
1294 |
break;
|
|
1295 |
case 32:
|
|
1296 |
vs->depth = 4;
|
|
1297 |
vs->server_red_max = 255;
|
|
1298 |
vs->server_green_max = 255;
|
|
1299 |
vs->server_blue_max = 255;
|
|
1300 |
vs->server_red_shift = 16;
|
|
1301 |
vs->server_green_shift = 8;
|
|
1302 |
vs->server_blue_shift = 0;
|
|
1303 |
break;
|
|
1304 |
default:
|
|
1305 |
return;
|
|
1306 |
}
|
|
1307 |
|
|
1308 |
if (vs->pix_bpp == 4 && vs->depth == 4 &&
|
|
1309 |
host_big_endian_flag == vs->pix_big_endian &&
|
|
1310 |
vs->client_red_max == 0xff && vs->client_green_max == 0xff && vs->client_blue_max == 0xff &&
|
|
1311 |
vs->client_red_shift == 16 && vs->client_green_shift == 8 && vs->client_blue_shift == 0) {
|
|
1312 |
vs->write_pixels = vnc_write_pixels_copy;
|
|
1313 |
vs->send_hextile_tile = send_hextile_tile_32;
|
|
1314 |
} else if (vs->pix_bpp == 2 && vs->depth == 2 &&
|
|
1315 |
host_big_endian_flag == vs->pix_big_endian &&
|
|
1316 |
vs->client_red_max == 31 && vs->client_green_max == 63 && vs->client_blue_max == 31 &&
|
|
1317 |
vs->client_red_shift == 11 && vs->client_green_shift == 5 && vs->client_blue_shift == 0) {
|
|
1318 |
vs->write_pixels = vnc_write_pixels_copy;
|
|
1319 |
vs->send_hextile_tile = send_hextile_tile_16;
|
|
1320 |
} else if (vs->pix_bpp == 1 && vs->depth == 1 &&
|
|
1321 |
host_big_endian_flag == vs->pix_big_endian &&
|
|
1322 |
vs->client_red_max == 7 && vs->client_green_max == 7 && vs->client_blue_max == 3 &&
|
|
1323 |
vs->client_red_shift == 5 && vs->client_green_shift == 2 && vs->client_blue_shift == 0) {
|
|
1324 |
vs->write_pixels = vnc_write_pixels_copy;
|
|
1325 |
vs->send_hextile_tile = send_hextile_tile_8;
|
|
1326 |
} else {
|
|
1327 |
if (vs->depth == 4) {
|
|
1328 |
vs->send_hextile_tile = send_hextile_tile_generic_32;
|
|
1329 |
} else if (vs->depth == 2) {
|
|
1330 |
vs->send_hextile_tile = send_hextile_tile_generic_16;
|
|
1331 |
} else {
|
|
1332 |
vs->send_hextile_tile = send_hextile_tile_generic_8;
|
|
1333 |
}
|
|
1334 |
vs->write_pixels = vnc_write_pixels_generic;
|
|
1335 |
}
|
|
1336 |
}
|
|
1337 |
|
1216 |
1338 |
static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
|
1217 |
1339 |
{
|
1218 |
1340 |
int i;
|
... | ... | |
1316 |
1438 |
vnc_write_u16(vs, vs->ds->height);
|
1317 |
1439 |
|
1318 |
1440 |
vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
|
1319 |
|
vnc_write_u8(vs, vs->depth * 8); /* depth */
|
|
1441 |
if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */
|
|
1442 |
else vnc_write_u8(vs, vs->depth * 8); /* depth */
|
|
1443 |
|
1320 |
1444 |
#ifdef WORDS_BIGENDIAN
|
1321 |
1445 |
vnc_write_u8(vs, 1); /* big-endian-flag */
|
1322 |
1446 |
#else
|
... | ... | |
2006 |
2130 |
|
2007 |
2131 |
vs->lsock = -1;
|
2008 |
2132 |
vs->csock = -1;
|
2009 |
|
vs->depth = 4;
|
2010 |
2133 |
vs->last_x = -1;
|
2011 |
2134 |
vs->last_y = -1;
|
2012 |
2135 |
|
... | ... | |
2027 |
2150 |
vs->ds->dpy_resize = vnc_dpy_resize;
|
2028 |
2151 |
vs->ds->dpy_refresh = NULL;
|
2029 |
2152 |
|
|
2153 |
vnc_colordepth(vs->ds, 32);
|
2030 |
2154 |
vnc_dpy_resize(vs->ds, 640, 400);
|
2031 |
2155 |
}
|
2032 |
2156 |
|