xref: /qemu/ui/vnc-enc-hextile-template.h (revision c152379422a204109f34ca2b43ecc538c7d738ae)
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