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