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