Commit 7eac3a87f132dd68139a6fe29b81c25c4c00e96d

Authored by aliguori
1 parent 82b36dc3

vnc dynamic resolution (Stefano Stabellini)

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@5229 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 177 additions and 53 deletions
... ... @@ -71,8 +71,8 @@ typedef void VncWritePixels(VncState *vs, void *data, int size);
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,9 +164,9 @@ struct VncState
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,6 +208,8 @@ static void vnc_flush(VncState *vs);
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,14 +332,17 @@ static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
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,14 +375,34 @@ static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t 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,6 +439,18 @@ static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
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,18 +460,23 @@ static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, i
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,17 +1175,6 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
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,6 +1194,7 @@ static void set_pixel_format(VncState *vs,
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,6 +1203,7 @@ static void set_pixel_format(VncState *vs,
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,6 +1212,7 @@ static void set_pixel_format(VncState *vs,
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,28 +1225,116 @@ static void set_pixel_format(VncState *vs,
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,7 +1438,9 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
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,7 +2130,6 @@ void vnc_display_init(DisplayState *ds)
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,6 +2150,7 @@ void vnc_display_init(DisplayState *ds)
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  
... ...
vnchextile.h
... ... @@ -2,29 +2,29 @@
2 2 #define CONCAT(a, b) CONCAT_I(a, b)
3 3 #define pixel_t CONCAT(uint, CONCAT(BPP, _t))
4 4 #ifdef GENERIC
5   -#define NAME generic
  5 +#define NAME CONCAT(generic_, BPP)
6 6 #else
7 7 #define NAME BPP
8 8 #endif
9 9  
10 10 static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
11 11 int x, int y, int w, int h,
12   - uint32_t *last_bg32,
13   - uint32_t *last_fg32,
  12 + void *last_bg_,
  13 + void *last_fg_,
14 14 int *has_bg, int *has_fg)
15 15 {
16 16 uint8_t *row = (vs->ds->data + y * vs->ds->linesize + x * vs->depth);
17 17 pixel_t *irow = (pixel_t *)row;
18 18 int j, i;
19   - pixel_t *last_bg = (pixel_t *)last_bg32;
20   - pixel_t *last_fg = (pixel_t *)last_fg32;
  19 + pixel_t *last_bg = (pixel_t *)last_bg_;
  20 + pixel_t *last_fg = (pixel_t *)last_fg_;
21 21 pixel_t bg = 0;
22 22 pixel_t fg = 0;
23 23 int n_colors = 0;
24 24 int bg_count = 0;
25 25 int fg_count = 0;
26 26 int flags = 0;
27   - uint8_t data[(sizeof(pixel_t) + 2) * 16 * 16];
  27 + uint8_t data[(vs->pix_bpp + 2) * 16 * 16];
28 28 int n_data = 0;
29 29 int n_subtiles = 0;
30 30  
... ...