xref: /qemu/ui/vnc-enc-hextile-template.h (revision 1fc624122fb923c7fc4c1f426541d953e7df13c9)
124236869Sbellard #define CONCAT_I(a, b) a ## b
224236869Sbellard #define CONCAT(a, b) CONCAT_I(a, b)
324236869Sbellard #define pixel_t CONCAT(uint, CONCAT(BPP, _t))
43512779aSbellard #ifdef GENERIC
57eac3a87Saliguori #define NAME CONCAT(generic_, BPP)
63512779aSbellard #else
73512779aSbellard #define NAME BPP
83512779aSbellard #endif
924236869Sbellard 
103512779aSbellard static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
1124236869Sbellard                                              int x, int y, int w, int h,
127eac3a87Saliguori                                              void *last_bg_,
137eac3a87Saliguori                                              void *last_fg_,
1424236869Sbellard                                              int *has_bg, int *has_fg)
1524236869Sbellard {
16*1fc62412SStefano Stabellini     VncDisplay *vd = vs->vd;
17*1fc62412SStefano Stabellini     uint8_t *row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
1824236869Sbellard     pixel_t *irow = (pixel_t *)row;
1924236869Sbellard     int j, i;
207eac3a87Saliguori     pixel_t *last_bg = (pixel_t *)last_bg_;
217eac3a87Saliguori     pixel_t *last_fg = (pixel_t *)last_fg_;
2224236869Sbellard     pixel_t bg = 0;
2324236869Sbellard     pixel_t fg = 0;
2424236869Sbellard     int n_colors = 0;
2524236869Sbellard     int bg_count = 0;
2624236869Sbellard     int fg_count = 0;
2724236869Sbellard     int flags = 0;
286cec5487Saliguori     uint8_t data[(vs->clientds.pf.bytes_per_pixel + 2) * 16 * 16];
2924236869Sbellard     int n_data = 0;
3024236869Sbellard     int n_subtiles = 0;
3124236869Sbellard 
3224236869Sbellard     for (j = 0; j < h; j++) {
3324236869Sbellard 	for (i = 0; i < w; i++) {
3424236869Sbellard 	    switch (n_colors) {
3524236869Sbellard 	    case 0:
3624236869Sbellard 		bg = irow[i];
3724236869Sbellard 		n_colors = 1;
3824236869Sbellard 		break;
3924236869Sbellard 	    case 1:
4024236869Sbellard 		if (irow[i] != bg) {
4124236869Sbellard 		    fg = irow[i];
4224236869Sbellard 		    n_colors = 2;
4324236869Sbellard 		}
4424236869Sbellard 		break;
4524236869Sbellard 	    case 2:
4624236869Sbellard 		if (irow[i] != bg && irow[i] != fg) {
4724236869Sbellard 		    n_colors = 3;
4824236869Sbellard 		} else {
4924236869Sbellard 		    if (irow[i] == bg)
5024236869Sbellard 			bg_count++;
5124236869Sbellard 		    else if (irow[i] == fg)
5224236869Sbellard 			fg_count++;
5324236869Sbellard 		}
5424236869Sbellard 		break;
5524236869Sbellard 	    default:
5624236869Sbellard 		break;
5724236869Sbellard 	    }
5824236869Sbellard 	}
5924236869Sbellard 	if (n_colors > 2)
6024236869Sbellard 	    break;
610e1f5a0cSaliguori 	irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
6224236869Sbellard     }
6324236869Sbellard 
6424236869Sbellard     if (n_colors > 1 && fg_count > bg_count) {
6524236869Sbellard 	pixel_t tmp = fg;
6624236869Sbellard 	fg = bg;
6724236869Sbellard 	bg = tmp;
6824236869Sbellard     }
6924236869Sbellard 
7024236869Sbellard     if (!*has_bg || *last_bg != bg) {
7124236869Sbellard 	flags |= 0x02;
7224236869Sbellard 	*has_bg = 1;
7324236869Sbellard 	*last_bg = bg;
7424236869Sbellard     }
7524236869Sbellard 
7624236869Sbellard     if (!*has_fg || *last_fg != fg) {
7724236869Sbellard 	flags |= 0x04;
7824236869Sbellard 	*has_fg = 1;
7924236869Sbellard 	*last_fg = fg;
8024236869Sbellard     }
8124236869Sbellard 
8224236869Sbellard     switch (n_colors) {
8324236869Sbellard     case 1:
8424236869Sbellard 	n_data = 0;
8524236869Sbellard 	break;
8624236869Sbellard     case 2:
8724236869Sbellard 	flags |= 0x08;
8824236869Sbellard 
8924236869Sbellard 	irow = (pixel_t *)row;
9024236869Sbellard 
9124236869Sbellard 	for (j = 0; j < h; j++) {
9224236869Sbellard 	    int min_x = -1;
9324236869Sbellard 	    for (i = 0; i < w; i++) {
9424236869Sbellard 		if (irow[i] == fg) {
9524236869Sbellard 		    if (min_x == -1)
9624236869Sbellard 			min_x = i;
9724236869Sbellard 		} else if (min_x != -1) {
9824236869Sbellard 		    hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
9924236869Sbellard 		    n_data += 2;
10024236869Sbellard 		    n_subtiles++;
10124236869Sbellard 		    min_x = -1;
10224236869Sbellard 		}
10324236869Sbellard 	    }
10424236869Sbellard 	    if (min_x != -1) {
10524236869Sbellard 		hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
10624236869Sbellard 		n_data += 2;
10724236869Sbellard 		n_subtiles++;
10824236869Sbellard 	    }
1090e1f5a0cSaliguori 	    irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
11024236869Sbellard 	}
11124236869Sbellard 	break;
11224236869Sbellard     case 3:
11324236869Sbellard 	flags |= 0x18;
11424236869Sbellard 
11524236869Sbellard 	irow = (pixel_t *)row;
11624236869Sbellard 
11724236869Sbellard 	if (!*has_bg || *last_bg != bg)
11824236869Sbellard 	    flags |= 0x02;
11924236869Sbellard 
12024236869Sbellard 	for (j = 0; j < h; j++) {
12124236869Sbellard 	    int has_color = 0;
12224236869Sbellard 	    int min_x = -1;
12392190c64Sths 	    pixel_t color = 0; /* shut up gcc */
12424236869Sbellard 
12524236869Sbellard 	    for (i = 0; i < w; i++) {
12624236869Sbellard 		if (!has_color) {
12724236869Sbellard 		    if (irow[i] == bg)
12824236869Sbellard 			continue;
12924236869Sbellard 		    color = irow[i];
13024236869Sbellard 		    min_x = i;
13124236869Sbellard 		    has_color = 1;
13224236869Sbellard 		} else if (irow[i] != color) {
13324236869Sbellard 		    has_color = 0;
1343512779aSbellard #ifdef GENERIC
1353512779aSbellard                     vnc_convert_pixel(vs, data + n_data, color);
1366cec5487Saliguori                     n_data += vs->clientds.pf.bytes_per_pixel;
1373512779aSbellard #else
13824236869Sbellard 		    memcpy(data + n_data, &color, sizeof(color));
1393512779aSbellard                     n_data += sizeof(pixel_t);
1403512779aSbellard #endif
1413512779aSbellard 		    hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
1423512779aSbellard 		    n_data += 2;
14324236869Sbellard 		    n_subtiles++;
14424236869Sbellard 
14524236869Sbellard 		    min_x = -1;
14624236869Sbellard 		    if (irow[i] != bg) {
14724236869Sbellard 			color = irow[i];
14824236869Sbellard 			min_x = i;
14924236869Sbellard 			has_color = 1;
15024236869Sbellard 		    }
15124236869Sbellard 		}
15224236869Sbellard 	    }
15324236869Sbellard 	    if (has_color) {
1543512779aSbellard #ifdef GENERIC
1553512779aSbellard                 vnc_convert_pixel(vs, data + n_data, color);
1566cec5487Saliguori                 n_data += vs->clientds.pf.bytes_per_pixel;
1573512779aSbellard #else
15824236869Sbellard                 memcpy(data + n_data, &color, sizeof(color));
1593512779aSbellard                 n_data += sizeof(pixel_t);
1603512779aSbellard #endif
1613512779aSbellard 		hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
1623512779aSbellard 		n_data += 2;
16324236869Sbellard 		n_subtiles++;
16424236869Sbellard 	    }
1650e1f5a0cSaliguori 	    irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
16624236869Sbellard 	}
16724236869Sbellard 
16824236869Sbellard 	/* A SubrectsColoured subtile invalidates the foreground color */
16924236869Sbellard 	*has_fg = 0;
17024236869Sbellard 	if (n_data > (w * h * sizeof(pixel_t))) {
17124236869Sbellard 	    n_colors = 4;
17224236869Sbellard 	    flags = 0x01;
17324236869Sbellard 	    *has_bg = 0;
17424236869Sbellard 
17524236869Sbellard 	    /* we really don't have to invalidate either the bg or fg
17624236869Sbellard 	       but we've lost the old values.  oh well. */
17724236869Sbellard 	}
17824236869Sbellard     default:
17924236869Sbellard 	break;
18024236869Sbellard     }
18124236869Sbellard 
18224236869Sbellard     if (n_colors > 3) {
18324236869Sbellard 	flags = 0x01;
18424236869Sbellard 	*has_fg = 0;
18524236869Sbellard 	*has_bg = 0;
18624236869Sbellard 	n_colors = 4;
18724236869Sbellard     }
18824236869Sbellard 
18924236869Sbellard     vnc_write_u8(vs, flags);
19024236869Sbellard     if (n_colors < 4) {
19124236869Sbellard 	if (flags & 0x02)
1923512779aSbellard 	    vs->write_pixels(vs, last_bg, sizeof(pixel_t));
19324236869Sbellard 	if (flags & 0x04)
1943512779aSbellard 	    vs->write_pixels(vs, last_fg, sizeof(pixel_t));
19524236869Sbellard 	if (n_subtiles) {
19624236869Sbellard 	    vnc_write_u8(vs, n_subtiles);
19724236869Sbellard 	    vnc_write(vs, data, n_data);
19824236869Sbellard 	}
19924236869Sbellard     } else {
20024236869Sbellard 	for (j = 0; j < h; j++) {
2016cec5487Saliguori 	    vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
2020e1f5a0cSaliguori 	    row += ds_get_linesize(vs->ds);
20324236869Sbellard 	}
20424236869Sbellard     }
20524236869Sbellard }
20624236869Sbellard 
2073512779aSbellard #undef NAME
20824236869Sbellard #undef pixel_t
20924236869Sbellard #undef CONCAT_I
21024236869Sbellard #undef CONCAT
211