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