Home | History | Annotate | Line # | Download | only in rasops
rasops8.c revision 1.2
      1 /* $NetBSD: rasops8.c,v 1.2 1999/04/13 00:40:09 ad Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1999 Andy Doran <ad (at) NetBSD.org>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  *
     28  */
     29 
     30 #include "opt_rasops.h"
     31 #ifdef RASOPS8
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.2 1999/04/13 00:40:09 ad Exp $");
     35 
     36 #include <sys/types.h>
     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 __P((void *, int, int, u_int, long attr));
     46 static void 	rasops8_putchar8 __P((void *, int, int, u_int, long attr));
     47 static void 	rasops8_putchar12 __P((void *, int, int, u_int, long attr));
     48 static void 	rasops8_putchar16 __P((void *, int, int, u_int, long attr));
     49 static void 	rasops8_erasecols __P((void *, int, int, int, long));
     50 static void 	rasops8_eraserows __P((void *, int, int, long));
     51 static void	rasops8_makestamp __P((long));
     52 static int32_t	rasops8_bg_color __P((long));
     53 static void	rasops8_do_cursor __P((struct rasops_info *));
     54 void		rasops8_init __P((struct rasops_info *ri));
     55 
     56 /*
     57  * 4x1 stamp for optimized character blitting
     58  */
     59 static int32_t	stamp[16];
     60 static long	stamp_attr;
     61 static int	stamp_mutex;	/* XXX see note in README */
     62 
     63 /*
     64  * XXX this confuses the hell out of gcc2 (not egcs) which always insists
     65  * that the shift count is negative.
     66  *
     67  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
     68  * destination = STAMP_READ(offset)
     69  */
     70 #define STAMP_SHIFT(fb,n)	((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
     71 #define STAMP_MASK		(15 << 2)
     72 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
     73 
     74 
     75 /*
     76  * Initalize a 'rasops_info' descriptor for this depth.
     77  */
     78 void
     79 rasops8_init(ri)
     80 	struct rasops_info *ri;
     81 {
     82 
     83 	switch (ri->ri_font->fontwidth) {
     84 	case 8:
     85 		ri->ri_ops.putchar = rasops8_putchar8;
     86 		break;
     87 
     88 	case 12:
     89 		ri->ri_ops.putchar = rasops8_putchar12;
     90 		break;
     91 
     92 	case 16:
     93 		ri->ri_ops.putchar = rasops8_putchar16;
     94 		break;
     95 
     96 	default:
     97 		ri->ri_ops.putchar = rasops8_putchar;
     98 		break;
     99 	}
    100 
    101 	ri->ri_ops.erasecols = rasops8_erasecols;
    102 	ri->ri_ops.eraserows = rasops8_eraserows;
    103 	ri->ri_do_cursor = rasops8_do_cursor;
    104 }
    105 
    106 
    107 /*
    108  * Get background color from attribute and copy across all 4 bytes
    109  * of an int32_t.
    110  */
    111 static __inline__ int32_t
    112 rasops8_bg_color(attr)
    113 	long attr;
    114 {
    115 	int32_t bg;
    116 
    117 	bg = ((int32_t)attr >> 16) & 15;
    118 	return bg | (bg << 8) | (bg << 16) | (bg << 24);
    119 }
    120 
    121 
    122 /*
    123  * Actually turn the cursor on or off. This does the dirty work for
    124  * rasops_cursor().
    125  */
    126 static void
    127 rasops8_do_cursor(ri)
    128 	struct rasops_info *ri;
    129 {
    130 	u_char *dp, *rp;
    131 	int full1, height, cnt, slop1, slop2, row, col;
    132 
    133 	row = ri->ri_crow;
    134 	col = ri->ri_ccol;
    135 
    136 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    137 	height = ri->ri_font->fontheight;
    138 
    139 	slop1 = (int)rp & 3;
    140 	slop2 = (ri->ri_xscale - slop1) & 3;
    141 	full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
    142 
    143 	while (height--) {
    144 		dp = rp;
    145 		rp += ri->ri_stride;
    146 
    147 		for (cnt = slop1; cnt; cnt--)
    148 			*dp++ ^= 0xff;
    149 
    150 		for (cnt = full1; cnt; cnt--) {
    151 			*(int32_t *)dp ^= 0xffffffff;
    152 			dp += 4;
    153 		}
    154 
    155 		for (cnt = slop2; cnt; cnt--)
    156 			*dp++ ^= 0xff;
    157 	}
    158 }
    159 
    160 
    161 /*
    162  * Paint a single character.
    163  */
    164 static void
    165 rasops8_putchar(cookie, row, col, uc, attr)
    166 	void *cookie;
    167 	int row, col;
    168 	u_int uc;
    169 	long attr;
    170 {
    171 	struct rasops_info *ri;
    172 	u_char *dp, *rp, *fr, clr[2];
    173 	int width, height, cnt, fs, fb;
    174 
    175 	ri = (struct rasops_info *)cookie;
    176 
    177 #ifdef RASOPS_CLIPPING
    178 	/* Catches 'row < 0' case too */
    179 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    180 		return;
    181 
    182 	if ((unsigned)col >= (unsigned)ri->ri_cols)
    183 		return;
    184 #endif
    185 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    186 
    187 	height = ri->ri_font->fontheight;
    188 	width = ri->ri_font->fontwidth;
    189 	clr[0] = (u_char)(attr >> 16);
    190 	clr[1] = (u_char)(attr >> 24);
    191 
    192 	if (uc == ' ') {
    193 		while (height--) {
    194 			dp = rp;
    195 			rp += ri->ri_stride;
    196 
    197 			for (cnt = width; cnt; cnt--)
    198 				*dp++ = clr[0];
    199 		}
    200 	} else {
    201 		uc -= ri->ri_font->firstchar;
    202 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    203 		fs = ri->ri_font->stride;
    204 
    205 		while (height--) {
    206 			dp = rp;
    207 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
    208 			fr += fs;
    209 			rp += ri->ri_stride;
    210 
    211 			for (cnt = width; cnt; cnt--) {
    212 				*dp++ = clr[(fb >> 31) & 1];
    213 				fb <<= 1;
    214 			}
    215 		}
    216 	}
    217 
    218 	/* Do underline */
    219 	if (attr & 1) {
    220 		rp -= (ri->ri_stride << 1);
    221 
    222 		while (width--)
    223 			*rp++ = clr[1];
    224 	}
    225 
    226 }
    227 
    228 
    229 /*
    230  * Recompute the 4x1 blitting stamp.
    231  */
    232 static void
    233 rasops8_makestamp(long attr)
    234 {
    235 	int i;
    236 	int32_t fg, bg;
    237 
    238 	fg = (attr >> 24) & 15;
    239 	bg = (attr >> 16) & 15;
    240 	stamp_attr = attr;
    241 
    242 	for (i = 0; i < 16; i++) {
    243 #if BYTE_ORDER == LITTLE_ENDIAN
    244 		stamp[i] = (i & 8 ? fg : bg);
    245 		stamp[i] |= ((i & 4 ? fg : bg) << 8);
    246 		stamp[i] |= ((i & 2 ? fg : bg) << 16);
    247 		stamp[i] |= ((i & 1 ? fg : bg) << 24);
    248 #else
    249 		stamp[i] = (i & 1 ? fg : bg);
    250 		stamp[i] |= ((i & 2 ? fg : bg) << 8);
    251 		stamp[i] |= ((i & 4 ? fg : bg) << 16);
    252 		stamp[i] |= ((i & 8 ? fg : bg) << 24);
    253 #endif
    254 	}
    255 }
    256 
    257 
    258 /*
    259  * Paint a single character. This is for 8-pixel wide fonts.
    260  */
    261 static void
    262 rasops8_putchar8(cookie, row, col, uc, attr)
    263 	void *cookie;
    264 	int row, col;
    265 	u_int uc;
    266 	long attr;
    267 {
    268 	struct rasops_info *ri;
    269 	int height, fs;
    270 	int32_t *rp;
    271 	u_char *fr;
    272 
    273 	/* Can't risk remaking the stamp if it's already in use */
    274 	if (stamp_mutex++) {
    275 		stamp_mutex--;
    276 		rasops8_putchar(cookie, row, col, uc, attr);
    277 		return;
    278 	}
    279 
    280 	ri = (struct rasops_info *)cookie;
    281 
    282 #ifdef RASOPS_CLIPPING
    283 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    284 		stamp_mutex--;
    285 		return;
    286 	}
    287 
    288 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    289 		stamp_mutex--;
    290 		return;
    291 	}
    292 #endif
    293 
    294 	/* Recompute stamp? */
    295 	if (attr != stamp_attr)
    296 		rasops8_makestamp(attr);
    297 
    298 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    299 	height = ri->ri_font->fontheight;
    300 
    301 	if (uc == ' ') {
    302 		while (height--) {
    303 			rp[0] = stamp[0];
    304 			rp[1] = stamp[0];
    305 			DELTA(rp, ri->ri_stride, int32_t *);
    306 		}
    307 	} else {
    308 		uc -= ri->ri_font->firstchar;
    309 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    310 		fs = ri->ri_font->stride;
    311 
    312 		while (height--) {
    313 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    314 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    315 
    316 			fr += fs;
    317 			DELTA(rp, ri->ri_stride, int32_t *);
    318 		}
    319 	}
    320 
    321 	/* Do underline */
    322 	if (attr & 1) {
    323 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    324 		rp[0] = stamp[15];
    325 		rp[1] = stamp[15];
    326 	}
    327 
    328 	stamp_mutex--;
    329 }
    330 
    331 
    332 /*
    333  * Paint a single character. This is for 12-pixel wide fonts.
    334  */
    335 static void
    336 rasops8_putchar12(cookie, row, col, uc, attr)
    337 	void *cookie;
    338 	int row, col;
    339 	u_int uc;
    340 	long attr;
    341 {
    342 	struct rasops_info *ri;
    343 	int height, fs;
    344 	int32_t *rp;
    345 	u_char *fr;
    346 
    347 	/* Can't risk remaking the stamp if it's already in use */
    348 	if (stamp_mutex++) {
    349 		stamp_mutex--;
    350 		rasops8_putchar(cookie, row, col, uc, attr);
    351 		return;
    352 	}
    353 
    354 	ri = (struct rasops_info *)cookie;
    355 
    356 #ifdef RASOPS_CLIPPING
    357 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    358 		stamp_mutex--;
    359 		return;
    360 	}
    361 
    362 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    363 		stamp_mutex--;
    364 		return;
    365 	}
    366 #endif
    367 
    368 	/* Recompute stamp? */
    369 	if (attr != stamp_attr)
    370 		rasops8_makestamp(attr);
    371 
    372 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    373 	height = ri->ri_font->fontheight;
    374 
    375 	if (uc == ' ') {
    376 		while (height--) {
    377 			rp[0] = stamp[0];
    378 			rp[1] = stamp[0];
    379 			rp[2] = stamp[0];
    380 			DELTA(rp, ri->ri_stride, int32_t *);
    381 		}
    382 	} else {
    383 		uc -= ri->ri_font->firstchar;
    384 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    385 		fs = ri->ri_font->stride;
    386 
    387 		while (height--) {
    388 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    389 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    390 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    391 
    392 			fr += fs;
    393 			DELTA(rp, ri->ri_stride, int32_t *);
    394 		}
    395 	}
    396 
    397 	/* Do underline */
    398 	if (attr & 1) {
    399 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    400 		rp[0] = stamp[15];
    401 		rp[1] = stamp[15];
    402 		rp[2] = stamp[15];
    403 	}
    404 
    405 	stamp_mutex--;
    406 }
    407 
    408 
    409 /*
    410  * Paint a single character. This is for 16-pixel wide fonts.
    411  */
    412 static void
    413 rasops8_putchar16(cookie, row, col, uc, attr)
    414 	void *cookie;
    415 	int row, col;
    416 	u_int uc;
    417 	long attr;
    418 {
    419 	struct rasops_info *ri;
    420 	int height, fs;
    421 	int32_t *rp;
    422 	u_char *fr;
    423 
    424 	/* Can't risk remaking the stamp if it's already in use */
    425 	if (stamp_mutex++) {
    426 		stamp_mutex--;
    427 		rasops8_putchar(cookie, row, col, uc, attr);
    428 		return;
    429 	}
    430 
    431 	ri = (struct rasops_info *)cookie;
    432 
    433 #ifdef RASOPS_CLIPPING
    434 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    435 		stamp_mutex--;
    436 		return;
    437 	}
    438 
    439 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    440 		stamp_mutex--;
    441 		return;
    442 	}
    443 #endif
    444 
    445 	/* Recompute stamp? */
    446 	if (attr != stamp_attr)
    447 		rasops8_makestamp(attr);
    448 
    449 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    450 	height = ri->ri_font->fontheight;
    451 
    452 	if (uc == ' ') {
    453 		while (height--) {
    454 			rp[0] = stamp[0];
    455 			rp[1] = stamp[0];
    456 			rp[2] = stamp[0];
    457 			rp[3] = stamp[0];
    458 			DELTA(rp, ri->ri_stride, int32_t *);
    459 		}
    460 	} else {
    461 		uc -= ri->ri_font->firstchar;
    462 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    463 		fs = ri->ri_font->stride;
    464 
    465 		while (height--) {
    466 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    467 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    468 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    469 			rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
    470 
    471 			fr += fs;
    472 			DELTA(rp, ri->ri_stride, int32_t *);
    473 		}
    474 	}
    475 
    476 	/* Do underline */
    477 	if (attr & 1) {
    478 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    479 		rp[0] = stamp[15];
    480 		rp[1] = stamp[15];
    481 		rp[2] = stamp[15];
    482 		rp[3] = stamp[15];
    483 	}
    484 
    485 	stamp_mutex--;
    486 }
    487 
    488 
    489 /*
    490  * Erase rows.
    491  */
    492 static void
    493 rasops8_eraserows(cookie, row, num, attr)
    494 	void *cookie;
    495 	int row, num;
    496 	long attr;
    497 {
    498 	struct rasops_info *ri;
    499 	int32_t *dp, clr;
    500 	int n8, n1, cnt;
    501 
    502 	ri = (struct rasops_info *)cookie;
    503 
    504 #ifdef RASOPS_CLIPPING
    505 	if (row < 0) {
    506 		num += row;
    507 		row = 0;
    508 	}
    509 
    510 	if ((row + num) > ri->ri_rows)
    511 		num = ri->ri_rows - row;
    512 
    513 	if (num <= 0)
    514 		return;
    515 #endif
    516 
    517 	num *= ri->ri_font->fontheight;
    518 	dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
    519 	clr = rasops8_bg_color(attr);
    520 
    521 	n8 = ri->ri_emustride >> 5;
    522 	n1 = (ri->ri_emustride >> 2) & 7;
    523 
    524 	while (num--) {
    525 		for (cnt = n8; cnt; cnt--) {
    526 			dp[0] = clr;
    527 			dp[1] = clr;
    528 			dp[2] = clr;
    529 			dp[3] = clr;
    530 			dp[4] = clr;
    531 			dp[5] = clr;
    532 			dp[6] = clr;
    533 			dp[7] = clr;
    534 			dp += 8;
    535 		}
    536 
    537 		for (cnt = n1; cnt; cnt--)
    538 			*dp++ = clr;
    539 
    540 		DELTA(dp, ri->ri_delta, int32_t *);
    541 	}
    542 }
    543 
    544 
    545 /*
    546  * Erase columns.
    547  */
    548 static void
    549 rasops8_erasecols(cookie, row, col, num, attr)
    550 	void *cookie;
    551 	int row, col, num;
    552 	long attr;
    553 {
    554 	int n8, clr, height, cnt, slop1, slop2;
    555 	struct rasops_info *ri;
    556 	int32_t *dst;
    557 	u_char *dstb, *rp;
    558 
    559 	ri = (struct rasops_info *)cookie;
    560 
    561 #ifdef RASOPS_CLIPPING
    562 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    563 		return;
    564 
    565 	if (col < 0) {
    566 		num += col;
    567 		col = 0;
    568 	}
    569 
    570 	if ((col + num) > ri->ri_cols)
    571 		num = ri->ri_cols - col;
    572 
    573 	if (num <= 0)
    574 		return;
    575 #endif
    576 
    577 	num = num * ri->ri_xscale;
    578 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    579 	clr = rasops8_bg_color(attr);
    580 	height = ri->ri_font->fontheight;
    581 
    582 	slop1 = (int)rp & 3;
    583 	slop2 = (num - slop1) & 3;
    584 	num -= slop1 + slop2;
    585 	n8 = num >> 5;
    586 	num = (num >> 2) & 7;
    587 
    588 	while (height--) {
    589 		dstb = rp;
    590 		rp += ri->ri_stride;
    591 
    592 		/* Align span to 4 bytes */
    593 		for (cnt = slop1; cnt; cnt--)
    594 			*dstb++ = (u_char)clr;
    595 
    596 		dst = (int32_t *)dstb;
    597 
    598 		/* Write 32 bytes per loop */
    599 		for (cnt = n8; cnt; cnt--) {
    600 			dst[0] = clr;
    601 			dst[1] = clr;
    602 			dst[2] = clr;
    603 			dst[3] = clr;
    604 			dst[4] = clr;
    605 			dst[5] = clr;
    606 			dst[6] = clr;
    607 			dst[7] = clr;
    608 			dst += 8;
    609 		}
    610 
    611 		/* Write 4 bytes per loop */
    612 		for (cnt = num; cnt; cnt--)
    613 			*dst++ = clr;
    614 
    615 		/* Write unaligned trailing slop */
    616 		if (slop2 == 0)
    617 			continue;
    618 
    619 		dstb = (u_char *)dst;
    620 
    621 		for (cnt = slop2; cnt; cnt--)
    622 			*dstb++ = (u_char)clr;
    623 	}
    624 }
    625 
    626 #endif /* RASOPS8 */
    627