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 #ifdef BGR_FORMAT 39 #define PIXEL_NAME glue(DEPTH, bgr) 40 #else 41 #define PIXEL_NAME DEPTH 42 #endif /* BGR_FORMAT */ 43 44 #if DEPTH != 15 && !defined(BGR_FORMAT) 45 46 static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d, 47 uint32_t font_data, 48 uint32_t xorcol, 49 uint32_t bgcol) 50 { 51 #if BPP == 1 52 ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; 53 ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; 54 #elif BPP == 2 55 ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; 56 ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol; 57 ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol; 58 ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; 59 #else 60 ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; 61 ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; 62 ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; 63 ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; 64 ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; 65 ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; 66 ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; 67 ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; 68 #endif 69 } 70 71 static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize, 72 const uint8_t *font_ptr, int h, 73 uint32_t fgcol, uint32_t bgcol) 74 { 75 uint32_t font_data, xorcol; 76 77 xorcol = bgcol ^ fgcol; 78 do { 79 font_data = font_ptr[0]; 80 glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol); 81 font_ptr += 4; 82 d += linesize; 83 } while (--h); 84 } 85 86 static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize, 87 const uint8_t *font_ptr, int h, 88 uint32_t fgcol, uint32_t bgcol) 89 { 90 uint32_t font_data, xorcol; 91 92 xorcol = bgcol ^ fgcol; 93 do { 94 font_data = font_ptr[0]; 95 glue(vga_draw_glyph_line_, DEPTH)(d, 96 expand4to8[font_data >> 4], 97 xorcol, bgcol); 98 glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP, 99 expand4to8[font_data & 0x0f], 100 xorcol, bgcol); 101 font_ptr += 4; 102 d += linesize; 103 } while (--h); 104 } 105 106 static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize, 107 const uint8_t *font_ptr, int h, 108 uint32_t fgcol, uint32_t bgcol, int dup9) 109 { 110 uint32_t font_data, xorcol, v; 111 112 xorcol = bgcol ^ fgcol; 113 do { 114 font_data = font_ptr[0]; 115 #if BPP == 1 116 cpu_to_32wu((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol); 117 v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; 118 cpu_to_32wu(((uint32_t *)d)+1, v); 119 if (dup9) 120 ((uint8_t *)d)[8] = v >> (24 * (1 - BIG)); 121 else 122 ((uint8_t *)d)[8] = bgcol; 123 124 #elif BPP == 2 125 cpu_to_32wu(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol); 126 cpu_to_32wu(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol); 127 cpu_to_32wu(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol); 128 v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; 129 cpu_to_32wu(((uint32_t *)d)+3, v); 130 if (dup9) 131 ((uint16_t *)d)[8] = v >> (16 * (1 - BIG)); 132 else 133 ((uint16_t *)d)[8] = bgcol; 134 #else 135 ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; 136 ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; 137 ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; 138 ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; 139 ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; 140 ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; 141 ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; 142 v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; 143 ((uint32_t *)d)[7] = v; 144 if (dup9) 145 ((uint32_t *)d)[8] = v; 146 else 147 ((uint32_t *)d)[8] = bgcol; 148 #endif 149 font_ptr += 4; 150 d += linesize; 151 } while (--h); 152 } 153 154 /* 155 * 4 color mode 156 */ 157 static void glue(vga_draw_line2_, DEPTH)(VGACommonState *s1, uint8_t *d, 158 const uint8_t *s, int width) 159 { 160 uint32_t plane_mask, *palette, data, v; 161 int x; 162 163 palette = s1->last_palette; 164 plane_mask = mask16[s1->ar[0x12] & 0xf]; 165 width >>= 3; 166 for(x = 0; x < width; x++) { 167 data = ((uint32_t *)s)[0]; 168 data &= plane_mask; 169 v = expand2[GET_PLANE(data, 0)]; 170 v |= expand2[GET_PLANE(data, 2)] << 2; 171 ((PIXEL_TYPE *)d)[0] = palette[v >> 12]; 172 ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf]; 173 ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf]; 174 ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf]; 175 176 v = expand2[GET_PLANE(data, 1)]; 177 v |= expand2[GET_PLANE(data, 3)] << 2; 178 ((PIXEL_TYPE *)d)[4] = palette[v >> 12]; 179 ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf]; 180 ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf]; 181 ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf]; 182 d += BPP * 8; 183 s += 4; 184 } 185 } 186 187 #if BPP == 1 188 #define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v) 189 #elif BPP == 2 190 #define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v) 191 #else 192 #define PUT_PIXEL2(d, n, v) \ 193 ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v) 194 #endif 195 196 /* 197 * 4 color mode, dup2 horizontal 198 */ 199 static void glue(vga_draw_line2d2_, DEPTH)(VGACommonState *s1, uint8_t *d, 200 const uint8_t *s, int width) 201 { 202 uint32_t plane_mask, *palette, data, v; 203 int x; 204 205 palette = s1->last_palette; 206 plane_mask = mask16[s1->ar[0x12] & 0xf]; 207 width >>= 3; 208 for(x = 0; x < width; x++) { 209 data = ((uint32_t *)s)[0]; 210 data &= plane_mask; 211 v = expand2[GET_PLANE(data, 0)]; 212 v |= expand2[GET_PLANE(data, 2)] << 2; 213 PUT_PIXEL2(d, 0, palette[v >> 12]); 214 PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]); 215 PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]); 216 PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]); 217 218 v = expand2[GET_PLANE(data, 1)]; 219 v |= expand2[GET_PLANE(data, 3)] << 2; 220 PUT_PIXEL2(d, 4, palette[v >> 12]); 221 PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); 222 PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); 223 PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); 224 d += BPP * 16; 225 s += 4; 226 } 227 } 228 229 /* 230 * 16 color mode 231 */ 232 static void glue(vga_draw_line4_, DEPTH)(VGACommonState *s1, uint8_t *d, 233 const uint8_t *s, int width) 234 { 235 uint32_t plane_mask, data, v, *palette; 236 int x; 237 238 palette = s1->last_palette; 239 plane_mask = mask16[s1->ar[0x12] & 0xf]; 240 width >>= 3; 241 for(x = 0; x < width; x++) { 242 data = ((uint32_t *)s)[0]; 243 data &= plane_mask; 244 v = expand4[GET_PLANE(data, 0)]; 245 v |= expand4[GET_PLANE(data, 1)] << 1; 246 v |= expand4[GET_PLANE(data, 2)] << 2; 247 v |= expand4[GET_PLANE(data, 3)] << 3; 248 ((PIXEL_TYPE *)d)[0] = palette[v >> 28]; 249 ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf]; 250 ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf]; 251 ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf]; 252 ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf]; 253 ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf]; 254 ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf]; 255 ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf]; 256 d += BPP * 8; 257 s += 4; 258 } 259 } 260 261 /* 262 * 16 color mode, dup2 horizontal 263 */ 264 static void glue(vga_draw_line4d2_, DEPTH)(VGACommonState *s1, uint8_t *d, 265 const uint8_t *s, int width) 266 { 267 uint32_t plane_mask, data, v, *palette; 268 int x; 269 270 palette = s1->last_palette; 271 plane_mask = mask16[s1->ar[0x12] & 0xf]; 272 width >>= 3; 273 for(x = 0; x < width; x++) { 274 data = ((uint32_t *)s)[0]; 275 data &= plane_mask; 276 v = expand4[GET_PLANE(data, 0)]; 277 v |= expand4[GET_PLANE(data, 1)] << 1; 278 v |= expand4[GET_PLANE(data, 2)] << 2; 279 v |= expand4[GET_PLANE(data, 3)] << 3; 280 PUT_PIXEL2(d, 0, palette[v >> 28]); 281 PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]); 282 PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]); 283 PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]); 284 PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]); 285 PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); 286 PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); 287 PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); 288 d += BPP * 16; 289 s += 4; 290 } 291 } 292 293 /* 294 * 256 color mode, double pixels 295 * 296 * XXX: add plane_mask support (never used in standard VGA modes) 297 */ 298 static void glue(vga_draw_line8d2_, DEPTH)(VGACommonState *s1, uint8_t *d, 299 const uint8_t *s, int width) 300 { 301 uint32_t *palette; 302 int x; 303 304 palette = s1->last_palette; 305 width >>= 3; 306 for(x = 0; x < width; x++) { 307 PUT_PIXEL2(d, 0, palette[s[0]]); 308 PUT_PIXEL2(d, 1, palette[s[1]]); 309 PUT_PIXEL2(d, 2, palette[s[2]]); 310 PUT_PIXEL2(d, 3, palette[s[3]]); 311 d += BPP * 8; 312 s += 4; 313 } 314 } 315 316 /* 317 * standard 256 color mode 318 * 319 * XXX: add plane_mask support (never used in standard VGA modes) 320 */ 321 static void glue(vga_draw_line8_, DEPTH)(VGACommonState *s1, uint8_t *d, 322 const uint8_t *s, int width) 323 { 324 uint32_t *palette; 325 int x; 326 327 palette = s1->last_palette; 328 width >>= 3; 329 for(x = 0; x < width; x++) { 330 ((PIXEL_TYPE *)d)[0] = palette[s[0]]; 331 ((PIXEL_TYPE *)d)[1] = palette[s[1]]; 332 ((PIXEL_TYPE *)d)[2] = palette[s[2]]; 333 ((PIXEL_TYPE *)d)[3] = palette[s[3]]; 334 ((PIXEL_TYPE *)d)[4] = palette[s[4]]; 335 ((PIXEL_TYPE *)d)[5] = palette[s[5]]; 336 ((PIXEL_TYPE *)d)[6] = palette[s[6]]; 337 ((PIXEL_TYPE *)d)[7] = palette[s[7]]; 338 d += BPP * 8; 339 s += 8; 340 } 341 } 342 343 #endif /* DEPTH != 15 */ 344 345 346 /* XXX: optimize */ 347 348 /* 349 * 15 bit color 350 */ 351 static void glue(vga_draw_line15_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d, 352 const uint8_t *s, int width) 353 { 354 #if DEPTH == 15 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) 355 memcpy(d, s, width * 2); 356 #else 357 int w; 358 uint32_t v, r, g, b; 359 360 w = width; 361 do { 362 v = lduw_raw((void *)s); 363 r = (v >> 7) & 0xf8; 364 g = (v >> 2) & 0xf8; 365 b = (v << 3) & 0xf8; 366 ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); 367 s += 2; 368 d += BPP; 369 } while (--w != 0); 370 #endif 371 } 372 373 /* 374 * 16 bit color 375 */ 376 static void glue(vga_draw_line16_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d, 377 const uint8_t *s, int width) 378 { 379 #if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) 380 memcpy(d, s, width * 2); 381 #else 382 int w; 383 uint32_t v, r, g, b; 384 385 w = width; 386 do { 387 v = lduw_raw((void *)s); 388 r = (v >> 8) & 0xf8; 389 g = (v >> 3) & 0xfc; 390 b = (v << 3) & 0xf8; 391 ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); 392 s += 2; 393 d += BPP; 394 } while (--w != 0); 395 #endif 396 } 397 398 /* 399 * 24 bit color 400 */ 401 static void glue(vga_draw_line24_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d, 402 const uint8_t *s, int width) 403 { 404 int w; 405 uint32_t r, g, b; 406 407 w = width; 408 do { 409 #if defined(TARGET_WORDS_BIGENDIAN) 410 r = s[0]; 411 g = s[1]; 412 b = s[2]; 413 #else 414 b = s[0]; 415 g = s[1]; 416 r = s[2]; 417 #endif 418 ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); 419 s += 3; 420 d += BPP; 421 } while (--w != 0); 422 } 423 424 /* 425 * 32 bit color 426 */ 427 static void glue(vga_draw_line32_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d, 428 const uint8_t *s, int width) 429 { 430 #if DEPTH == 32 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) && !defined(BGR_FORMAT) 431 memcpy(d, s, width * 4); 432 #else 433 int w; 434 uint32_t r, g, b; 435 436 w = width; 437 do { 438 #if defined(TARGET_WORDS_BIGENDIAN) 439 r = s[1]; 440 g = s[2]; 441 b = s[3]; 442 #else 443 b = s[0]; 444 g = s[1]; 445 r = s[2]; 446 #endif 447 ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b); 448 s += 4; 449 d += BPP; 450 } while (--w != 0); 451 #endif 452 } 453 454 #undef PUT_PIXEL2 455 #undef DEPTH 456 #undef BPP 457 #undef PIXEL_TYPE 458 #undef PIXEL_NAME 459 #undef BGR_FORMAT 460