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) 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) 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 b = s[0]; 405 g = s[1]; 406 r = s[2]; 407 ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); 408 s += 3; 409 d += BPP; 410 } while (--w != 0); 411 } 412 413 /* 414 * 32 bit color 415 */ 416 static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d, 417 const uint8_t *s, int width) 418 { 419 #if DEPTH == 32 && !defined(WORDS_BIGENDIAN) 420 memcpy(d, s, width * 4); 421 #else 422 int w; 423 uint32_t r, g, b; 424 425 w = width; 426 do { 427 b = s[0]; 428 g = s[1]; 429 r = s[2]; 430 ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); 431 s += 4; 432 d += BPP; 433 } while (--w != 0); 434 #endif 435 } 436 437 #if DEPTH != 15 438 void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1, 439 const uint8_t *src1, 440 int poffset, int w, 441 unsigned int color0, 442 unsigned int color1, 443 unsigned int color_xor) 444 { 445 const uint8_t *plane0, *plane1; 446 int x, b0, b1; 447 uint8_t *d; 448 449 d = d1; 450 plane0 = src1; 451 plane1 = src1 + poffset; 452 for(x = 0; x < w; x++) { 453 b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1; 454 b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1; 455 #if DEPTH == 8 456 switch(b0 | (b1 << 1)) { 457 case 0: 458 break; 459 case 1: 460 d[0] ^= color_xor; 461 break; 462 case 2: 463 d[0] = color0; 464 break; 465 case 3: 466 d[0] = color1; 467 break; 468 } 469 #elif DEPTH == 16 470 switch(b0 | (b1 << 1)) { 471 case 0: 472 break; 473 case 1: 474 ((uint16_t *)d)[0] ^= color_xor; 475 break; 476 case 2: 477 ((uint16_t *)d)[0] = color0; 478 break; 479 case 3: 480 ((uint16_t *)d)[0] = color1; 481 break; 482 } 483 #elif DEPTH == 32 484 switch(b0 | (b1 << 1)) { 485 case 0: 486 break; 487 case 1: 488 ((uint32_t *)d)[0] ^= color_xor; 489 break; 490 case 2: 491 ((uint32_t *)d)[0] = color0; 492 break; 493 case 3: 494 ((uint32_t *)d)[0] = color1; 495 break; 496 } 497 #else 498 #error unsupported depth 499 #endif 500 d += BPP; 501 } 502 } 503 #endif 504 505 #undef PUT_PIXEL2 506 #undef DEPTH 507 #undef BPP 508 #undef PIXEL_TYPE 509