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 static 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 38 static 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 53 static 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 71 static 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 98 /* 99 * 4 color mode 100 */ 101 static void vga_draw_line2(VGACommonState *s1, uint8_t *d, 102 const uint8_t *s, int width) 103 { 104 uint32_t plane_mask, *palette, data, v; 105 int x; 106 107 palette = s1->last_palette; 108 plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; 109 width >>= 3; 110 for(x = 0; x < width; x++) { 111 data = ((uint32_t *)s)[0]; 112 data &= plane_mask; 113 v = expand2[GET_PLANE(data, 0)]; 114 v |= expand2[GET_PLANE(data, 2)] << 2; 115 ((uint32_t *)d)[0] = palette[v >> 12]; 116 ((uint32_t *)d)[1] = palette[(v >> 8) & 0xf]; 117 ((uint32_t *)d)[2] = palette[(v >> 4) & 0xf]; 118 ((uint32_t *)d)[3] = palette[(v >> 0) & 0xf]; 119 120 v = expand2[GET_PLANE(data, 1)]; 121 v |= expand2[GET_PLANE(data, 3)] << 2; 122 ((uint32_t *)d)[4] = palette[v >> 12]; 123 ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf]; 124 ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; 125 ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; 126 d += 32; 127 s += 4; 128 } 129 } 130 131 #define PUT_PIXEL2(d, n, v) \ 132 ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v) 133 134 /* 135 * 4 color mode, dup2 horizontal 136 */ 137 static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d, 138 const uint8_t *s, int width) 139 { 140 uint32_t plane_mask, *palette, data, v; 141 int x; 142 143 palette = s1->last_palette; 144 plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; 145 width >>= 3; 146 for(x = 0; x < width; x++) { 147 data = ((uint32_t *)s)[0]; 148 data &= plane_mask; 149 v = expand2[GET_PLANE(data, 0)]; 150 v |= expand2[GET_PLANE(data, 2)] << 2; 151 PUT_PIXEL2(d, 0, palette[v >> 12]); 152 PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]); 153 PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]); 154 PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]); 155 156 v = expand2[GET_PLANE(data, 1)]; 157 v |= expand2[GET_PLANE(data, 3)] << 2; 158 PUT_PIXEL2(d, 4, palette[v >> 12]); 159 PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); 160 PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); 161 PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); 162 d += 64; 163 s += 4; 164 } 165 } 166 167 /* 168 * 16 color mode 169 */ 170 static void vga_draw_line4(VGACommonState *s1, uint8_t *d, 171 const uint8_t *s, int width) 172 { 173 uint32_t plane_mask, data, v, *palette; 174 int x; 175 176 palette = s1->last_palette; 177 plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; 178 width >>= 3; 179 for(x = 0; x < width; x++) { 180 data = ((uint32_t *)s)[0]; 181 data &= plane_mask; 182 v = expand4[GET_PLANE(data, 0)]; 183 v |= expand4[GET_PLANE(data, 1)] << 1; 184 v |= expand4[GET_PLANE(data, 2)] << 2; 185 v |= expand4[GET_PLANE(data, 3)] << 3; 186 ((uint32_t *)d)[0] = palette[v >> 28]; 187 ((uint32_t *)d)[1] = palette[(v >> 24) & 0xf]; 188 ((uint32_t *)d)[2] = palette[(v >> 20) & 0xf]; 189 ((uint32_t *)d)[3] = palette[(v >> 16) & 0xf]; 190 ((uint32_t *)d)[4] = palette[(v >> 12) & 0xf]; 191 ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf]; 192 ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; 193 ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; 194 d += 32; 195 s += 4; 196 } 197 } 198 199 /* 200 * 16 color mode, dup2 horizontal 201 */ 202 static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d, 203 const uint8_t *s, int width) 204 { 205 uint32_t plane_mask, data, v, *palette; 206 int x; 207 208 palette = s1->last_palette; 209 plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; 210 width >>= 3; 211 for(x = 0; x < width; x++) { 212 data = ((uint32_t *)s)[0]; 213 data &= plane_mask; 214 v = expand4[GET_PLANE(data, 0)]; 215 v |= expand4[GET_PLANE(data, 1)] << 1; 216 v |= expand4[GET_PLANE(data, 2)] << 2; 217 v |= expand4[GET_PLANE(data, 3)] << 3; 218 PUT_PIXEL2(d, 0, palette[v >> 28]); 219 PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]); 220 PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]); 221 PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]); 222 PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]); 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 += 64; 227 s += 4; 228 } 229 } 230 231 /* 232 * 256 color mode, double pixels 233 * 234 * XXX: add plane_mask support (never used in standard VGA modes) 235 */ 236 static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d, 237 const uint8_t *s, int width) 238 { 239 uint32_t *palette; 240 int x; 241 242 palette = s1->last_palette; 243 width >>= 3; 244 for(x = 0; x < width; x++) { 245 PUT_PIXEL2(d, 0, palette[s[0]]); 246 PUT_PIXEL2(d, 1, palette[s[1]]); 247 PUT_PIXEL2(d, 2, palette[s[2]]); 248 PUT_PIXEL2(d, 3, palette[s[3]]); 249 d += 32; 250 s += 4; 251 } 252 } 253 254 /* 255 * standard 256 color mode 256 * 257 * XXX: add plane_mask support (never used in standard VGA modes) 258 */ 259 static void vga_draw_line8(VGACommonState *s1, uint8_t *d, 260 const uint8_t *s, int width) 261 { 262 uint32_t *palette; 263 int x; 264 265 palette = s1->last_palette; 266 width >>= 3; 267 for(x = 0; x < width; x++) { 268 ((uint32_t *)d)[0] = palette[s[0]]; 269 ((uint32_t *)d)[1] = palette[s[1]]; 270 ((uint32_t *)d)[2] = palette[s[2]]; 271 ((uint32_t *)d)[3] = palette[s[3]]; 272 ((uint32_t *)d)[4] = palette[s[4]]; 273 ((uint32_t *)d)[5] = palette[s[5]]; 274 ((uint32_t *)d)[6] = palette[s[6]]; 275 ((uint32_t *)d)[7] = palette[s[7]]; 276 d += 32; 277 s += 8; 278 } 279 } 280 281 /* 282 * 15 bit color 283 */ 284 static void vga_draw_line15_le(VGACommonState *s1, uint8_t *d, 285 const uint8_t *s, int width) 286 { 287 int w; 288 uint32_t v, r, g, b; 289 290 w = width; 291 do { 292 v = lduw_le_p((void *)s); 293 r = (v >> 7) & 0xf8; 294 g = (v >> 2) & 0xf8; 295 b = (v << 3) & 0xf8; 296 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 297 s += 2; 298 d += 4; 299 } while (--w != 0); 300 } 301 302 static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d, 303 const uint8_t *s, int width) 304 { 305 int w; 306 uint32_t v, r, g, b; 307 308 w = width; 309 do { 310 v = lduw_be_p((void *)s); 311 r = (v >> 7) & 0xf8; 312 g = (v >> 2) & 0xf8; 313 b = (v << 3) & 0xf8; 314 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 315 s += 2; 316 d += 4; 317 } while (--w != 0); 318 } 319 320 /* 321 * 16 bit color 322 */ 323 static void vga_draw_line16_le(VGACommonState *s1, uint8_t *d, 324 const uint8_t *s, int width) 325 { 326 int w; 327 uint32_t v, r, g, b; 328 329 w = width; 330 do { 331 v = lduw_le_p((void *)s); 332 r = (v >> 8) & 0xf8; 333 g = (v >> 3) & 0xfc; 334 b = (v << 3) & 0xf8; 335 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 336 s += 2; 337 d += 4; 338 } while (--w != 0); 339 } 340 341 static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d, 342 const uint8_t *s, int width) 343 { 344 int w; 345 uint32_t v, r, g, b; 346 347 w = width; 348 do { 349 v = lduw_be_p((void *)s); 350 r = (v >> 8) & 0xf8; 351 g = (v >> 3) & 0xfc; 352 b = (v << 3) & 0xf8; 353 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 354 s += 2; 355 d += 4; 356 } while (--w != 0); 357 } 358 359 /* 360 * 24 bit color 361 */ 362 static void vga_draw_line24_le(VGACommonState *s1, uint8_t *d, 363 const uint8_t *s, int width) 364 { 365 int w; 366 uint32_t r, g, b; 367 368 w = width; 369 do { 370 b = s[0]; 371 g = s[1]; 372 r = s[2]; 373 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 374 s += 3; 375 d += 4; 376 } while (--w != 0); 377 } 378 379 static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d, 380 const uint8_t *s, int width) 381 { 382 int w; 383 uint32_t r, g, b; 384 385 w = width; 386 do { 387 r = s[0]; 388 g = s[1]; 389 b = s[2]; 390 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 391 s += 3; 392 d += 4; 393 } while (--w != 0); 394 } 395 396 /* 397 * 32 bit color 398 */ 399 static void vga_draw_line32_le(VGACommonState *s1, uint8_t *d, 400 const uint8_t *s, int width) 401 { 402 #ifndef HOST_WORDS_BIGENDIAN 403 memcpy(d, s, width * 4); 404 #else 405 int w; 406 uint32_t r, g, b; 407 408 w = width; 409 do { 410 b = s[0]; 411 g = s[1]; 412 r = s[2]; 413 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 414 s += 4; 415 d += 4; 416 } while (--w != 0); 417 #endif 418 } 419 420 static void vga_draw_line32_be(VGACommonState *s1, uint8_t *d, 421 const uint8_t *s, int width) 422 { 423 #ifdef HOST_WORDS_BIGENDIAN 424 memcpy(d, s, width * 4); 425 #else 426 int w; 427 uint32_t r, g, b; 428 429 w = width; 430 do { 431 r = s[1]; 432 g = s[2]; 433 b = s[3]; 434 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 435 s += 4; 436 d += 4; 437 } while (--w != 0); 438 #endif 439 } 440