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
10*e12acaf7SPeter Maydell #define MAX_BYTES_PER_PIXEL 4
11*e12acaf7SPeter Maydell
CONCAT(send_hextile_tile_,NAME)123512779aSbellard static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
1324236869Sbellard int x, int y, int w, int h,
147eac3a87Saliguori void *last_bg_,
157eac3a87Saliguori void *last_fg_,
1624236869Sbellard int *has_bg, int *has_fg)
1724236869Sbellard {
181fc62412SStefano Stabellini VncDisplay *vd = vs->vd;
199f64916dSGerd Hoffmann uint8_t *row = vnc_server_fb_ptr(vd, x, y);
2024236869Sbellard pixel_t *irow = (pixel_t *)row;
2124236869Sbellard int j, i;
227eac3a87Saliguori pixel_t *last_bg = (pixel_t *)last_bg_;
237eac3a87Saliguori pixel_t *last_fg = (pixel_t *)last_fg_;
2424236869Sbellard pixel_t bg = 0;
2524236869Sbellard pixel_t fg = 0;
2624236869Sbellard int n_colors = 0;
2724236869Sbellard int bg_count = 0;
2824236869Sbellard int fg_count = 0;
2924236869Sbellard int flags = 0;
30*e12acaf7SPeter Maydell uint8_t data[(MAX_BYTES_PER_PIXEL + 2) * 16 * 16];
3124236869Sbellard int n_data = 0;
3224236869Sbellard int n_subtiles = 0;
3324236869Sbellard
34*e12acaf7SPeter Maydell /* Enforced by set_pixel_format() */
35*e12acaf7SPeter Maydell assert(vs->client_pf.bytes_per_pixel <= MAX_BYTES_PER_PIXEL);
36*e12acaf7SPeter Maydell
3724236869Sbellard for (j = 0; j < h; j++) {
3824236869Sbellard for (i = 0; i < w; i++) {
3924236869Sbellard switch (n_colors) {
4024236869Sbellard case 0:
4124236869Sbellard bg = irow[i];
4224236869Sbellard n_colors = 1;
4324236869Sbellard break;
4424236869Sbellard case 1:
4524236869Sbellard if (irow[i] != bg) {
4624236869Sbellard fg = irow[i];
4724236869Sbellard n_colors = 2;
4824236869Sbellard }
4924236869Sbellard break;
5024236869Sbellard case 2:
5124236869Sbellard if (irow[i] != bg && irow[i] != fg) {
5224236869Sbellard n_colors = 3;
5324236869Sbellard } else {
5424236869Sbellard if (irow[i] == bg)
5524236869Sbellard bg_count++;
5624236869Sbellard else if (irow[i] == fg)
5724236869Sbellard fg_count++;
5824236869Sbellard }
5924236869Sbellard break;
6024236869Sbellard default:
6124236869Sbellard break;
6224236869Sbellard }
6324236869Sbellard }
6424236869Sbellard if (n_colors > 2)
6524236869Sbellard break;
669f64916dSGerd Hoffmann irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
6724236869Sbellard }
6824236869Sbellard
6924236869Sbellard if (n_colors > 1 && fg_count > bg_count) {
7024236869Sbellard pixel_t tmp = fg;
7124236869Sbellard fg = bg;
7224236869Sbellard bg = tmp;
7324236869Sbellard }
7424236869Sbellard
7524236869Sbellard if (!*has_bg || *last_bg != bg) {
7624236869Sbellard flags |= 0x02;
7724236869Sbellard *has_bg = 1;
7824236869Sbellard *last_bg = bg;
7924236869Sbellard }
8024236869Sbellard
8102c2b87fSAnthony Liguori if (n_colors < 3 && (!*has_fg || *last_fg != fg)) {
8224236869Sbellard flags |= 0x04;
8324236869Sbellard *has_fg = 1;
8424236869Sbellard *last_fg = fg;
8524236869Sbellard }
8624236869Sbellard
8724236869Sbellard switch (n_colors) {
8824236869Sbellard case 1:
8924236869Sbellard n_data = 0;
9024236869Sbellard break;
9124236869Sbellard case 2:
9224236869Sbellard flags |= 0x08;
9324236869Sbellard
9424236869Sbellard irow = (pixel_t *)row;
9524236869Sbellard
9624236869Sbellard for (j = 0; j < h; j++) {
9724236869Sbellard int min_x = -1;
9824236869Sbellard for (i = 0; i < w; i++) {
9924236869Sbellard if (irow[i] == fg) {
10024236869Sbellard if (min_x == -1)
10124236869Sbellard min_x = i;
10224236869Sbellard } else if (min_x != -1) {
10324236869Sbellard hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
10424236869Sbellard n_data += 2;
10524236869Sbellard n_subtiles++;
10624236869Sbellard min_x = -1;
10724236869Sbellard }
10824236869Sbellard }
10924236869Sbellard if (min_x != -1) {
11024236869Sbellard hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
11124236869Sbellard n_data += 2;
11224236869Sbellard n_subtiles++;
11324236869Sbellard }
1149f64916dSGerd Hoffmann irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
11524236869Sbellard }
11624236869Sbellard break;
11724236869Sbellard case 3:
11824236869Sbellard flags |= 0x18;
11924236869Sbellard
12024236869Sbellard irow = (pixel_t *)row;
12124236869Sbellard
12224236869Sbellard if (!*has_bg || *last_bg != bg)
12324236869Sbellard flags |= 0x02;
12424236869Sbellard
12524236869Sbellard for (j = 0; j < h; j++) {
12624236869Sbellard int has_color = 0;
12724236869Sbellard int min_x = -1;
12892190c64Sths pixel_t color = 0; /* shut up gcc */
12924236869Sbellard
13024236869Sbellard for (i = 0; i < w; i++) {
13124236869Sbellard if (!has_color) {
13224236869Sbellard if (irow[i] == bg)
13324236869Sbellard continue;
13424236869Sbellard color = irow[i];
13524236869Sbellard min_x = i;
13624236869Sbellard has_color = 1;
13724236869Sbellard } else if (irow[i] != color) {
13824236869Sbellard has_color = 0;
1393512779aSbellard #ifdef GENERIC
1403512779aSbellard vnc_convert_pixel(vs, data + n_data, color);
1419f64916dSGerd Hoffmann n_data += vs->client_pf.bytes_per_pixel;
1423512779aSbellard #else
14324236869Sbellard memcpy(data + n_data, &color, sizeof(color));
1443512779aSbellard n_data += sizeof(pixel_t);
1453512779aSbellard #endif
1463512779aSbellard hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
1473512779aSbellard n_data += 2;
14824236869Sbellard n_subtiles++;
14924236869Sbellard
15024236869Sbellard min_x = -1;
15124236869Sbellard if (irow[i] != bg) {
15224236869Sbellard color = irow[i];
15324236869Sbellard min_x = i;
15424236869Sbellard has_color = 1;
15524236869Sbellard }
15624236869Sbellard }
15724236869Sbellard }
15824236869Sbellard if (has_color) {
1593512779aSbellard #ifdef GENERIC
1603512779aSbellard vnc_convert_pixel(vs, data + n_data, color);
1619f64916dSGerd Hoffmann n_data += vs->client_pf.bytes_per_pixel;
1623512779aSbellard #else
16324236869Sbellard memcpy(data + n_data, &color, sizeof(color));
1643512779aSbellard n_data += sizeof(pixel_t);
1653512779aSbellard #endif
1663512779aSbellard hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
1673512779aSbellard n_data += 2;
16824236869Sbellard n_subtiles++;
16924236869Sbellard }
1709f64916dSGerd Hoffmann irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
17124236869Sbellard }
17224236869Sbellard
17318cb1d85SAnthony Liguori /* A SubrectsColoured subtile invalidates the foreground color */
17418cb1d85SAnthony Liguori *has_fg = 0;
17524236869Sbellard if (n_data > (w * h * sizeof(pixel_t))) {
17624236869Sbellard n_colors = 4;
17724236869Sbellard flags = 0x01;
17824236869Sbellard *has_bg = 0;
17924236869Sbellard
18024236869Sbellard /* we really don't have to invalidate either the bg or fg
18124236869Sbellard but we've lost the old values. oh well. */
18224236869Sbellard }
1830ea5c0cdSStefan Weil break;
18424236869Sbellard default:
18524236869Sbellard break;
18624236869Sbellard }
18724236869Sbellard
18824236869Sbellard if (n_colors > 3) {
18924236869Sbellard flags = 0x01;
19024236869Sbellard *has_fg = 0;
19124236869Sbellard *has_bg = 0;
19224236869Sbellard n_colors = 4;
19324236869Sbellard }
19424236869Sbellard
19524236869Sbellard vnc_write_u8(vs, flags);
19624236869Sbellard if (n_colors < 4) {
19724236869Sbellard if (flags & 0x02)
1989f64916dSGerd Hoffmann vs->write_pixels(vs, last_bg, sizeof(pixel_t));
19924236869Sbellard if (flags & 0x04)
2009f64916dSGerd Hoffmann vs->write_pixels(vs, last_fg, sizeof(pixel_t));
20124236869Sbellard if (n_subtiles) {
20224236869Sbellard vnc_write_u8(vs, n_subtiles);
20324236869Sbellard vnc_write(vs, data, n_data);
20424236869Sbellard }
20524236869Sbellard } else {
20624236869Sbellard for (j = 0; j < h; j++) {
2079f64916dSGerd Hoffmann vs->write_pixels(vs, row, w * 4);
2089f64916dSGerd Hoffmann row += vnc_server_fb_stride(vd);
20924236869Sbellard }
21024236869Sbellard }
21124236869Sbellard }
21224236869Sbellard
213*e12acaf7SPeter Maydell #undef MAX_BYTES_PER_PIXEL
2143512779aSbellard #undef NAME
21524236869Sbellard #undef pixel_t
21624236869Sbellard #undef CONCAT_I
21724236869Sbellard #undef CONCAT
218