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,8 +71,8 @@ typedef void VncWritePixels(VncState *vs, void *data, int size);
71 71
72 typedef void VncSendHextileTile(VncState *vs, 72 typedef void VncSendHextileTile(VncState *vs,
73 int x, int y, int w, int h, 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 int *has_bg, int *has_fg); 76 int *has_bg, int *has_fg);
77 77
78 #define VNC_MAX_WIDTH 2048 78 #define VNC_MAX_WIDTH 2048
@@ -164,9 +164,9 @@ struct VncState @@ -164,9 +164,9 @@ struct VncState
164 VncWritePixels *write_pixels; 164 VncWritePixels *write_pixels;
165 VncSendHextileTile *send_hextile_tile; 165 VncSendHextileTile *send_hextile_tile;
166 int pix_bpp, pix_big_endian; 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 VncReadEvent *read_handler; 171 VncReadEvent *read_handler;
172 size_t read_handler_expect; 172 size_t read_handler_expect;
@@ -208,6 +208,8 @@ static void vnc_flush(VncState *vs); @@ -208,6 +208,8 @@ static void vnc_flush(VncState *vs);
208 static void vnc_update_client(void *opaque); 208 static void vnc_update_client(void *opaque);
209 static void vnc_client_read(void *opaque); 209 static void vnc_client_read(void *opaque);
210 210
  211 +static void vnc_colordepth(DisplayState *ds, int depth);
  212 +
211 static inline void vnc_set_bit(uint32_t *d, int k) 213 static inline void vnc_set_bit(uint32_t *d, int k)
212 { 214 {
213 d[k >> 5] |= 1 << (k & 0x1f); 215 d[k >> 5] |= 1 << (k & 0x1f);
@@ -330,14 +332,17 @@ static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size) @@ -330,14 +332,17 @@ static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
330 /* slowest but generic code. */ 332 /* slowest but generic code. */
331 static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) 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 switch(vs->pix_bpp) { 346 switch(vs->pix_bpp) {
342 case 1: 347 case 1:
343 buf[0] = v; 348 buf[0] = v;
@@ -370,14 +375,34 @@ static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) @@ -370,14 +375,34 @@ static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
370 375
371 static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size) 376 static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
372 { 377 {
373 - uint32_t *pixels = pixels1;  
374 uint8_t buf[4]; 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,6 +439,18 @@ static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
414 #undef BPP 439 #undef BPP
415 440
416 #define GENERIC 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 #define BPP 32 454 #define BPP 32
418 #include "vnchextile.h" 455 #include "vnchextile.h"
419 #undef BPP 456 #undef BPP
@@ -423,18 +460,23 @@ static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, i @@ -423,18 +460,23 @@ static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, i
423 { 460 {
424 int i, j; 461 int i, j;
425 int has_fg, has_bg; 462 int has_fg, has_bg;
426 - uint32_t last_fg32, last_bg32; 463 + uint8_t *last_fg, *last_bg;
427 464
428 vnc_framebuffer_update(vs, x, y, w, h, 5); 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 has_fg = has_bg = 0; 469 has_fg = has_bg = 0;
431 for (j = y; j < (y + h); j += 16) { 470 for (j = y; j < (y + h); j += 16) {
432 for (i = x; i < (x + w); i += 16) { 471 for (i = x; i < (x + w); i += 16) {
433 vs->send_hextile_tile(vs, i, j, 472 vs->send_hextile_tile(vs, i, j,
434 MIN(16, x + w - i), MIN(16, y + h - j), 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 static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h) 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,17 +1175,6 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1133 check_pointer_type_change(vs, kbd_mouse_is_absolute()); 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 static void set_pixel_format(VncState *vs, 1178 static void set_pixel_format(VncState *vs,
1148 int bits_per_pixel, int depth, 1179 int bits_per_pixel, int depth,
1149 int big_endian_flag, int true_color_flag, 1180 int big_endian_flag, int true_color_flag,
@@ -1163,6 +1194,7 @@ static void set_pixel_format(VncState *vs, @@ -1163,6 +1194,7 @@ static void set_pixel_format(VncState *vs,
1163 return; 1194 return;
1164 } 1195 }
1165 if (bits_per_pixel == 32 && 1196 if (bits_per_pixel == 32 &&
  1197 + bits_per_pixel == vs->depth * 8 &&
1166 host_big_endian_flag == big_endian_flag && 1198 host_big_endian_flag == big_endian_flag &&
1167 red_max == 0xff && green_max == 0xff && blue_max == 0xff && 1199 red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
1168 red_shift == 16 && green_shift == 8 && blue_shift == 0) { 1200 red_shift == 16 && green_shift == 8 && blue_shift == 0) {
@@ -1171,6 +1203,7 @@ static void set_pixel_format(VncState *vs, @@ -1171,6 +1203,7 @@ static void set_pixel_format(VncState *vs,
1171 vs->send_hextile_tile = send_hextile_tile_32; 1203 vs->send_hextile_tile = send_hextile_tile_32;
1172 } else 1204 } else
1173 if (bits_per_pixel == 16 && 1205 if (bits_per_pixel == 16 &&
  1206 + bits_per_pixel == vs->depth * 8 &&
1174 host_big_endian_flag == big_endian_flag && 1207 host_big_endian_flag == big_endian_flag &&
1175 red_max == 31 && green_max == 63 && blue_max == 31 && 1208 red_max == 31 && green_max == 63 && blue_max == 31 &&
1176 red_shift == 11 && green_shift == 5 && blue_shift == 0) { 1209 red_shift == 11 && green_shift == 5 && blue_shift == 0) {
@@ -1179,6 +1212,7 @@ static void set_pixel_format(VncState *vs, @@ -1179,6 +1212,7 @@ static void set_pixel_format(VncState *vs,
1179 vs->send_hextile_tile = send_hextile_tile_16; 1212 vs->send_hextile_tile = send_hextile_tile_16;
1180 } else 1213 } else
1181 if (bits_per_pixel == 8 && 1214 if (bits_per_pixel == 8 &&
  1215 + bits_per_pixel == vs->depth * 8 &&
1182 red_max == 7 && green_max == 7 && blue_max == 3 && 1216 red_max == 7 && green_max == 7 && blue_max == 3 &&
1183 red_shift == 5 && green_shift == 2 && blue_shift == 0) { 1217 red_shift == 5 && green_shift == 2 && blue_shift == 0) {
1184 vs->depth = 1; 1218 vs->depth = 1;
@@ -1191,28 +1225,116 @@ static void set_pixel_format(VncState *vs, @@ -1191,28 +1225,116 @@ static void set_pixel_format(VncState *vs,
1191 bits_per_pixel != 16 && 1225 bits_per_pixel != 16 &&
1192 bits_per_pixel != 32) 1226 bits_per_pixel != 32)
1193 goto fail; 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 vs->pix_big_endian = big_endian_flag; 1236 vs->pix_big_endian = big_endian_flag;
1206 vs->write_pixels = vnc_write_pixels_generic; 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 vga_hw_invalidate(); 1248 vga_hw_invalidate();
1213 vga_hw_update(); 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 static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) 1338 static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1217 { 1339 {
1218 int i; 1340 int i;
@@ -1316,7 +1438,9 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len) @@ -1316,7 +1438,9 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1316 vnc_write_u16(vs, vs->ds->height); 1438 vnc_write_u16(vs, vs->ds->height);
1317 1439
1318 vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */ 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 #ifdef WORDS_BIGENDIAN 1444 #ifdef WORDS_BIGENDIAN
1321 vnc_write_u8(vs, 1); /* big-endian-flag */ 1445 vnc_write_u8(vs, 1); /* big-endian-flag */
1322 #else 1446 #else
@@ -2006,7 +2130,6 @@ void vnc_display_init(DisplayState *ds) @@ -2006,7 +2130,6 @@ void vnc_display_init(DisplayState *ds)
2006 2130
2007 vs->lsock = -1; 2131 vs->lsock = -1;
2008 vs->csock = -1; 2132 vs->csock = -1;
2009 - vs->depth = 4;  
2010 vs->last_x = -1; 2133 vs->last_x = -1;
2011 vs->last_y = -1; 2134 vs->last_y = -1;
2012 2135
@@ -2027,6 +2150,7 @@ void vnc_display_init(DisplayState *ds) @@ -2027,6 +2150,7 @@ void vnc_display_init(DisplayState *ds)
2027 vs->ds->dpy_resize = vnc_dpy_resize; 2150 vs->ds->dpy_resize = vnc_dpy_resize;
2028 vs->ds->dpy_refresh = NULL; 2151 vs->ds->dpy_refresh = NULL;
2029 2152
  2153 + vnc_colordepth(vs->ds, 32);
2030 vnc_dpy_resize(vs->ds, 640, 400); 2154 vnc_dpy_resize(vs->ds, 640, 400);
2031 } 2155 }
2032 2156
vnchextile.h
@@ -2,29 +2,29 @@ @@ -2,29 +2,29 @@
2 #define CONCAT(a, b) CONCAT_I(a, b) 2 #define CONCAT(a, b) CONCAT_I(a, b)
3 #define pixel_t CONCAT(uint, CONCAT(BPP, _t)) 3 #define pixel_t CONCAT(uint, CONCAT(BPP, _t))
4 #ifdef GENERIC 4 #ifdef GENERIC
5 -#define NAME generic 5 +#define NAME CONCAT(generic_, BPP)
6 #else 6 #else
7 #define NAME BPP 7 #define NAME BPP
8 #endif 8 #endif
9 9
10 static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, 10 static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
11 int x, int y, int w, int h, 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 int *has_bg, int *has_fg) 14 int *has_bg, int *has_fg)
15 { 15 {
16 uint8_t *row = (vs->ds->data + y * vs->ds->linesize + x * vs->depth); 16 uint8_t *row = (vs->ds->data + y * vs->ds->linesize + x * vs->depth);
17 pixel_t *irow = (pixel_t *)row; 17 pixel_t *irow = (pixel_t *)row;
18 int j, i; 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 pixel_t bg = 0; 21 pixel_t bg = 0;
22 pixel_t fg = 0; 22 pixel_t fg = 0;
23 int n_colors = 0; 23 int n_colors = 0;
24 int bg_count = 0; 24 int bg_count = 0;
25 int fg_count = 0; 25 int fg_count = 0;
26 int flags = 0; 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 int n_data = 0; 28 int n_data = 0;
29 int n_subtiles = 0; 29 int n_subtiles = 0;
30 30