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