rasops15.c revision 1.12
1/* $NetBSD: rasops15.c,v 1.12 2005/02/04 02:10:47 perry 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.12 2005/02/04 02:10:47 perry 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/* 61 * (2x2)x1 stamp for optimized character blitting 62 */ 63static int32_t stamp[32]; 64static long stamp_attr; 65static int stamp_mutex; /* XXX see note in readme */ 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 int32_t[0] = STAMP_READ(offset) 73 * destination int32_t[1] = STAMP_READ(offset + 4) 74 */ 75#define STAMP_SHIFT(fb,n) ((n*4-3) >= 0 ? (fb)>>(n*4-3):(fb)<<-(n*4-3)) 76#define STAMP_MASK (15 << 3) 77#define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o))) 78 79/* 80 * Initialize rasops_info struct for this colordepth. 81 */ 82void 83rasops15_init(ri) 84 struct rasops_info *ri; 85{ 86 87 switch (ri->ri_font->fontwidth) { 88#ifndef RASOPS_SMALL 89 case 8: 90 ri->ri_ops.putchar = rasops15_putchar8; 91 break; 92 93 case 12: 94 ri->ri_ops.putchar = rasops15_putchar12; 95 break; 96 97 case 16: 98 ri->ri_ops.putchar = rasops15_putchar16; 99 break; 100#endif /* !RASOPS_SMALL */ 101 default: 102 ri->ri_ops.putchar = rasops15_putchar; 103 break; 104 } 105 106 if (ri->ri_rnum == 0) { 107 ri->ri_rnum = 5; 108 ri->ri_rpos = 0; 109 ri->ri_gnum = 5 + (ri->ri_depth == 16); 110 ri->ri_gpos = 5; 111 ri->ri_bnum = 5; 112 ri->ri_bpos = 10 + (ri->ri_depth == 16); 113 } 114} 115 116/* 117 * Paint a single character. 118 */ 119static void 120rasops15_putchar(cookie, row, col, uc, attr) 121 void *cookie; 122 int row, col; 123 u_int uc; 124 long attr; 125{ 126 int fb, width, height, cnt, clr[2]; 127 struct rasops_info *ri; 128 u_char *dp, *rp, *fr; 129 130 ri = (struct rasops_info *)cookie; 131 132#ifdef RASOPS_CLIPPING 133 /* Catches 'row < 0' case too */ 134 if ((unsigned)row >= (unsigned)ri->ri_rows) 135 return; 136 137 if ((unsigned)col >= (unsigned)ri->ri_cols) 138 return; 139#endif 140 141 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; 142 height = ri->ri_font->fontheight; 143 width = ri->ri_font->fontwidth; 144 145 clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 0xf]; 146 clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 0xf]; 147 148 if (uc == ' ') { 149 int16_t c = (int16_t)clr[0]; 150 while (height--) { 151 dp = rp; 152 rp += ri->ri_stride; 153 154 for (cnt = width; cnt; cnt--) { 155 *(int16_t *)dp = c; 156 dp += 2; 157 } 158 } 159 } else { 160 uc -= ri->ri_font->firstchar; 161 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 162 163 while (height--) { 164 dp = rp; 165 fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24); 166 fr += ri->ri_font->stride; 167 rp += ri->ri_stride; 168 169 for (cnt = width; cnt; cnt--) { 170 *(int16_t *)dp = (int16_t)clr[(fb >> 31) & 1]; 171 fb <<= 1; 172 dp += 2; 173 } 174 } 175 } 176 177 /* Do underline */ 178 if ((attr & 1) != 0) { 179 int16_t c = (int16_t)clr[1]; 180 rp -= ri->ri_stride << 1; 181 182 while (width--) { 183 *(int16_t *)rp = c; 184 rp += 2; 185 } 186 } 187} 188 189#ifndef RASOPS_SMALL 190/* 191 * Recompute the (2x2)x1 blitting stamp. 192 */ 193static void 194rasops15_makestamp(ri, attr) 195 struct rasops_info *ri; 196 long attr; 197{ 198 int32_t fg, bg; 199 int i; 200 201 fg = ri->ri_devcmap[((u_int)attr >> 24) & 0xf] & 0xffff; 202 bg = ri->ri_devcmap[((u_int)attr >> 16) & 0xf] & 0xffff; 203 stamp_attr = attr; 204 205 for (i = 0; i < 32; i += 2) { 206#if BYTE_ORDER == LITTLE_ENDIAN 207 stamp[i] = (i & 16 ? fg : bg); 208 stamp[i] |= ((i & 8 ? fg : bg) << 16); 209 stamp[i + 1] = (i & 4 ? fg : bg); 210 stamp[i + 1] |= ((i & 2 ? fg : bg) << 16); 211#else 212 stamp[i] = (i & 2 ? fg : bg); 213 stamp[i] |= ((i & 4 ? fg : bg) << 16); 214 stamp[i + 1] = (i & 8 ? fg : bg); 215 stamp[i + 1] |= ((i & 16 ? fg : bg) << 16); 216#endif 217 } 218} 219 220/* 221 * Paint a single character. This is for 8-pixel wide fonts. 222 */ 223static void 224rasops15_putchar8(cookie, row, col, uc, attr) 225 void *cookie; 226 int row, col; 227 u_int uc; 228 long attr; 229{ 230 struct rasops_info *ri; 231 int height, so, fs; 232 int32_t *rp; 233 u_char *fr; 234 235 /* Can't risk remaking the stamp if it's already in use */ 236 if (stamp_mutex++) { 237 stamp_mutex--; 238 rasops15_putchar(cookie, row, col, uc, attr); 239 return; 240 } 241 242 ri = (struct rasops_info *)cookie; 243 244#ifdef RASOPS_CLIPPING 245 if ((unsigned)row >= (unsigned)ri->ri_rows) { 246 stamp_mutex--; 247 return; 248 } 249 250 if ((unsigned)col >= (unsigned)ri->ri_cols) { 251 stamp_mutex--; 252 return; 253 } 254#endif 255 256 /* Recompute stamp? */ 257 if (attr != stamp_attr) 258 rasops15_makestamp(ri, attr); 259 260 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 261 height = ri->ri_font->fontheight; 262 263 if (uc == (u_int)-1) { 264 int32_t c = stamp[0]; 265 while (height--) { 266 rp[0] = rp[1] = rp[2] = rp[3] = c; 267 DELTA(rp, ri->ri_stride, int32_t *); 268 } 269 } else { 270 uc -= ri->ri_font->firstchar; 271 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale; 272 fs = ri->ri_font->stride; 273 274 while (height--) { 275 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 276 rp[0] = STAMP_READ(so); 277 rp[1] = STAMP_READ(so + 4); 278 279 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 280 rp[2] = STAMP_READ(so); 281 rp[3] = STAMP_READ(so + 4); 282 283 fr += fs; 284 DELTA(rp, ri->ri_stride, int32_t *); 285 } 286 } 287 288 /* Do underline */ 289 if ((attr & 1) != 0) { 290 int32_t c = STAMP_READ(28); 291 292 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 293 rp[0] = rp[1] = rp[2] = rp[3] = c; 294 } 295 296 stamp_mutex--; 297} 298 299/* 300 * Paint a single character. This is for 12-pixel wide fonts. 301 */ 302static void 303rasops15_putchar12(cookie, row, col, uc, attr) 304 void *cookie; 305 int row, col; 306 u_int uc; 307 long attr; 308{ 309 struct rasops_info *ri; 310 int height, so, fs; 311 int32_t *rp; 312 u_char *fr; 313 314 /* Can't risk remaking the stamp if it's already in use */ 315 if (stamp_mutex++) { 316 stamp_mutex--; 317 rasops15_putchar(cookie, row, col, uc, attr); 318 return; 319 } 320 321 ri = (struct rasops_info *)cookie; 322 323#ifdef RASOPS_CLIPPING 324 if ((unsigned)row >= (unsigned)ri->ri_rows) { 325 stamp_mutex--; 326 return; 327 } 328 329 if ((unsigned)col >= (unsigned)ri->ri_cols) { 330 stamp_mutex--; 331 return; 332 } 333#endif 334 335 /* Recompute stamp? */ 336 if (attr != stamp_attr) 337 rasops15_makestamp(ri, attr); 338 339 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 340 height = ri->ri_font->fontheight; 341 342 if (uc == (u_int)-1) { 343 int32_t c = stamp[0]; 344 while (height--) { 345 rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c; 346 DELTA(rp, ri->ri_stride, int32_t *); 347 } 348 } else { 349 uc -= ri->ri_font->firstchar; 350 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale; 351 fs = ri->ri_font->stride; 352 353 while (height--) { 354 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 355 rp[0] = STAMP_READ(so); 356 rp[1] = STAMP_READ(so + 4); 357 358 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 359 rp[2] = STAMP_READ(so); 360 rp[3] = STAMP_READ(so + 4); 361 362 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK; 363 rp[4] = STAMP_READ(so); 364 rp[5] = STAMP_READ(so + 4); 365 366 fr += fs; 367 DELTA(rp, ri->ri_stride, int32_t *); 368 } 369 } 370 371 /* Do underline */ 372 if (attr & 1) { 373 int32_t c = STAMP_READ(28); 374 375 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 376 rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c; 377 } 378 379 stamp_mutex--; 380} 381 382/* 383 * Paint a single character. This is for 16-pixel wide fonts. 384 */ 385static void 386rasops15_putchar16(cookie, row, col, uc, attr) 387 void *cookie; 388 int row, col; 389 u_int uc; 390 long attr; 391{ 392 struct rasops_info *ri; 393 int height, so, fs; 394 int32_t *rp; 395 u_char *fr; 396 397 /* Can't risk remaking the stamp if it's already in use */ 398 if (stamp_mutex++) { 399 stamp_mutex--; 400 rasops15_putchar(cookie, row, col, uc, attr); 401 return; 402 } 403 404 ri = (struct rasops_info *)cookie; 405 406#ifdef RASOPS_CLIPPING 407 if ((unsigned)row >= (unsigned)ri->ri_rows) { 408 stamp_mutex--; 409 return; 410 } 411 412 if ((unsigned)col >= (unsigned)ri->ri_cols) { 413 stamp_mutex--; 414 return; 415 } 416#endif 417 418 /* Recompute stamp? */ 419 if (attr != stamp_attr) 420 rasops15_makestamp(ri, attr); 421 422 rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); 423 height = ri->ri_font->fontheight; 424 425 if (uc == (u_int)-1) { 426 int32_t c = stamp[0]; 427 while (height--) { 428 rp[0] = rp[1] = rp[2] = rp[3] = 429 rp[4] = rp[5] = rp[6] = rp[7] = c; 430 DELTA(rp, ri->ri_stride, int32_t *); 431 } 432 } else { 433 uc -= ri->ri_font->firstchar; 434 fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale; 435 fs = ri->ri_font->stride; 436 437 while (height--) { 438 so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK; 439 rp[0] = STAMP_READ(so); 440 rp[1] = STAMP_READ(so + 4); 441 442 so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK; 443 rp[2] = STAMP_READ(so); 444 rp[3] = STAMP_READ(so + 4); 445 446 so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK; 447 rp[4] = STAMP_READ(so); 448 rp[5] = STAMP_READ(so + 4); 449 450 so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK; 451 rp[6] = STAMP_READ(so); 452 rp[7] = STAMP_READ(so + 4); 453 454 DELTA(rp, ri->ri_stride, int32_t *); 455 fr += fs; 456 } 457 } 458 459 /* Do underline */ 460 if (attr & 1) { 461 int32_t c = STAMP_READ(28); 462 463 DELTA(rp, -(ri->ri_stride << 1), int32_t *); 464 rp[0] = rp[1] = rp[2] = rp[3] = 465 rp[4] = rp[5] = rp[6] = rp[7] = c; 466 } 467 468 stamp_mutex--; 469} 470#endif /* !RASOPS_SMALL */ 471