Home | History | Annotate | Download | only in qemu
      1 #define CONCAT_I(a, b) a ## b
      2 #define CONCAT(a, b) CONCAT_I(a, b)
      3 #define pixel_t CONCAT(uint, CONCAT(BPP, _t))
      4 #ifdef GENERIC
      5 #define NAME CONCAT(generic_, BPP)
      6 #else
      7 #define NAME BPP
      8 #endif
      9 
     10 static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
     11                                              int x, int y, int w, int h,
     12                                              void *last_bg_,
     13                                              void *last_fg_,
     14                                              int *has_bg, int *has_fg)
     15 {
     16     uint8_t *row = vs->server.ds->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
     17     pixel_t *irow = (pixel_t *)row;
     18     int j, i;
     19     pixel_t *last_bg = (pixel_t *)last_bg_;
     20     pixel_t *last_fg = (pixel_t *)last_fg_;
     21     pixel_t bg = 0;
     22     pixel_t fg = 0;
     23     int n_colors = 0;
     24     int bg_count = 0;
     25     int fg_count = 0;
     26     int flags = 0;
     27     uint8_t data[(vs->clientds.pf.bytes_per_pixel + 2) * 16 * 16];
     28     int n_data = 0;
     29     int n_subtiles = 0;
     30 
     31     for (j = 0; j < h; j++) {
     32 	for (i = 0; i < w; i++) {
     33 	    switch (n_colors) {
     34 	    case 0:
     35 		bg = irow[i];
     36 		n_colors = 1;
     37 		break;
     38 	    case 1:
     39 		if (irow[i] != bg) {
     40 		    fg = irow[i];
     41 		    n_colors = 2;
     42 		}
     43 		break;
     44 	    case 2:
     45 		if (irow[i] != bg && irow[i] != fg) {
     46 		    n_colors = 3;
     47 		} else {
     48 		    if (irow[i] == bg)
     49 			bg_count++;
     50 		    else if (irow[i] == fg)
     51 			fg_count++;
     52 		}
     53 		break;
     54 	    default:
     55 		break;
     56 	    }
     57 	}
     58 	if (n_colors > 2)
     59 	    break;
     60 	irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
     61     }
     62 
     63     if (n_colors > 1 && fg_count > bg_count) {
     64 	pixel_t tmp = fg;
     65 	fg = bg;
     66 	bg = tmp;
     67     }
     68 
     69     if (!*has_bg || *last_bg != bg) {
     70 	flags |= 0x02;
     71 	*has_bg = 1;
     72 	*last_bg = bg;
     73     }
     74 
     75     if (n_colors < 3 && (!*has_fg || *last_fg != fg)) {
     76 	flags |= 0x04;
     77 	*has_fg = 1;
     78 	*last_fg = fg;
     79     }
     80 
     81     switch (n_colors) {
     82     case 1:
     83 	n_data = 0;
     84 	break;
     85     case 2:
     86 	flags |= 0x08;
     87 
     88 	irow = (pixel_t *)row;
     89 
     90 	for (j = 0; j < h; j++) {
     91 	    int min_x = -1;
     92 	    for (i = 0; i < w; i++) {
     93 		if (irow[i] == fg) {
     94 		    if (min_x == -1)
     95 			min_x = i;
     96 		} else if (min_x != -1) {
     97 		    hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
     98 		    n_data += 2;
     99 		    n_subtiles++;
    100 		    min_x = -1;
    101 		}
    102 	    }
    103 	    if (min_x != -1) {
    104 		hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
    105 		n_data += 2;
    106 		n_subtiles++;
    107 	    }
    108 	    irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
    109 	}
    110 	break;
    111     case 3:
    112 	flags |= 0x18;
    113 
    114 	irow = (pixel_t *)row;
    115 
    116 	if (!*has_bg || *last_bg != bg)
    117 	    flags |= 0x02;
    118 
    119 	for (j = 0; j < h; j++) {
    120 	    int has_color = 0;
    121 	    int min_x = -1;
    122 	    pixel_t color = 0; /* shut up gcc */
    123 
    124 	    for (i = 0; i < w; i++) {
    125 		if (!has_color) {
    126 		    if (irow[i] == bg)
    127 			continue;
    128 		    color = irow[i];
    129 		    min_x = i;
    130 		    has_color = 1;
    131 		} else if (irow[i] != color) {
    132 		    has_color = 0;
    133 #ifdef GENERIC
    134                     vnc_convert_pixel(vs, data + n_data, color);
    135                     n_data += vs->clientds.pf.bytes_per_pixel;
    136 #else
    137 		    memcpy(data + n_data, &color, sizeof(color));
    138                     n_data += sizeof(pixel_t);
    139 #endif
    140 		    hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
    141 		    n_data += 2;
    142 		    n_subtiles++;
    143 
    144 		    min_x = -1;
    145 		    if (irow[i] != bg) {
    146 			color = irow[i];
    147 			min_x = i;
    148 			has_color = 1;
    149 		    }
    150 		}
    151 	    }
    152 	    if (has_color) {
    153 #ifdef GENERIC
    154                 vnc_convert_pixel(vs, data + n_data, color);
    155                 n_data += vs->clientds.pf.bytes_per_pixel;
    156 #else
    157                 memcpy(data + n_data, &color, sizeof(color));
    158                 n_data += sizeof(pixel_t);
    159 #endif
    160 		hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
    161 		n_data += 2;
    162 		n_subtiles++;
    163 	    }
    164 	    irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
    165 	}
    166 
    167 	/* A SubrectsColoured subtile invalidates the foreground color */
    168 	*has_fg = 0;
    169 	if (n_data > (w * h * sizeof(pixel_t))) {
    170 	    n_colors = 4;
    171 	    flags = 0x01;
    172 	    *has_bg = 0;
    173 
    174 	    /* we really don't have to invalidate either the bg or fg
    175 	       but we've lost the old values.  oh well. */
    176 	}
    177     default:
    178 	break;
    179     }
    180 
    181     if (n_colors > 3) {
    182 	flags = 0x01;
    183 	*has_fg = 0;
    184 	*has_bg = 0;
    185 	n_colors = 4;
    186     }
    187 
    188     vnc_write_u8(vs, flags);
    189     if (n_colors < 4) {
    190 	if (flags & 0x02)
    191 	    vs->write_pixels(vs, last_bg, sizeof(pixel_t));
    192 	if (flags & 0x04)
    193 	    vs->write_pixels(vs, last_fg, sizeof(pixel_t));
    194 	if (n_subtiles) {
    195 	    vnc_write_u8(vs, n_subtiles);
    196 	    vnc_write(vs, data, n_data);
    197 	}
    198     } else {
    199 	for (j = 0; j < h; j++) {
    200 	    vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
    201 	    row += ds_get_linesize(vs->ds);
    202 	}
    203     }
    204 }
    205 
    206 #undef NAME
    207 #undef pixel_t
    208 #undef CONCAT_I
    209 #undef CONCAT
    210