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