xref: /qemu/hw/display/vga-helpers.h (revision 658178c3)
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 
269     /* For 256 color modes, we can adjust the source address and write directly
270      * to the destination, even if horizontal pel panning is active.  However,
271      * the loop below assumes that the address does not wrap in the middle of a
272      * plane.  If that happens...
273      */
274     if (addr + (width >> 3) * 4 < VGA_VRAM_SIZE) {
275         addr += hpel * 4;
276         hpel = 0;
277     }
278 
279     /* ... use the panning buffer as in planar modes.  */
280     if (hpel) {
281         width += 8;
282         d = vga->panning_buf;
283     }
284     width >>= 3;
285     for(x = 0; x < width; x++) {
286         addr &= VGA_VRAM_SIZE - 1;
287         PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]);
288         PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]);
289         PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]);
290         PUT_PIXEL2(d, 3, palette[vga_read_byte(vga, addr + 3)]);
291         d += 32;
292         addr += 4;
293     }
294     return hpel ? vga->panning_buf + 8 * hpel : NULL;
295 }
296 
297 /*
298  * standard 256 color mode
299  *
300  * XXX: add plane_mask support (never used in standard VGA modes)
301  */
302 static void *vga_draw_line8(VGACommonState *vga, uint8_t *d,
303                             uint32_t addr, int width, int hpel)
304 {
305     uint32_t *palette;
306     int x;
307 
308     palette = vga->last_palette;
309     hpel = (hpel >> 1) & 3;
310     if (hpel) {
311         width += 8;
312         d = vga->panning_buf;
313     }
314     width >>= 3;
315     for(x = 0; x < width; x++) {
316         ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)];
317         ((uint32_t *)d)[1] = palette[vga_read_byte(vga, addr + 1)];
318         ((uint32_t *)d)[2] = palette[vga_read_byte(vga, addr + 2)];
319         ((uint32_t *)d)[3] = palette[vga_read_byte(vga, addr + 3)];
320         ((uint32_t *)d)[4] = palette[vga_read_byte(vga, addr + 4)];
321         ((uint32_t *)d)[5] = palette[vga_read_byte(vga, addr + 5)];
322         ((uint32_t *)d)[6] = palette[vga_read_byte(vga, addr + 6)];
323         ((uint32_t *)d)[7] = palette[vga_read_byte(vga, addr + 7)];
324         d += 32;
325         addr += 8;
326     }
327     return hpel ? vga->panning_buf + 4 * hpel : NULL;
328 }
329 
330 /*
331  * 15 bit color
332  */
333 static void *vga_draw_line15_le(VGACommonState *vga, uint8_t *d,
334                                 uint32_t addr, int width, int hpel)
335 {
336     int w;
337     uint32_t v, r, g, b;
338 
339     w = width;
340     do {
341         v = vga_read_word_le(vga, addr);
342         r = (v >> 7) & 0xf8;
343         g = (v >> 2) & 0xf8;
344         b = (v << 3) & 0xf8;
345         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
346         addr += 2;
347         d += 4;
348     } while (--w != 0);
349     return NULL;
350 }
351 
352 static void *vga_draw_line15_be(VGACommonState *vga, uint8_t *d,
353                                 uint32_t addr, int width, int hpel)
354 {
355     int w;
356     uint32_t v, r, g, b;
357 
358     w = width;
359     do {
360         v = vga_read_word_be(vga, addr);
361         r = (v >> 7) & 0xf8;
362         g = (v >> 2) & 0xf8;
363         b = (v << 3) & 0xf8;
364         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
365         addr += 2;
366         d += 4;
367     } while (--w != 0);
368     return NULL;
369 }
370 
371 /*
372  * 16 bit color
373  */
374 static void *vga_draw_line16_le(VGACommonState *vga, uint8_t *d,
375                                 uint32_t addr, int width, int hpel)
376 {
377     int w;
378     uint32_t v, r, g, b;
379 
380     w = width;
381     do {
382         v = vga_read_word_le(vga, addr);
383         r = (v >> 8) & 0xf8;
384         g = (v >> 3) & 0xfc;
385         b = (v << 3) & 0xf8;
386         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
387         addr += 2;
388         d += 4;
389     } while (--w != 0);
390     return NULL;
391 }
392 
393 static void *vga_draw_line16_be(VGACommonState *vga, uint8_t *d,
394                                 uint32_t addr, int width, int hpel)
395 {
396     int w;
397     uint32_t v, r, g, b;
398 
399     w = width;
400     do {
401         v = vga_read_word_be(vga, addr);
402         r = (v >> 8) & 0xf8;
403         g = (v >> 3) & 0xfc;
404         b = (v << 3) & 0xf8;
405         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
406         addr += 2;
407         d += 4;
408     } while (--w != 0);
409     return NULL;
410 }
411 
412 /*
413  * 24 bit color
414  */
415 static void *vga_draw_line24_le(VGACommonState *vga, uint8_t *d,
416                                 uint32_t addr, int width, int hpel)
417 {
418     int w;
419     uint32_t r, g, b;
420 
421     w = width;
422     do {
423         b = vga_read_byte(vga, addr + 0);
424         g = vga_read_byte(vga, addr + 1);
425         r = vga_read_byte(vga, addr + 2);
426         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
427         addr += 3;
428         d += 4;
429     } while (--w != 0);
430     return NULL;
431 }
432 
433 static void *vga_draw_line24_be(VGACommonState *vga, uint8_t *d,
434                                 uint32_t addr, int width, int hpel)
435 {
436     int w;
437     uint32_t r, g, b;
438 
439     w = width;
440     do {
441         r = vga_read_byte(vga, addr + 0);
442         g = vga_read_byte(vga, addr + 1);
443         b = vga_read_byte(vga, addr + 2);
444         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
445         addr += 3;
446         d += 4;
447     } while (--w != 0);
448     return NULL;
449 }
450 
451 /*
452  * 32 bit color
453  */
454 static void *vga_draw_line32_le(VGACommonState *vga, uint8_t *d,
455                                 uint32_t addr, int width, int hpel)
456 {
457     int w;
458     uint32_t r, g, b;
459 
460     w = width;
461     do {
462         b = vga_read_byte(vga, addr + 0);
463         g = vga_read_byte(vga, addr + 1);
464         r = vga_read_byte(vga, addr + 2);
465         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
466         addr += 4;
467         d += 4;
468     } while (--w != 0);
469     return NULL;
470 }
471 
472 static void *vga_draw_line32_be(VGACommonState *vga, uint8_t *d,
473                                 uint32_t addr, int width, int hpel)
474 {
475     int w;
476     uint32_t r, g, b;
477 
478     w = width;
479     do {
480         r = vga_read_byte(vga, addr + 1);
481         g = vga_read_byte(vga, addr + 2);
482         b = vga_read_byte(vga, addr + 3);
483         ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
484         addr += 4;
485         d += 4;
486     } while (--w != 0);
487     return NULL;
488 }
489