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