Merge branch 'master' of /home/nchip/public_html/qemu into garage-push
[qemu] / 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     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 (!*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