mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 04:06:46 +00:00 
			
		
		
		
	 b86d01ba47
			
		
	
	
		b86d01ba47
		
	
	
	
	
		
			
			Suggested-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
		
			
				
	
	
		
			212 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #define CONCAT_I(a, b) a ## b
 | |
| #define CONCAT(a, b) CONCAT_I(a, b)
 | |
| #define pixel_t CONCAT(uint, CONCAT(BPP, _t))
 | |
| #ifdef GENERIC
 | |
| #define NAME CONCAT(generic_, BPP)
 | |
| #else
 | |
| #define NAME BPP
 | |
| #endif
 | |
| 
 | |
| static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
 | |
|                                              int x, int y, int w, int h,
 | |
|                                              void *last_bg_,
 | |
|                                              void *last_fg_,
 | |
|                                              int *has_bg, int *has_fg)
 | |
| {
 | |
|     VncDisplay *vd = vs->vd;
 | |
|     uint8_t *row = vnc_server_fb_ptr(vd, x, y);
 | |
|     pixel_t *irow = (pixel_t *)row;
 | |
|     int j, i;
 | |
|     pixel_t *last_bg = (pixel_t *)last_bg_;
 | |
|     pixel_t *last_fg = (pixel_t *)last_fg_;
 | |
|     pixel_t bg = 0;
 | |
|     pixel_t fg = 0;
 | |
|     int n_colors = 0;
 | |
|     int bg_count = 0;
 | |
|     int fg_count = 0;
 | |
|     int flags = 0;
 | |
|     uint8_t data[(vs->client_pf.bytes_per_pixel + 2) * 16 * 16];
 | |
|     int n_data = 0;
 | |
|     int n_subtiles = 0;
 | |
| 
 | |
|     for (j = 0; j < h; j++) {
 | |
|         for (i = 0; i < w; i++) {
 | |
|             switch (n_colors) {
 | |
|             case 0:
 | |
|                 bg = irow[i];
 | |
|                 n_colors = 1;
 | |
|                 break;
 | |
|             case 1:
 | |
|                 if (irow[i] != bg) {
 | |
|                     fg = irow[i];
 | |
|                     n_colors = 2;
 | |
|                 }
 | |
|                 break;
 | |
|             case 2:
 | |
|                 if (irow[i] != bg && irow[i] != fg) {
 | |
|                     n_colors = 3;
 | |
|                 } else {
 | |
|                     if (irow[i] == bg)
 | |
|                         bg_count++;
 | |
|                     else if (irow[i] == fg)
 | |
|                         fg_count++;
 | |
|                 }
 | |
|                 break;
 | |
|             default:
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         if (n_colors > 2)
 | |
|             break;
 | |
|         irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
 | |
|     }
 | |
| 
 | |
|     if (n_colors > 1 && fg_count > bg_count) {
 | |
|         pixel_t tmp = fg;
 | |
|         fg = bg;
 | |
|         bg = tmp;
 | |
|     }
 | |
| 
 | |
|     if (!*has_bg || *last_bg != bg) {
 | |
|         flags |= 0x02;
 | |
|         *has_bg = 1;
 | |
|         *last_bg = bg;
 | |
|     }
 | |
| 
 | |
|     if (n_colors < 3 && (!*has_fg || *last_fg != fg)) {
 | |
|         flags |= 0x04;
 | |
|         *has_fg = 1;
 | |
|         *last_fg = fg;
 | |
|     }
 | |
| 
 | |
|     switch (n_colors) {
 | |
|     case 1:
 | |
|         n_data = 0;
 | |
|         break;
 | |
|     case 2:
 | |
|         flags |= 0x08;
 | |
| 
 | |
|         irow = (pixel_t *)row;
 | |
| 
 | |
|         for (j = 0; j < h; j++) {
 | |
|             int min_x = -1;
 | |
|             for (i = 0; i < w; i++) {
 | |
|                 if (irow[i] == fg) {
 | |
|                     if (min_x == -1)
 | |
|                         min_x = i;
 | |
|                 } else if (min_x != -1) {
 | |
|                     hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
 | |
|                     n_data += 2;
 | |
|                     n_subtiles++;
 | |
|                     min_x = -1;
 | |
|                 }
 | |
|             }
 | |
|             if (min_x != -1) {
 | |
|                 hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
 | |
|                 n_data += 2;
 | |
|                 n_subtiles++;
 | |
|             }
 | |
|             irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
 | |
|         }
 | |
|         break;
 | |
|     case 3:
 | |
|         flags |= 0x18;
 | |
| 
 | |
|         irow = (pixel_t *)row;
 | |
| 
 | |
|         if (!*has_bg || *last_bg != bg)
 | |
|             flags |= 0x02;
 | |
| 
 | |
|         for (j = 0; j < h; j++) {
 | |
|             int has_color = 0;
 | |
|             int min_x = -1;
 | |
|             pixel_t color = 0; /* shut up gcc */
 | |
| 
 | |
|             for (i = 0; i < w; i++) {
 | |
|                 if (!has_color) {
 | |
|                     if (irow[i] == bg)
 | |
|                         continue;
 | |
|                     color = irow[i];
 | |
|                     min_x = i;
 | |
|                     has_color = 1;
 | |
|                 } else if (irow[i] != color) {
 | |
|                     has_color = 0;
 | |
| #ifdef GENERIC
 | |
|                     vnc_convert_pixel(vs, data + n_data, color);
 | |
|                     n_data += vs->client_pf.bytes_per_pixel;
 | |
| #else
 | |
|                     memcpy(data + n_data, &color, sizeof(color));
 | |
|                     n_data += sizeof(pixel_t);
 | |
| #endif
 | |
|                     hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
 | |
|                     n_data += 2;
 | |
|                     n_subtiles++;
 | |
| 
 | |
|                     min_x = -1;
 | |
|                     if (irow[i] != bg) {
 | |
|                         color = irow[i];
 | |
|                         min_x = i;
 | |
|                         has_color = 1;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             if (has_color) {
 | |
| #ifdef GENERIC
 | |
|                 vnc_convert_pixel(vs, data + n_data, color);
 | |
|                 n_data += vs->client_pf.bytes_per_pixel;
 | |
| #else
 | |
|                 memcpy(data + n_data, &color, sizeof(color));
 | |
|                 n_data += sizeof(pixel_t);
 | |
| #endif
 | |
|                 hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
 | |
|                 n_data += 2;
 | |
|                 n_subtiles++;
 | |
|             }
 | |
|             irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
 | |
|         }
 | |
| 
 | |
|         /* A SubrectsColoured subtile invalidates the foreground color */
 | |
|         *has_fg = 0;
 | |
|         if (n_data > (w * h * sizeof(pixel_t))) {
 | |
|             n_colors = 4;
 | |
|             flags = 0x01;
 | |
|             *has_bg = 0;
 | |
| 
 | |
|             /* we really don't have to invalidate either the bg or fg
 | |
|                but we've lost the old values.  oh well. */
 | |
|         }
 | |
|         break;
 | |
|     default:
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     if (n_colors > 3) {
 | |
|         flags = 0x01;
 | |
|         *has_fg = 0;
 | |
|         *has_bg = 0;
 | |
|         n_colors = 4;
 | |
|     }
 | |
| 
 | |
|     vnc_write_u8(vs, flags);
 | |
|     if (n_colors < 4) {
 | |
|         if (flags & 0x02)
 | |
|             vs->write_pixels(vs, last_bg, sizeof(pixel_t));
 | |
|         if (flags & 0x04)
 | |
|             vs->write_pixels(vs, last_fg, sizeof(pixel_t));
 | |
|         if (n_subtiles) {
 | |
|             vnc_write_u8(vs, n_subtiles);
 | |
|             vnc_write(vs, data, n_data);
 | |
|         }
 | |
|     } else {
 | |
|         for (j = 0; j < h; j++) {
 | |
|             vs->write_pixels(vs, row, w * 4);
 | |
|             row += vnc_server_fb_stride(vd);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| #undef NAME
 | |
| #undef pixel_t
 | |
| #undef CONCAT_I
 | |
| #undef CONCAT
 |