]> Git Repo - qemu.git/blob - vnchextile.h
vnc: hextile: do not generate ForegroundSpecified and SubrectsColoured tiles
[qemu.git] / vnchextile.h
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     VncDisplay *vd = vs->vd;
17     uint8_t *row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
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->clientds.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 += ds_get_linesize(vs->ds) / 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 += ds_get_linesize(vs->ds) / 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->clientds.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->clientds.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 += ds_get_linesize(vs->ds) / sizeof(pixel_t);
166         }
167
168         if (n_data > (w * h * sizeof(pixel_t))) {
169             n_colors = 4;
170             flags = 0x01;
171             *has_bg = 0;
172
173             /* we really don't have to invalidate either the bg or fg
174                but we've lost the old values.  oh well. */
175         }
176     default:
177         break;
178     }
179
180     if (n_colors > 3) {
181         flags = 0x01;
182         *has_fg = 0;
183         *has_bg = 0;
184         n_colors = 4;
185     }
186
187     vnc_write_u8(vs, flags);
188     if (n_colors < 4) {
189         if (flags & 0x02)
190             vs->write_pixels(vs, last_bg, sizeof(pixel_t));
191         if (flags & 0x04)
192             vs->write_pixels(vs, last_fg, sizeof(pixel_t));
193         if (n_subtiles) {
194             vnc_write_u8(vs, n_subtiles);
195             vnc_write(vs, data, n_data);
196         }
197     } else {
198         for (j = 0; j < h; j++) {
199             vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
200             row += ds_get_linesize(vs->ds);
201         }
202     }
203 }
204
205 #undef NAME
206 #undef pixel_t
207 #undef CONCAT_I
208 #undef CONCAT
This page took 0.038127 seconds and 4 git commands to generate.