rasops15.c revision 1.18
1/* $NetBSD: rasops15.c,v 1.18 2009/03/14 21:04:22 dsl 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.18 2009/03/14 21:04:22 dsl 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(struct rasops_info *ri) 79{ 80 81 switch (ri->ri_font->fontwidth) { 82#ifndef RASOPS_SMALL 83 case 8: 84 ri->ri_ops.putchar = rasops15_putchar8; 85 break; 86 87 case 12: 88 ri->ri_ops.putchar = rasops15_putchar12; 89 break; 90 91 case 16: 92 ri->ri_ops.putchar = rasops15_putchar16; 93 break; 94#endif /* !RASOPS_SMALL */ 95 default: 96 ri->ri_ops.putchar = rasops15_putchar; 97 break; 98 } 99 100 if (ri->ri_rnum == 0) { 101 ri->ri_rnum = 5; 102 ri->ri_rpos = 0; 103 ri->ri_gnum = 5 + (ri->ri_depth == 16); 104 ri->ri_gpos = 5; 105 ri->ri_bnum = 5; 106 ri->ri_bpos = 10 + (ri->ri_depth == 16); 107 } 108} 109 110/* 111 * Paint a single character. 112 */ 113static void 114rasops15_putchar(void *cookie, int row, int col, u_int uc, long attr) 115{ 116 int fb, width, height, cnt, clr[2]; 117 struct rasops_info *ri; 118 u_char *dp, *rp, *hp, *hrp, *fr; 119 120 ri = (struct rasops_info *)cookie; 121 hp = hrp = NULL; 122 123#ifdef RASOPS_CLIPPING 124 /* Catches 'row < 0' case too */ 125 if ((unsigned)row >= (unsigned)ri->ri_rows) 126 return; 127 128 if ((unsigned)col >= (unsigned)ri->ri_cols) 129 return; 130#endif 131 132 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; 133 if (ri->ri_hwbits) 134 hrp = ri->ri_hwbits + row * ri->ri_yscale + 135 col * ri->ri_xscale; 136 height = ri->ri_font->fontheight; 137 width = ri->ri_font->fontwidth; 138 139 clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 0xf]; 140 clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 0xf]; 141 142 if (uc == ' ') { 143 int16_t c = (int16_t)clr[0]; 144 while (height--) { 145 dp = rp; 146 rp += ri->ri_stride; 147 if (ri->ri_hwbits) { 148 hp = hrp; 149 hrp += ri->ri_stride; 150 } 151 152 for (cnt = width; cnt; cnt--) { 153 *(int16_t *)dp = c; 154 dp += 2; 155 if (ri->ri_hwbits) { 156 *(int16_t *)hp = c; 157 hp += 2; 158 } 159 } 160 } 161 } else { 162 uc -= ri->ri_font->firstchar; 163 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 164 165 while (height--) { 166 dp = rp; 167 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24); 168 fr += ri->ri_font->stride; 169 rp += ri->ri_stride; 170 if (ri->ri_hwbits) { 171 hp = hrp; 172 hrp += ri->ri_stride; 173 } 174 175 for (cnt = width; cnt; cnt--) { 176 *(int16_t *)dp = (int16_t)clr[(fb >> 31) & 1]; 177 if (ri->ri_hwbits) 178 *(int16_t *)hp = 179 (int16_t)clr[(fb >> 31) & 1]; 180 fb <<= 1; 181 dp += 2; 182 if (ri->ri_hwbits) 183 hp += 2; 184 } 185 } 186 } 187 188 /* Do underline */ 189 if ((attr & 1) != 0) { 190 int16_t c = (int16_t)clr[1]; 191 rp -= ri->ri_stride << 1; 192 if (ri->ri_hwbits) 193 hrp -= ri->ri_stride << 1; 194 195 while (width--) { 196 *(int16_t *)rp = c; 197 rp += 2; 198 if (ri->ri_hwbits) { 199 *(int16_t *)hrp = c; 200 hrp += 2; 201 } 202 } 203 } 204} 205 206#ifndef RASOPS_SMALL 207/* 208 * Recompute the (2x2)x1 blitting stamp. 209 */ 210static void 211rasops15_makestamp(struct rasops_info *ri, long attr) 212{ 213 int32_t fg, bg; 214 int i; 215 216 fg = ri->ri_devcmap[((u_int)attr >> 24) & 0xf] & 0xffff; 217 bg = ri->ri_devcmap[((u_int)attr >> 16) & 0xf] & 0xffff; 218 stamp_attr = attr; 219 220 for (i = 0; i < 32; i += 2) { 221#if BYTE_ORDER == LITTLE_ENDIAN 222 stamp[i] = (i & 16 ? fg : bg); 223 stamp[i] |= ((i & 8 ? fg : bg) << 16); 224 stamp[i + 1] = (i & 4 ? fg : bg); 225 stamp[i + 1] |= ((i & 2 ? fg : bg) << 16); 226#else 227 stamp[i] = (i & 2 ? fg : bg); 228 stamp[i] |= ((i & 4 ? fg : bg) << 16); 229 stamp[i + 1] = (i & 8 ? fg : bg); 230 stamp[i + 1] |= ((i & 16 ? fg : bg) << 16); 231#endif 232 } 233} 234 235/* 236 * Paint a single character. This is for 8-pixel wide fonts. 237 */ 238static void 239rasops15_putchar8(void *cookie, int row, int col, u_int uc, long attr) 240{ 241 struct rasops_info *ri; 242 int height, so, fs; 243 int32_t *rp, *hrp; 244 u_char *fr; 245 246 /* Can't risk remaking the stamp if it's already in use */ 247 if (stamp_mutex++) { 248 stamp_mutex--; 249 rasops15_putchar(cookie, row, col, uc, attr); 250 return; 251 } 252 253 ri = (struct rasops_info *)cookie; 254 hrp = NULL; 255 256#ifdef RASOPS_CLIPPING 257 if ((unsigned)row >= (unsigned)ri->ri_rows) { 258 stamp_mutex--; 259 return; 260 } 261 262 if ((unsigned)col >= (unsigned)ri->ri_cols) { 263 stamp_mutex--; 264 return; 265 } 266#endif 267 268 /* Recompute stamp? */ 269 if (attr != stamp_attr) 270 rasops15_makestamp(ri, attr); 271 272 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 273 if (ri->ri_hwbits) 274 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 275 col*ri->ri_xscale); 276 height = ri->ri_font->fontheight; 277 278 if (uc == (u_int)-1) { 279 int32_t c = stamp[0]; 280 while (height--) { 281 rp[0] = rp[1] = rp[2] = rp[3] = c; 282 DELTA(rp, ri->ri_stride, int32_t *); 283 if (ri->ri_hwbits) { 284 hrp[0] = hrp[1] = hrp[2] = hrp[3] = c; 285 DELTA(hrp, ri->ri_stride, int32_t *); 286 } 287 } 288 } else { 289 uc -= ri->ri_font->firstchar; 290 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale; 291 fs = ri->ri_font->stride; 292 293 while (height--) { 294 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 295 rp[0] = STAMP_READ(so); 296 rp[1] = STAMP_READ(so + 4); 297 if (ri->ri_hwbits) { 298 hrp[0] = STAMP_READ(so); 299 hrp[1] = STAMP_READ(so + 4); 300 } 301 302 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 303 rp[2] = STAMP_READ(so); 304 rp[3] = STAMP_READ(so + 4); 305 if (ri->ri_hwbits) { 306 hrp[2] = STAMP_READ(so); 307 hrp[3] = STAMP_READ(so + 4); 308 } 309 310 fr += fs; 311 DELTA(rp, ri->ri_stride, int32_t *); 312 if (ri->ri_hwbits) 313 DELTA(hrp, ri->ri_stride, int32_t *); 314 } 315 } 316 317 /* Do underline */ 318 if ((attr & 1) != 0) { 319 int32_t c = STAMP_READ(28); 320 321 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 322 rp[0] = rp[1] = rp[2] = rp[3] = c; 323 if (ri->ri_hwbits) { 324 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 325 hrp[0] = hrp[1] = hrp[2] = hrp[3] = c; 326 } 327 } 328 329 stamp_mutex--; 330} 331 332/* 333 * Paint a single character. This is for 12-pixel wide fonts. 334 */ 335static void 336rasops15_putchar12(void *cookie, int row, int col, u_int uc, long attr) 337{ 338 struct rasops_info *ri; 339 int height, so, fs; 340 int32_t *rp, *hrp; 341 u_char *fr; 342 343 /* Can't risk remaking the stamp if it's already in use */ 344 if (stamp_mutex++) { 345 stamp_mutex--; 346 rasops15_putchar(cookie, row, col, uc, attr); 347 return; 348 } 349 350 ri = (struct rasops_info *)cookie; 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 = ri->ri_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] = rp[4] = rp[5] = c; 379 DELTA(rp, ri->ri_stride, int32_t *); 380 if (ri->ri_hwbits) { 381 hrp[0] = hrp[1] = hrp[2] = hrp[3] = hrp[4] = 382 hrp[5] = c; 383 DELTA(hrp, ri->ri_stride, int32_t *); 384 } 385 } 386 } else { 387 uc -= ri->ri_font->firstchar; 388 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale; 389 fs = ri->ri_font->stride; 390 391 while (height--) { 392 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 393 rp[0] = STAMP_READ(so); 394 rp[1] = STAMP_READ(so + 4); 395 if (ri->ri_hwbits) { 396 hrp[0] = STAMP_READ(so); 397 hrp[1] = STAMP_READ(so + 4); 398 } 399 400 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 401 rp[2] = STAMP_READ(so); 402 rp[3] = STAMP_READ(so + 4); 403 if (ri->ri_hwbits) { 404 hrp[2] = STAMP_READ(so); 405 hrp[3] = STAMP_READ(so + 4); 406 } 407 408 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK; 409 rp[4] = STAMP_READ(so); 410 rp[5] = STAMP_READ(so + 4); 411 if (ri->ri_hwbits) { 412 hrp[4] = STAMP_READ(so); 413 hrp[5] = STAMP_READ(so + 4); 414 } 415 416 fr += fs; 417 DELTA(rp, ri->ri_stride, int32_t *); 418 if (ri->ri_hwbits) 419 DELTA(hrp, ri->ri_stride, int32_t *); 420 } 421 } 422 423 /* Do underline */ 424 if (attr & 1) { 425 int32_t c = STAMP_READ(28); 426 427 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 428 rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c; 429 if (ri->ri_hwbits) { 430 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 431 hrp[0] = hrp[1] = hrp[2] = hrp[3] = hrp[4] = hrp[5] = c; 432 } 433 } 434 435 stamp_mutex--; 436} 437 438/* 439 * Paint a single character. This is for 16-pixel wide fonts. 440 */ 441static void 442rasops15_putchar16(void *cookie, int row, int col, u_int uc, long attr) 443{ 444 struct rasops_info *ri; 445 int height, so, fs; 446 int32_t *rp, *hrp; 447 u_char *fr; 448 449 /* Can't risk remaking the stamp if it's already in use */ 450 if (stamp_mutex++) { 451 stamp_mutex--; 452 rasops15_putchar(cookie, row, col, uc, attr); 453 return; 454 } 455 456 ri = (struct rasops_info *)cookie; 457 hrp = NULL; 458 459#ifdef RASOPS_CLIPPING 460 if ((unsigned)row >= (unsigned)ri->ri_rows) { 461 stamp_mutex--; 462 return; 463 } 464 465 if ((unsigned)col >= (unsigned)ri->ri_cols) { 466 stamp_mutex--; 467 return; 468 } 469#endif 470 471 /* Recompute stamp? */ 472 if (attr != stamp_attr) 473 rasops15_makestamp(ri, attr); 474 475 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 476 if (ri->ri_hwbits) 477 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 478 col*ri->ri_xscale); 479 height = ri->ri_font->fontheight; 480 481 if (uc == (u_int)-1) { 482 int32_t c = stamp[0]; 483 while (height--) { 484 rp[0] = rp[1] = rp[2] = rp[3] = 485 rp[4] = rp[5] = rp[6] = rp[7] = c; 486 DELTA(rp, ri->ri_stride, int32_t *); 487 if (ri->ri_hwbits) { 488 hrp[0] = hrp[1] = hrp[2] = hrp[3] = 489 hrp[4] = hrp[5] = hrp[6] = hrp[7] = c; 490 DELTA(hrp, ri->ri_stride, int32_t *); 491 } 492 } 493 } else { 494 uc -= ri->ri_font->firstchar; 495 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale; 496 fs = ri->ri_font->stride; 497 498 while (height--) { 499 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 500 rp[0] = STAMP_READ(so); 501 rp[1] = STAMP_READ(so + 4); 502 if (ri->ri_hwbits) { 503 hrp[0] = STAMP_READ(so); 504 hrp[1] = STAMP_READ(so + 4); 505 } 506 507 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 508 rp[2] = STAMP_READ(so); 509 rp[3] = STAMP_READ(so + 4); 510 if (ri->ri_hwbits) { 511 hrp[2] = STAMP_READ(so); 512 hrp[3] = STAMP_READ(so + 4); 513 } 514 515 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK; 516 rp[4] = STAMP_READ(so); 517 rp[5] = STAMP_READ(so + 4); 518 if (ri->ri_hwbits) { 519 hrp[4] = STAMP_READ(so); 520 hrp[5] = STAMP_READ(so + 4); 521 } 522 523 so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK; 524 rp[6] = STAMP_READ(so); 525 rp[7] = STAMP_READ(so + 4); 526 if (ri->ri_hwbits) { 527 hrp[6] = STAMP_READ(so); 528 hrp[7] = STAMP_READ(so + 4); 529 } 530 531 DELTA(rp, ri->ri_stride, int32_t *); 532 if (ri->ri_hwbits) 533 DELTA(hrp, ri->ri_stride, int32_t *); 534 fr += fs; 535 } 536 } 537 538 /* Do underline */ 539 if (attr & 1) { 540 int32_t c = STAMP_READ(28); 541 542 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 543 rp[0] = rp[1] = rp[2] = rp[3] = 544 rp[4] = rp[5] = rp[6] = rp[7] = c; 545 if (ri->ri_hwbits) { 546 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 547 hrp[0] = hrp[1] = hrp[2] = hrp[3] = 548 hrp[4] = hrp[5] = hrp[6] = hrp[7] = c; 549 } 550 } 551 552 stamp_mutex--; 553} 554#endif /* !RASOPS_SMALL */ 555