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)[1] = (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 #if BPP == 1 110 cpu_to_32wu((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol); 111 v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; 112 cpu_to_32wu(((uint32_t *)d)+1, v); 113 if (dup9) 114 ((uint8_t *)d)[8] = v >> (24 * (1 - BIG)); 115 else 116 ((uint8_t *)d)[8] = bgcol; 117 118 #elif BPP == 2 119 cpu_to_32wu(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol); 120 cpu_to_32wu(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol); 121 cpu_to_32wu(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol); 122 v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; 123 cpu_to_32wu(((uint32_t *)d)+3, v); 124 if (dup9) 125 ((uint16_t *)d)[8] = v >> (16 * (1 - BIG)); 126 else 127 ((uint16_t *)d)[8] = bgcol; 128 #else 129 ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; 130 ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; 131 ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; 132 ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; 133 ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; 134 ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; 135 ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; 136 v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; 137 ((uint32_t *)d)[7] = v; 138 if (dup9) 139 ((uint32_t *)d)[8] = v; 140 else 141 ((uint32_t *)d)[8] = bgcol; 142 #endif 143 font_ptr += 4; 144 d += linesize; 145 } while (--h); 146 } 147 148 /* 149 * 4 color mode 150 */ 151 static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d, 152 const uint8_t *s, int width) 153 { 154 uint32_t plane_mask, *palette, data, v; 155 int x; 156 157 palette = s1->last_palette; 158 plane_mask = mask16[s1->ar[0x12] & 0xf]; 159 width >>= 3; 160 for(x = 0; x < width; x++) { 161 data = ((uint32_t *)s)[0]; 162 data &= plane_mask; 163 v = expand2[GET_PLANE(data, 0)]; 164 v |= expand2[GET_PLANE(data, 2)] << 2; 165 ((PIXEL_TYPE *)d)[0] = palette[v >> 12]; 166 ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf]; 167 ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf]; 168 ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf]; 169 170 v = expand2[GET_PLANE(data, 1)]; 171 v |= expand2[GET_PLANE(data, 3)] << 2; 172 ((PIXEL_TYPE *)d)[4] = palette[v >> 12]; 173 ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf]; 174 ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf]; 175 ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf]; 176 d += BPP * 8; 177 s += 4; 178 } 179 } 180 181 #if BPP == 1 182 #define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v) 183 #elif BPP == 2 184 #define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v) 185 #else 186 #define PUT_PIXEL2(d, n, v) \ 187 ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v) 188 #endif 189 190 /* 191 * 4 color mode, dup2 horizontal 192 */ 193 static void glue(vga_draw_line2d2_, DEPTH)(VGAState *s1, uint8_t *d, 194 const uint8_t *s, int width) 195 { 196 uint32_t plane_mask, *palette, data, v; 197 int x; 198 199 palette = s1->last_palette; 200 plane_mask = mask16[s1->ar[0x12] & 0xf]; 201 width >>= 3; 202 for(x = 0; x < width; x++) { 203 data = ((uint32_t *)s)[0]; 204 data &= plane_mask; 205 v = expand2[GET_PLANE(data, 0)]; 206 v |= expand2[GET_PLANE(data, 2)] << 2; 207 PUT_PIXEL2(d, 0, palette[v >> 12]); 208 PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]); 209 PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]); 210 PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]); 211 212 v = expand2[GET_PLANE(data, 1)]; 213 v |= expand2[GET_PLANE(data, 3)] << 2; 214 PUT_PIXEL2(d, 4, palette[v >> 12]); 215 PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); 216 PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); 217 PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); 218 d += BPP * 16; 219 s += 4; 220 } 221 } 222 223 /* 224 * 16 color mode 225 */ 226 static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d, 227 const uint8_t *s, int width) 228 { 229 uint32_t plane_mask, data, v, *palette; 230 int x; 231 232 palette = s1->last_palette; 233 plane_mask = mask16[s1->ar[0x12] & 0xf]; 234 width >>= 3; 235 for(x = 0; x < width; x++) { 236 data = ((uint32_t *)s)[0]; 237 data &= plane_mask; 238 v = expand4[GET_PLANE(data, 0)]; 239 v |= expand4[GET_PLANE(data, 1)] << 1; 240 v |= expand4[GET_PLANE(data, 2)] << 2; 241 v |= expand4[GET_PLANE(data, 3)] << 3; 242 ((PIXEL_TYPE *)d)[0] = palette[v >> 28]; 243 ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf]; 244 ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf]; 245 ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf]; 246 ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf]; 247 ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf]; 248 ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf]; 249 ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf]; 250 d += BPP * 8; 251 s += 4; 252 } 253 } 254 255 /* 256 * 16 color mode, dup2 horizontal 257 */ 258 static void glue(vga_draw_line4d2_, DEPTH)(VGAState *s1, uint8_t *d, 259 const uint8_t *s, int width) 260 { 261 uint32_t plane_mask, data, v, *palette; 262 int x; 263 264 palette = s1->last_palette; 265 plane_mask = mask16[s1->ar[0x12] & 0xf]; 266 width >>= 3; 267 for(x = 0; x < width; x++) { 268 data = ((uint32_t *)s)[0]; 269 data &= plane_mask; 270 v = expand4[GET_PLANE(data, 0)]; 271 v |= expand4[GET_PLANE(data, 1)] << 1; 272 v |= expand4[GET_PLANE(data, 2)] << 2; 273 v |= expand4[GET_PLANE(data, 3)] << 3; 274 PUT_PIXEL2(d, 0, palette[v >> 28]); 275 PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]); 276 PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]); 277 PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]); 278 PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]); 279 PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); 280 PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); 281 PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); 282 d += BPP * 16; 283 s += 4; 284 } 285 } 286 287 /* 288 * 256 color mode, double pixels 289 * 290 * XXX: add plane_mask support (never used in standard VGA modes) 291 */ 292 static void glue(vga_draw_line8d2_, DEPTH)(VGAState *s1, uint8_t *d, 293 const uint8_t *s, int width) 294 { 295 uint32_t *palette; 296 int x; 297 298 palette = s1->last_palette; 299 width >>= 3; 300 for(x = 0; x < width; x++) { 301 PUT_PIXEL2(d, 0, palette[s[0]]); 302 PUT_PIXEL2(d, 1, palette[s[1]]); 303 PUT_PIXEL2(d, 2, palette[s[2]]); 304 PUT_PIXEL2(d, 3, palette[s[3]]); 305 d += BPP * 8; 306 s += 4; 307 } 308 } 309 310 /* 311 * standard 256 color mode 312 * 313 * XXX: add plane_mask support (never used in standard VGA modes) 314 */ 315 static void glue(vga_draw_line8_, DEPTH)(VGAState *s1, uint8_t *d, 316 const uint8_t *s, int width) 317 { 318 uint32_t *palette; 319 int x; 320 321 palette = s1->last_palette; 322 width >>= 3; 323 for(x = 0; x < width; x++) { 324 ((PIXEL_TYPE *)d)[0] = palette[s[0]]; 325 ((PIXEL_TYPE *)d)[1] = palette[s[1]]; 326 ((PIXEL_TYPE *)d)[2] = palette[s[2]]; 327 ((PIXEL_TYPE *)d)[3] = palette[s[3]]; 328 ((PIXEL_TYPE *)d)[4] = palette[s[4]]; 329 ((PIXEL_TYPE *)d)[5] = palette[s[5]]; 330 ((PIXEL_TYPE *)d)[6] = palette[s[6]]; 331 ((PIXEL_TYPE *)d)[7] = palette[s[7]]; 332 d += BPP * 8; 333 s += 8; 334 } 335 } 336 337 #endif /* DEPTH != 15 */ 338 339 340 /* XXX: optimize */ 341 342 /* 343 * 15 bit color 344 */ 345 static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d, 346 const uint8_t *s, int width) 347 { 348 #if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) 349 memcpy(d, s, width * 2); 350 #else 351 int w; 352 uint32_t v, r, g, b; 353 354 w = width; 355 do { 356 v = lduw_raw((void *)s); 357 r = (v >> 7) & 0xf8; 358 g = (v >> 2) & 0xf8; 359 b = (v << 3) & 0xf8; 360 ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); 361 s += 2; 362 d += BPP; 363 } while (--w != 0); 364 #endif 365 } 366 367 /* 368 * 16 bit color 369 */ 370 static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d, 371 const uint8_t *s, int width) 372 { 373 #if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) 374 memcpy(d, s, width * 2); 375 #else 376 int w; 377 uint32_t v, r, g, b; 378 379 w = width; 380 do { 381 v = lduw_raw((void *)s); 382 r = (v >> 8) & 0xf8; 383 g = (v >> 3) & 0xfc; 384 b = (v << 3) & 0xf8; 385 ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); 386 s += 2; 387 d += BPP; 388 } while (--w != 0); 389 #endif 390 } 391 392 /* 393 * 24 bit color 394 */ 395 static void glue(vga_draw_line24_, DEPTH)(VGAState *s1, uint8_t *d, 396 const uint8_t *s, int width) 397 { 398 int w; 399 uint32_t r, g, b; 400 401 w = width; 402 do { 403 #if defined(TARGET_WORDS_BIGENDIAN) 404 r = s[0]; 405 g = s[1]; 406 b = s[2]; 407 #else 408 b = s[0]; 409 g = s[1]; 410 r = s[2]; 411 #endif 412 ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); 413 s += 3; 414 d += BPP; 415 } while (--w != 0); 416 } 417 418 /* 419 * 32 bit color 420 */ 421 static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d, 422 const uint8_t *s, int width) 423 { 424 #if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) 425 memcpy(d, s, width * 4); 426 #else 427 int w; 428 uint32_t r, g, b; 429 430 w = width; 431 do { 432 #if defined(TARGET_WORDS_BIGENDIAN) 433 r = s[1]; 434 g = s[2]; 435 b = s[3]; 436 #else 437 b = s[0]; 438 g = s[1]; 439 r = s[2]; 440 #endif 441 ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); 442 s += 4; 443 d += BPP; 444 } while (--w != 0); 445 #endif 446 } 447 448 #if DEPTH != 15 449 void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1, 450 const uint8_t *src1, 451 int poffset, int w, 452 unsigned int color0, 453 unsigned int color1, 454 unsigned int color_xor) 455 { 456 const uint8_t *plane0, *plane1; 457 int x, b0, b1; 458 uint8_t *d; 459 460 d = d1; 461 plane0 = src1; 462 plane1 = src1 + poffset; 463 for(x = 0; x < w; x++) { 464 b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1; 465 b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1; 466 #if DEPTH == 8 467 switch(b0 | (b1 << 1)) { 468 case 0: 469 break; 470 case 1: 471 d[0] ^= color_xor; 472 break; 473 case 2: 474 d[0] = color0; 475 break; 476 case 3: 477 d[0] = color1; 478 break; 479 } 480 #elif DEPTH == 16 481 switch(b0 | (b1 << 1)) { 482 case 0: 483 break; 484 case 1: 485 ((uint16_t *)d)[0] ^= color_xor; 486 break; 487 case 2: 488 ((uint16_t *)d)[0] = color0; 489 break; 490 case 3: 491 ((uint16_t *)d)[0] = color1; 492 break; 493 } 494 #elif DEPTH == 32 495 switch(b0 | (b1 << 1)) { 496 case 0: 497 break; 498 case 1: 499 ((uint32_t *)d)[0] ^= color_xor; 500 break; 501 case 2: 502 ((uint32_t *)d)[0] = color0; 503 break; 504 case 3: 505 ((uint32_t *)d)[0] = color1; 506 break; 507 } 508 #else 509 #error unsupported depth 510 #endif 511 d += BPP; 512 } 513 } 514 #endif 515 516 #undef PUT_PIXEL2 517 #undef DEPTH 518 #undef BPP 519 #undef PIXEL_TYPE 520