1 /* $NetBSD: rasops8.c,v 1.21 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: rasops8.c,v 1.21 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 52 static void rasops8_putchar(void *, int, int, u_int, long attr); 53 #ifndef RASOPS_SMALL 54 static void rasops8_putchar8(void *, int, int, u_int, long attr); 55 static void rasops8_putchar12(void *, int, int, u_int, long attr); 56 static void rasops8_putchar16(void *, int, int, u_int, long attr); 57 static void rasops8_makestamp(struct rasops_info *ri, long); 58 59 /* 60 * 4x1 stamp for optimized character blitting 61 */ 62 static int32_t stamp[16]; 63 static long stamp_attr; 64 static int stamp_mutex; /* XXX see note in README */ 65 #endif 66 67 /* 68 * XXX this confuses the hell out of gcc2 (not egcs) which always insists 69 * that the shift count is negative. 70 * 71 * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK 72 * destination = STAMP_READ(offset) 73 */ 74 #define STAMP_SHIFT(fb,n) ((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2)) 75 #define STAMP_MASK (0xf << 2) 76 #define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o))) 77 78 /* 79 * Initialize a 'rasops_info' descriptor for this depth. 80 */ 81 void 82 rasops8_init(ri) 83 struct rasops_info *ri; 84 { 85 86 switch (ri->ri_font->fontwidth) { 87 #ifndef RASOPS_SMALL 88 case 8: 89 ri->ri_ops.putchar = rasops8_putchar8; 90 break; 91 case 12: 92 ri->ri_ops.putchar = rasops8_putchar12; 93 break; 94 case 16: 95 ri->ri_ops.putchar = rasops8_putchar16; 96 break; 97 #endif /* !RASOPS_SMALL */ 98 default: 99 ri->ri_ops.putchar = rasops8_putchar; 100 break; 101 } 102 } 103 104 /* 105 * Put a single character. 106 */ 107 static void 108 rasops8_putchar(cookie, row, col, uc, attr) 109 void *cookie; 110 int row, col; 111 u_int uc; 112 long attr; 113 { 114 int width, height, cnt, fs, fb; 115 u_char *dp, *rp, *hp, *hrp, *fr, clr[2]; 116 struct rasops_info *ri; 117 118 ri = (struct rasops_info *)cookie; 119 hp = hrp = NULL; 120 121 if (!CHAR_IN_FONT(uc, ri->ri_font)) 122 return; 123 124 #ifdef RASOPS_CLIPPING 125 /* Catches 'row < 0' case too */ 126 if ((unsigned)row >= (unsigned)ri->ri_rows) 127 return; 128 129 if ((unsigned)col >= (unsigned)ri->ri_cols) 130 return; 131 #endif 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 + col * 135 ri->ri_xscale; 136 137 height = ri->ri_font->fontheight; 138 width = ri->ri_font->fontwidth; 139 clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf]; 140 clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf]; 141 142 if (uc == ' ') { 143 u_char c = clr[0]; 144 145 while (height--) { 146 dp = rp; 147 rp += ri->ri_stride; 148 if (ri->ri_hwbits) { 149 hp = hrp; 150 hrp += ri->ri_stride; 151 } 152 153 for (cnt = width; cnt; cnt--) { 154 *dp++ = c; 155 if (ri->ri_hwbits) 156 *hp++ = c; 157 } 158 } 159 } else { 160 uc -= ri->ri_font->firstchar; 161 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 162 fs = ri->ri_font->stride; 163 164 while (height--) { 165 dp = rp; 166 if (ri->ri_hwbits) 167 hp = hrp; 168 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24); 169 fr += fs; 170 rp += ri->ri_stride; 171 if (ri->ri_hwbits) 172 hrp += ri->ri_stride; 173 174 for (cnt = width; cnt; cnt--) { 175 *dp++ = clr[(fb >> 31) & 1]; 176 if (ri->ri_hwbits) 177 *hp++ = clr[(fb >> 31) & 1]; 178 fb <<= 1; 179 } 180 } 181 } 182 183 /* Do underline */ 184 if ((attr & 1) != 0) { 185 u_char c = clr[1]; 186 187 rp -= (ri->ri_stride << 1); 188 if (ri->ri_hwbits) 189 hrp -= (ri->ri_stride << 1); 190 191 while (width--) { 192 *rp++ = c; 193 if (ri->ri_hwbits) 194 *hrp++ = c; 195 } 196 } 197 } 198 199 #ifndef RASOPS_SMALL 200 /* 201 * Recompute the 4x1 blitting stamp. 202 */ 203 static void 204 rasops8_makestamp(ri, attr) 205 struct rasops_info *ri; 206 long attr; 207 { 208 int32_t fg, bg; 209 int i; 210 211 fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff; 212 bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff; 213 stamp_attr = attr; 214 215 for (i = 0; i < 16; i++) { 216 #if BYTE_ORDER == BIG_ENDIAN 217 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP 218 #else 219 #define NEED_LITTLE_ENDIAN_STAMP 0 220 #endif 221 if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) { 222 /* little endian */ 223 stamp[i] = (i & 8 ? fg : bg); 224 stamp[i] |= ((i & 4 ? fg : bg) << 8); 225 stamp[i] |= ((i & 2 ? fg : bg) << 16); 226 stamp[i] |= ((i & 1 ? fg : bg) << 24); 227 } else { 228 /* big endian */ 229 stamp[i] = (i & 1 ? fg : bg); 230 stamp[i] |= ((i & 2 ? fg : bg) << 8); 231 stamp[i] |= ((i & 4 ? fg : bg) << 16); 232 stamp[i] |= ((i & 8 ? fg : bg) << 24); 233 } 234 } 235 } 236 237 /* 238 * Put a single character. This is for 8-pixel wide fonts. 239 */ 240 static void 241 rasops8_putchar8(cookie, row, col, uc, attr) 242 void *cookie; 243 int row, col; 244 u_int uc; 245 long attr; 246 { 247 struct rasops_info *ri; 248 int height, fs; 249 int32_t *rp, *hp; 250 u_char *fr; 251 252 /* Can't risk remaking the stamp if it's already in use */ 253 if (stamp_mutex++) { 254 stamp_mutex--; 255 rasops8_putchar(cookie, row, col, uc, attr); 256 return; 257 } 258 259 ri = (struct rasops_info *)cookie; 260 hp = NULL; 261 262 if (!CHAR_IN_FONT(uc, ri->ri_font)) 263 return; 264 265 #ifdef RASOPS_CLIPPING 266 if ((unsigned)row >= (unsigned)ri->ri_rows) { 267 stamp_mutex--; 268 return; 269 } 270 271 if ((unsigned)col >= (unsigned)ri->ri_cols) { 272 stamp_mutex--; 273 return; 274 } 275 #endif 276 277 /* Recompute stamp? */ 278 if (attr != stamp_attr) 279 rasops8_makestamp(ri, attr); 280 281 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 282 if (ri->ri_hwbits) 283 hp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 284 col*ri->ri_xscale); 285 height = ri->ri_font->fontheight; 286 287 if (uc == ' ') { 288 while (height--) { 289 rp[0] = rp[1] = stamp[0]; 290 DELTA(rp, ri->ri_stride, int32_t *); 291 if (ri->ri_hwbits) { 292 hp[0] = hp[1] = stamp[0]; 293 DELTA(hp, ri->ri_stride, int32_t *); 294 } 295 } 296 } else { 297 uc -= ri->ri_font->firstchar; 298 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 299 fs = ri->ri_font->stride; 300 301 while (height--) { 302 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK); 303 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK); 304 if (ri->ri_hwbits) { 305 hp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & 306 STAMP_MASK); 307 hp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & 308 STAMP_MASK); 309 } 310 311 fr += fs; 312 DELTA(rp, ri->ri_stride, int32_t *); 313 if (ri->ri_hwbits) 314 DELTA(hp, ri->ri_stride, int32_t *); 315 } 316 } 317 318 /* Do underline */ 319 if ((attr & 1) != 0) { 320 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 321 rp[0] = rp[1] = stamp[15]; 322 if (ri->ri_hwbits) { 323 DELTA(hp, -(ri->ri_stride << 1), int32_t *); 324 hp[0] = hp[1] = stamp[15]; 325 } 326 } 327 328 stamp_mutex--; 329 } 330 331 /* 332 * Put a single character. This is for 12-pixel wide fonts. 333 */ 334 static void 335 rasops8_putchar12(cookie, row, col, uc, attr) 336 void *cookie; 337 int row, col; 338 u_int uc; 339 long attr; 340 { 341 struct rasops_info *ri; 342 int height, fs; 343 int32_t *rp, *hrp; 344 u_char *fr; 345 346 /* Can't risk remaking the stamp if it's already in use */ 347 if (stamp_mutex++) { 348 stamp_mutex--; 349 rasops8_putchar(cookie, row, col, uc, attr); 350 return; 351 } 352 353 ri = (struct rasops_info *)cookie; 354 hrp = NULL; 355 356 if (!CHAR_IN_FONT(uc, ri->ri_font)) 357 return; 358 359 #ifdef RASOPS_CLIPPING 360 if ((unsigned)row >= (unsigned)ri->ri_rows) { 361 stamp_mutex--; 362 return; 363 } 364 365 if ((unsigned)col >= (unsigned)ri->ri_cols) { 366 stamp_mutex--; 367 return; 368 } 369 #endif 370 371 /* Recompute stamp? */ 372 if (attr != stamp_attr) 373 rasops8_makestamp(ri, attr); 374 375 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 376 if (ri->ri_hwbits) 377 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 378 col*ri->ri_xscale); 379 height = ri->ri_font->fontheight; 380 381 if (uc == ' ') { 382 while (height--) { 383 int32_t c = stamp[0]; 384 385 rp[0] = rp[1] = rp[2] = c; 386 DELTA(rp, ri->ri_stride, int32_t *); 387 if (ri->ri_hwbits) { 388 hrp[0] = hrp[1] = hrp[2] = c; 389 DELTA(hrp, ri->ri_stride, int32_t *); 390 } 391 } 392 } else { 393 uc -= ri->ri_font->firstchar; 394 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 395 fs = ri->ri_font->stride; 396 397 while (height--) { 398 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK); 399 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK); 400 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK); 401 if (ri->ri_hwbits) { 402 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK); 403 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK); 404 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK); 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 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 417 rp[0] = rp[1] = rp[2] = stamp[15]; 418 if (ri->ri_hwbits) { 419 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 420 hrp[0] = hrp[1] = hrp[2] = stamp[15]; 421 } 422 } 423 424 stamp_mutex--; 425 } 426 427 /* 428 * Put a single character. This is for 16-pixel wide fonts. 429 */ 430 static void 431 rasops8_putchar16(cookie, row, col, uc, attr) 432 void *cookie; 433 int row, col; 434 u_int uc; 435 long attr; 436 { 437 struct rasops_info *ri; 438 int height, fs; 439 int32_t *rp, *hrp; 440 u_char *fr; 441 442 /* Can't risk remaking the stamp if it's already in use */ 443 if (stamp_mutex++) { 444 stamp_mutex--; 445 rasops8_putchar(cookie, row, col, uc, attr); 446 return; 447 } 448 449 ri = (struct rasops_info *)cookie; 450 hrp = NULL; 451 452 if (!CHAR_IN_FONT(uc, ri->ri_font)) 453 return; 454 455 #ifdef RASOPS_CLIPPING 456 if ((unsigned)row >= (unsigned)ri->ri_rows) { 457 stamp_mutex--; 458 return; 459 } 460 461 if ((unsigned)col >= (unsigned)ri->ri_cols) { 462 stamp_mutex--; 463 return; 464 } 465 #endif 466 467 /* Recompute stamp? */ 468 if (attr != stamp_attr) 469 rasops8_makestamp(ri, attr); 470 471 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 472 if (ri->ri_hwbits) 473 hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale + 474 col*ri->ri_xscale); 475 476 height = ri->ri_font->fontheight; 477 478 if (uc == ' ') { 479 while (height--) { 480 rp[0] = rp[1] = rp[2] = rp[3] = stamp[0]; 481 if (ri->ri_hwbits) 482 hrp[0] = hrp[1] = hrp[2] = hrp[3] = stamp[0]; 483 } 484 } else { 485 uc -= ri->ri_font->firstchar; 486 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 487 fs = ri->ri_font->stride; 488 489 while (height--) { 490 rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK); 491 rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK); 492 rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK); 493 rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK); 494 if (ri->ri_hwbits) { 495 hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK); 496 hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK); 497 hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK); 498 hrp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK); 499 } 500 501 fr += fs; 502 DELTA(rp, ri->ri_stride, int32_t *); 503 if (ri->ri_hwbits) 504 DELTA(hrp, ri->ri_stride, int32_t *); 505 } 506 } 507 508 /* Do underline */ 509 if ((attr & 1) != 0) { 510 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 511 rp[0] = rp[1] = rp[2] = rp[3] = stamp[15]; 512 if (ri->ri_hwbits) { 513 DELTA(hrp, -(ri->ri_stride << 1), int32_t *); 514 hrp[0] = hrp[1] = hrp[2] = hrp[3] = stamp[15]; 515 } 516 } 517 518 stamp_mutex--; 519 } 520 #endif /* !RASOPS_SMALL */ 521