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