qemu/hw/vga_template.h
<<
>>
Prefs
   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
  46static 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
  71static 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
  86static 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
 106static 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 */
 157static 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 */
 199static 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 */
 232static 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 */
 264static 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 */
 298static 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 */
 321static 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
 343void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
 344                                        const uint8_t *src1,
 345                                        int poffset, int w,
 346                                        unsigned int color0,
 347                                        unsigned int color1,
 348                                        unsigned int color_xor)
 349{
 350    const uint8_t *plane0, *plane1;
 351    int x, b0, b1;
 352    uint8_t *d;
 353
 354    d = d1;
 355    plane0 = src1;
 356    plane1 = src1 + poffset;
 357    for(x = 0; x < w; x++) {
 358        b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
 359        b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
 360#if DEPTH == 8
 361        switch(b0 | (b1 << 1)) {
 362        case 0:
 363            break;
 364        case 1:
 365            d[0] ^= color_xor;
 366            break;
 367        case 2:
 368            d[0] = color0;
 369            break;
 370        case 3:
 371            d[0] = color1;
 372            break;
 373        }
 374#elif DEPTH == 16
 375        switch(b0 | (b1 << 1)) {
 376        case 0:
 377            break;
 378        case 1:
 379            ((uint16_t *)d)[0] ^= color_xor;
 380            break;
 381        case 2:
 382            ((uint16_t *)d)[0] = color0;
 383            break;
 384        case 3:
 385            ((uint16_t *)d)[0] = color1;
 386            break;
 387        }
 388#elif DEPTH == 32
 389        switch(b0 | (b1 << 1)) {
 390        case 0:
 391            break;
 392        case 1:
 393            ((uint32_t *)d)[0] ^= color_xor;
 394            break;
 395        case 2:
 396            ((uint32_t *)d)[0] = color0;
 397            break;
 398        case 3:
 399            ((uint32_t *)d)[0] = color1;
 400            break;
 401        }
 402#else
 403#error unsupported depth
 404#endif
 405        d += BPP;
 406    }
 407}
 408
 409#endif /* DEPTH != 15 */
 410
 411
 412/* XXX: optimize */
 413
 414/*
 415 * 15 bit color
 416 */
 417static void glue(vga_draw_line15_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 418                                          const uint8_t *s, int width)
 419{
 420#if DEPTH == 15 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
 421    memcpy(d, s, width * 2);
 422#else
 423    int w;
 424    uint32_t v, r, g, b;
 425
 426    w = width;
 427    do {
 428        v = lduw_raw((void *)s);
 429        r = (v >> 7) & 0xf8;
 430        g = (v >> 2) & 0xf8;
 431        b = (v << 3) & 0xf8;
 432        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 433        s += 2;
 434        d += BPP;
 435    } while (--w != 0);
 436#endif
 437}
 438
 439/*
 440 * 16 bit color
 441 */
 442static void glue(vga_draw_line16_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 443                                          const uint8_t *s, int width)
 444{
 445#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
 446    memcpy(d, s, width * 2);
 447#else
 448    int w;
 449    uint32_t v, r, g, b;
 450
 451    w = width;
 452    do {
 453        v = lduw_raw((void *)s);
 454        r = (v >> 8) & 0xf8;
 455        g = (v >> 3) & 0xfc;
 456        b = (v << 3) & 0xf8;
 457        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 458        s += 2;
 459        d += BPP;
 460    } while (--w != 0);
 461#endif
 462}
 463
 464/*
 465 * 24 bit color
 466 */
 467static void glue(vga_draw_line24_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 468                                          const uint8_t *s, int width)
 469{
 470    int w;
 471    uint32_t r, g, b;
 472
 473    w = width;
 474    do {
 475#if defined(TARGET_WORDS_BIGENDIAN)
 476        r = s[0];
 477        g = s[1];
 478        b = s[2];
 479#else
 480        b = s[0];
 481        g = s[1];
 482        r = s[2];
 483#endif
 484        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 485        s += 3;
 486        d += BPP;
 487    } while (--w != 0);
 488}
 489
 490/*
 491 * 32 bit color
 492 */
 493static void glue(vga_draw_line32_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 494                                          const uint8_t *s, int width)
 495{
 496#if DEPTH == 32 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) && !defined(BGR_FORMAT)
 497    memcpy(d, s, width * 4);
 498#else
 499    int w;
 500    uint32_t r, g, b;
 501
 502    w = width;
 503    do {
 504#if defined(TARGET_WORDS_BIGENDIAN)
 505        r = s[1];
 506        g = s[2];
 507        b = s[3];
 508#else
 509        b = s[0];
 510        g = s[1];
 511        r = s[2];
 512#endif
 513        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 514        s += 4;
 515        d += BPP;
 516    } while (--w != 0);
 517#endif
 518}
 519
 520#undef PUT_PIXEL2
 521#undef DEPTH
 522#undef BPP
 523#undef PIXEL_TYPE
 524#undef PIXEL_NAME
 525#undef BGR_FORMAT
 526