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