vnc-enc-tight.c (59c58f96b270f5edd4ad10954c3a96556cb3a728) | vnc-enc-tight.c (6bf21f3d83e95bcc4ba35a7a07cc6655e8b010b0) |
---|---|
1/* 2 * QEMU VNC display driver: tight encoding 3 * 4 * From libvncserver/libvncserver/tight.c 5 * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. 6 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 7 * 8 * Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com> --- 102 unchanged lines hidden (view full) --- 111 { 9, PNG_ALL_FILTERS }, 112}; 113 114static int send_png_rect(VncState *vs, int x, int y, int w, int h, 115 VncPalette *palette); 116 117static bool tight_can_send_png_rect(VncState *vs, int w, int h) 118{ | 1/* 2 * QEMU VNC display driver: tight encoding 3 * 4 * From libvncserver/libvncserver/tight.c 5 * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. 6 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 7 * 8 * Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com> --- 102 unchanged lines hidden (view full) --- 111 { 9, PNG_ALL_FILTERS }, 112}; 113 114static int send_png_rect(VncState *vs, int x, int y, int w, int h, 115 VncPalette *palette); 116 117static bool tight_can_send_png_rect(VncState *vs, int w, int h) 118{ |
119 if (vs->tight.type != VNC_ENCODING_TIGHT_PNG) { | 119 if (vs->tight->type != VNC_ENCODING_TIGHT_PNG) { |
120 return false; 121 } 122 123 if (surface_bytes_per_pixel(vs->vd->ds) == 1 || 124 vs->client_pf.bytes_per_pixel == 1) { 125 return false; 126 } 127 --- 11 unchanged lines hidden (view full) --- 139{ 140 int off; 141 int x, y, d, dx; 142 unsigned int c; 143 unsigned int stats[256]; 144 int pixels = 0; 145 int pix, left[3]; 146 unsigned int errors; | 120 return false; 121 } 122 123 if (surface_bytes_per_pixel(vs->vd->ds) == 1 || 124 vs->client_pf.bytes_per_pixel == 1) { 125 return false; 126 } 127 --- 11 unchanged lines hidden (view full) --- 139{ 140 int off; 141 int x, y, d, dx; 142 unsigned int c; 143 unsigned int stats[256]; 144 int pixels = 0; 145 int pix, left[3]; 146 unsigned int errors; |
147 unsigned char *buf = vs->tight.tight.buffer; | 147 unsigned char *buf = vs->tight->tight.buffer; |
148 149 /* 150 * If client is big-endian, color samples begin from the second 151 * byte (offset 1) of a 32-bit pixel value. 152 */ 153 off = vs->client_be; 154 155 memset(stats, 0, sizeof (stats)); --- 54 unchanged lines hidden (view full) --- 210 uint##bpp##_t pix; \ 211 int max[3], shift[3]; \ 212 int x, y, d, dx; \ 213 unsigned int c; \ 214 unsigned int stats[256]; \ 215 int pixels = 0; \ 216 int sample, sum, left[3]; \ 217 unsigned int errors; \ | 148 149 /* 150 * If client is big-endian, color samples begin from the second 151 * byte (offset 1) of a 32-bit pixel value. 152 */ 153 off = vs->client_be; 154 155 memset(stats, 0, sizeof (stats)); --- 54 unchanged lines hidden (view full) --- 210 uint##bpp##_t pix; \ 211 int max[3], shift[3]; \ 212 int x, y, d, dx; \ 213 unsigned int c; \ 214 unsigned int stats[256]; \ 215 int pixels = 0; \ 216 int sample, sum, left[3]; \ 217 unsigned int errors; \ |
218 unsigned char *buf = vs->tight.tight.buffer; \ | 218 unsigned char *buf = vs->tight->tight.buffer; \ |
219 \ 220 endian = 0; /* FIXME */ \ 221 \ 222 \ 223 max[0] = vs->client_pf.rmax; \ 224 max[1] = vs->client_pf.gmax; \ 225 max[2] = vs->client_pf.bmax; \ 226 shift[0] = vs->client_pf.rshift; \ --- 64 unchanged lines hidden (view full) --- 291 292DEFINE_DETECT_FUNCTION(16) 293DEFINE_DETECT_FUNCTION(32) 294 295static int 296tight_detect_smooth_image(VncState *vs, int w, int h) 297{ 298 unsigned int errors; | 219 \ 220 endian = 0; /* FIXME */ \ 221 \ 222 \ 223 max[0] = vs->client_pf.rmax; \ 224 max[1] = vs->client_pf.gmax; \ 225 max[2] = vs->client_pf.bmax; \ 226 shift[0] = vs->client_pf.rshift; \ --- 64 unchanged lines hidden (view full) --- 291 292DEFINE_DETECT_FUNCTION(16) 293DEFINE_DETECT_FUNCTION(32) 294 295static int 296tight_detect_smooth_image(VncState *vs, int w, int h) 297{ 298 unsigned int errors; |
299 int compression = vs->tight.compression; 300 int quality = vs->tight.quality; | 299 int compression = vs->tight->compression; 300 int quality = vs->tight->quality; |
301 302 if (!vs->vd->lossy) { 303 return 0; 304 } 305 306 if (surface_bytes_per_pixel(vs->vd->ds) == 1 || 307 vs->client_pf.bytes_per_pixel == 1 || 308 w < VNC_TIGHT_DETECT_MIN_WIDTH || h < VNC_TIGHT_DETECT_MIN_HEIGHT) { 309 return 0; 310 } 311 | 301 302 if (!vs->vd->lossy) { 303 return 0; 304 } 305 306 if (surface_bytes_per_pixel(vs->vd->ds) == 1 || 307 vs->client_pf.bytes_per_pixel == 1 || 308 w < VNC_TIGHT_DETECT_MIN_WIDTH || h < VNC_TIGHT_DETECT_MIN_HEIGHT) { 309 return 0; 310 } 311 |
312 if (vs->tight.quality != (uint8_t)-1) { | 312 if (vs->tight->quality != (uint8_t)-1) { |
313 if (w * h < VNC_TIGHT_JPEG_MIN_RECT_SIZE) { 314 return 0; 315 } 316 } else { 317 if (w * h < tight_conf[compression].gradient_min_rect_size) { 318 return 0; 319 } 320 } 321 322 if (vs->client_pf.bytes_per_pixel == 4) { | 313 if (w * h < VNC_TIGHT_JPEG_MIN_RECT_SIZE) { 314 return 0; 315 } 316 } else { 317 if (w * h < tight_conf[compression].gradient_min_rect_size) { 318 return 0; 319 } 320 } 321 322 if (vs->client_pf.bytes_per_pixel == 4) { |
323 if (vs->tight.pixel24) { | 323 if (vs->tight->pixel24) { |
324 errors = tight_detect_smooth_image24(vs, w, h); | 324 errors = tight_detect_smooth_image24(vs, w, h); |
325 if (vs->tight.quality != (uint8_t)-1) { | 325 if (vs->tight->quality != (uint8_t)-1) { |
326 return (errors < tight_conf[quality].jpeg_threshold24); 327 } 328 return (errors < tight_conf[compression].gradient_threshold24); 329 } else { 330 errors = tight_detect_smooth_image32(vs, w, h); 331 } 332 } else { 333 errors = tight_detect_smooth_image16(vs, w, h); --- 13 unchanged lines hidden (view full) --- 347 tight_fill_palette##bpp(VncState *vs, int x, int y, \ 348 int max, size_t count, \ 349 uint32_t *bg, uint32_t *fg, \ 350 VncPalette *palette) { \ 351 uint##bpp##_t *data; \ 352 uint##bpp##_t c0, c1, ci; \ 353 int i, n0, n1; \ 354 \ | 326 return (errors < tight_conf[quality].jpeg_threshold24); 327 } 328 return (errors < tight_conf[compression].gradient_threshold24); 329 } else { 330 errors = tight_detect_smooth_image32(vs, w, h); 331 } 332 } else { 333 errors = tight_detect_smooth_image16(vs, w, h); --- 13 unchanged lines hidden (view full) --- 347 tight_fill_palette##bpp(VncState *vs, int x, int y, \ 348 int max, size_t count, \ 349 uint32_t *bg, uint32_t *fg, \ 350 VncPalette *palette) { \ 351 uint##bpp##_t *data; \ 352 uint##bpp##_t c0, c1, ci; \ 353 int i, n0, n1; \ 354 \ |
355 data = (uint##bpp##_t *)vs->tight.tight.buffer; \ | 355 data = (uint##bpp##_t *)vs->tight->tight.buffer; \ |
356 \ 357 c0 = data[0]; \ 358 i = 1; \ 359 while (i < count && data[i] == c0) \ 360 i++; \ 361 if (i >= count) { \ 362 *bg = *fg = c0; \ 363 return 1; \ --- 54 unchanged lines hidden (view full) --- 418DEFINE_FILL_PALETTE_FUNCTION(32) 419 420static int tight_fill_palette(VncState *vs, int x, int y, 421 size_t count, uint32_t *bg, uint32_t *fg, 422 VncPalette *palette) 423{ 424 int max; 425 | 356 \ 357 c0 = data[0]; \ 358 i = 1; \ 359 while (i < count && data[i] == c0) \ 360 i++; \ 361 if (i >= count) { \ 362 *bg = *fg = c0; \ 363 return 1; \ --- 54 unchanged lines hidden (view full) --- 418DEFINE_FILL_PALETTE_FUNCTION(32) 419 420static int tight_fill_palette(VncState *vs, int x, int y, 421 size_t count, uint32_t *bg, uint32_t *fg, 422 VncPalette *palette) 423{ 424 int max; 425 |
426 max = count / tight_conf[vs->tight.compression].idx_max_colors_divisor; | 426 max = count / tight_conf[vs->tight->compression].idx_max_colors_divisor; |
427 if (max < 2 && | 427 if (max < 2 && |
428 count >= tight_conf[vs->tight.compression].mono_min_rect_size) { | 428 count >= tight_conf[vs->tight->compression].mono_min_rect_size) { |
429 max = 2; 430 } 431 if (max >= 256) { 432 max = 256; 433 } 434 435 switch (vs->client_pf.bytes_per_pixel) { 436 case 4: --- 116 unchanged lines hidden (view full) --- 553 uint32_t pix32; 554 int shift[3]; 555 int *prev; 556 int here[3], upper[3], left[3], upperleft[3]; 557 int prediction; 558 int x, y, c; 559 560 buf32 = (uint32_t *)buf; | 429 max = 2; 430 } 431 if (max >= 256) { 432 max = 256; 433 } 434 435 switch (vs->client_pf.bytes_per_pixel) { 436 case 4: --- 116 unchanged lines hidden (view full) --- 553 uint32_t pix32; 554 int shift[3]; 555 int *prev; 556 int here[3], upper[3], left[3], upperleft[3]; 557 int prediction; 558 int x, y, c; 559 560 buf32 = (uint32_t *)buf; |
561 memset(vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); | 561 memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); |
562 563 if (1 /* FIXME */) { 564 shift[0] = vs->client_pf.rshift; 565 shift[1] = vs->client_pf.gshift; 566 shift[2] = vs->client_pf.bshift; 567 } else { 568 shift[0] = 24 - vs->client_pf.rshift; 569 shift[1] = 24 - vs->client_pf.gshift; 570 shift[2] = 24 - vs->client_pf.bshift; 571 } 572 573 for (y = 0; y < h; y++) { 574 for (c = 0; c < 3; c++) { 575 upper[c] = 0; 576 here[c] = 0; 577 } | 562 563 if (1 /* FIXME */) { 564 shift[0] = vs->client_pf.rshift; 565 shift[1] = vs->client_pf.gshift; 566 shift[2] = vs->client_pf.bshift; 567 } else { 568 shift[0] = 24 - vs->client_pf.rshift; 569 shift[1] = 24 - vs->client_pf.gshift; 570 shift[2] = 24 - vs->client_pf.bshift; 571 } 572 573 for (y = 0; y < h; y++) { 574 for (c = 0; c < 3; c++) { 575 upper[c] = 0; 576 here[c] = 0; 577 } |
578 prev = (int *)vs->tight.gradient.buffer; | 578 prev = (int *)vs->tight->gradient.buffer; |
579 for (x = 0; x < w; x++) { 580 pix32 = *buf32++; 581 for (c = 0; c < 3; c++) { 582 upperleft[c] = upper[c]; 583 left[c] = here[c]; 584 upper[c] = *prev; 585 here[c] = (int)(pix32 >> shift[c] & 0xFF); 586 *prev++ = here[c]; --- 23 unchanged lines hidden (view full) --- 610 uint##bpp##_t pix, diff; \ 611 bool endian; \ 612 int *prev; \ 613 int max[3], shift[3]; \ 614 int here[3], upper[3], left[3], upperleft[3]; \ 615 int prediction; \ 616 int x, y, c; \ 617 \ | 579 for (x = 0; x < w; x++) { 580 pix32 = *buf32++; 581 for (c = 0; c < 3; c++) { 582 upperleft[c] = upper[c]; 583 left[c] = here[c]; 584 upper[c] = *prev; 585 here[c] = (int)(pix32 >> shift[c] & 0xFF); 586 *prev++ = here[c]; --- 23 unchanged lines hidden (view full) --- 610 uint##bpp##_t pix, diff; \ 611 bool endian; \ 612 int *prev; \ 613 int max[3], shift[3]; \ 614 int here[3], upper[3], left[3], upperleft[3]; \ 615 int prediction; \ 616 int x, y, c; \ 617 \ |
618 memset (vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); \ | 618 memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); \ |
619 \ 620 endian = 0; /* FIXME */ \ 621 \ 622 max[0] = vs->client_pf.rmax; \ 623 max[1] = vs->client_pf.gmax; \ 624 max[2] = vs->client_pf.bmax; \ 625 shift[0] = vs->client_pf.rshift; \ 626 shift[1] = vs->client_pf.gshift; \ 627 shift[2] = vs->client_pf.bshift; \ 628 \ 629 for (y = 0; y < h; y++) { \ 630 for (c = 0; c < 3; c++) { \ 631 upper[c] = 0; \ 632 here[c] = 0; \ 633 } \ | 619 \ 620 endian = 0; /* FIXME */ \ 621 \ 622 max[0] = vs->client_pf.rmax; \ 623 max[1] = vs->client_pf.gmax; \ 624 max[2] = vs->client_pf.bmax; \ 625 shift[0] = vs->client_pf.rshift; \ 626 shift[1] = vs->client_pf.gshift; \ 627 shift[2] = vs->client_pf.bshift; \ 628 \ 629 for (y = 0; y < h; y++) { \ 630 for (c = 0; c < 3; c++) { \ 631 upper[c] = 0; \ 632 here[c] = 0; \ 633 } \ |
634 prev = (int *)vs->tight.gradient.buffer; \ | 634 prev = (int *)vs->tight->gradient.buffer; \ |
635 for (x = 0; x < w; x++) { \ 636 pix = *buf; \ 637 if (endian) { \ 638 pix = bswap##bpp(pix); \ 639 } \ 640 diff = 0; \ 641 for (c = 0; c < 3; c++) { \ 642 upperleft[c] = upper[c]; \ --- 137 unchanged lines hidden (view full) --- 780 check_solid_tile(vs, cx, *y_ptr, 1, *h_ptr, &color, true); 781 cx++ ); 782 *w_ptr += cx - (*x_ptr + *w_ptr); 783} 784 785static int tight_init_stream(VncState *vs, int stream_id, 786 int level, int strategy) 787{ | 635 for (x = 0; x < w; x++) { \ 636 pix = *buf; \ 637 if (endian) { \ 638 pix = bswap##bpp(pix); \ 639 } \ 640 diff = 0; \ 641 for (c = 0; c < 3; c++) { \ 642 upperleft[c] = upper[c]; \ --- 137 unchanged lines hidden (view full) --- 780 check_solid_tile(vs, cx, *y_ptr, 1, *h_ptr, &color, true); 781 cx++ ); 782 *w_ptr += cx - (*x_ptr + *w_ptr); 783} 784 785static int tight_init_stream(VncState *vs, int stream_id, 786 int level, int strategy) 787{ |
788 z_streamp zstream = &vs->tight.stream[stream_id]; | 788 z_streamp zstream = &vs->tight->stream[stream_id]; |
789 790 if (zstream->opaque == NULL) { 791 int err; 792 793 VNC_DEBUG("VNC: TIGHT: initializing zlib stream %d\n", stream_id); 794 VNC_DEBUG("VNC: TIGHT: opaque = %p | vs = %p\n", zstream->opaque, vs); 795 zstream->zalloc = vnc_zlib_zalloc; 796 zstream->zfree = vnc_zlib_zfree; 797 798 err = deflateInit2(zstream, level, Z_DEFLATED, MAX_WBITS, 799 MAX_MEM_LEVEL, strategy); 800 801 if (err != Z_OK) { 802 fprintf(stderr, "VNC: error initializing zlib\n"); 803 return -1; 804 } 805 | 789 790 if (zstream->opaque == NULL) { 791 int err; 792 793 VNC_DEBUG("VNC: TIGHT: initializing zlib stream %d\n", stream_id); 794 VNC_DEBUG("VNC: TIGHT: opaque = %p | vs = %p\n", zstream->opaque, vs); 795 zstream->zalloc = vnc_zlib_zalloc; 796 zstream->zfree = vnc_zlib_zfree; 797 798 err = deflateInit2(zstream, level, Z_DEFLATED, MAX_WBITS, 799 MAX_MEM_LEVEL, strategy); 800 801 if (err != Z_OK) { 802 fprintf(stderr, "VNC: error initializing zlib\n"); 803 return -1; 804 } 805 |
806 vs->tight.levels[stream_id] = level; | 806 vs->tight->levels[stream_id] = level; |
807 zstream->opaque = vs; 808 } 809 | 807 zstream->opaque = vs; 808 } 809 |
810 if (vs->tight.levels[stream_id] != level) { | 810 if (vs->tight->levels[stream_id] != level) { |
811 if (deflateParams(zstream, level, strategy) != Z_OK) { 812 return -1; 813 } | 811 if (deflateParams(zstream, level, strategy) != Z_OK) { 812 return -1; 813 } |
814 vs->tight.levels[stream_id] = level; | 814 vs->tight->levels[stream_id] = level; |
815 } 816 return 0; 817} 818 819static void tight_send_compact_size(VncState *vs, size_t len) 820{ 821 int lpc = 0; 822 int bytes = 0; --- 11 unchanged lines hidden (view full) --- 834 for (lpc = 0; lpc < bytes; lpc++) { 835 vnc_write_u8(vs, buf[lpc]); 836 } 837} 838 839static int tight_compress_data(VncState *vs, int stream_id, size_t bytes, 840 int level, int strategy) 841{ | 815 } 816 return 0; 817} 818 819static void tight_send_compact_size(VncState *vs, size_t len) 820{ 821 int lpc = 0; 822 int bytes = 0; --- 11 unchanged lines hidden (view full) --- 834 for (lpc = 0; lpc < bytes; lpc++) { 835 vnc_write_u8(vs, buf[lpc]); 836 } 837} 838 839static int tight_compress_data(VncState *vs, int stream_id, size_t bytes, 840 int level, int strategy) 841{ |
842 z_streamp zstream = &vs->tight.stream[stream_id]; | 842 z_streamp zstream = &vs->tight->stream[stream_id]; |
843 int previous_out; 844 845 if (bytes < VNC_TIGHT_MIN_TO_COMPRESS) { | 843 int previous_out; 844 845 if (bytes < VNC_TIGHT_MIN_TO_COMPRESS) { |
846 vnc_write(vs, vs->tight.tight.buffer, vs->tight.tight.offset); | 846 vnc_write(vs, vs->tight->tight.buffer, vs->tight->tight.offset); |
847 return bytes; 848 } 849 850 if (tight_init_stream(vs, stream_id, level, strategy)) { 851 return -1; 852 } 853 854 /* reserve memory in output buffer */ | 847 return bytes; 848 } 849 850 if (tight_init_stream(vs, stream_id, level, strategy)) { 851 return -1; 852 } 853 854 /* reserve memory in output buffer */ |
855 buffer_reserve(&vs->tight.zlib, bytes + 64); | 855 buffer_reserve(&vs->tight->zlib, bytes + 64); |
856 857 /* set pointers */ | 856 857 /* set pointers */ |
858 zstream->next_in = vs->tight.tight.buffer; 859 zstream->avail_in = vs->tight.tight.offset; 860 zstream->next_out = vs->tight.zlib.buffer + vs->tight.zlib.offset; 861 zstream->avail_out = vs->tight.zlib.capacity - vs->tight.zlib.offset; | 858 zstream->next_in = vs->tight->tight.buffer; 859 zstream->avail_in = vs->tight->tight.offset; 860 zstream->next_out = vs->tight->zlib.buffer + vs->tight->zlib.offset; 861 zstream->avail_out = vs->tight->zlib.capacity - vs->tight->zlib.offset; |
862 previous_out = zstream->avail_out; 863 zstream->data_type = Z_BINARY; 864 865 /* start encoding */ 866 if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) { 867 fprintf(stderr, "VNC: error during tight compression\n"); 868 return -1; 869 } 870 | 862 previous_out = zstream->avail_out; 863 zstream->data_type = Z_BINARY; 864 865 /* start encoding */ 866 if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) { 867 fprintf(stderr, "VNC: error during tight compression\n"); 868 return -1; 869 } 870 |
871 vs->tight.zlib.offset = vs->tight.zlib.capacity - zstream->avail_out; | 871 vs->tight->zlib.offset = vs->tight->zlib.capacity - zstream->avail_out; |
872 /* ...how much data has actually been produced by deflate() */ 873 bytes = previous_out - zstream->avail_out; 874 875 tight_send_compact_size(vs, bytes); | 872 /* ...how much data has actually been produced by deflate() */ 873 bytes = previous_out - zstream->avail_out; 874 875 tight_send_compact_size(vs, bytes); |
876 vnc_write(vs, vs->tight.zlib.buffer, bytes); | 876 vnc_write(vs, vs->tight->zlib.buffer, bytes); |
877 | 877 |
878 buffer_reset(&vs->tight.zlib); | 878 buffer_reset(&vs->tight->zlib); |
879 880 return bytes; 881} 882 883/* 884 * Subencoding implementations. 885 */ 886static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret) --- 35 unchanged lines hidden (view full) --- 922#ifdef CONFIG_VNC_PNG 923 if (tight_can_send_png_rect(vs, w, h)) { 924 return send_png_rect(vs, x, y, w, h, NULL); 925 } 926#endif 927 928 vnc_write_u8(vs, stream << 4); /* no flushing, no filter */ 929 | 879 880 return bytes; 881} 882 883/* 884 * Subencoding implementations. 885 */ 886static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret) --- 35 unchanged lines hidden (view full) --- 922#ifdef CONFIG_VNC_PNG 923 if (tight_can_send_png_rect(vs, w, h)) { 924 return send_png_rect(vs, x, y, w, h, NULL); 925 } 926#endif 927 928 vnc_write_u8(vs, stream << 4); /* no flushing, no filter */ 929 |
930 if (vs->tight.pixel24) { 931 tight_pack24(vs, vs->tight.tight.buffer, w * h, &vs->tight.tight.offset); | 930 if (vs->tight->pixel24) { 931 tight_pack24(vs, vs->tight->tight.buffer, w * h, 932 &vs->tight->tight.offset); |
932 bytes = 3; 933 } else { 934 bytes = vs->client_pf.bytes_per_pixel; 935 } 936 937 bytes = tight_compress_data(vs, stream, w * h * bytes, | 933 bytes = 3; 934 } else { 935 bytes = vs->client_pf.bytes_per_pixel; 936 } 937 938 bytes = tight_compress_data(vs, stream, w * h * bytes, |
938 tight_conf[vs->tight.compression].raw_zlib_level, 939 Z_DEFAULT_STRATEGY); | 939 tight_conf[vs->tight->compression].raw_zlib_level, 940 Z_DEFAULT_STRATEGY); |
940 941 return (bytes >= 0); 942} 943 944static int send_solid_rect(VncState *vs) 945{ 946 size_t bytes; 947 948 vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */ 949 | 941 942 return (bytes >= 0); 943} 944 945static int send_solid_rect(VncState *vs) 946{ 947 size_t bytes; 948 949 vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */ 950 |
950 if (vs->tight.pixel24) { 951 tight_pack24(vs, vs->tight.tight.buffer, 1, &vs->tight.tight.offset); | 951 if (vs->tight->pixel24) { 952 tight_pack24(vs, vs->tight->tight.buffer, 1, &vs->tight->tight.offset); |
952 bytes = 3; 953 } else { 954 bytes = vs->client_pf.bytes_per_pixel; 955 } 956 | 953 bytes = 3; 954 } else { 955 bytes = vs->client_pf.bytes_per_pixel; 956 } 957 |
957 vnc_write(vs, vs->tight.tight.buffer, bytes); | 958 vnc_write(vs, vs->tight->tight.buffer, bytes); |
958 return 1; 959} 960 961static int send_mono_rect(VncState *vs, int x, int y, 962 int w, int h, uint32_t bg, uint32_t fg) 963{ 964 ssize_t bytes; 965 int stream = 1; | 959 return 1; 960} 961 962static int send_mono_rect(VncState *vs, int x, int y, 963 int w, int h, uint32_t bg, uint32_t fg) 964{ 965 ssize_t bytes; 966 int stream = 1; |
966 int level = tight_conf[vs->tight.compression].mono_zlib_level; | 967 int level = tight_conf[vs->tight->compression].mono_zlib_level; |
967 968#ifdef CONFIG_VNC_PNG 969 if (tight_can_send_png_rect(vs, w, h)) { 970 int ret; 971 int bpp = vs->client_pf.bytes_per_pixel * 8; 972 VncPalette *palette = palette_new(2, bpp); 973 974 palette_put(palette, bg); --- 11 unchanged lines hidden (view full) --- 986 vnc_write_u8(vs, 1); 987 988 switch (vs->client_pf.bytes_per_pixel) { 989 case 4: 990 { 991 uint32_t buf[2] = {bg, fg}; 992 size_t ret = sizeof (buf); 993 | 968 969#ifdef CONFIG_VNC_PNG 970 if (tight_can_send_png_rect(vs, w, h)) { 971 int ret; 972 int bpp = vs->client_pf.bytes_per_pixel * 8; 973 VncPalette *palette = palette_new(2, bpp); 974 975 palette_put(palette, bg); --- 11 unchanged lines hidden (view full) --- 987 vnc_write_u8(vs, 1); 988 989 switch (vs->client_pf.bytes_per_pixel) { 990 case 4: 991 { 992 uint32_t buf[2] = {bg, fg}; 993 size_t ret = sizeof (buf); 994 |
994 if (vs->tight.pixel24) { | 995 if (vs->tight->pixel24) { |
995 tight_pack24(vs, (unsigned char*)buf, 2, &ret); 996 } 997 vnc_write(vs, buf, ret); 998 | 996 tight_pack24(vs, (unsigned char*)buf, 2, &ret); 997 } 998 vnc_write(vs, buf, ret); 999 |
999 tight_encode_mono_rect32(vs->tight.tight.buffer, w, h, bg, fg); | 1000 tight_encode_mono_rect32(vs->tight->tight.buffer, w, h, bg, fg); |
1000 break; 1001 } 1002 case 2: 1003 vnc_write(vs, &bg, 2); 1004 vnc_write(vs, &fg, 2); | 1001 break; 1002 } 1003 case 2: 1004 vnc_write(vs, &bg, 2); 1005 vnc_write(vs, &fg, 2); |
1005 tight_encode_mono_rect16(vs->tight.tight.buffer, w, h, bg, fg); | 1006 tight_encode_mono_rect16(vs->tight->tight.buffer, w, h, bg, fg); |
1006 break; 1007 default: 1008 vnc_write_u8(vs, bg); 1009 vnc_write_u8(vs, fg); | 1007 break; 1008 default: 1009 vnc_write_u8(vs, bg); 1010 vnc_write_u8(vs, fg); |
1010 tight_encode_mono_rect8(vs->tight.tight.buffer, w, h, bg, fg); | 1011 tight_encode_mono_rect8(vs->tight->tight.buffer, w, h, bg, fg); |
1011 break; 1012 } | 1012 break; 1013 } |
1013 vs->tight.tight.offset = bytes; | 1014 vs->tight->tight.offset = bytes; |
1014 1015 bytes = tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRATEGY); 1016 return (bytes >= 0); 1017} 1018 1019struct palette_cb_priv { 1020 VncState *vs; 1021 uint8_t *header; --- 13 unchanged lines hidden (view full) --- 1035 } else { 1036 ((uint16_t*)priv->header)[idx] = color; 1037 } 1038} 1039 1040static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) 1041{ 1042 int stream = 3; | 1015 1016 bytes = tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRATEGY); 1017 return (bytes >= 0); 1018} 1019 1020struct palette_cb_priv { 1021 VncState *vs; 1022 uint8_t *header; --- 13 unchanged lines hidden (view full) --- 1036 } else { 1037 ((uint16_t*)priv->header)[idx] = color; 1038 } 1039} 1040 1041static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) 1042{ 1043 int stream = 3; |
1043 int level = tight_conf[vs->tight.compression].gradient_zlib_level; | 1044 int level = tight_conf[vs->tight->compression].gradient_zlib_level; |
1044 ssize_t bytes; 1045 1046 if (vs->client_pf.bytes_per_pixel == 1) { 1047 return send_full_color_rect(vs, x, y, w, h); 1048 } 1049 1050 vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4); 1051 vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT); 1052 | 1045 ssize_t bytes; 1046 1047 if (vs->client_pf.bytes_per_pixel == 1) { 1048 return send_full_color_rect(vs, x, y, w, h); 1049 } 1050 1051 vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4); 1052 vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT); 1053 |
1053 buffer_reserve(&vs->tight.gradient, w * 3 * sizeof (int)); | 1054 buffer_reserve(&vs->tight->gradient, w * 3 * sizeof(int)); |
1054 | 1055 |
1055 if (vs->tight.pixel24) { 1056 tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h); | 1056 if (vs->tight->pixel24) { 1057 tight_filter_gradient24(vs, vs->tight->tight.buffer, w, h); |
1057 bytes = 3; 1058 } else if (vs->client_pf.bytes_per_pixel == 4) { | 1058 bytes = 3; 1059 } else if (vs->client_pf.bytes_per_pixel == 4) { |
1059 tight_filter_gradient32(vs, (uint32_t *)vs->tight.tight.buffer, w, h); | 1060 tight_filter_gradient32(vs, (uint32_t *)vs->tight->tight.buffer, w, h); |
1060 bytes = 4; 1061 } else { | 1061 bytes = 4; 1062 } else { |
1062 tight_filter_gradient16(vs, (uint16_t *)vs->tight.tight.buffer, w, h); | 1063 tight_filter_gradient16(vs, (uint16_t *)vs->tight->tight.buffer, w, h); |
1063 bytes = 2; 1064 } 1065 | 1064 bytes = 2; 1065 } 1066 |
1066 buffer_reset(&vs->tight.gradient); | 1067 buffer_reset(&vs->tight->gradient); |
1067 1068 bytes = w * h * bytes; | 1068 1069 bytes = w * h * bytes; |
1069 vs->tight.tight.offset = bytes; | 1070 vs->tight->tight.offset = bytes; |
1070 1071 bytes = tight_compress_data(vs, stream, bytes, 1072 level, Z_FILTERED); 1073 return (bytes >= 0); 1074} 1075 1076static int send_palette_rect(VncState *vs, int x, int y, 1077 int w, int h, VncPalette *palette) 1078{ 1079 int stream = 2; | 1071 1072 bytes = tight_compress_data(vs, stream, bytes, 1073 level, Z_FILTERED); 1074 return (bytes >= 0); 1075} 1076 1077static int send_palette_rect(VncState *vs, int x, int y, 1078 int w, int h, VncPalette *palette) 1079{ 1080 int stream = 2; |
1080 int level = tight_conf[vs->tight.compression].idx_zlib_level; | 1081 int level = tight_conf[vs->tight->compression].idx_zlib_level; |
1081 int colors; 1082 ssize_t bytes; 1083 1084#ifdef CONFIG_VNC_PNG 1085 if (tight_can_send_png_rect(vs, w, h)) { 1086 return send_png_rect(vs, x, y, w, h, palette); 1087 } 1088#endif --- 10 unchanged lines hidden (view full) --- 1099 size_t old_offset, offset; 1100 uint32_t header[palette_size(palette)]; 1101 struct palette_cb_priv priv = { vs, (uint8_t *)header }; 1102 1103 old_offset = vs->output.offset; 1104 palette_iter(palette, write_palette, &priv); 1105 vnc_write(vs, header, sizeof(header)); 1106 | 1082 int colors; 1083 ssize_t bytes; 1084 1085#ifdef CONFIG_VNC_PNG 1086 if (tight_can_send_png_rect(vs, w, h)) { 1087 return send_png_rect(vs, x, y, w, h, palette); 1088 } 1089#endif --- 10 unchanged lines hidden (view full) --- 1100 size_t old_offset, offset; 1101 uint32_t header[palette_size(palette)]; 1102 struct palette_cb_priv priv = { vs, (uint8_t *)header }; 1103 1104 old_offset = vs->output.offset; 1105 palette_iter(palette, write_palette, &priv); 1106 vnc_write(vs, header, sizeof(header)); 1107 |
1107 if (vs->tight.pixel24) { | 1108 if (vs->tight->pixel24) { |
1108 tight_pack24(vs, vs->output.buffer + old_offset, colors, &offset); 1109 vs->output.offset = old_offset + offset; 1110 } 1111 | 1109 tight_pack24(vs, vs->output.buffer + old_offset, colors, &offset); 1110 vs->output.offset = old_offset + offset; 1111 } 1112 |
1112 tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); | 1113 tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, palette); |
1113 break; 1114 } 1115 case 2: 1116 { 1117 uint16_t header[palette_size(palette)]; 1118 struct palette_cb_priv priv = { vs, (uint8_t *)header }; 1119 1120 palette_iter(palette, write_palette, &priv); 1121 vnc_write(vs, header, sizeof(header)); | 1114 break; 1115 } 1116 case 2: 1117 { 1118 uint16_t header[palette_size(palette)]; 1119 struct palette_cb_priv priv = { vs, (uint8_t *)header }; 1120 1121 palette_iter(palette, write_palette, &priv); 1122 vnc_write(vs, header, sizeof(header)); |
1122 tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); | 1123 tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, palette); |
1123 break; 1124 } 1125 default: 1126 return -1; /* No palette for 8bits colors */ 1127 break; 1128 } 1129 bytes = w * h; | 1124 break; 1125 } 1126 default: 1127 return -1; /* No palette for 8bits colors */ 1128 break; 1129 } 1130 bytes = w * h; |
1130 vs->tight.tight.offset = bytes; | 1131 vs->tight->tight.offset = bytes; |
1131 1132 bytes = tight_compress_data(vs, stream, bytes, 1133 level, Z_DEFAULT_STRATEGY); 1134 return (bytes >= 0); 1135} 1136 1137/* 1138 * JPEG compression stuff. 1139 */ 1140#ifdef CONFIG_VNC_JPEG 1141/* 1142 * Destination manager implementation for JPEG library. 1143 */ 1144 1145/* This is called once per encoding */ 1146static void jpeg_init_destination(j_compress_ptr cinfo) 1147{ 1148 VncState *vs = cinfo->client_data; | 1132 1133 bytes = tight_compress_data(vs, stream, bytes, 1134 level, Z_DEFAULT_STRATEGY); 1135 return (bytes >= 0); 1136} 1137 1138/* 1139 * JPEG compression stuff. 1140 */ 1141#ifdef CONFIG_VNC_JPEG 1142/* 1143 * Destination manager implementation for JPEG library. 1144 */ 1145 1146/* This is called once per encoding */ 1147static void jpeg_init_destination(j_compress_ptr cinfo) 1148{ 1149 VncState *vs = cinfo->client_data; |
1149 Buffer *buffer = &vs->tight.jpeg; | 1150 Buffer *buffer = &vs->tight->jpeg; |
1150 1151 cinfo->dest->next_output_byte = (JOCTET *)buffer->buffer + buffer->offset; 1152 cinfo->dest->free_in_buffer = (size_t)(buffer->capacity - buffer->offset); 1153} 1154 1155/* This is called when we ran out of buffer (shouldn't happen!) */ 1156static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) 1157{ 1158 VncState *vs = cinfo->client_data; | 1151 1152 cinfo->dest->next_output_byte = (JOCTET *)buffer->buffer + buffer->offset; 1153 cinfo->dest->free_in_buffer = (size_t)(buffer->capacity - buffer->offset); 1154} 1155 1156/* This is called when we ran out of buffer (shouldn't happen!) */ 1157static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) 1158{ 1159 VncState *vs = cinfo->client_data; |
1159 Buffer *buffer = &vs->tight.jpeg; | 1160 Buffer *buffer = &vs->tight->jpeg; |
1160 1161 buffer->offset = buffer->capacity; 1162 buffer_reserve(buffer, 2048); 1163 jpeg_init_destination(cinfo); 1164 return TRUE; 1165} 1166 1167/* This is called when we are done processing data */ 1168static void jpeg_term_destination(j_compress_ptr cinfo) 1169{ 1170 VncState *vs = cinfo->client_data; | 1161 1162 buffer->offset = buffer->capacity; 1163 buffer_reserve(buffer, 2048); 1164 jpeg_init_destination(cinfo); 1165 return TRUE; 1166} 1167 1168/* This is called when we are done processing data */ 1169static void jpeg_term_destination(j_compress_ptr cinfo) 1170{ 1171 VncState *vs = cinfo->client_data; |
1171 Buffer *buffer = &vs->tight.jpeg; | 1172 Buffer *buffer = &vs->tight->jpeg; |
1172 1173 buffer->offset = buffer->capacity - cinfo->dest->free_in_buffer; 1174} 1175 1176static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) 1177{ 1178 struct jpeg_compress_struct cinfo; 1179 struct jpeg_error_mgr jerr; 1180 struct jpeg_destination_mgr manager; 1181 pixman_image_t *linebuf; 1182 JSAMPROW row[1]; 1183 uint8_t *buf; 1184 int dy; 1185 1186 if (surface_bytes_per_pixel(vs->vd->ds) == 1) { 1187 return send_full_color_rect(vs, x, y, w, h); 1188 } 1189 | 1173 1174 buffer->offset = buffer->capacity - cinfo->dest->free_in_buffer; 1175} 1176 1177static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) 1178{ 1179 struct jpeg_compress_struct cinfo; 1180 struct jpeg_error_mgr jerr; 1181 struct jpeg_destination_mgr manager; 1182 pixman_image_t *linebuf; 1183 JSAMPROW row[1]; 1184 uint8_t *buf; 1185 int dy; 1186 1187 if (surface_bytes_per_pixel(vs->vd->ds) == 1) { 1188 return send_full_color_rect(vs, x, y, w, h); 1189 } 1190 |
1190 buffer_reserve(&vs->tight.jpeg, 2048); | 1191 buffer_reserve(&vs->tight->jpeg, 2048); |
1191 1192 cinfo.err = jpeg_std_error(&jerr); 1193 jpeg_create_compress(&cinfo); 1194 1195 cinfo.client_data = vs; 1196 cinfo.image_width = w; 1197 cinfo.image_height = h; 1198 cinfo.input_components = 3; --- 18 unchanged lines hidden (view full) --- 1217 } 1218 qemu_pixman_image_unref(linebuf); 1219 1220 jpeg_finish_compress(&cinfo); 1221 jpeg_destroy_compress(&cinfo); 1222 1223 vnc_write_u8(vs, VNC_TIGHT_JPEG << 4); 1224 | 1192 1193 cinfo.err = jpeg_std_error(&jerr); 1194 jpeg_create_compress(&cinfo); 1195 1196 cinfo.client_data = vs; 1197 cinfo.image_width = w; 1198 cinfo.image_height = h; 1199 cinfo.input_components = 3; --- 18 unchanged lines hidden (view full) --- 1218 } 1219 qemu_pixman_image_unref(linebuf); 1220 1221 jpeg_finish_compress(&cinfo); 1222 jpeg_destroy_compress(&cinfo); 1223 1224 vnc_write_u8(vs, VNC_TIGHT_JPEG << 4); 1225 |
1225 tight_send_compact_size(vs, vs->tight.jpeg.offset); 1226 vnc_write(vs, vs->tight.jpeg.buffer, vs->tight.jpeg.offset); 1227 buffer_reset(&vs->tight.jpeg); | 1226 tight_send_compact_size(vs, vs->tight->jpeg.offset); 1227 vnc_write(vs, vs->tight->jpeg.buffer, vs->tight->jpeg.offset); 1228 buffer_reset(&vs->tight->jpeg); |
1228 1229 return 1; 1230} 1231#endif /* CONFIG_VNC_JPEG */ 1232 1233/* 1234 * PNG compression stuff. 1235 */ 1236#ifdef CONFIG_VNC_PNG 1237static void write_png_palette(int idx, uint32_t pix, void *opaque) 1238{ 1239 struct palette_cb_priv *priv = opaque; 1240 VncState *vs = priv->vs; 1241 png_colorp color = &priv->png_palette[idx]; 1242 | 1229 1230 return 1; 1231} 1232#endif /* CONFIG_VNC_JPEG */ 1233 1234/* 1235 * PNG compression stuff. 1236 */ 1237#ifdef CONFIG_VNC_PNG 1238static void write_png_palette(int idx, uint32_t pix, void *opaque) 1239{ 1240 struct palette_cb_priv *priv = opaque; 1241 VncState *vs = priv->vs; 1242 png_colorp color = &priv->png_palette[idx]; 1243 |
1243 if (vs->tight.pixel24) | 1244 if (vs->tight->pixel24) |
1244 { 1245 color->red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax; 1246 color->green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax; 1247 color->blue = (pix >> vs->client_pf.bshift) & vs->client_pf.bmax; 1248 } 1249 else 1250 { 1251 int red, green, blue; --- 10 unchanged lines hidden (view full) --- 1262 } 1263} 1264 1265static void png_write_data(png_structp png_ptr, png_bytep data, 1266 png_size_t length) 1267{ 1268 VncState *vs = png_get_io_ptr(png_ptr); 1269 | 1245 { 1246 color->red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax; 1247 color->green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax; 1248 color->blue = (pix >> vs->client_pf.bshift) & vs->client_pf.bmax; 1249 } 1250 else 1251 { 1252 int red, green, blue; --- 10 unchanged lines hidden (view full) --- 1263 } 1264} 1265 1266static void png_write_data(png_structp png_ptr, png_bytep data, 1267 png_size_t length) 1268{ 1269 VncState *vs = png_get_io_ptr(png_ptr); 1270 |
1270 buffer_reserve(&vs->tight.png, vs->tight.png.offset + length); 1271 memcpy(vs->tight.png.buffer + vs->tight.png.offset, data, length); | 1271 buffer_reserve(&vs->tight->png, vs->tight->png.offset + length); 1272 memcpy(vs->tight->png.buffer + vs->tight->png.offset, data, length); |
1272 | 1273 |
1273 vs->tight.png.offset += length; | 1274 vs->tight->png.offset += length; |
1274} 1275 1276static void png_flush_data(png_structp png_ptr) 1277{ 1278} 1279 1280static void *vnc_png_malloc(png_structp png_ptr, png_size_t size) 1281{ --- 8 unchanged lines hidden (view full) --- 1290static int send_png_rect(VncState *vs, int x, int y, int w, int h, 1291 VncPalette *palette) 1292{ 1293 png_byte color_type; 1294 png_structp png_ptr; 1295 png_infop info_ptr; 1296 png_colorp png_palette = NULL; 1297 pixman_image_t *linebuf; | 1275} 1276 1277static void png_flush_data(png_structp png_ptr) 1278{ 1279} 1280 1281static void *vnc_png_malloc(png_structp png_ptr, png_size_t size) 1282{ --- 8 unchanged lines hidden (view full) --- 1291static int send_png_rect(VncState *vs, int x, int y, int w, int h, 1292 VncPalette *palette) 1293{ 1294 png_byte color_type; 1295 png_structp png_ptr; 1296 png_infop info_ptr; 1297 png_colorp png_palette = NULL; 1298 pixman_image_t *linebuf; |
1298 int level = tight_png_conf[vs->tight.compression].png_zlib_level; 1299 int filters = tight_png_conf[vs->tight.compression].png_filters; | 1299 int level = tight_png_conf[vs->tight->compression].png_zlib_level; 1300 int filters = tight_png_conf[vs->tight->compression].png_filters; |
1300 uint8_t *buf; 1301 int dy; 1302 1303 png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, 1304 NULL, vnc_png_malloc, vnc_png_free); 1305 1306 if (png_ptr == NULL) 1307 return -1; --- 27 unchanged lines hidden (view full) --- 1335 1336 priv.vs = vs; 1337 priv.png_palette = png_palette; 1338 palette_iter(palette, write_png_palette, &priv); 1339 1340 png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); 1341 1342 if (vs->client_pf.bytes_per_pixel == 4) { | 1301 uint8_t *buf; 1302 int dy; 1303 1304 png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, 1305 NULL, vnc_png_malloc, vnc_png_free); 1306 1307 if (png_ptr == NULL) 1308 return -1; --- 27 unchanged lines hidden (view full) --- 1336 1337 priv.vs = vs; 1338 priv.png_palette = png_palette; 1339 palette_iter(palette, write_png_palette, &priv); 1340 1341 png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); 1342 1343 if (vs->client_pf.bytes_per_pixel == 4) { |
1343 tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); | 1344 tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, 1345 palette); |
1344 } else { | 1346 } else { |
1345 tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); | 1347 tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, 1348 palette); |
1346 } 1347 } 1348 1349 png_write_info(png_ptr, info_ptr); 1350 | 1349 } 1350 } 1351 1352 png_write_info(png_ptr, info_ptr); 1353 |
1351 buffer_reserve(&vs->tight.png, 2048); | 1354 buffer_reserve(&vs->tight->png, 2048); |
1352 linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); 1353 buf = (uint8_t *)pixman_image_get_data(linebuf); 1354 for (dy = 0; dy < h; dy++) 1355 { 1356 if (color_type == PNG_COLOR_TYPE_PALETTE) { | 1355 linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); 1356 buf = (uint8_t *)pixman_image_get_data(linebuf); 1357 for (dy = 0; dy < h; dy++) 1358 { 1359 if (color_type == PNG_COLOR_TYPE_PALETTE) { |
1357 memcpy(buf, vs->tight.tight.buffer + (dy * w), w); | 1360 memcpy(buf, vs->tight->tight.buffer + (dy * w), w); |
1358 } else { 1359 qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, x, y + dy); 1360 } 1361 png_write_row(png_ptr, buf); 1362 } 1363 qemu_pixman_image_unref(linebuf); 1364 1365 png_write_end(png_ptr, NULL); 1366 1367 if (color_type == PNG_COLOR_TYPE_PALETTE) { 1368 png_free(png_ptr, png_palette); 1369 } 1370 1371 png_destroy_write_struct(&png_ptr, &info_ptr); 1372 1373 vnc_write_u8(vs, VNC_TIGHT_PNG << 4); 1374 | 1361 } else { 1362 qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, x, y + dy); 1363 } 1364 png_write_row(png_ptr, buf); 1365 } 1366 qemu_pixman_image_unref(linebuf); 1367 1368 png_write_end(png_ptr, NULL); 1369 1370 if (color_type == PNG_COLOR_TYPE_PALETTE) { 1371 png_free(png_ptr, png_palette); 1372 } 1373 1374 png_destroy_write_struct(&png_ptr, &info_ptr); 1375 1376 vnc_write_u8(vs, VNC_TIGHT_PNG << 4); 1377 |
1375 tight_send_compact_size(vs, vs->tight.png.offset); 1376 vnc_write(vs, vs->tight.png.buffer, vs->tight.png.offset); 1377 buffer_reset(&vs->tight.png); | 1378 tight_send_compact_size(vs, vs->tight->png.offset); 1379 vnc_write(vs, vs->tight->png.buffer, vs->tight->png.offset); 1380 buffer_reset(&vs->tight->png); |
1378 return 1; 1379} 1380#endif /* CONFIG_VNC_PNG */ 1381 1382static void vnc_tight_start(VncState *vs) 1383{ | 1381 return 1; 1382} 1383#endif /* CONFIG_VNC_PNG */ 1384 1385static void vnc_tight_start(VncState *vs) 1386{ |
1384 buffer_reset(&vs->tight.tight); | 1387 buffer_reset(&vs->tight->tight); |
1385 1386 // make the output buffer be the zlib buffer, so we can compress it later | 1388 1389 // make the output buffer be the zlib buffer, so we can compress it later |
1387 vs->tight.tmp = vs->output; 1388 vs->output = vs->tight.tight; | 1390 vs->tight->tmp = vs->output; 1391 vs->output = vs->tight->tight; |
1389} 1390 1391static void vnc_tight_stop(VncState *vs) 1392{ 1393 // switch back to normal output/zlib buffers | 1392} 1393 1394static void vnc_tight_stop(VncState *vs) 1395{ 1396 // switch back to normal output/zlib buffers |
1394 vs->tight.tight = vs->output; 1395 vs->output = vs->tight.tmp; | 1397 vs->tight->tight = vs->output; 1398 vs->output = vs->tight->tmp; |
1396} 1397 1398static int send_sub_rect_nojpeg(VncState *vs, int x, int y, int w, int h, 1399 int bg, int fg, int colors, VncPalette *palette) 1400{ 1401 int ret; 1402 1403 if (colors == 0) { --- 17 unchanged lines hidden (view full) --- 1421#ifdef CONFIG_VNC_JPEG 1422static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h, 1423 int bg, int fg, int colors, 1424 VncPalette *palette, bool force) 1425{ 1426 int ret; 1427 1428 if (colors == 0) { | 1399} 1400 1401static int send_sub_rect_nojpeg(VncState *vs, int x, int y, int w, int h, 1402 int bg, int fg, int colors, VncPalette *palette) 1403{ 1404 int ret; 1405 1406 if (colors == 0) { --- 17 unchanged lines hidden (view full) --- 1424#ifdef CONFIG_VNC_JPEG 1425static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h, 1426 int bg, int fg, int colors, 1427 VncPalette *palette, bool force) 1428{ 1429 int ret; 1430 1431 if (colors == 0) { |
1429 if (force || (tight_jpeg_conf[vs->tight.quality].jpeg_full && | 1432 if (force || (tight_jpeg_conf[vs->tight->quality].jpeg_full && |
1430 tight_detect_smooth_image(vs, w, h))) { | 1433 tight_detect_smooth_image(vs, w, h))) { |
1431 int quality = tight_conf[vs->tight.quality].jpeg_quality; | 1434 int quality = tight_conf[vs->tight->quality].jpeg_quality; |
1432 1433 ret = send_jpeg_rect(vs, x, y, w, h, quality); 1434 } else { 1435 ret = send_full_color_rect(vs, x, y, w, h); 1436 } 1437 } else if (colors == 1) { 1438 ret = send_solid_rect(vs); 1439 } else if (colors == 2) { 1440 ret = send_mono_rect(vs, x, y, w, h, bg, fg); 1441 } else if (colors <= 256) { 1442 if (force || (colors > 96 && | 1435 1436 ret = send_jpeg_rect(vs, x, y, w, h, quality); 1437 } else { 1438 ret = send_full_color_rect(vs, x, y, w, h); 1439 } 1440 } else if (colors == 1) { 1441 ret = send_solid_rect(vs); 1442 } else if (colors == 2) { 1443 ret = send_mono_rect(vs, x, y, w, h, bg, fg); 1444 } else if (colors <= 256) { 1445 if (force || (colors > 96 && |
1443 tight_jpeg_conf[vs->tight.quality].jpeg_idx && | 1446 tight_jpeg_conf[vs->tight->quality].jpeg_idx && |
1444 tight_detect_smooth_image(vs, w, h))) { | 1447 tight_detect_smooth_image(vs, w, h))) { |
1445 int quality = tight_conf[vs->tight.quality].jpeg_quality; | 1448 int quality = tight_conf[vs->tight->quality].jpeg_quality; |
1446 1447 ret = send_jpeg_rect(vs, x, y, w, h, quality); 1448 } else { 1449 ret = send_palette_rect(vs, x, y, w, h, palette); 1450 } 1451 } else { 1452 ret = 0; 1453 } --- 21 unchanged lines hidden (view full) --- 1475#endif 1476 1477 if (!color_count_palette) { 1478 color_count_palette = g_malloc(sizeof(VncPalette)); 1479 vnc_tight_cleanup_notifier.notify = vnc_tight_cleanup; 1480 qemu_thread_atexit_add(&vnc_tight_cleanup_notifier); 1481 } 1482 | 1449 1450 ret = send_jpeg_rect(vs, x, y, w, h, quality); 1451 } else { 1452 ret = send_palette_rect(vs, x, y, w, h, palette); 1453 } 1454 } else { 1455 ret = 0; 1456 } --- 21 unchanged lines hidden (view full) --- 1478#endif 1479 1480 if (!color_count_palette) { 1481 color_count_palette = g_malloc(sizeof(VncPalette)); 1482 vnc_tight_cleanup_notifier.notify = vnc_tight_cleanup; 1483 qemu_thread_atexit_add(&vnc_tight_cleanup_notifier); 1484 } 1485 |
1483 vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type); | 1486 vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type); |
1484 1485 vnc_tight_start(vs); 1486 vnc_raw_send_framebuffer_update(vs, x, y, w, h); 1487 vnc_tight_stop(vs); 1488 1489#ifdef CONFIG_VNC_JPEG | 1487 1488 vnc_tight_start(vs); 1489 vnc_raw_send_framebuffer_update(vs, x, y, w, h); 1490 vnc_tight_stop(vs); 1491 1492#ifdef CONFIG_VNC_JPEG |
1490 if (!vs->vd->non_adaptive && vs->tight.quality != (uint8_t)-1) { | 1493 if (!vs->vd->non_adaptive && vs->tight->quality != (uint8_t)-1) { |
1491 double freq = vnc_update_freq(vs, x, y, w, h); 1492 | 1494 double freq = vnc_update_freq(vs, x, y, w, h); 1495 |
1493 if (freq < tight_jpeg_conf[vs->tight.quality].jpeg_freq_min) { | 1496 if (freq < tight_jpeg_conf[vs->tight->quality].jpeg_freq_min) { |
1494 allow_jpeg = false; 1495 } | 1497 allow_jpeg = false; 1498 } |
1496 if (freq >= tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) { | 1499 if (freq >= tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold) { |
1497 force_jpeg = true; 1498 vnc_sent_lossy_rect(vs, x, y, w, h); 1499 } 1500 } 1501#endif 1502 1503 colors = tight_fill_palette(vs, x, y, w * h, &bg, &fg, color_count_palette); 1504 1505#ifdef CONFIG_VNC_JPEG | 1500 force_jpeg = true; 1501 vnc_sent_lossy_rect(vs, x, y, w, h); 1502 } 1503 } 1504#endif 1505 1506 colors = tight_fill_palette(vs, x, y, w * h, &bg, &fg, color_count_palette); 1507 1508#ifdef CONFIG_VNC_JPEG |
1506 if (allow_jpeg && vs->tight.quality != (uint8_t)-1) { | 1509 if (allow_jpeg && vs->tight->quality != (uint8_t)-1) { |
1507 ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, 1508 color_count_palette, force_jpeg); 1509 } else { 1510 ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, 1511 color_count_palette); 1512 } 1513#else 1514 ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, 1515 color_count_palette); 1516#endif 1517 1518 return ret; 1519} 1520 1521static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h) 1522{ | 1510 ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, 1511 color_count_palette, force_jpeg); 1512 } else { 1513 ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, 1514 color_count_palette); 1515 } 1516#else 1517 ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, 1518 color_count_palette); 1519#endif 1520 1521 return ret; 1522} 1523 1524static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h) 1525{ |
1523 vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type); | 1526 vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type); |
1524 1525 vnc_tight_start(vs); 1526 vnc_raw_send_framebuffer_update(vs, x, y, w, h); 1527 vnc_tight_stop(vs); 1528 1529 return send_solid_rect(vs); 1530} 1531 1532static int send_rect_simple(VncState *vs, int x, int y, int w, int h, 1533 bool split) 1534{ 1535 int max_size, max_width; 1536 int max_sub_width, max_sub_height; 1537 int dx, dy; 1538 int rw, rh; 1539 int n = 0; 1540 | 1527 1528 vnc_tight_start(vs); 1529 vnc_raw_send_framebuffer_update(vs, x, y, w, h); 1530 vnc_tight_stop(vs); 1531 1532 return send_solid_rect(vs); 1533} 1534 1535static int send_rect_simple(VncState *vs, int x, int y, int w, int h, 1536 bool split) 1537{ 1538 int max_size, max_width; 1539 int max_sub_width, max_sub_height; 1540 int dx, dy; 1541 int rw, rh; 1542 int n = 0; 1543 |
1541 max_size = tight_conf[vs->tight.compression].max_rect_size; 1542 max_width = tight_conf[vs->tight.compression].max_rect_width; | 1544 max_size = tight_conf[vs->tight->compression].max_rect_size; 1545 max_width = tight_conf[vs->tight->compression].max_rect_width; |
1543 1544 if (split && (w > max_width || w * h > max_size)) { 1545 max_sub_width = (w > max_width) ? max_width : w; 1546 max_sub_height = max_size / max_sub_width; 1547 1548 for (dy = 0; dy < h; dy += max_sub_height) { 1549 for (dx = 0; dx < w; dx += max_width) { 1550 rw = MIN(max_sub_width, w - dx); --- 92 unchanged lines hidden (view full) --- 1643 1644static int tight_send_framebuffer_update(VncState *vs, int x, int y, 1645 int w, int h) 1646{ 1647 int max_rows; 1648 1649 if (vs->client_pf.bytes_per_pixel == 4 && vs->client_pf.rmax == 0xFF && 1650 vs->client_pf.bmax == 0xFF && vs->client_pf.gmax == 0xFF) { | 1546 1547 if (split && (w > max_width || w * h > max_size)) { 1548 max_sub_width = (w > max_width) ? max_width : w; 1549 max_sub_height = max_size / max_sub_width; 1550 1551 for (dy = 0; dy < h; dy += max_sub_height) { 1552 for (dx = 0; dx < w; dx += max_width) { 1553 rw = MIN(max_sub_width, w - dx); --- 92 unchanged lines hidden (view full) --- 1646 1647static int tight_send_framebuffer_update(VncState *vs, int x, int y, 1648 int w, int h) 1649{ 1650 int max_rows; 1651 1652 if (vs->client_pf.bytes_per_pixel == 4 && vs->client_pf.rmax == 0xFF && 1653 vs->client_pf.bmax == 0xFF && vs->client_pf.gmax == 0xFF) { |
1651 vs->tight.pixel24 = true; | 1654 vs->tight->pixel24 = true; |
1652 } else { | 1655 } else { |
1653 vs->tight.pixel24 = false; | 1656 vs->tight->pixel24 = false; |
1654 } 1655 1656#ifdef CONFIG_VNC_JPEG | 1657 } 1658 1659#ifdef CONFIG_VNC_JPEG |
1657 if (vs->tight.quality != (uint8_t)-1) { | 1660 if (vs->tight->quality != (uint8_t)-1) { |
1658 double freq = vnc_update_freq(vs, x, y, w, h); 1659 | 1661 double freq = vnc_update_freq(vs, x, y, w, h); 1662 |
1660 if (freq > tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) { | 1663 if (freq > tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold) { |
1661 return send_rect_simple(vs, x, y, w, h, false); 1662 } 1663 } 1664#endif 1665 1666 if (w * h < VNC_TIGHT_MIN_SPLIT_RECT_SIZE) { 1667 return send_rect_simple(vs, x, y, w, h, true); 1668 } 1669 1670 /* Calculate maximum number of rows in one non-solid rectangle. */ 1671 | 1664 return send_rect_simple(vs, x, y, w, h, false); 1665 } 1666 } 1667#endif 1668 1669 if (w * h < VNC_TIGHT_MIN_SPLIT_RECT_SIZE) { 1670 return send_rect_simple(vs, x, y, w, h, true); 1671 } 1672 1673 /* Calculate maximum number of rows in one non-solid rectangle. */ 1674 |
1672 max_rows = tight_conf[vs->tight.compression].max_rect_size; 1673 max_rows /= MIN(tight_conf[vs->tight.compression].max_rect_width, w); | 1675 max_rows = tight_conf[vs->tight->compression].max_rect_size; 1676 max_rows /= MIN(tight_conf[vs->tight->compression].max_rect_width, w); |
1674 1675 return find_large_solid_color_rect(vs, x, y, w, h, max_rows); 1676} 1677 1678int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y, 1679 int w, int h) 1680{ | 1677 1678 return find_large_solid_color_rect(vs, x, y, w, h, max_rows); 1679} 1680 1681int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y, 1682 int w, int h) 1683{ |
1681 vs->tight.type = VNC_ENCODING_TIGHT; | 1684 vs->tight->type = VNC_ENCODING_TIGHT; |
1682 return tight_send_framebuffer_update(vs, x, y, w, h); 1683} 1684 1685int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y, 1686 int w, int h) 1687{ | 1685 return tight_send_framebuffer_update(vs, x, y, w, h); 1686} 1687 1688int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y, 1689 int w, int h) 1690{ |
1688 vs->tight.type = VNC_ENCODING_TIGHT_PNG; | 1691 vs->tight->type = VNC_ENCODING_TIGHT_PNG; |
1689 return tight_send_framebuffer_update(vs, x, y, w, h); 1690} 1691 1692void vnc_tight_clear(VncState *vs) 1693{ 1694 int i; | 1692 return tight_send_framebuffer_update(vs, x, y, w, h); 1693} 1694 1695void vnc_tight_clear(VncState *vs) 1696{ 1697 int i; |
1695 for (i=0; i<ARRAY_SIZE(vs->tight.stream); i++) { 1696 if (vs->tight.stream[i].opaque) { 1697 deflateEnd(&vs->tight.stream[i]); | 1698 for (i = 0; i < ARRAY_SIZE(vs->tight->stream); i++) { 1699 if (vs->tight->stream[i].opaque) { 1700 deflateEnd(&vs->tight->stream[i]); |
1698 } 1699 } 1700 | 1701 } 1702 } 1703 |
1701 buffer_free(&vs->tight.tight); 1702 buffer_free(&vs->tight.zlib); 1703 buffer_free(&vs->tight.gradient); | 1704 buffer_free(&vs->tight->tight); 1705 buffer_free(&vs->tight->zlib); 1706 buffer_free(&vs->tight->gradient); |
1704#ifdef CONFIG_VNC_JPEG | 1707#ifdef CONFIG_VNC_JPEG |
1705 buffer_free(&vs->tight.jpeg); | 1708 buffer_free(&vs->tight->jpeg); |
1706#endif 1707#ifdef CONFIG_VNC_PNG | 1709#endif 1710#ifdef CONFIG_VNC_PNG |
1708 buffer_free(&vs->tight.png); | 1711 buffer_free(&vs->tight->png); |
1709#endif 1710} | 1712#endif 1713} |