qemu/hw/display/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[VGA_ATC_PLANE_ENABLE] & 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[VGA_ATC_PLANE_ENABLE] & 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[VGA_ATC_PLANE_ENABLE] & 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[VGA_ATC_PLANE_ENABLE] & 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
 343#endif /* DEPTH != 15 */
 344
 345
 346/* XXX: optimize */
 347
 348/*
 349 * 15 bit color
 350 */
 351static 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 */
 376static 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 */
 401static 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 */
 427static 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