xref: /openbmc/qemu/hw/display/vga-helpers.h (revision 973a724eb006f674301a0c45f34b3c08dee0fe49)
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 static inline void vga_draw_glyph_line(uint8_t *d, uint32_t font_data,
26                                        uint32_t xorcol, uint32_t bgcol)
27 {
28         ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
29         ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
30         ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
31         ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
32         ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
33         ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
34         ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
35         ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
36 }
37 
38 static void vga_draw_glyph8(uint8_t *d, int linesize,
39                             const uint8_t *font_ptr, int h,
40                             uint32_t fgcol, uint32_t bgcol)
41 {
42     uint32_t font_data, xorcol;
43 
44     xorcol = bgcol ^ fgcol;
45     do {
46         font_data = font_ptr[0];
47         vga_draw_glyph_line(d, font_data, xorcol, bgcol);
48         font_ptr += 4;
49         d += linesize;
50     } while (--h);
51 }
52 
53 static void vga_draw_glyph16(uint8_t *d, int linesize,
54                                           const uint8_t *font_ptr, int h,
55                                           uint32_t fgcol, uint32_t bgcol)
56 {
57     uint32_t font_data, xorcol;
58 
59     xorcol = bgcol ^ fgcol;
60     do {
61         font_data = font_ptr[0];
62         vga_draw_glyph_line(d, expand4to8[font_data >> 4],
63                             xorcol, bgcol);
64         vga_draw_glyph_line(d + 32, expand4to8[font_data & 0x0f],
65                             xorcol, bgcol);
66         font_ptr += 4;
67         d += linesize;
68     } while (--h);
69 }
70 
71 static void vga_draw_glyph9(uint8_t *d, int linesize,
72                             const uint8_t *font_ptr, int h,
73                             uint32_t fgcol, uint32_t bgcol, int dup9)
74 {
75     uint32_t font_data, xorcol, v;
76 
77     xorcol = bgcol ^ fgcol;
78     do {
79         font_data = font_ptr[0];
80         ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
81         ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
82         ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
83         ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
84         ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
85         ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
86         ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
87         v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
88         ((uint32_t *)d)[7] = v;
89         if (dup9)
90             ((uint32_t *)d)[8] = v;
91         else
92             ((uint32_t *)d)[8] = bgcol;
93         font_ptr += 4;
94         d += linesize;
95     } while (--h);
96 }
97 
98 /*
99  * 4 color mode
100  */
101 static void *vga_draw_line2(VGACommonState *vga, uint8_t *d,
102                             uint32_t addr, int width, int hpel)
103 {
104     uint32_t plane_mask, *palette, data, v;
105     int x;
106 
107     palette = vga->last_palette;
108     plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
109     hpel &= 7;
110     if (hpel) {
111         width += 8;
112         d = vga->panning_buf;
113     }
114     width >>= 3;
115     for(x = 0; x < width; x++) {
116         data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
117         data &= plane_mask;
118         v = expand2[GET_PLANE(data, 0)];
119         v |= expand2[GET_PLANE(data, 2)] << 2;
120         ((uint32_t *)d)[0] = palette[v >> 12];
121         ((uint32_t *)d)[1] = palette[(v >> 8) & 0xf];
122         ((uint32_t *)d)[2] = palette[(v >> 4) & 0xf];
123         ((uint32_t *)d)[3] = palette[(v >> 0) & 0xf];
124 
125         v = expand2[GET_PLANE(data, 1)];
126         v |= expand2[GET_PLANE(data, 3)] << 2;
127         ((uint32_t *)d)[4] = palette[v >> 12];
128         ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf];
129         ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
130         ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
131         d += 32;
132         addr += 4;
133     }
134     return hpel ? vga->panning_buf + 4 * hpel : NULL;
135 }
136 
137 #define PUT_PIXEL2(d, n, v) \
138 ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
139 
140 /*
141  * 4 color mode, dup2 horizontal
142  */
143 static void *vga_draw_line2d2(VGACommonState *vga, uint8_t *d,
144                               uint32_t addr, int width, int hpel)
145 {
146     uint32_t plane_mask, *palette, data, v;
147     int x;
148 
149     palette = vga->last_palette;
150     plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
151     hpel &= 7;
152     if (hpel) {
153         width += 8;
154         d = vga->panning_buf;
155     }
156     width >>= 3;
157     for(x = 0; x < width; x++) {
158         data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
159         data &= plane_mask;
160         v = expand2[GET_PLANE(data, 0)];
161         v |= expand2[GET_PLANE(data, 2)] << 2;
162         PUT_PIXEL2(d, 0, palette[v >> 12]);
163         PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
164         PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
165         PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
166 
167         v = expand2[GET_PLANE(data, 1)];
168         v |= expand2[GET_PLANE(data, 3)] << 2;
169         PUT_PIXEL2(d, 4, palette[v >> 12]);
170         PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
171         PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
172         PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
173         d += 64;
174         addr += 4;
175     }
176     return hpel ? vga->panning_buf + 8 * hpel : NULL;
177 }
178 
179 /*
180  * 16 color mode
181  */
182 static void *vga_draw_line4(VGACommonState *vga, uint8_t *d,
183                             uint32_t addr, int width, int hpel)
184 {
185     uint32_t plane_mask, data, v, *palette;
186     int x;
187 
188     palette = vga->last_palette;
189     plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
190     hpel &= 7;
191     if (hpel) {
192         width += 8;
193         d = vga->panning_buf;
194     }
195     width >>= 3;
196     for(x = 0; x < width; x++) {
197         data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
198         data &= plane_mask;
199         v = expand4[GET_PLANE(data, 0)];
200         v |= expand4[GET_PLANE(data, 1)] << 1;
201         v |= expand4[GET_PLANE(data, 2)] << 2;
202         v |= expand4[GET_PLANE(data, 3)] << 3;
203         ((uint32_t *)d)[0] = palette[v >> 28];
204         ((uint32_t *)d)[1] = palette[(v >> 24) & 0xf];
205         ((uint32_t *)d)[2] = palette[(v >> 20) & 0xf];
206         ((uint32_t *)d)[3] = palette[(v >> 16) & 0xf];
207         ((uint32_t *)d)[4] = palette[(v >> 12) & 0xf];
208         ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf];
209         ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
210         ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
211         d += 32;
212         addr += 4;
213     }
214     return hpel ? vga->panning_buf + 4 * hpel : NULL;
215 }
216 
217 /*
218  * 16 color mode, dup2 horizontal
219  */
220 static void *vga_draw_line4d2(VGACommonState *vga, uint8_t *d,
221                               uint32_t addr, int width, int hpel)
222 {
223     uint32_t plane_mask, data, v, *palette;
224     int x;
225 
226     palette = vga->last_palette;
227     plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
228     hpel &= 7;
229     if (hpel) {
230         width += 8;
231         d = vga->panning_buf;
232     }
233     width >>= 3;
234     for(x = 0; x < width; x++) {
235         data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
236         data &= plane_mask;
237         v = expand4[GET_PLANE(data, 0)];
238         v |= expand4[GET_PLANE(data, 1)] << 1;
239         v |= expand4[GET_PLANE(data, 2)] << 2;
240         v |= expand4[GET_PLANE(data, 3)] << 3;
241         PUT_PIXEL2(d, 0, palette[v >> 28]);
242         PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
243         PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
244         PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
245         PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
246         PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
247         PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
248         PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
249         d += 64;
250         addr += 4;
251     }
252     return hpel ? vga->panning_buf + 8 * hpel : NULL;
253 }
254 
255 /*
256  * 256 color mode, double pixels
257  *
258  * XXX: add plane_mask support (never used in standard VGA modes)
259  */
260 static void *vga_draw_line8d2(VGACommonState *vga, uint8_t *d,
261                               uint32_t addr, int width, int hpel)
262 {
263     uint32_t *palette;
264     int x;
265 
266     palette = vga->last_palette;
267     hpel = (hpel >> 1) & 3;
268     if (hpel) {
269         width += 8;
270         d = vga->panning_buf;
271     }
272     width >>= 3;
273     for(x = 0; x < width; x++) {
274         addr &= VGA_VRAM_SIZE - 1;
275         PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]);
276         PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]);
277         PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]);
278         PUT_PIXEL2(d, 3, palette[vga_read_byte(vga, addr + 3)]);
279         d += 32;
280         addr += 4;
281     }
282     return hpel ? vga->panning_buf + 8 * hpel : NULL;
283 }
284 
285 /*
286  * standard 256 color mode
287  *
288  * XXX: add plane_mask support (never used in standard VGA modes)
289  */
290 static void *vga_draw_line8(VGACommonState *vga, uint8_t *d,
291                             uint32_t addr, int width, int hpel)
292 {
293     uint32_t *palette;
294     int x;
295 
296     palette = vga->last_palette;
297     hpel = (hpel >> 1) & 3;
298     if (hpel) {
299         width += 8;
300         d = vga->panning_buf;
301     }
302     width >>= 3;
303     for(x = 0; x < width; x++) {
304         ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)];
305         ((uint32_t *)d)[1] = palette[vga_read_byte(vga, addr + 1)];
306         ((uint32_t *)d)[2] = palette[vga_read_byte(vga, addr + 2)];
307         ((uint32_t *)d)[3] = palette[vga_read_byte(vga, addr + 3)];
308         ((uint32_t *)d)[4] = palette[vga_read_byte(vga, addr + 4)];
309         ((uint32_t *)d)[5] = palette[vga_read_byte(vga, addr + 5)];
310         ((uint32_t *)d)[6] = palette[vga_read_byte(vga, addr + 6)];
311         ((uint32_t *)d)[7] = palette[vga_read_byte(vga, addr + 7)];
312         d += 32;
313         addr += 8;
314     }
315     return hpel ? vga->panning_buf + 4 * hpel : NULL;
316 }
317 
318 /*
319  * 15 bit color
320  */
321 static void *vga_draw_line15_le(VGACommonState *vga, uint8_t *d,
322                                 uint32_t addr, int width, int hpel)
323 {
324     int w;
325     uint32_t v, r, g, b;
326 
327     w = width;
328     do {
329         v = vga_read_word_le(vga, addr);
330         r = (v >> 7) & 0xf8;
331         g = (v >> 2) & 0xf8;
332         b = (v << 3) & 0xf8;
333         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
334         addr += 2;
335         d += 4;
336     } while (--w != 0);
337     return NULL;
338 }
339 
340 static void *vga_draw_line15_be(VGACommonState *vga, uint8_t *d,
341                                 uint32_t addr, int width, int hpel)
342 {
343     int w;
344     uint32_t v, r, g, b;
345 
346     w = width;
347     do {
348         v = vga_read_word_be(vga, addr);
349         r = (v >> 7) & 0xf8;
350         g = (v >> 2) & 0xf8;
351         b = (v << 3) & 0xf8;
352         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
353         addr += 2;
354         d += 4;
355     } while (--w != 0);
356     return NULL;
357 }
358 
359 /*
360  * 16 bit color
361  */
362 static void *vga_draw_line16_le(VGACommonState *vga, uint8_t *d,
363                                 uint32_t addr, int width, int hpel)
364 {
365     int w;
366     uint32_t v, r, g, b;
367 
368     w = width;
369     do {
370         v = vga_read_word_le(vga, addr);
371         r = (v >> 8) & 0xf8;
372         g = (v >> 3) & 0xfc;
373         b = (v << 3) & 0xf8;
374         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
375         addr += 2;
376         d += 4;
377     } while (--w != 0);
378     return NULL;
379 }
380 
381 static void *vga_draw_line16_be(VGACommonState *vga, uint8_t *d,
382                                 uint32_t addr, int width, int hpel)
383 {
384     int w;
385     uint32_t v, r, g, b;
386 
387     w = width;
388     do {
389         v = vga_read_word_be(vga, addr);
390         r = (v >> 8) & 0xf8;
391         g = (v >> 3) & 0xfc;
392         b = (v << 3) & 0xf8;
393         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
394         addr += 2;
395         d += 4;
396     } while (--w != 0);
397     return NULL;
398 }
399 
400 /*
401  * 24 bit color
402  */
403 static void *vga_draw_line24_le(VGACommonState *vga, uint8_t *d,
404                                 uint32_t addr, int width, int hpel)
405 {
406     int w;
407     uint32_t r, g, b;
408 
409     w = width;
410     do {
411         b = vga_read_byte(vga, addr + 0);
412         g = vga_read_byte(vga, addr + 1);
413         r = vga_read_byte(vga, addr + 2);
414         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
415         addr += 3;
416         d += 4;
417     } while (--w != 0);
418     return NULL;
419 }
420 
421 static void *vga_draw_line24_be(VGACommonState *vga, uint8_t *d,
422                                 uint32_t addr, int width, int hpel)
423 {
424     int w;
425     uint32_t r, g, b;
426 
427     w = width;
428     do {
429         r = vga_read_byte(vga, addr + 0);
430         g = vga_read_byte(vga, addr + 1);
431         b = vga_read_byte(vga, addr + 2);
432         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
433         addr += 3;
434         d += 4;
435     } while (--w != 0);
436     return NULL;
437 }
438 
439 /*
440  * 32 bit color
441  */
442 static void *vga_draw_line32_le(VGACommonState *vga, uint8_t *d,
443                                 uint32_t addr, int width, int hpel)
444 {
445     int w;
446     uint32_t r, g, b;
447 
448     w = width;
449     do {
450         b = vga_read_byte(vga, addr + 0);
451         g = vga_read_byte(vga, addr + 1);
452         r = vga_read_byte(vga, addr + 2);
453         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
454         addr += 4;
455         d += 4;
456     } while (--w != 0);
457     return NULL;
458 }
459 
460 static void *vga_draw_line32_be(VGACommonState *vga, uint8_t *d,
461                                 uint32_t addr, int width, int hpel)
462 {
463     int w;
464     uint32_t r, g, b;
465 
466     w = width;
467     do {
468         r = vga_read_byte(vga, addr + 1);
469         g = vga_read_byte(vga, addr + 2);
470         b = vga_read_byte(vga, addr + 3);
471         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
472         addr += 4;
473         d += 4;
474     } while (--w != 0);
475     return NULL;
476 }
477