spelling fixes
[qemu] / hw / vga_template.h
1 /*
2  * QEMU VGA Emulator templates
3  * 
4  * Copyright (c) 2003 Fabrice Bellard
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #if DEPTH == 8
26 #define BPP 1
27 #define PIXEL_TYPE uint8_t 
28 #elif DEPTH == 15 || DEPTH == 16
29 #define BPP 2
30 #define PIXEL_TYPE uint16_t 
31 #elif DEPTH == 32
32 #define BPP 4
33 #define PIXEL_TYPE uint32_t 
34 #else
35 #error unsupport depth
36 #endif
37
38 #if DEPTH != 15
39
40 static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d, 
41                                                      uint32_t font_data,
42                                                      uint32_t xorcol, 
43                                                      uint32_t bgcol)
44 {
45 #if BPP == 1
46         ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
47         ((uint32_t *)d)[3] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
48 #elif BPP == 2
49         ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
50         ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
51         ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
52         ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
53 #else
54         ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
55         ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
56         ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
57         ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
58         ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
59         ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
60         ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
61         ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
62 #endif
63 }
64
65 static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
66                                           const uint8_t *font_ptr, int h,
67                                           uint32_t fgcol, uint32_t bgcol)
68 {
69     uint32_t font_data, xorcol;
70     
71     xorcol = bgcol ^ fgcol;
72     do {
73         font_data = font_ptr[0];
74         glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
75         font_ptr += 4;
76         d += linesize;
77     } while (--h);
78 }
79
80 static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
81                                           const uint8_t *font_ptr, int h,
82                                           uint32_t fgcol, uint32_t bgcol)
83 {
84     uint32_t font_data, xorcol;
85     
86     xorcol = bgcol ^ fgcol;
87     do {
88         font_data = font_ptr[0];
89         glue(vga_draw_glyph_line_, DEPTH)(d, 
90                                           expand4to8[font_data >> 4], 
91                                           xorcol, bgcol);
92         glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP, 
93                                           expand4to8[font_data & 0x0f], 
94                                           xorcol, bgcol);
95         font_ptr += 4;
96         d += linesize;
97     } while (--h);
98 }
99
100 static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
101                                           const uint8_t *font_ptr, int h, 
102                                           uint32_t fgcol, uint32_t bgcol, int dup9)
103 {
104     uint32_t font_data, xorcol, v;
105     
106     xorcol = bgcol ^ fgcol;
107     do {
108         font_data = font_ptr[0];
109         /* XXX: unaligned accesses are done */
110 #if BPP == 1
111         ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
112         v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
113         ((uint32_t *)d)[3] = v;
114         if (dup9)
115             ((uint8_t *)d)[8] = v >> (24 * (1 - BIG));
116         else
117             ((uint8_t *)d)[8] = bgcol;
118         
119 #elif BPP == 2
120         ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
121         ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
122         ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
123         v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
124         ((uint32_t *)d)[3] = v;
125         if (dup9)
126             ((uint16_t *)d)[8] = v >> (16 * (1 - BIG));
127         else
128             ((uint16_t *)d)[8] = bgcol;
129 #else
130         ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
131         ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
132         ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
133         ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
134         ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
135         ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
136         ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
137         v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
138         ((uint32_t *)d)[7] = v;
139         if (dup9)
140             ((uint32_t *)d)[8] = v;
141         else
142             ((uint32_t *)d)[8] = bgcol;
143 #endif
144         font_ptr += 4;
145         d += linesize;
146     } while (--h);
147 }
148
149 /* 
150  * 4 color mode
151  */
152 static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d, 
153                                          const uint8_t *s, int width)
154 {
155     uint32_t plane_mask, *palette, data, v;
156     int x;
157
158     palette = s1->last_palette;
159     plane_mask = mask16[s1->ar[0x12] & 0xf];
160     width >>= 3;
161     for(x = 0; x < width; x++) {
162         data = ((uint32_t *)s)[0];
163         data &= plane_mask;
164         v = expand2[GET_PLANE(data, 0)];
165         v |= expand2[GET_PLANE(data, 2)] << 2;
166         ((PIXEL_TYPE *)d)[0] = palette[v >> 12];
167         ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf];
168         ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf];
169         ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf];
170
171         v = expand2[GET_PLANE(data, 1)];
172         v |= expand2[GET_PLANE(data, 3)] << 2;
173         ((PIXEL_TYPE *)d)[4] = palette[v >> 12];
174         ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
175         ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
176         ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
177         d += BPP * 8;
178         s += 4;
179     }
180 }
181
182 #if BPP == 1
183 #define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
184 #elif BPP == 2
185 #define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
186 #else
187 #define PUT_PIXEL2(d, n, v) \
188 ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
189 #endif
190
191 /* 
192  * 4 color mode, dup2 horizontal
193  */
194 static void glue(vga_draw_line2d2_, DEPTH)(VGAState *s1, uint8_t *d, 
195                                            const uint8_t *s, int width)
196 {
197     uint32_t plane_mask, *palette, data, v;
198     int x;
199
200     palette = s1->last_palette;
201     plane_mask = mask16[s1->ar[0x12] & 0xf];
202     width >>= 3;
203     for(x = 0; x < width; x++) {
204         data = ((uint32_t *)s)[0];
205         data &= plane_mask;
206         v = expand2[GET_PLANE(data, 0)];
207         v |= expand2[GET_PLANE(data, 2)] << 2;
208         PUT_PIXEL2(d, 0, palette[v >> 12]);
209         PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
210         PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
211         PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
212
213         v = expand2[GET_PLANE(data, 1)];
214         v |= expand2[GET_PLANE(data, 3)] << 2;
215         PUT_PIXEL2(d, 4, palette[v >> 12]);
216         PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
217         PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
218         PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
219         d += BPP * 16;
220         s += 4;
221     }
222 }
223
224 /* 
225  * 16 color mode
226  */
227 static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d, 
228                                          const uint8_t *s, int width)
229 {
230     uint32_t plane_mask, data, v, *palette;
231     int x;
232
233     palette = s1->last_palette;
234     plane_mask = mask16[s1->ar[0x12] & 0xf];
235     width >>= 3;
236     for(x = 0; x < width; x++) {
237         data = ((uint32_t *)s)[0];
238         data &= plane_mask;
239         v = expand4[GET_PLANE(data, 0)];
240         v |= expand4[GET_PLANE(data, 1)] << 1;
241         v |= expand4[GET_PLANE(data, 2)] << 2;
242         v |= expand4[GET_PLANE(data, 3)] << 3;
243         ((PIXEL_TYPE *)d)[0] = palette[v >> 28];
244         ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf];
245         ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf];
246         ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf];
247         ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf];
248         ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
249         ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
250         ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
251         d += BPP * 8;
252         s += 4;
253     }
254 }
255
256 /* 
257  * 16 color mode, dup2 horizontal
258  */
259 static void glue(vga_draw_line4d2_, DEPTH)(VGAState *s1, uint8_t *d, 
260                                            const uint8_t *s, int width)
261 {
262     uint32_t plane_mask, data, v, *palette;
263     int x;
264
265     palette = s1->last_palette;
266     plane_mask = mask16[s1->ar[0x12] & 0xf];
267     width >>= 3;
268     for(x = 0; x < width; x++) {
269         data = ((uint32_t *)s)[0];
270         data &= plane_mask;
271         v = expand4[GET_PLANE(data, 0)];
272         v |= expand4[GET_PLANE(data, 1)] << 1;
273         v |= expand4[GET_PLANE(data, 2)] << 2;
274         v |= expand4[GET_PLANE(data, 3)] << 3;
275         PUT_PIXEL2(d, 0, palette[v >> 28]);
276         PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
277         PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
278         PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
279         PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
280         PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
281         PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
282         PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
283         d += BPP * 16;
284         s += 4;
285     }
286 }
287
288 /* 
289  * 256 color mode, double pixels
290  *
291  * XXX: add plane_mask support (never used in standard VGA modes)
292  */
293 static void glue(vga_draw_line8d2_, DEPTH)(VGAState *s1, uint8_t *d, 
294                                            const uint8_t *s, int width)
295 {
296     uint32_t *palette;
297     int x;
298
299     palette = s1->last_palette;
300     width >>= 3;
301     for(x = 0; x < width; x++) {
302         PUT_PIXEL2(d, 0, palette[s[0]]);
303         PUT_PIXEL2(d, 1, palette[s[1]]);
304         PUT_PIXEL2(d, 2, palette[s[2]]);
305         PUT_PIXEL2(d, 3, palette[s[3]]);
306         d += BPP * 8;
307         s += 4;
308     }
309 }
310
311 /* 
312  * standard 256 color mode
313  *
314  * XXX: add plane_mask support (never used in standard VGA modes)
315  */
316 static void glue(vga_draw_line8_, DEPTH)(VGAState *s1, uint8_t *d, 
317                                          const uint8_t *s, int width)
318 {
319     uint32_t *palette;
320     int x;
321
322     palette = s1->last_palette;
323     width >>= 3;
324     for(x = 0; x < width; x++) {
325         ((PIXEL_TYPE *)d)[0] = palette[s[0]];
326         ((PIXEL_TYPE *)d)[1] = palette[s[1]];
327         ((PIXEL_TYPE *)d)[2] = palette[s[2]];
328         ((PIXEL_TYPE *)d)[3] = palette[s[3]];
329         ((PIXEL_TYPE *)d)[4] = palette[s[4]];
330         ((PIXEL_TYPE *)d)[5] = palette[s[5]];
331         ((PIXEL_TYPE *)d)[6] = palette[s[6]];
332         ((PIXEL_TYPE *)d)[7] = palette[s[7]];
333         d += BPP * 8;
334         s += 8;
335     }
336 }
337
338 #endif /* DEPTH != 15 */
339
340
341 /* XXX: optimize */
342
343 /* 
344  * 15 bit color
345  */
346 static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d, 
347                                           const uint8_t *s, int width)
348 {
349 #if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
350     memcpy(d, s, width * 2);
351 #else
352     int w;
353     uint32_t v, r, g, b;
354
355     w = width;
356     do {
357         v = lduw_raw((void *)s);
358         r = (v >> 7) & 0xf8;
359         g = (v >> 2) & 0xf8;
360         b = (v << 3) & 0xf8;
361         ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
362         s += 2;
363         d += BPP;
364     } while (--w != 0);
365 #endif    
366 }
367
368 /* 
369  * 16 bit color
370  */
371 static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d, 
372                                           const uint8_t *s, int width)
373 {
374 #if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
375     memcpy(d, s, width * 2);
376 #else
377     int w;
378     uint32_t v, r, g, b;
379
380     w = width;
381     do {
382         v = lduw_raw((void *)s);
383         r = (v >> 8) & 0xf8;
384         g = (v >> 3) & 0xfc;
385         b = (v << 3) & 0xf8;
386         ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
387         s += 2;
388         d += BPP;
389     } while (--w != 0);
390 #endif    
391 }
392
393 /* 
394  * 24 bit color
395  */
396 static void glue(vga_draw_line24_, DEPTH)(VGAState *s1, uint8_t *d, 
397                                           const uint8_t *s, int width)
398 {
399     int w;
400     uint32_t r, g, b;
401
402     w = width;
403     do {
404 #if defined(TARGET_WORDS_BIGENDIAN)
405         r = s[0];
406         g = s[1];
407         b = s[2];
408 #else
409         b = s[0];
410         g = s[1];
411         r = s[2];
412 #endif
413         ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
414         s += 3;
415         d += BPP;
416     } while (--w != 0);
417 }
418
419 /* 
420  * 32 bit color
421  */
422 static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d, 
423                                           const uint8_t *s, int width)
424 {
425 #if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
426     memcpy(d, s, width * 4);
427 #else
428     int w;
429     uint32_t r, g, b;
430
431     w = width;
432     do {
433 #if defined(TARGET_WORDS_BIGENDIAN)
434         r = s[1];
435         g = s[2];
436         b = s[3];
437 #else
438         b = s[0];
439         g = s[1];
440         r = s[2];
441 #endif
442         ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
443         s += 4;
444         d += BPP;
445     } while (--w != 0);
446 #endif
447 }
448
449 #if DEPTH != 15
450 void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1, 
451                                         const uint8_t *src1, 
452                                         int poffset, int w,
453                                         unsigned int color0, 
454                                         unsigned int color1,
455                                         unsigned int color_xor)
456 {
457     const uint8_t *plane0, *plane1;
458     int x, b0, b1;
459     uint8_t *d;
460
461     d = d1;
462     plane0 = src1;
463     plane1 = src1 + poffset;
464     for(x = 0; x < w; x++) {
465         b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
466         b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
467 #if DEPTH == 8
468         switch(b0 | (b1 << 1)) {
469         case 0:
470             break;
471         case 1:
472             d[0] ^= color_xor;
473             break;
474         case 2:
475             d[0] = color0;
476             break;
477         case 3:
478             d[0] = color1;
479             break;
480         }
481 #elif DEPTH == 16
482         switch(b0 | (b1 << 1)) {
483         case 0:
484             break;
485         case 1:
486             ((uint16_t *)d)[0] ^= color_xor;
487             break;
488         case 2:
489             ((uint16_t *)d)[0] = color0;
490             break;
491         case 3:
492             ((uint16_t *)d)[0] = color1;
493             break;
494         }
495 #elif DEPTH == 32
496         switch(b0 | (b1 << 1)) {
497         case 0:
498             break;
499         case 1:
500             ((uint32_t *)d)[0] ^= color_xor;
501             break;
502         case 2:
503             ((uint32_t *)d)[0] = color0;
504             break;
505         case 3:
506             ((uint32_t *)d)[0] = color1;
507             break;
508         }
509 #else
510 #error unsupported depth
511 #endif
512         d += BPP;
513     }
514 }
515 #endif
516
517 #undef PUT_PIXEL2
518 #undef DEPTH
519 #undef BPP
520 #undef PIXEL_TYPE