Home | History | Annotate | Line # | Download | only in rasops
rasops8.c revision 1.25
      1 /* 	$NetBSD: rasops8.c,v 1.25 2009/03/14 15:36:20 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.25 2009/03/14 15:36:20 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(cookie, row, col, uc, attr)
    101 	void *cookie;
    102 	int row, col;
    103 	u_int uc;
    104 	long attr;
    105 {
    106 	int width, height, cnt, fs, fb;
    107 	u_char *dp, *rp, *hp, *hrp, *fr, clr[2];
    108 	struct rasops_info *ri;
    109 
    110 	ri = (struct rasops_info *)cookie;
    111 	hp = hrp = NULL;
    112 
    113 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    114 		return;
    115 
    116 #ifdef RASOPS_CLIPPING
    117 	/* Catches 'row < 0' case too */
    118 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    119 		return;
    120 
    121 	if ((unsigned)col >= (unsigned)ri->ri_cols)
    122 		return;
    123 #endif
    124 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    125 	if (ri->ri_hwbits)
    126 		hrp = ri->ri_hwbits + row * ri->ri_yscale + col *
    127 		    ri->ri_xscale;
    128 
    129 	height = ri->ri_font->fontheight;
    130 	width = ri->ri_font->fontwidth;
    131 	clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
    132 	clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
    133 
    134 	if (uc == ' ') {
    135 		u_char c = clr[0];
    136 
    137 		while (height--) {
    138 			dp = rp;
    139 			rp += ri->ri_stride;
    140 			if (ri->ri_hwbits) {
    141 				hp = hrp;
    142 				hrp += ri->ri_stride;
    143 			}
    144 
    145 			for (cnt = width; cnt; cnt--) {
    146 				*dp++ = c;
    147 				if (ri->ri_hwbits)
    148 					*hp++ = c;
    149 			}
    150 		}
    151 	} else {
    152 		uc -= ri->ri_font->firstchar;
    153 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    154 		fs = ri->ri_font->stride;
    155 
    156 		while (height--) {
    157 			dp = rp;
    158 			if (ri->ri_hwbits)
    159 				hp = hrp;
    160 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
    161 			fr += fs;
    162 			rp += ri->ri_stride;
    163 			if (ri->ri_hwbits)
    164 				hrp += ri->ri_stride;
    165 
    166 			for (cnt = width; cnt; cnt--) {
    167 				*dp++ = clr[(fb >> 31) & 1];
    168 				if (ri->ri_hwbits)
    169 					*hp++ = clr[(fb >> 31) & 1];
    170 				fb <<= 1;
    171 			}
    172 		}
    173 	}
    174 
    175 	/* Do underline */
    176 	if ((attr & 1) != 0) {
    177 		u_char c = clr[1];
    178 
    179 		rp -= (ri->ri_stride << 1);
    180 		if (ri->ri_hwbits)
    181 			hrp -= (ri->ri_stride << 1);
    182 
    183 		while (width--) {
    184 			*rp++ = c;
    185 			if (ri->ri_hwbits)
    186 				*hrp++ = c;
    187 		}
    188 	}
    189 }
    190 
    191 #ifndef RASOPS_SMALL
    192 /*
    193  * Recompute the 4x1 blitting stamp.
    194  */
    195 static void
    196 rasops8_makestamp(struct rasops_info *ri, long attr)
    197 {
    198 	int32_t fg, bg;
    199 	int i;
    200 
    201 	fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
    202 	bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
    203 	stamp_attr = attr;
    204 
    205 	for (i = 0; i < 16; i++) {
    206 #if BYTE_ORDER == BIG_ENDIAN
    207 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
    208 #else
    209 #define NEED_LITTLE_ENDIAN_STAMP 0
    210 #endif
    211 		if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
    212 			/* little endian */
    213 			stamp[i] = (i & 8 ? fg : bg);
    214 			stamp[i] |= ((i & 4 ? fg : bg) << 8);
    215 			stamp[i] |= ((i & 2 ? fg : bg) << 16);
    216 			stamp[i] |= ((i & 1 ? fg : bg) << 24);
    217 		} else {
    218 			/* big endian */
    219 			stamp[i] = (i & 1 ? fg : bg);
    220 			stamp[i] |= ((i & 2 ? fg : bg) << 8);
    221 			stamp[i] |= ((i & 4 ? fg : bg) << 16);
    222 			stamp[i] |= ((i & 8 ? fg : bg) << 24);
    223 		}
    224 	}
    225 }
    226 
    227 /*
    228  * Put a single character. This is for 8-pixel wide fonts.
    229  */
    230 static void
    231 rasops8_putchar8(cookie, row, col, uc, attr)
    232 	void *cookie;
    233 	int row, col;
    234 	u_int uc;
    235 	long attr;
    236 {
    237 	struct rasops_info *ri;
    238 	int height, fs;
    239 	int32_t *rp, *hp;
    240 	u_char *fr;
    241 
    242 	/* Can't risk remaking the stamp if it's already in use */
    243 	if (stamp_mutex++) {
    244 		stamp_mutex--;
    245 		rasops8_putchar(cookie, row, col, uc, attr);
    246 		return;
    247 	}
    248 
    249 	ri = (struct rasops_info *)cookie;
    250 	hp = NULL;
    251 
    252 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    253 		return;
    254 
    255 #ifdef RASOPS_CLIPPING
    256 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    257 		stamp_mutex--;
    258 		return;
    259 	}
    260 
    261 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    262 		stamp_mutex--;
    263 		return;
    264 	}
    265 #endif
    266 
    267 	/* Recompute stamp? */
    268 	if (attr != stamp_attr)
    269 		rasops8_makestamp(ri, attr);
    270 
    271 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    272 	if (ri->ri_hwbits)
    273 		hp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
    274 		    col*ri->ri_xscale);
    275 	height = ri->ri_font->fontheight;
    276 
    277 	if (uc == ' ') {
    278 		while (height--) {
    279 			rp[0] = rp[1] = stamp[0];
    280 			DELTA(rp, ri->ri_stride, int32_t *);
    281 			if (ri->ri_hwbits) {
    282 				hp[0] = stamp[0];
    283 				hp[1] = stamp[0];
    284 				DELTA(hp, ri->ri_stride, int32_t *);
    285 			}
    286 		}
    287 	} else {
    288 		uc -= ri->ri_font->firstchar;
    289 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    290 		fs = ri->ri_font->stride;
    291 
    292 		while (height--) {
    293 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    294 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    295 			if (ri->ri_hwbits) {
    296 				hp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) &
    297 				    STAMP_MASK);
    298 				hp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) &
    299 				    STAMP_MASK);
    300 			}
    301 
    302 			fr += fs;
    303 			DELTA(rp, ri->ri_stride, int32_t *);
    304 			if (ri->ri_hwbits)
    305 				DELTA(hp, ri->ri_stride, int32_t *);
    306 		}
    307 	}
    308 
    309 	/* Do underline */
    310 	if ((attr & 1) != 0) {
    311 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    312 		rp[0] = rp[1] = stamp[15];
    313 		if (ri->ri_hwbits) {
    314 			DELTA(hp, -(ri->ri_stride << 1), int32_t *);
    315 			hp[0] = stamp[15];
    316 			hp[1] = stamp[15];
    317 		}
    318 	}
    319 
    320 	stamp_mutex--;
    321 }
    322 
    323 /*
    324  * Put a single character. This is for 12-pixel wide fonts.
    325  */
    326 static void
    327 rasops8_putchar12(cookie, row, col, uc, attr)
    328 	void *cookie;
    329 	int row, col;
    330 	u_int uc;
    331 	long attr;
    332 {
    333 	struct rasops_info *ri;
    334 	int height, fs;
    335 	int32_t *rp,  *hrp;
    336 	u_char *fr;
    337 
    338 	/* Can't risk remaking the stamp if it's already in use */
    339 	if (stamp_mutex++) {
    340 		stamp_mutex--;
    341 		rasops8_putchar(cookie, row, col, uc, attr);
    342 		return;
    343 	}
    344 
    345 	ri = (struct rasops_info *)cookie;
    346 	hrp = NULL;
    347 
    348 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    349 	    return;
    350 
    351 #ifdef RASOPS_CLIPPING
    352 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    353 		stamp_mutex--;
    354 		return;
    355 	}
    356 
    357 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    358 		stamp_mutex--;
    359 		return;
    360 	}
    361 #endif
    362 
    363 	/* Recompute stamp? */
    364 	if (attr != stamp_attr)
    365 		rasops8_makestamp(ri, attr);
    366 
    367 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    368 	if (ri->ri_hwbits)
    369 		hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
    370 		    col*ri->ri_xscale);
    371 	height = ri->ri_font->fontheight;
    372 
    373 	if (uc == ' ') {
    374 		while (height--) {
    375 			int32_t c = stamp[0];
    376 
    377 			rp[0] = rp[1] = rp[2] = c;
    378 			DELTA(rp, ri->ri_stride, int32_t *);
    379 			if (ri->ri_hwbits) {
    380 				hrp[0] = c;
    381 				hrp[1] = c;
    382 				hrp[2] = 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 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    393 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    394 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    395 			if (ri->ri_hwbits) {
    396 				hrp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    397 				hrp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    398 				hrp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    399 			}
    400 
    401 			fr += fs;
    402 			DELTA(rp, ri->ri_stride, int32_t *);
    403 			if (ri->ri_hwbits)
    404 				DELTA(hrp, ri->ri_stride, int32_t *);
    405 		}
    406 	}
    407 
    408 	/* Do underline */
    409 	if ((attr & 1) != 0) {
    410 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    411 		rp[0] = rp[1] = rp[2] = stamp[15];
    412 		if (ri->ri_hwbits) {
    413 			DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
    414 			hrp[0] = stamp[15];
    415 			hrp[1] = stamp[15];
    416 			hrp[2] = stamp[15];
    417 		}
    418 	}
    419 
    420 	stamp_mutex--;
    421 }
    422 
    423 /*
    424  * Put a single character. This is for 16-pixel wide fonts.
    425  */
    426 static void
    427 rasops8_putchar16(cookie, row, col, uc, attr)
    428 	void *cookie;
    429 	int row, col;
    430 	u_int uc;
    431 	long attr;
    432 {
    433 	struct rasops_info *ri;
    434 	int height, fs;
    435 	int32_t *rp, *hrp;
    436 	u_char *fr;
    437 
    438 	/* Can't risk remaking the stamp if it's already in use */
    439 	if (stamp_mutex++) {
    440 		stamp_mutex--;
    441 		rasops8_putchar(cookie, row, col, uc, attr);
    442 		return;
    443 	}
    444 
    445 	ri = (struct rasops_info *)cookie;
    446 	hrp = NULL;
    447 
    448 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    449 		return;
    450 
    451 #ifdef RASOPS_CLIPPING
    452 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    453 		stamp_mutex--;
    454 		return;
    455 	}
    456 
    457 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    458 		stamp_mutex--;
    459 		return;
    460 	}
    461 #endif
    462 
    463 	/* Recompute stamp? */
    464 	if (attr != stamp_attr)
    465 		rasops8_makestamp(ri, attr);
    466 
    467 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    468 	if (ri->ri_hwbits)
    469 		hrp = (int32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
    470 		    col*ri->ri_xscale);
    471 
    472 	height = ri->ri_font->fontheight;
    473 
    474 	if (uc == ' ') {
    475 		while (height--) {
    476 			rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
    477 			if (ri->ri_hwbits) {
    478 				hrp[0] = stamp[0];
    479 				hrp[1] = stamp[0];
    480 				hrp[2] = stamp[0];
    481 				hrp[3] = stamp[0];
    482 			}
    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] = stamp[15];
    515 			hrp[1] = stamp[15];
    516 			hrp[2] = stamp[15];
    517 			hrp[3] = stamp[15];
    518 		}
    519 	}
    520 
    521 	stamp_mutex--;
    522 }
    523 #endif /* !RASOPS_SMALL */
    524