rasops15.c revision 1.21
1/* $NetBSD: rasops15.c,v 1.21 2017/01/25 14:53:43 jakllsch Exp $ */ 2 3/*- 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: rasops15.c,v 1.21 2017/01/25 14:53:43 jakllsch Exp $"); 34 35#include "opt_rasops.h" 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/time.h> 40 41#include <dev/wscons/wsdisplayvar.h> 42#include <dev/wscons/wsconsio.h> 43#include <dev/rasops/rasops.h> 44 45static void rasops15_putchar(void *, int, int, u_int, long attr); 46static void rasops15_putchar_aa(void *, int, int, u_int, long attr); 47#ifndef RASOPS_SMALL 48static void rasops15_putchar8(void *, int, int, u_int, long attr); 49static void rasops15_putchar12(void *, int, int, u_int, long attr); 50static void rasops15_putchar16(void *, int, int, u_int, long attr); 51static void rasops15_makestamp(struct rasops_info *, long); 52#endif 53 54#ifndef RASOPS_SMALL 55/* 56 * (2x2)x1 stamp for optimized character blitting 57 */ 58static int32_t stamp[32]; 59static long stamp_attr; 60static int stamp_mutex; /* XXX see note in readme */ 61 62/* 63 * XXX this confuses the hell out of gcc2 (not egcs) which always insists 64 * that the shift count is negative. 65 * 66 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK 67 * destination int32_t[0] = STAMP_READ(offset) 68 * destination int32_t[1] = STAMP_READ(offset + 4) 69 */ 70#define STAMP_SHIFT(fb,n) ((n*4-3) >= 0 ? (fb)>>(n*4-3):(fb)<<-(n*4-3)) 71#define STAMP_MASK (15 << 3) 72#define STAMP_READ(o) (*(int32_t *)((char *)stamp + (o))) 73#endif 74 75/* 76 * Initialize rasops_info struct for this colordepth. 77 */ 78void 79rasops15_init(struct rasops_info *ri) 80{ 81 82 if (FONT_IS_ALPHA(ri->ri_font)) { 83 ri->ri_ops.putchar = rasops15_putchar_aa; 84 } else { 85 switch (ri->ri_font->fontwidth) { 86#ifndef RASOPS_SMALL 87 case 8: 88 ri->ri_ops.putchar = rasops15_putchar8; 89 break; 90 91 case 12: 92 ri->ri_ops.putchar = rasops15_putchar12; 93 break; 94 95 case 16: 96 ri->ri_ops.putchar = rasops15_putchar16; 97 break; 98#endif /* !RASOPS_SMALL */ 99 default: 100 ri->ri_ops.putchar = rasops15_putchar; 101 break; 102 } 103 } 104 105 if (ri->ri_rnum == 0) { 106 ri->ri_rnum = 5; 107 ri->ri_rpos = 10 + (ri->ri_depth == 16); 108 ri->ri_gnum = 5 + (ri->ri_depth == 16); 109 ri->ri_gpos = 5; 110 ri->ri_bnum = 5; 111 ri->ri_bpos = 0; 112 } 113} 114 115/* 116 * Paint a single character. 117 */ 118static void 119rasops15_putchar(void *cookie, int row, int col, u_int uc, long attr) 120{ 121 int fb, width, height, cnt, clr[2]; 122 struct rasops_info *ri = (struct rasops_info *)cookie; 123 struct wsdisplay_font *font = PICK_FONT(ri, uc); 124 u_char *dp, *rp, *hp, *hrp, *fr; 125 126 hp = hrp = NULL; 127 128#ifdef RASOPS_CLIPPING 129 /* Catches 'row < 0' case too */ 130 if ((unsigned)row >= (unsigned)ri->ri_rows) 131 return; 132 133 if ((unsigned)col >= (unsigned)ri->ri_cols) 134 return; 135#endif 136 137 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; 138 if (ri->ri_hwbits) 139 hrp = ri->ri_hwbits + row * ri->ri_yscale + 140 col * ri->ri_xscale; 141 height = font->fontheight; 142 width = font->fontwidth; 143 144 clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 0xf]; 145 clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 0xf]; 146 147 if (uc == ' ') { 148 int16_t c = (int16_t)clr[0]; 149 while (height--) { 150 dp = rp; 151 rp += ri->ri_stride; 152 if (ri->ri_hwbits) { 153 hp = hrp; 154 hrp += ri->ri_stride; 155 } 156 157 for (cnt = width; cnt; cnt--) { 158 *(int16_t *)dp = c; 159 dp += 2; 160 if (ri->ri_hwbits) { 161 *(int16_t *)hp = c; 162 hp += 2; 163 } 164 } 165 } 166 } else { 167 uc -= font->firstchar; 168 fr = (u_char *)font->data + uc * ri->ri_fontscale; 169 170 while (height--) { 171 dp = rp; 172 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24); 173 fr += font->stride; 174 rp += ri->ri_stride; 175 if (ri->ri_hwbits) { 176 hp = hrp; 177 hrp += ri->ri_stride; 178 } 179 180 for (cnt = width; cnt; cnt--) { 181 *(int16_t *)dp = (int16_t)clr[(fb >> 31) & 1]; 182 if (ri->ri_hwbits) 183 *(int16_t *)hp = 184 (int16_t)clr[(fb >> 31) & 1]; 185 fb <<= 1; 186 dp += 2; 187 if (ri->ri_hwbits) 188 hp += 2; 189 } 190 } 191 } 192 193 /* Do underline */ 194 if ((attr & 1) != 0) { 195 int16_t c = (int16_t)clr[1]; 196 rp -= ri->ri_stride << 1; 197 if (ri->ri_hwbits) 198 hrp -= ri->ri_stride << 1; 199 200 while (width--) { 201 *(int16_t *)rp = c; 202 rp += 2; 203 if (ri->ri_hwbits) { 204 *(int16_t *)hrp = c; 205 hrp += 2; 206 } 207 } 208 } 209} 210 211static void 212rasops15_putchar_aa(void *cookie, int row, int col, u_int uc, long attr) 213{ 214 int width, height, cnt, clr[2]; 215 struct rasops_info *ri = (struct rasops_info *)cookie; 216 struct wsdisplay_font *font = PICK_FONT(ri, uc); 217 int16_t *dp, *rp; 218 uint8_t *rrp; 219 u_char *fr; 220 uint16_t buffer[64]; /* XXX */ 221 int x, y, r, g, b, aval; 222 int r1, g1, b1, r0, g0, b0, fgo, bgo; 223 224 225#ifdef RASOPS_CLIPPING 226 /* Catches 'row < 0' case too */ 227 if ((unsigned)row >= (unsigned)ri->ri_rows) 228 return; 229 230 if ((unsigned)col >= (unsigned)ri->ri_cols) 231 return; 232#endif 233 234 /* check if character fits into font limits */ 235 if (!CHAR_IN_FONT(uc, font)) 236 return; 237 238 rrp = (ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 239 rp = (int16_t *)rrp; 240 241 height = font->fontheight; 242 width = font->fontwidth; 243 244 clr[0] = ri->ri_devcmap[(attr >> 16) & 0xf]; 245 clr[1] = ri->ri_devcmap[(attr >> 24) & 0xf]; 246 247 if (uc == ' ') { 248 for (cnt = 0; cnt < width; cnt++) 249 buffer[cnt] = clr[0]; 250 while (height--) { 251 dp = rp; 252 DELTA(rp, ri->ri_stride, int16_t *); 253 memcpy(dp, buffer, width << 1); 254 } 255 } else { 256 fr = WSFONT_GLYPH(uc, font); 257 258 fgo = ((attr >> 24) & 0xf) * 3; 259 bgo = ((attr >> 16) & 0xf) * 3; 260 261 r0 = rasops_cmap[bgo]; 262 r1 = rasops_cmap[fgo]; 263 g0 = rasops_cmap[bgo + 1]; 264 g1 = rasops_cmap[fgo + 1]; 265 b0 = rasops_cmap[bgo + 2]; 266 b1 = rasops_cmap[fgo + 2]; 267 268 for (y = 0; y < height; y++) { 269 dp = (uint16_t *)(rrp + ri->ri_stride * y); 270 for (x = 0; x < width; x++) { 271 aval = *fr; 272 if (aval == 0) { 273 buffer[x] = clr[0]; 274 } else if (aval == 255) { 275 buffer[x] = clr[1]; 276 } else { 277 r = aval * r1 + (255 - aval) * r0; 278 g = aval * g1 + (255 - aval) * g0; 279 b = aval * b1 + (255 - aval) * b0; 280 buffer[x] = 281 ((r >> (16 - ri->ri_rnum)) << 282 ri->ri_rpos) | 283 ((g >> (16 - ri->ri_gnum)) << 284 ri->ri_gpos) | 285 ((b >> (16 - ri->ri_bnum)) << 286 ri->ri_bpos); 287 } 288 fr++; 289 } 290 memcpy(dp, buffer, width << 1); 291 } 292 } 293 294 /* Do underline */ 295 if ((attr & 1) != 0) { 296 rp = (uint16_t *)rrp; 297 DELTA(rp, (ri->ri_stride * (height - 2)), int16_t *); 298 while (width--) 299 *rp++ = clr[1]; 300 } 301} 302 303#ifndef RASOPS_SMALL 304/* 305 * Recompute the (2x2)x1 blitting stamp. 306 */ 307static void 308rasops15_makestamp(struct rasops_info *ri, long attr) 309{ 310 int32_t fg, bg; 311 int i; 312 313 fg = ri->ri_devcmap[((u_int)attr >> 24) & 0xf] & 0xffff; 314 bg = ri->ri_devcmap[((u_int)attr >> 16) & 0xf] & 0xffff; 315 stamp_attr = attr; 316 317 for (i = 0; i < 32; i += 2) { 318#if BYTE_ORDER == LITTLE_ENDIAN 319 stamp[i] = (i & 16 ? fg : bg); 320 stamp[i] |= ((i & 8 ? fg : bg) << 16); 321 stamp[i + 1] = (i & 4 ? fg : bg); 322 stamp[i + 1] |= ((i & 2 ? fg : bg) << 16); 323#else 324 stamp[i] = (i & 2 ? fg : bg); 325 stamp[i] |= ((i & 4 ? fg : bg) << 16); 326 stamp[i + 1] = (i & 8 ? fg : bg); 327 stamp[i + 1] |= ((i & 16 ? fg : bg) << 16); 328#endif 329 } 330} 331 332/* 333 * Paint a single character. This is for 8-pixel wide fonts. 334 */ 335static void 336rasops15_putchar8(void *cookie, int row, int col, u_int uc, long attr) 337{ 338 struct rasops_info *ri = (struct rasops_info *)cookie; 339 struct wsdisplay_font *font = PICK_FONT(ri, uc); 340 int height, so, fs; 341 int32_t *rp, *hrp; 342 u_char *fr; 343 344 /* Can't risk remaking the stamp if it's already in use */ 345 if (stamp_mutex++) { 346 stamp_mutex--; 347 rasops15_putchar(cookie, row, col, uc, attr); 348 return; 349 } 350 351 hrp = NULL; 352 353#ifdef RASOPS_CLIPPING 354 if ((unsigned)row >= (unsigned)ri->ri_rows) { 355 stamp_mutex--; 356 return; 357 } 358 359 if ((unsigned)col >= (unsigned)ri->ri_cols) { 360 stamp_mutex--; 361 return; 362 } 363#endif 364 365 /* Recompute stamp? */ 366 if (attr != stamp_attr) 367 rasops15_makestamp(ri, attr); 368 369 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 370 if (ri->ri_hwbits) 371 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 372 col*ri->ri_xscale); 373 height = font->fontheight; 374 375 if (uc == (u_int)-1) { 376 int32_t c = stamp[0]; 377 while (height--) { 378 rp[0] = rp[1] = rp[2] = rp[3] = c; 379 DELTA(rp, ri->ri_stride, int32_t *); 380 if (ri->ri_hwbits) { 381 hrp[0] = hrp[1] = hrp[2] = hrp[3] = c; 382 DELTA(hrp, ri->ri_stride, int32_t *); 383 } 384 } 385 } else { 386 uc -= font->firstchar; 387 fr = (u_char *)font->data + uc*ri->ri_fontscale; 388 fs = font->stride; 389 390 while (height--) { 391 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 392 rp[0] = STAMP_READ(so); 393 rp[1] = STAMP_READ(so + 4); 394 if (ri->ri_hwbits) { 395 hrp[0] = STAMP_READ(so); 396 hrp[1] = STAMP_READ(so + 4); 397 } 398 399 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 400 rp[2] = STAMP_READ(so); 401 rp[3] = STAMP_READ(so + 4); 402 if (ri->ri_hwbits) { 403 hrp[2] = STAMP_READ(so); 404 hrp[3] = STAMP_READ(so + 4); 405 } 406 407 fr += fs; 408 DELTA(rp, ri->ri_stride, int32_t *); 409 if (ri->ri_hwbits) 410 DELTA(hrp, ri->ri_stride, int32_t *); 411 } 412 } 413 414 /* Do underline */ 415 if ((attr & 1) != 0) { 416 int32_t c = STAMP_READ(28); 417 418 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 419 rp[0] = rp[1] = rp[2] = rp[3] = c; 420 if (ri->ri_hwbits) { 421 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 422 hrp[0] = hrp[1] = hrp[2] = hrp[3] = c; 423 } 424 } 425 426 stamp_mutex--; 427} 428 429/* 430 * Paint a single character. This is for 12-pixel wide fonts. 431 */ 432static void 433rasops15_putchar12(void *cookie, int row, int col, u_int uc, long attr) 434{ 435 struct rasops_info *ri = (struct rasops_info *)cookie; 436 struct wsdisplay_font *font = PICK_FONT(ri, uc); 437 int height, so, fs; 438 int32_t *rp, *hrp; 439 u_char *fr; 440 441 /* Can't risk remaking the stamp if it's already in use */ 442 if (stamp_mutex++) { 443 stamp_mutex--; 444 rasops15_putchar(cookie, row, col, uc, attr); 445 return; 446 } 447 448 hrp = NULL; 449 450#ifdef RASOPS_CLIPPING 451 if ((unsigned)row >= (unsigned)ri->ri_rows) { 452 stamp_mutex--; 453 return; 454 } 455 456 if ((unsigned)col >= (unsigned)ri->ri_cols) { 457 stamp_mutex--; 458 return; 459 } 460#endif 461 462 /* Recompute stamp? */ 463 if (attr != stamp_attr) 464 rasops15_makestamp(ri, attr); 465 466 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 467 if (ri->ri_hwbits) 468 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 469 col*ri->ri_xscale); 470 height = font->fontheight; 471 472 if (uc == (u_int)-1) { 473 int32_t c = stamp[0]; 474 while (height--) { 475 rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c; 476 DELTA(rp, ri->ri_stride, int32_t *); 477 if (ri->ri_hwbits) { 478 hrp[0] = hrp[1] = hrp[2] = hrp[3] = hrp[4] = 479 hrp[5] = c; 480 DELTA(hrp, ri->ri_stride, int32_t *); 481 } 482 } 483 } else { 484 uc -= font->firstchar; 485 fr = (u_char *)font->data + uc*ri->ri_fontscale; 486 fs = font->stride; 487 488 while (height--) { 489 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 490 rp[0] = STAMP_READ(so); 491 rp[1] = STAMP_READ(so + 4); 492 if (ri->ri_hwbits) { 493 hrp[0] = STAMP_READ(so); 494 hrp[1] = STAMP_READ(so + 4); 495 } 496 497 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 498 rp[2] = STAMP_READ(so); 499 rp[3] = STAMP_READ(so + 4); 500 if (ri->ri_hwbits) { 501 hrp[2] = STAMP_READ(so); 502 hrp[3] = STAMP_READ(so + 4); 503 } 504 505 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK; 506 rp[4] = STAMP_READ(so); 507 rp[5] = STAMP_READ(so + 4); 508 if (ri->ri_hwbits) { 509 hrp[4] = STAMP_READ(so); 510 hrp[5] = STAMP_READ(so + 4); 511 } 512 513 fr += fs; 514 DELTA(rp, ri->ri_stride, int32_t *); 515 if (ri->ri_hwbits) 516 DELTA(hrp, ri->ri_stride, int32_t *); 517 } 518 } 519 520 /* Do underline */ 521 if (attr & 1) { 522 int32_t c = STAMP_READ(28); 523 524 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 525 rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c; 526 if (ri->ri_hwbits) { 527 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 528 hrp[0] = hrp[1] = hrp[2] = hrp[3] = hrp[4] = hrp[5] = c; 529 } 530 } 531 532 stamp_mutex--; 533} 534 535/* 536 * Paint a single character. This is for 16-pixel wide fonts. 537 */ 538static void 539rasops15_putchar16(void *cookie, int row, int col, u_int uc, long attr) 540{ 541 struct rasops_info *ri = (struct rasops_info *)cookie; 542 struct wsdisplay_font *font = PICK_FONT(ri, uc); 543 int height, so, fs; 544 int32_t *rp, *hrp; 545 u_char *fr; 546 547 /* Can't risk remaking the stamp if it's already in use */ 548 if (stamp_mutex++) { 549 stamp_mutex--; 550 rasops15_putchar(cookie, row, col, uc, attr); 551 return; 552 } 553 554 hrp = NULL; 555 556#ifdef RASOPS_CLIPPING 557 if ((unsigned)row >= (unsigned)ri->ri_rows) { 558 stamp_mutex--; 559 return; 560 } 561 562 if ((unsigned)col >= (unsigned)ri->ri_cols) { 563 stamp_mutex--; 564 return; 565 } 566#endif 567 568 /* Recompute stamp? */ 569 if (attr != stamp_attr) 570 rasops15_makestamp(ri, attr); 571 572 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 573 if (ri->ri_hwbits) 574 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 575 col*ri->ri_xscale); 576 height = font->fontheight; 577 578 if (uc == (u_int)-1) { 579 int32_t c = stamp[0]; 580 while (height--) { 581 rp[0] = rp[1] = rp[2] = rp[3] = 582 rp[4] = rp[5] = rp[6] = rp[7] = c; 583 DELTA(rp, ri->ri_stride, int32_t *); 584 if (ri->ri_hwbits) { 585 hrp[0] = hrp[1] = hrp[2] = hrp[3] = 586 hrp[4] = hrp[5] = hrp[6] = hrp[7] = c; 587 DELTA(hrp, ri->ri_stride, int32_t *); 588 } 589 } 590 } else { 591 uc -= font->firstchar; 592 fr = (u_char *)font->data + uc*ri->ri_fontscale; 593 fs = font->stride; 594 595 while (height--) { 596 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 597 rp[0] = STAMP_READ(so); 598 rp[1] = STAMP_READ(so + 4); 599 if (ri->ri_hwbits) { 600 hrp[0] = STAMP_READ(so); 601 hrp[1] = STAMP_READ(so + 4); 602 } 603 604 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 605 rp[2] = STAMP_READ(so); 606 rp[3] = STAMP_READ(so + 4); 607 if (ri->ri_hwbits) { 608 hrp[2] = STAMP_READ(so); 609 hrp[3] = STAMP_READ(so + 4); 610 } 611 612 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK; 613 rp[4] = STAMP_READ(so); 614 rp[5] = STAMP_READ(so + 4); 615 if (ri->ri_hwbits) { 616 hrp[4] = STAMP_READ(so); 617 hrp[5] = STAMP_READ(so + 4); 618 } 619 620 so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK; 621 rp[6] = STAMP_READ(so); 622 rp[7] = STAMP_READ(so + 4); 623 if (ri->ri_hwbits) { 624 hrp[6] = STAMP_READ(so); 625 hrp[7] = STAMP_READ(so + 4); 626 } 627 628 DELTA(rp, ri->ri_stride, int32_t *); 629 if (ri->ri_hwbits) 630 DELTA(hrp, ri->ri_stride, int32_t *); 631 fr += fs; 632 } 633 } 634 635 /* Do underline */ 636 if (attr & 1) { 637 int32_t c = STAMP_READ(28); 638 639 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 640 rp[0] = rp[1] = rp[2] = rp[3] = 641 rp[4] = rp[5] = rp[6] = rp[7] = c; 642 if (ri->ri_hwbits) { 643 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 644 hrp[0] = hrp[1] = hrp[2] = hrp[3] = 645 hrp[4] = hrp[5] = hrp[6] = hrp[7] = c; 646 } 647 } 648 649 stamp_mutex--; 650} 651#endif /* !RASOPS_SMALL */ 652