Home | History | Annotate | Line # | Download | only in rasops
rasops8.c revision 1.23
      1 /* 	$NetBSD: rasops8.c,v 1.23 2007/12/09 20:28:14 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.23 2007/12/09 20:28:14 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 *)((char *)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] = stamp[0];
    293 				hp[1] = stamp[0];
    294 				DELTA(hp, ri->ri_stride, int32_t *);
    295 			}
    296 		}
    297 	} else {
    298 		uc -= ri->ri_font->firstchar;
    299 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    300 		fs = ri->ri_font->stride;
    301 
    302 		while (height--) {
    303 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    304 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    305 			if (ri->ri_hwbits) {
    306 				hp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) &
    307 				    STAMP_MASK);
    308 				hp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) &
    309 				    STAMP_MASK);
    310 			}
    311 
    312 			fr += fs;
    313 			DELTA(rp, ri->ri_stride, int32_t *);
    314 			if (ri->ri_hwbits)
    315 				DELTA(hp, ri->ri_stride, int32_t *);
    316 		}
    317 	}
    318 
    319 	/* Do underline */
    320 	if ((attr & 1) != 0) {
    321 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    322 		rp[0] = rp[1] = stamp[15];
    323 		if (ri->ri_hwbits) {
    324 			DELTA(hp, -(ri->ri_stride << 1), int32_t *);
    325 			hp[0] = stamp[15];
    326 			hp[1] = stamp[15];
    327 		}
    328 	}
    329 
    330 	stamp_mutex--;
    331 }
    332 
    333 /*
    334  * Put a single character. This is for 12-pixel wide fonts.
    335  */
    336 static void
    337 rasops8_putchar12(cookie, row, col, uc, attr)
    338 	void *cookie;
    339 	int row, col;
    340 	u_int uc;
    341 	long attr;
    342 {
    343 	struct rasops_info *ri;
    344 	int height, fs;
    345 	int32_t *rp,  *hrp;
    346 	u_char *fr;
    347 
    348 	/* Can't risk remaking the stamp if it's already in use */
    349 	if (stamp_mutex++) {
    350 		stamp_mutex--;
    351 		rasops8_putchar(cookie, row, col, uc, attr);
    352 		return;
    353 	}
    354 
    355 	ri = (struct rasops_info *)cookie;
    356 	hrp = NULL;
    357 
    358 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    359 	    return;
    360 
    361 #ifdef RASOPS_CLIPPING
    362 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    363 		stamp_mutex--;
    364 		return;
    365 	}
    366 
    367 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    368 		stamp_mutex--;
    369 		return;
    370 	}
    371 #endif
    372 
    373 	/* Recompute stamp? */
    374 	if (attr != stamp_attr)
    375 		rasops8_makestamp(ri, attr);
    376 
    377 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    378 	if (ri->ri_hwbits)
    379 		hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
    380 		    col*ri->ri_xscale);
    381 	height = ri->ri_font->fontheight;
    382 
    383 	if (uc == ' ') {
    384 		while (height--) {
    385 			int32_t c = stamp[0];
    386 
    387 			rp[0] = rp[1] = rp[2] = c;
    388 			DELTA(rp, ri->ri_stride, int32_t *);
    389 			if (ri->ri_hwbits) {
    390 				hrp[0] = c;
    391 				hrp[1] = c;
    392 				hrp[2] = c;
    393 				DELTA(hrp, ri->ri_stride, int32_t *);
    394 			}
    395 		}
    396 	} else {
    397 		uc -= ri->ri_font->firstchar;
    398 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    399 		fs = ri->ri_font->stride;
    400 
    401 		while (height--) {
    402 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    403 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    404 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    405 			if (ri->ri_hwbits) {
    406 				hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    407 				hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    408 				hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    409 			}
    410 
    411 			fr += fs;
    412 			DELTA(rp, ri->ri_stride, int32_t *);
    413 			if (ri->ri_hwbits)
    414 				DELTA(hrp, ri->ri_stride, int32_t *);
    415 		}
    416 	}
    417 
    418 	/* Do underline */
    419 	if ((attr & 1) != 0) {
    420 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    421 		rp[0] = rp[1] = rp[2] = stamp[15];
    422 		if (ri->ri_hwbits) {
    423 			DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
    424 			hrp[0] = stamp[15];
    425 			hrp[1] = stamp[15];
    426 			hrp[2] = stamp[15];
    427 		}
    428 	}
    429 
    430 	stamp_mutex--;
    431 }
    432 
    433 /*
    434  * Put a single character. This is for 16-pixel wide fonts.
    435  */
    436 static void
    437 rasops8_putchar16(cookie, row, col, uc, attr)
    438 	void *cookie;
    439 	int row, col;
    440 	u_int uc;
    441 	long attr;
    442 {
    443 	struct rasops_info *ri;
    444 	int height, fs;
    445 	int32_t *rp, *hrp;
    446 	u_char *fr;
    447 
    448 	/* Can't risk remaking the stamp if it's already in use */
    449 	if (stamp_mutex++) {
    450 		stamp_mutex--;
    451 		rasops8_putchar(cookie, row, col, uc, attr);
    452 		return;
    453 	}
    454 
    455 	ri = (struct rasops_info *)cookie;
    456 	hrp = NULL;
    457 
    458 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    459 		return;
    460 
    461 #ifdef RASOPS_CLIPPING
    462 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    463 		stamp_mutex--;
    464 		return;
    465 	}
    466 
    467 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    468 		stamp_mutex--;
    469 		return;
    470 	}
    471 #endif
    472 
    473 	/* Recompute stamp? */
    474 	if (attr != stamp_attr)
    475 		rasops8_makestamp(ri, attr);
    476 
    477 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    478 	if (ri->ri_hwbits)
    479 		hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
    480 		    col*ri->ri_xscale);
    481 
    482 	height = ri->ri_font->fontheight;
    483 
    484 	if (uc == ' ') {
    485 		while (height--) {
    486 			rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
    487 			if (ri->ri_hwbits) {
    488 				hrp[0] = stamp[0];
    489 				hrp[1] = stamp[0];
    490 				hrp[2] = stamp[0];
    491 				hrp[3] = stamp[0];
    492 			}
    493 		}
    494 	} else {
    495 		uc -= ri->ri_font->firstchar;
    496 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    497 		fs = ri->ri_font->stride;
    498 
    499 		while (height--) {
    500 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    501 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    502 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    503 			rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
    504 			if (ri->ri_hwbits) {
    505 				hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    506 				hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    507 				hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    508 				hrp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
    509 			}
    510 
    511 			fr += fs;
    512 			DELTA(rp, ri->ri_stride, int32_t *);
    513 			if (ri->ri_hwbits)
    514 				DELTA(hrp, ri->ri_stride, int32_t *);
    515 		}
    516 	}
    517 
    518 	/* Do underline */
    519 	if ((attr & 1) != 0) {
    520 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    521 		rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
    522 		if (ri->ri_hwbits) {
    523 			DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
    524 			hrp[0] = stamp[15];
    525 			hrp[1] = stamp[15];
    526 			hrp[2] = stamp[15];
    527 			hrp[3] = stamp[15];
    528 		}
    529 	}
    530 
    531 	stamp_mutex--;
    532 }
    533 #endif /* !RASOPS_SMALL */
    534