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 *s1, uint8_t *d, 102 const uint8_t *s, int width) 103 { 104 uint32_t plane_mask, *palette, data, v; 105 int x; 106 107 palette = s1->last_palette; 108 plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; 109 width >>= 3; 110 for(x = 0; x < width; x++) { 111 data = ((uint32_t *)s)[0]; 112 data &= plane_mask; 113 v = expand2[GET_PLANE(data, 0)]; 114 v |= expand2[GET_PLANE(data, 2)] << 2; 115 ((uint32_t *)d)[0] = palette[v >> 12]; 116 ((uint32_t *)d)[1] = palette[(v >> 8) & 0xf]; 117 ((uint32_t *)d)[2] = palette[(v >> 4) & 0xf]; 118 ((uint32_t *)d)[3] = palette[(v >> 0) & 0xf]; 119 120 v = expand2[GET_PLANE(data, 1)]; 121 v |= expand2[GET_PLANE(data, 3)] << 2; 122 ((uint32_t *)d)[4] = palette[v >> 12]; 123 ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf]; 124 ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; 125 ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; 126 d += 32; 127 s += 4; 128 } 129 } 130 131 #define PUT_PIXEL2(d, n, v) \ 132 ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v) 133 134 /* 135 * 4 color mode, dup2 horizontal 136 */ 137 static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d, 138 const uint8_t *s, int width) 139 { 140 uint32_t plane_mask, *palette, data, v; 141 int x; 142 143 palette = s1->last_palette; 144 plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; 145 width >>= 3; 146 for(x = 0; x < width; x++) { 147 data = ((uint32_t *)s)[0]; 148 data &= plane_mask; 149 v = expand2[GET_PLANE(data, 0)]; 150 v |= expand2[GET_PLANE(data, 2)] << 2; 151 PUT_PIXEL2(d, 0, palette[v >> 12]); 152 PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]); 153 PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]); 154 PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]); 155 156 v = expand2[GET_PLANE(data, 1)]; 157 v |= expand2[GET_PLANE(data, 3)] << 2; 158 PUT_PIXEL2(d, 4, palette[v >> 12]); 159 PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); 160 PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); 161 PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); 162 d += 64; 163 s += 4; 164 } 165 } 166 167 /* 168 * 16 color mode 169 */ 170 static void vga_draw_line4(VGACommonState *s1, uint8_t *d, 171 const uint8_t *s, int width) 172 { 173 uint32_t plane_mask, data, v, *palette; 174 int x; 175 176 palette = s1->last_palette; 177 plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; 178 width >>= 3; 179 for(x = 0; x < width; x++) { 180 data = ((uint32_t *)s)[0]; 181 data &= plane_mask; 182 v = expand4[GET_PLANE(data, 0)]; 183 v |= expand4[GET_PLANE(data, 1)] << 1; 184 v |= expand4[GET_PLANE(data, 2)] << 2; 185 v |= expand4[GET_PLANE(data, 3)] << 3; 186 ((uint32_t *)d)[0] = palette[v >> 28]; 187 ((uint32_t *)d)[1] = palette[(v >> 24) & 0xf]; 188 ((uint32_t *)d)[2] = palette[(v >> 20) & 0xf]; 189 ((uint32_t *)d)[3] = palette[(v >> 16) & 0xf]; 190 ((uint32_t *)d)[4] = palette[(v >> 12) & 0xf]; 191 ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf]; 192 ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; 193 ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; 194 d += 32; 195 s += 4; 196 } 197 } 198 199 /* 200 * 16 color mode, dup2 horizontal 201 */ 202 static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d, 203 const uint8_t *s, int width) 204 { 205 uint32_t plane_mask, data, v, *palette; 206 int x; 207 208 palette = s1->last_palette; 209 plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; 210 width >>= 3; 211 for(x = 0; x < width; x++) { 212 data = ((uint32_t *)s)[0]; 213 data &= plane_mask; 214 v = expand4[GET_PLANE(data, 0)]; 215 v |= expand4[GET_PLANE(data, 1)] << 1; 216 v |= expand4[GET_PLANE(data, 2)] << 2; 217 v |= expand4[GET_PLANE(data, 3)] << 3; 218 PUT_PIXEL2(d, 0, palette[v >> 28]); 219 PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]); 220 PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]); 221 PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]); 222 PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]); 223 PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); 224 PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); 225 PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); 226 d += 64; 227 s += 4; 228 } 229 } 230 231 /* 232 * 256 color mode, double pixels 233 * 234 * XXX: add plane_mask support (never used in standard VGA modes) 235 */ 236 static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d, 237 const uint8_t *s, int width) 238 { 239 uint32_t *palette; 240 int x; 241 242 palette = s1->last_palette; 243 width >>= 3; 244 for(x = 0; x < width; x++) { 245 PUT_PIXEL2(d, 0, palette[s[0]]); 246 PUT_PIXEL2(d, 1, palette[s[1]]); 247 PUT_PIXEL2(d, 2, palette[s[2]]); 248 PUT_PIXEL2(d, 3, palette[s[3]]); 249 d += 32; 250 s += 4; 251 } 252 } 253 254 /* 255 * standard 256 color mode 256 * 257 * XXX: add plane_mask support (never used in standard VGA modes) 258 */ 259 static void vga_draw_line8(VGACommonState *s1, uint8_t *d, 260 const uint8_t *s, int width) 261 { 262 uint32_t *palette; 263 int x; 264 265 palette = s1->last_palette; 266 width >>= 3; 267 for(x = 0; x < width; x++) { 268 ((uint32_t *)d)[0] = palette[s[0]]; 269 ((uint32_t *)d)[1] = palette[s[1]]; 270 ((uint32_t *)d)[2] = palette[s[2]]; 271 ((uint32_t *)d)[3] = palette[s[3]]; 272 ((uint32_t *)d)[4] = palette[s[4]]; 273 ((uint32_t *)d)[5] = palette[s[5]]; 274 ((uint32_t *)d)[6] = palette[s[6]]; 275 ((uint32_t *)d)[7] = palette[s[7]]; 276 d += 32; 277 s += 8; 278 } 279 } 280 281 282 /* XXX: optimize */ 283 284 /* 285 * 15 bit color 286 */ 287 static void vga_draw_line15(VGACommonState *s1, uint8_t *d, 288 const uint8_t *s, int width) 289 { 290 int w; 291 uint32_t v, r, g, b; 292 293 w = width; 294 do { 295 v = lduw_p((void *)s); 296 r = (v >> 7) & 0xf8; 297 g = (v >> 2) & 0xf8; 298 b = (v << 3) & 0xf8; 299 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 300 s += 2; 301 d += 4; 302 } while (--w != 0); 303 } 304 305 /* 306 * 16 bit color 307 */ 308 static void vga_draw_line16(VGACommonState *s1, uint8_t *d, 309 const uint8_t *s, int width) 310 { 311 int w; 312 uint32_t v, r, g, b; 313 314 w = width; 315 do { 316 v = lduw_p((void *)s); 317 r = (v >> 8) & 0xf8; 318 g = (v >> 3) & 0xfc; 319 b = (v << 3) & 0xf8; 320 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 321 s += 2; 322 d += 4; 323 } while (--w != 0); 324 } 325 326 /* 327 * 24 bit color 328 */ 329 static void vga_draw_line24(VGACommonState *s1, uint8_t *d, 330 const uint8_t *s, int width) 331 { 332 int w; 333 uint32_t r, g, b; 334 335 w = width; 336 do { 337 #if defined(TARGET_WORDS_BIGENDIAN) 338 r = s[0]; 339 g = s[1]; 340 b = s[2]; 341 #else 342 b = s[0]; 343 g = s[1]; 344 r = s[2]; 345 #endif 346 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 347 s += 3; 348 d += 4; 349 } while (--w != 0); 350 } 351 352 /* 353 * 32 bit color 354 */ 355 static void vga_draw_line32(VGACommonState *s1, uint8_t *d, 356 const uint8_t *s, int width) 357 { 358 #if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) 359 memcpy(d, s, width * 4); 360 #else 361 int w; 362 uint32_t r, g, b; 363 364 w = width; 365 do { 366 #if defined(TARGET_WORDS_BIGENDIAN) 367 r = s[1]; 368 g = s[2]; 369 b = s[3]; 370 #else 371 b = s[0]; 372 g = s[1]; 373 r = s[2]; 374 #endif 375 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 376 s += 4; 377 d += 4; 378 } while (--w != 0); 379 #endif 380 } 381