xref: /qemu/hw/display/vga-helpers.h (revision 7271a819)
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 static inline uint8_t vga_read_byte(VGACommonState *vga, uint32_t addr)
99 {
100     return vga->vram_ptr[addr & vga->vbe_size_mask];
101 }
102 
103 static inline uint16_t vga_read_word_le(VGACommonState *vga, uint32_t addr)
104 {
105     uint32_t offset = addr & vga->vbe_size_mask & ~1;
106     uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset);
107     return lduw_le_p(ptr);
108 }
109 
110 static inline uint16_t vga_read_word_be(VGACommonState *vga, uint32_t addr)
111 {
112     uint32_t offset = addr & vga->vbe_size_mask & ~1;
113     uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset);
114     return lduw_be_p(ptr);
115 }
116 
117 static inline uint32_t vga_read_dword_le(VGACommonState *vga, uint32_t addr)
118 {
119     uint32_t offset = addr & vga->vbe_size_mask & ~3;
120     uint32_t *ptr = (uint32_t *)(vga->vram_ptr + offset);
121     return ldl_le_p(ptr);
122 }
123 
124 /*
125  * 4 color mode
126  */
127 static void vga_draw_line2(VGACommonState *vga, uint8_t *d,
128                            uint32_t addr, int width)
129 {
130     uint32_t plane_mask, *palette, data, v;
131     int x;
132 
133     palette = vga->last_palette;
134     plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
135     width >>= 3;
136     for(x = 0; x < width; x++) {
137         data = vga_read_dword_le(vga, addr);
138         data &= plane_mask;
139         v = expand2[GET_PLANE(data, 0)];
140         v |= expand2[GET_PLANE(data, 2)] << 2;
141         ((uint32_t *)d)[0] = palette[v >> 12];
142         ((uint32_t *)d)[1] = palette[(v >> 8) & 0xf];
143         ((uint32_t *)d)[2] = palette[(v >> 4) & 0xf];
144         ((uint32_t *)d)[3] = palette[(v >> 0) & 0xf];
145 
146         v = expand2[GET_PLANE(data, 1)];
147         v |= expand2[GET_PLANE(data, 3)] << 2;
148         ((uint32_t *)d)[4] = palette[v >> 12];
149         ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf];
150         ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
151         ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
152         d += 32;
153         addr += 4;
154     }
155 }
156 
157 #define PUT_PIXEL2(d, n, v) \
158 ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
159 
160 /*
161  * 4 color mode, dup2 horizontal
162  */
163 static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d,
164                              uint32_t addr, int width)
165 {
166     uint32_t plane_mask, *palette, data, v;
167     int x;
168 
169     palette = vga->last_palette;
170     plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
171     width >>= 3;
172     for(x = 0; x < width; x++) {
173         data = vga_read_dword_le(vga, addr);
174         data &= plane_mask;
175         v = expand2[GET_PLANE(data, 0)];
176         v |= expand2[GET_PLANE(data, 2)] << 2;
177         PUT_PIXEL2(d, 0, palette[v >> 12]);
178         PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
179         PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
180         PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
181 
182         v = expand2[GET_PLANE(data, 1)];
183         v |= expand2[GET_PLANE(data, 3)] << 2;
184         PUT_PIXEL2(d, 4, palette[v >> 12]);
185         PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
186         PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
187         PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
188         d += 64;
189         addr += 4;
190     }
191 }
192 
193 /*
194  * 16 color mode
195  */
196 static void vga_draw_line4(VGACommonState *vga, uint8_t *d,
197                            uint32_t addr, int width)
198 {
199     uint32_t plane_mask, data, v, *palette;
200     int x;
201 
202     palette = vga->last_palette;
203     plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
204     width >>= 3;
205     for(x = 0; x < width; x++) {
206         data = vga_read_dword_le(vga, addr);
207         data &= plane_mask;
208         v = expand4[GET_PLANE(data, 0)];
209         v |= expand4[GET_PLANE(data, 1)] << 1;
210         v |= expand4[GET_PLANE(data, 2)] << 2;
211         v |= expand4[GET_PLANE(data, 3)] << 3;
212         ((uint32_t *)d)[0] = palette[v >> 28];
213         ((uint32_t *)d)[1] = palette[(v >> 24) & 0xf];
214         ((uint32_t *)d)[2] = palette[(v >> 20) & 0xf];
215         ((uint32_t *)d)[3] = palette[(v >> 16) & 0xf];
216         ((uint32_t *)d)[4] = palette[(v >> 12) & 0xf];
217         ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf];
218         ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
219         ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
220         d += 32;
221         addr += 4;
222     }
223 }
224 
225 /*
226  * 16 color mode, dup2 horizontal
227  */
228 static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d,
229                              uint32_t addr, int width)
230 {
231     uint32_t plane_mask, data, v, *palette;
232     int x;
233 
234     palette = vga->last_palette;
235     plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
236     width >>= 3;
237     for(x = 0; x < width; x++) {
238         data = vga_read_dword_le(vga, addr);
239         data &= plane_mask;
240         v = expand4[GET_PLANE(data, 0)];
241         v |= expand4[GET_PLANE(data, 1)] << 1;
242         v |= expand4[GET_PLANE(data, 2)] << 2;
243         v |= expand4[GET_PLANE(data, 3)] << 3;
244         PUT_PIXEL2(d, 0, palette[v >> 28]);
245         PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
246         PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
247         PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
248         PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
249         PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
250         PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
251         PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
252         d += 64;
253         addr += 4;
254     }
255 }
256 
257 /*
258  * 256 color mode, double pixels
259  *
260  * XXX: add plane_mask support (never used in standard VGA modes)
261  */
262 static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d,
263                              uint32_t addr, int width)
264 {
265     uint32_t *palette;
266     int x;
267 
268     palette = vga->last_palette;
269     width >>= 3;
270     for(x = 0; x < width; x++) {
271         PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]);
272         PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]);
273         PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]);
274         PUT_PIXEL2(d, 3, palette[vga_read_byte(vga, addr + 3)]);
275         d += 32;
276         addr += 4;
277     }
278 }
279 
280 /*
281  * standard 256 color mode
282  *
283  * XXX: add plane_mask support (never used in standard VGA modes)
284  */
285 static void vga_draw_line8(VGACommonState *vga, uint8_t *d,
286                            uint32_t addr, int width)
287 {
288     uint32_t *palette;
289     int x;
290 
291     palette = vga->last_palette;
292     width >>= 3;
293     for(x = 0; x < width; x++) {
294         ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)];
295         ((uint32_t *)d)[1] = palette[vga_read_byte(vga, addr + 1)];
296         ((uint32_t *)d)[2] = palette[vga_read_byte(vga, addr + 2)];
297         ((uint32_t *)d)[3] = palette[vga_read_byte(vga, addr + 3)];
298         ((uint32_t *)d)[4] = palette[vga_read_byte(vga, addr + 4)];
299         ((uint32_t *)d)[5] = palette[vga_read_byte(vga, addr + 5)];
300         ((uint32_t *)d)[6] = palette[vga_read_byte(vga, addr + 6)];
301         ((uint32_t *)d)[7] = palette[vga_read_byte(vga, addr + 7)];
302         d += 32;
303         addr += 8;
304     }
305 }
306 
307 /*
308  * 15 bit color
309  */
310 static void vga_draw_line15_le(VGACommonState *vga, uint8_t *d,
311                                uint32_t addr, int width)
312 {
313     int w;
314     uint32_t v, r, g, b;
315 
316     w = width;
317     do {
318         v = vga_read_word_le(vga, addr);
319         r = (v >> 7) & 0xf8;
320         g = (v >> 2) & 0xf8;
321         b = (v << 3) & 0xf8;
322         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
323         addr += 2;
324         d += 4;
325     } while (--w != 0);
326 }
327 
328 static void vga_draw_line15_be(VGACommonState *vga, uint8_t *d,
329                                uint32_t addr, int width)
330 {
331     int w;
332     uint32_t v, r, g, b;
333 
334     w = width;
335     do {
336         v = vga_read_word_be(vga, addr);
337         r = (v >> 7) & 0xf8;
338         g = (v >> 2) & 0xf8;
339         b = (v << 3) & 0xf8;
340         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
341         addr += 2;
342         d += 4;
343     } while (--w != 0);
344 }
345 
346 /*
347  * 16 bit color
348  */
349 static void vga_draw_line16_le(VGACommonState *vga, uint8_t *d,
350                                uint32_t addr, int width)
351 {
352     int w;
353     uint32_t v, r, g, b;
354 
355     w = width;
356     do {
357         v = vga_read_word_le(vga, addr);
358         r = (v >> 8) & 0xf8;
359         g = (v >> 3) & 0xfc;
360         b = (v << 3) & 0xf8;
361         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
362         addr += 2;
363         d += 4;
364     } while (--w != 0);
365 }
366 
367 static void vga_draw_line16_be(VGACommonState *vga, uint8_t *d,
368                                uint32_t addr, int width)
369 {
370     int w;
371     uint32_t v, r, g, b;
372 
373     w = width;
374     do {
375         v = vga_read_word_be(vga, addr);
376         r = (v >> 8) & 0xf8;
377         g = (v >> 3) & 0xfc;
378         b = (v << 3) & 0xf8;
379         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
380         addr += 2;
381         d += 4;
382     } while (--w != 0);
383 }
384 
385 /*
386  * 24 bit color
387  */
388 static void vga_draw_line24_le(VGACommonState *vga, uint8_t *d,
389                                uint32_t addr, int width)
390 {
391     int w;
392     uint32_t r, g, b;
393 
394     w = width;
395     do {
396         b = vga_read_byte(vga, addr + 0);
397         g = vga_read_byte(vga, addr + 1);
398         r = vga_read_byte(vga, addr + 2);
399         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
400         addr += 3;
401         d += 4;
402     } while (--w != 0);
403 }
404 
405 static void vga_draw_line24_be(VGACommonState *vga, uint8_t *d,
406                                uint32_t addr, int width)
407 {
408     int w;
409     uint32_t r, g, b;
410 
411     w = width;
412     do {
413         r = vga_read_byte(vga, addr + 0);
414         g = vga_read_byte(vga, addr + 1);
415         b = vga_read_byte(vga, addr + 2);
416         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
417         addr += 3;
418         d += 4;
419     } while (--w != 0);
420 }
421 
422 /*
423  * 32 bit color
424  */
425 static void vga_draw_line32_le(VGACommonState *vga, uint8_t *d,
426                                uint32_t addr, int width)
427 {
428     int w;
429     uint32_t r, g, b;
430 
431     w = width;
432     do {
433         b = vga_read_byte(vga, addr + 0);
434         g = vga_read_byte(vga, addr + 1);
435         r = vga_read_byte(vga, addr + 2);
436         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
437         addr += 4;
438         d += 4;
439     } while (--w != 0);
440 }
441 
442 static void vga_draw_line32_be(VGACommonState *vga, uint8_t *d,
443                                uint32_t addr, int width)
444 {
445     int w;
446     uint32_t r, g, b;
447 
448     w = width;
449     do {
450         r = vga_read_byte(vga, addr + 1);
451         g = vga_read_byte(vga, addr + 2);
452         b = vga_read_byte(vga, addr + 3);
453         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
454         addr += 4;
455         d += 4;
456     } while (--w != 0);
457 }
458