rasops15.c revision 1.16
1/* $NetBSD: rasops15.c,v 1.16 2008/04/28 20:23:56 martin 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.16 2008/04/28 20:23:56 martin 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); 46#ifndef RASOPS_SMALL 47static void rasops15_putchar8(void *, int, int, u_int, long attr); 48static void rasops15_putchar12(void *, int, int, u_int, long attr); 49static void rasops15_putchar16(void *, int, int, u_int, long attr); 50static void rasops15_makestamp(struct rasops_info *, long); 51#endif 52 53#ifndef RASOPS_SMALL 54/* 55 * (2x2)x1 stamp for optimized character blitting 56 */ 57static int32_t stamp[32]; 58static long stamp_attr; 59static int stamp_mutex; /* XXX see note in readme */ 60 61/* 62 * XXX this confuses the hell out of gcc2 (not egcs) which always insists 63 * that the shift count is negative. 64 * 65 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK 66 * destination int32_t[0] = STAMP_READ(offset) 67 * destination int32_t[1] = STAMP_READ(offset + 4) 68 */ 69#define STAMP_SHIFT(fb,n) ((n*4-3) >= 0 ? (fb)>>(n*4-3):(fb)<<-(n*4-3)) 70#define STAMP_MASK (15 << 3) 71#define STAMP_READ(o) (*(int32_t *)((char *)stamp + (o))) 72#endif 73 74/* 75 * Initialize rasops_info struct for this colordepth. 76 */ 77void 78rasops15_init(ri) 79 struct rasops_info *ri; 80{ 81 82 switch (ri->ri_font->fontwidth) { 83#ifndef RASOPS_SMALL 84 case 8: 85 ri->ri_ops.putchar = rasops15_putchar8; 86 break; 87 88 case 12: 89 ri->ri_ops.putchar = rasops15_putchar12; 90 break; 91 92 case 16: 93 ri->ri_ops.putchar = rasops15_putchar16; 94 break; 95#endif /* !RASOPS_SMALL */ 96 default: 97 ri->ri_ops.putchar = rasops15_putchar; 98 break; 99 } 100 101 if (ri->ri_rnum == 0) { 102 ri->ri_rnum = 5; 103 ri->ri_rpos = 0; 104 ri->ri_gnum = 5 + (ri->ri_depth == 16); 105 ri->ri_gpos = 5; 106 ri->ri_bnum = 5; 107 ri->ri_bpos = 10 + (ri->ri_depth == 16); 108 } 109} 110 111/* 112 * Paint a single character. 113 */ 114static void 115rasops15_putchar(cookie, row, col, uc, attr) 116 void *cookie; 117 int row, col; 118 u_int uc; 119 long attr; 120{ 121 int fb, width, height, cnt, clr[2]; 122 struct rasops_info *ri; 123 u_char *dp, *rp, *hp, *hrp, *fr; 124 125 ri = (struct rasops_info *)cookie; 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 = ri->ri_font->fontheight; 142 width = ri->ri_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 -= ri->ri_font->firstchar; 168 fr = (u_char *)ri->ri_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 += ri->ri_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 211#ifndef RASOPS_SMALL 212/* 213 * Recompute the (2x2)x1 blitting stamp. 214 */ 215static void 216rasops15_makestamp(ri, attr) 217 struct rasops_info *ri; 218 long attr; 219{ 220 int32_t fg, bg; 221 int i; 222 223 fg = ri->ri_devcmap[((u_int)attr >> 24) & 0xf] & 0xffff; 224 bg = ri->ri_devcmap[((u_int)attr >> 16) & 0xf] & 0xffff; 225 stamp_attr = attr; 226 227 for (i = 0; i < 32; i += 2) { 228#if BYTE_ORDER == LITTLE_ENDIAN 229 stamp[i] = (i & 16 ? fg : bg); 230 stamp[i] |= ((i & 8 ? fg : bg) << 16); 231 stamp[i + 1] = (i & 4 ? fg : bg); 232 stamp[i + 1] |= ((i & 2 ? fg : bg) << 16); 233#else 234 stamp[i] = (i & 2 ? fg : bg); 235 stamp[i] |= ((i & 4 ? fg : bg) << 16); 236 stamp[i + 1] = (i & 8 ? fg : bg); 237 stamp[i + 1] |= ((i & 16 ? fg : bg) << 16); 238#endif 239 } 240} 241 242/* 243 * Paint a single character. This is for 8-pixel wide fonts. 244 */ 245static void 246rasops15_putchar8(cookie, row, col, uc, attr) 247 void *cookie; 248 int row, col; 249 u_int uc; 250 long attr; 251{ 252 struct rasops_info *ri; 253 int height, so, fs; 254 int32_t *rp, *hrp; 255 u_char *fr; 256 257 /* Can't risk remaking the stamp if it's already in use */ 258 if (stamp_mutex++) { 259 stamp_mutex--; 260 rasops15_putchar(cookie, row, col, uc, attr); 261 return; 262 } 263 264 ri = (struct rasops_info *)cookie; 265 hrp = NULL; 266 267#ifdef RASOPS_CLIPPING 268 if ((unsigned)row >= (unsigned)ri->ri_rows) { 269 stamp_mutex--; 270 return; 271 } 272 273 if ((unsigned)col >= (unsigned)ri->ri_cols) { 274 stamp_mutex--; 275 return; 276 } 277#endif 278 279 /* Recompute stamp? */ 280 if (attr != stamp_attr) 281 rasops15_makestamp(ri, attr); 282 283 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 284 if (ri->ri_hwbits) 285 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 286 col*ri->ri_xscale); 287 height = ri->ri_font->fontheight; 288 289 if (uc == (u_int)-1) { 290 int32_t c = stamp[0]; 291 while (height--) { 292 rp[0] = rp[1] = rp[2] = rp[3] = c; 293 DELTA(rp, ri->ri_stride, int32_t *); 294 if (ri->ri_hwbits) { 295 hrp[0] = hrp[1] = hrp[2] = hrp[3] = c; 296 DELTA(hrp, ri->ri_stride, int32_t *); 297 } 298 } 299 } else { 300 uc -= ri->ri_font->firstchar; 301 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale; 302 fs = ri->ri_font->stride; 303 304 while (height--) { 305 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 306 rp[0] = STAMP_READ(so); 307 rp[1] = STAMP_READ(so + 4); 308 if (ri->ri_hwbits) { 309 hrp[0] = STAMP_READ(so); 310 hrp[1] = STAMP_READ(so + 4); 311 } 312 313 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 314 rp[2] = STAMP_READ(so); 315 rp[3] = STAMP_READ(so + 4); 316 if (ri->ri_hwbits) { 317 hrp[2] = STAMP_READ(so); 318 hrp[3] = STAMP_READ(so + 4); 319 } 320 321 fr += fs; 322 DELTA(rp, ri->ri_stride, int32_t *); 323 if (ri->ri_hwbits) 324 DELTA(hrp, ri->ri_stride, int32_t *); 325 } 326 } 327 328 /* Do underline */ 329 if ((attr & 1) != 0) { 330 int32_t c = STAMP_READ(28); 331 332 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 333 rp[0] = rp[1] = rp[2] = rp[3] = c; 334 if (ri->ri_hwbits) { 335 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 336 hrp[0] = hrp[1] = hrp[2] = hrp[3] = c; 337 } 338 } 339 340 stamp_mutex--; 341} 342 343/* 344 * Paint a single character. This is for 12-pixel wide fonts. 345 */ 346static void 347rasops15_putchar12(cookie, row, col, uc, attr) 348 void *cookie; 349 int row, col; 350 u_int uc; 351 long attr; 352{ 353 struct rasops_info *ri; 354 int height, so, fs; 355 int32_t *rp, *hrp; 356 u_char *fr; 357 358 /* Can't risk remaking the stamp if it's already in use */ 359 if (stamp_mutex++) { 360 stamp_mutex--; 361 rasops15_putchar(cookie, row, col, uc, attr); 362 return; 363 } 364 365 ri = (struct rasops_info *)cookie; 366 hrp = NULL; 367 368#ifdef RASOPS_CLIPPING 369 if ((unsigned)row >= (unsigned)ri->ri_rows) { 370 stamp_mutex--; 371 return; 372 } 373 374 if ((unsigned)col >= (unsigned)ri->ri_cols) { 375 stamp_mutex--; 376 return; 377 } 378#endif 379 380 /* Recompute stamp? */ 381 if (attr != stamp_attr) 382 rasops15_makestamp(ri, attr); 383 384 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 385 if (ri->ri_hwbits) 386 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 387 col*ri->ri_xscale); 388 height = ri->ri_font->fontheight; 389 390 if (uc == (u_int)-1) { 391 int32_t c = stamp[0]; 392 while (height--) { 393 rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c; 394 DELTA(rp, ri->ri_stride, int32_t *); 395 if (ri->ri_hwbits) { 396 hrp[0] = hrp[1] = hrp[2] = hrp[3] = hrp[4] = 397 hrp[5] = c; 398 DELTA(hrp, ri->ri_stride, int32_t *); 399 } 400 } 401 } else { 402 uc -= ri->ri_font->firstchar; 403 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale; 404 fs = ri->ri_font->stride; 405 406 while (height--) { 407 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 408 rp[0] = STAMP_READ(so); 409 rp[1] = STAMP_READ(so + 4); 410 if (ri->ri_hwbits) { 411 hrp[0] = STAMP_READ(so); 412 hrp[1] = STAMP_READ(so + 4); 413 } 414 415 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 416 rp[2] = STAMP_READ(so); 417 rp[3] = STAMP_READ(so + 4); 418 if (ri->ri_hwbits) { 419 hrp[2] = STAMP_READ(so); 420 hrp[3] = STAMP_READ(so + 4); 421 } 422 423 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK; 424 rp[4] = STAMP_READ(so); 425 rp[5] = STAMP_READ(so + 4); 426 if (ri->ri_hwbits) { 427 hrp[4] = STAMP_READ(so); 428 hrp[5] = STAMP_READ(so + 4); 429 } 430 431 fr += fs; 432 DELTA(rp, ri->ri_stride, int32_t *); 433 if (ri->ri_hwbits) 434 DELTA(hrp, ri->ri_stride, int32_t *); 435 } 436 } 437 438 /* Do underline */ 439 if (attr & 1) { 440 int32_t c = STAMP_READ(28); 441 442 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 443 rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c; 444 if (ri->ri_hwbits) { 445 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 446 hrp[0] = hrp[1] = hrp[2] = hrp[3] = hrp[4] = hrp[5] = c; 447 } 448 } 449 450 stamp_mutex--; 451} 452 453/* 454 * Paint a single character. This is for 16-pixel wide fonts. 455 */ 456static void 457rasops15_putchar16(cookie, row, col, uc, attr) 458 void *cookie; 459 int row, col; 460 u_int uc; 461 long attr; 462{ 463 struct rasops_info *ri; 464 int height, so, fs; 465 int32_t *rp, *hrp; 466 u_char *fr; 467 468 /* Can't risk remaking the stamp if it's already in use */ 469 if (stamp_mutex++) { 470 stamp_mutex--; 471 rasops15_putchar(cookie, row, col, uc, attr); 472 return; 473 } 474 475 ri = (struct rasops_info *)cookie; 476 hrp = NULL; 477 478#ifdef RASOPS_CLIPPING 479 if ((unsigned)row >= (unsigned)ri->ri_rows) { 480 stamp_mutex--; 481 return; 482 } 483 484 if ((unsigned)col >= (unsigned)ri->ri_cols) { 485 stamp_mutex--; 486 return; 487 } 488#endif 489 490 /* Recompute stamp? */ 491 if (attr != stamp_attr) 492 rasops15_makestamp(ri, attr); 493 494 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 495 if (ri->ri_hwbits) 496 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 497 col*ri->ri_xscale); 498 height = ri->ri_font->fontheight; 499 500 if (uc == (u_int)-1) { 501 int32_t c = stamp[0]; 502 while (height--) { 503 rp[0] = rp[1] = rp[2] = rp[3] = 504 rp[4] = rp[5] = rp[6] = rp[7] = c; 505 DELTA(rp, ri->ri_stride, int32_t *); 506 if (ri->ri_hwbits) { 507 hrp[0] = hrp[1] = hrp[2] = hrp[3] = 508 hrp[4] = hrp[5] = hrp[6] = hrp[7] = c; 509 DELTA(hrp, ri->ri_stride, int32_t *); 510 } 511 } 512 } else { 513 uc -= ri->ri_font->firstchar; 514 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale; 515 fs = ri->ri_font->stride; 516 517 while (height--) { 518 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 519 rp[0] = STAMP_READ(so); 520 rp[1] = STAMP_READ(so + 4); 521 if (ri->ri_hwbits) { 522 hrp[0] = STAMP_READ(so); 523 hrp[1] = STAMP_READ(so + 4); 524 } 525 526 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 527 rp[2] = STAMP_READ(so); 528 rp[3] = STAMP_READ(so + 4); 529 if (ri->ri_hwbits) { 530 hrp[2] = STAMP_READ(so); 531 hrp[3] = STAMP_READ(so + 4); 532 } 533 534 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK; 535 rp[4] = STAMP_READ(so); 536 rp[5] = STAMP_READ(so + 4); 537 if (ri->ri_hwbits) { 538 hrp[4] = STAMP_READ(so); 539 hrp[5] = STAMP_READ(so + 4); 540 } 541 542 so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK; 543 rp[6] = STAMP_READ(so); 544 rp[7] = STAMP_READ(so + 4); 545 if (ri->ri_hwbits) { 546 hrp[6] = STAMP_READ(so); 547 hrp[7] = STAMP_READ(so + 4); 548 } 549 550 DELTA(rp, ri->ri_stride, int32_t *); 551 if (ri->ri_hwbits) 552 DELTA(hrp, ri->ri_stride, int32_t *); 553 fr += fs; 554 } 555 } 556 557 /* Do underline */ 558 if (attr & 1) { 559 int32_t c = STAMP_READ(28); 560 561 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 562 rp[0] = rp[1] = rp[2] = rp[3] = 563 rp[4] = rp[5] = rp[6] = rp[7] = c; 564 if (ri->ri_hwbits) { 565 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 566 hrp[0] = hrp[1] = hrp[2] = hrp[3] = 567 hrp[4] = hrp[5] = hrp[6] = hrp[7] = c; 568 } 569 } 570 571 stamp_mutex--; 572} 573#endif /* !RASOPS_SMALL */ 574