Home | History | Annotate | Line # | Download | only in rasops
rasops15.c revision 1.1
      1 /*	$NetBSD: rasops15.c,v 1.1 1999/04/13 00:18:00 ad 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 Andy Doran <ad (at) NetBSD.org>.
      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 #include "opt_rasops.h"
     39 #ifdef RASOPS15
     40 
     41 #include <sys/cdefs.h>
     42 __KERNEL_RCSID(0, "$NetBSD: rasops15.c,v 1.1 1999/04/13 00:18:00 ad Exp $");
     43 
     44 #include <sys/types.h>
     45 #include <sys/param.h>
     46 #include <sys/systm.h>
     47 #include <sys/time.h>
     48 
     49 #include <dev/wscons/wsdisplayvar.h>
     50 #include <dev/wscons/wsconsio.h>
     51 #include <dev/rasops/rasops.h>
     52 
     53 static void 	rasops15_putchar __P((void *, int, int, u_int, long attr));
     54 static void 	rasops15_putchar8 __P((void *, int, int, u_int, long attr));
     55 static void 	rasops15_putchar12 __P((void *, int, int, u_int, long attr));
     56 static void 	rasops15_putchar16 __P((void *, int, int, u_int, long attr));
     57 static void 	rasops15_erasecols __P((void *, int, int, int, long));
     58 static void 	rasops15_eraserows __P((void *, int, int, long));
     59 static void	rasops15_makestamp __P((struct rasops_info *, long));
     60 static int32_t	rasops15_bg_color __P((struct rasops_info *, long));
     61 static void	rasops15_do_cursor __P((struct rasops_info *));
     62 
     63 void	rasops15_init __P((struct rasops_info *ri));
     64 
     65 /*
     66  * (2x2)x1 stamp for optimized character blitting
     67  */
     68 static int32_t	stamp[32];
     69 static long	stamp_attr;
     70 static int	stamp_mutex;	/* XXX see note in readme */
     71 
     72 /*
     73  * XXX this confuses the hell out of gcc2 (not egcs) which always insists
     74  * that the shift count is negative.
     75  *
     76  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
     77  * destination int32_t[0] = STAMP_READ(offset)
     78  * destination int32_t[1] = STAMP_READ(offset + 4)
     79  */
     80 #define STAMP_SHIFT(fb,n)	((n*4-3) >= 0 ? (fb)>>(n*4-3):(fb)<<-(n*4-3))
     81 #define STAMP_MASK		(15 << 3)
     82 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
     83 
     84 
     85 /*
     86  * Initalize rasops_info struct for this colordepth.
     87  */
     88 void
     89 rasops15_init(ri)
     90 	struct rasops_info *ri;
     91 {
     92 
     93 	switch (ri->ri_font->fontwidth) {
     94 	case 8:
     95 		ri->ri_ops.putchar = rasops15_putchar8;
     96 		break;
     97 
     98 	case 12:
     99 		ri->ri_ops.putchar = rasops15_putchar12;
    100 		break;
    101 
    102 	case 16:
    103 		ri->ri_ops.putchar = rasops15_putchar16;
    104 		break;
    105 
    106 	default:
    107 		ri->ri_ops.putchar = rasops15_putchar;
    108 		break;
    109 	}
    110 
    111 	/* Select defaults for color masks if none selected */
    112 	if (ri->ri_rnum == 0) {
    113 		ri->ri_rnum = 5;
    114 		ri->ri_rpos = 0;
    115 		ri->ri_gnum = 5 + (ri->ri_depth == 16);
    116 		ri->ri_gpos = 5;
    117 		ri->ri_bnum = 5;
    118 		ri->ri_bpos = 10 + (ri->ri_depth == 16);
    119 	}
    120 
    121 	ri->ri_ops.erasecols = rasops15_erasecols;
    122 	ri->ri_ops.eraserows = rasops15_eraserows;
    123 	ri->ri_do_cursor = rasops15_do_cursor;
    124 	rasops_init_devcmap(ri);
    125 }
    126 
    127 
    128 /*
    129  * Get background color from attribute and copy across all 4 bytes
    130  * in a int32_t.
    131  */
    132 static __inline__ int32_t
    133 rasops15_bg_color(ri, attr)
    134 	struct rasops_info *ri;
    135 	long attr;
    136 {
    137 	int32_t bg;
    138 
    139 	bg = ri->ri_devcmap[((u_int)attr >> 16) & 15];
    140 	return bg | (bg << 16);
    141 }
    142 
    143 
    144 /*
    145  * Actually turn the cursor on or off. This does the dirty work for
    146  * rasops_cursor().
    147  */
    148 static void
    149 rasops15_do_cursor(ri)
    150 	struct rasops_info *ri;
    151 {
    152 	u_char *rp, *dp;
    153 	int full1, height, cnt, slop1, slop2, row, col;
    154 	int32_t planemask;
    155 
    156 	row = ri->ri_crow;
    157 	col = ri->ri_ccol;
    158 
    159 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    160 	height = ri->ri_font->fontheight;
    161 
    162 	slop1 = (int)rp & 2;
    163 	slop2 = (ri->ri_xscale - slop1) & 2;
    164 	full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
    165 	planemask = ri->ri_devcmap[15] | (ri->ri_devcmap[15] << 16);
    166 
    167 	while (height--) {
    168 		dp = rp;
    169 		rp += ri->ri_stride;
    170 
    171 		if (slop1) {
    172 			*(int16_t *)dp ^= (int16_t)planemask;
    173 			dp += 2;
    174 		}
    175 
    176 		for (cnt = full1; cnt; cnt--) {
    177 			*(int32_t *)dp ^= planemask;
    178 			dp += 4;
    179 		}
    180 
    181 		if (slop2)
    182 			*(int16_t *)dp ^= (int16_t)planemask;
    183 	}
    184 }
    185 
    186 
    187 /*
    188  * Erase columns.
    189  */
    190 static void
    191 rasops15_erasecols(cookie, row, col, num, attr)
    192 	void *cookie;
    193 	int row, num;
    194 	long attr;
    195 {
    196 	int n8, clr, height, cnt, slop1, slop2;
    197 	struct rasops_info *ri;
    198 	int32_t *dp;
    199 	u_char *rp;
    200 
    201 	ri = (struct rasops_info *)cookie;
    202 
    203 #ifdef RASOPS_CLIPPING
    204 	/* Catches 'row < 0' case too */
    205 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    206 		return;
    207 
    208 	if (col < 0) {
    209 		num += col;
    210 		col = 0;
    211 	}
    212 
    213 	if ((col + num) > ri->ri_cols)
    214 		num = ri->ri_cols - col;
    215 
    216 	if (num <= 0)
    217 		return;
    218 #endif
    219 
    220 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    221 	num *= ri->ri_xscale;
    222 	clr = rasops15_bg_color(ri, attr);
    223 	height = ri->ri_font->fontheight;
    224 
    225 	slop1 = (int)rp & 2;
    226 	slop2 = (num - slop1) & 2;
    227 	num = num - slop1 - slop2;
    228 	n8 = num >> 5;
    229 	num = (num >> 2) & 7;
    230 
    231 	while (height--) {
    232 		dp = (u_int32_t *)rp;
    233 		rp += ri->ri_stride;
    234 
    235 		/* Align span to 4 bytes */
    236 		if (slop1) {
    237 			*(int16_t *)dp = (int16_t)clr;
    238 			DELTA(dp, 2, int32_t *);
    239 		}
    240 
    241 		/* Write 32 bytes per loop */
    242 		for (cnt = n8; cnt; cnt--) {
    243 			dp[0] = clr;
    244 			dp[1] = clr;
    245 			dp[2] = clr;
    246 			dp[3] = clr;
    247 			dp[4] = clr;
    248 			dp[5] = clr;
    249 			dp[6] = clr;
    250 			dp[7] = clr;
    251 			dp += 8;
    252 		}
    253 
    254 		/* Write 4 bytes per loop */
    255 		for (cnt = num; cnt; cnt--)
    256 			*dp++ = clr;
    257 
    258 		/* Write unaligned trailing slop */
    259 		if (slop2)
    260 			*(int16_t *)dp = (int16_t)clr;
    261 	}
    262 }
    263 
    264 
    265 /*
    266  * Paint a single character.
    267  */
    268 static void
    269 rasops15_putchar(cookie, row, col, uc, attr)
    270 	void *cookie;
    271 	int row, col;
    272 	u_int uc;
    273 	long attr;
    274 {
    275 	struct rasops_info *ri;
    276 	int fb, width, height, cnt, clr[2];
    277 	u_char *dp, *rp, *fr;
    278 
    279 	if (uc == (u_int)-1) {
    280 		rasops15_erasecols(cookie, row, col, 1, attr);
    281 		return;
    282 	}
    283 
    284 	ri = (struct rasops_info *)cookie;
    285 
    286 #ifdef RASOPS_CLIPPING
    287 	/* Catches 'row < 0' case too */
    288 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    289 		return;
    290 
    291 	if ((unsigned)col >= (unsigned)ri->ri_cols)
    292 		return;
    293 #endif
    294 
    295 	uc -= ri->ri_font->firstchar;
    296 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    297 	fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    298 
    299 	height = ri->ri_font->fontheight;
    300 	width = ri->ri_font->fontwidth;
    301 
    302 	clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 15];
    303 	clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 15];
    304 
    305 	while (height--) {
    306 		dp = rp;
    307 		fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
    308 		fr += ri->ri_font->stride;
    309 		rp += ri->ri_stride;
    310 
    311 		for (cnt = width; cnt; cnt--) {
    312 			*(int16_t *)dp = (int16_t)clr[(fb >> 31) & 1];
    313 			fb <<= 1;
    314 			dp += 2;
    315 		}
    316 	}
    317 }
    318 
    319 
    320 /*
    321  * Recompute the (2x2)x1 blitting stamp.
    322  */
    323 static void
    324 rasops15_makestamp(ri, attr)
    325 	struct rasops_info *ri;
    326 	long attr;
    327 {
    328 	int32_t fg, bg;
    329 	int i;
    330 
    331 	fg = ri->ri_devcmap[((u_int)attr >> 24) & 15];
    332 	bg = ri->ri_devcmap[((u_int)attr >> 16) & 15];
    333 	stamp_attr = attr;
    334 
    335 	for (i = 0; i < 16; i++) {
    336 #if BYTE_ORDER == LITTLE_ENDIAN
    337 		stamp[i << 1] = (i & 8 ? fg : bg);
    338 		stamp[i << 1] |= ((i & 4 ? fg : bg) << 16);
    339 		stamp[(i << 1) + 1] = (i & 2 ? fg : bg);
    340 		stamp[(i << 1) + 1] |= ((i & 1 ? fg : bg) << 16);
    341 #else
    342 		stamp[i << 1] = (i & 1 ? fg : bg);
    343 		stamp[i << 1] |= ((i & 2 ? fg : bg) << 16);
    344 		stamp[(i << 1) + 1] = (i & 4 ? fg : bg);
    345 		stamp[(i << 1) + 1] |= ((i & 8 ? fg : bg) << 16);
    346 #endif
    347 	}
    348 }
    349 
    350 
    351 /*
    352  * Paint a single character. This is for 8-pixel wide fonts.
    353  */
    354 static void
    355 rasops15_putchar8(cookie, row, col, uc, attr)
    356 	void *cookie;
    357 	int row, col;
    358 	u_int uc;
    359 	long attr;
    360 {
    361 	struct rasops_info *ri;
    362 	int height, so, fs;
    363 	int32_t *rp;
    364 	u_char *fr;
    365 
    366 	/* Can't risk remaking the stamp if it's already in use */
    367 	if (stamp_mutex++) {
    368 		stamp_mutex--;
    369 		rasops15_putchar(cookie, row, col, uc, attr);
    370 		return;
    371 	}
    372 
    373 	ri = (struct rasops_info *)cookie;
    374 
    375 #ifdef RASOPS_CLIPPING
    376 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    377 		stamp_mutex--;
    378 		return;
    379 	}
    380 
    381 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    382 		stamp_mutex--;
    383 		return;
    384 	}
    385 #endif
    386 
    387 	/* Recompute stamp? */
    388 	if (attr != stamp_attr)
    389 		rasops15_makestamp(ri, attr);
    390 
    391 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    392 	height = ri->ri_font->fontheight;
    393 
    394 	if (uc == (u_int)-1) {
    395 		while (height--) {
    396 			rp[0] = stamp[0];
    397 			rp[1] = stamp[0];
    398 			rp[2] = stamp[0];
    399 			rp[3] = stamp[0];
    400 			DELTA(rp, ri->ri_stride, int32_t *);
    401 		}
    402 	} else {
    403 		uc -= ri->ri_font->firstchar;
    404 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
    405 		fs = ri->ri_font->stride;
    406 
    407 		while (height--) {
    408 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
    409 			rp[0] = STAMP_READ(so);
    410 			rp[1] = STAMP_READ(so + 4);
    411 
    412 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
    413 			rp[2] = STAMP_READ(so);
    414 			rp[3] = STAMP_READ(so + 4);
    415 
    416 			fr += fs;
    417 			DELTA(rp, ri->ri_stride, int32_t *);
    418 		}
    419 	}
    420 
    421 	stamp_mutex--;
    422 }
    423 
    424 
    425 /*
    426  * Paint a single character. This is for 12-pixel wide fonts.
    427  */
    428 static void
    429 rasops15_putchar12(cookie, row, col, uc, attr)
    430 	void *cookie;
    431 	int row, col;
    432 	u_int uc;
    433 	long attr;
    434 {
    435 	struct rasops_info *ri;
    436 	int height, so, fs;
    437 	int32_t *rp;
    438 	u_char *fr;
    439 
    440 	/* Can't risk remaking the stamp if it's already in use */
    441 	if (stamp_mutex++) {
    442 		stamp_mutex--;
    443 		rasops15_putchar(cookie, row, col, uc, attr);
    444 		return;
    445 	}
    446 
    447 	ri = (struct rasops_info *)cookie;
    448 
    449 #ifdef RASOPS_CLIPPING
    450 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    451 		stamp_mutex--;
    452 		return;
    453 	}
    454 
    455 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    456 		stamp_mutex--;
    457 		return;
    458 	}
    459 #endif
    460 
    461 	/* Recompute stamp? */
    462 	if (attr != stamp_attr)
    463 		rasops15_makestamp(ri, attr);
    464 
    465 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    466 	height = ri->ri_font->fontheight;
    467 
    468 	if (uc == (u_int)-1) {
    469 		while (height--) {
    470 			rp[0] = stamp[0];
    471 			rp[1] = stamp[0];
    472 			rp[2] = stamp[0];
    473 			rp[3] = stamp[0];
    474 			rp[4] = stamp[0];
    475 			rp[5] = stamp[0];
    476 			DELTA(rp, ri->ri_stride, int32_t *);
    477 		}
    478 	} else {
    479 		uc -= ri->ri_font->firstchar;
    480 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
    481 		fs = ri->ri_font->stride;
    482 
    483 		while (height--) {
    484 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
    485 			rp[0] = STAMP_READ(so);
    486 			rp[1] = STAMP_READ(so + 4);
    487 
    488 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
    489 			rp[2] = STAMP_READ(so);
    490 			rp[3] = STAMP_READ(so + 4);
    491 
    492 			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
    493 			rp[4] = STAMP_READ(so);
    494 			rp[5] = STAMP_READ(so + 4);
    495 
    496 			fr += fs;
    497 			DELTA(rp, ri->ri_stride, int32_t *);
    498 		}
    499 	}
    500 
    501 	stamp_mutex--;
    502 }
    503 
    504 
    505 /*
    506  * Paint a single character. This is for 16-pixel wide fonts.
    507  */
    508 static void
    509 rasops15_putchar16(cookie, row, col, uc, attr)
    510 	void *cookie;
    511 	int row, col;
    512 	u_int uc;
    513 	long attr;
    514 {
    515 	struct rasops_info *ri;
    516 	int height, so, fs;
    517 	int32_t *rp;
    518 	u_char *fr;
    519 
    520 	/* Can't risk remaking the stamp if it's already in use */
    521 	if (stamp_mutex++) {
    522 		stamp_mutex--;
    523 		rasops15_putchar(cookie, row, col, uc, attr);
    524 		return;
    525 	}
    526 
    527 	ri = (struct rasops_info *)cookie;
    528 
    529 #ifdef RASOPS_CLIPPING
    530 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    531 		stamp_mutex--;
    532 		return;
    533 	}
    534 
    535 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    536 		stamp_mutex--;
    537 		return;
    538 	}
    539 #endif
    540 
    541 	/* Recompute stamp? */
    542 	if (attr != stamp_attr)
    543 		rasops15_makestamp(ri, attr);
    544 
    545 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    546 	height = ri->ri_font->fontheight;
    547 
    548 	if (uc == (u_int)-1) {
    549 		while (height--) {
    550 			rp[0] = stamp[0];
    551 			rp[1] = stamp[0];
    552 			rp[2] = stamp[0];
    553 			rp[3] = stamp[0];
    554 			rp[4] = stamp[0];
    555 			rp[5] = stamp[0];
    556 			rp[6] = stamp[0];
    557 			rp[7] = stamp[0];
    558 			DELTA(rp, ri->ri_stride, int32_t *);
    559 		}
    560 	} else {
    561 		uc -= ri->ri_font->firstchar;
    562 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
    563 		fs = ri->ri_font->stride;
    564 
    565 		while (height--) {
    566 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
    567 			rp[0] = STAMP_READ(so);
    568 			rp[1] = STAMP_READ(so + 4);
    569 
    570 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
    571 			rp[2] = STAMP_READ(so);
    572 			rp[3] = STAMP_READ(so + 4);
    573 
    574 			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
    575 			rp[4] = STAMP_READ(so);
    576 			rp[5] = STAMP_READ(so + 4);
    577 
    578 			so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
    579 			rp[6] = STAMP_READ(so);
    580 			rp[7] = STAMP_READ(so + 4);
    581 
    582 			DELTA(rp, ri->ri_stride, int32_t *);
    583 			fr += fs;
    584 		}
    585 	}
    586 
    587 	stamp_mutex--;
    588 }
    589 
    590 
    591 /*
    592  * Erase rows.
    593  */
    594 static void
    595 rasops15_eraserows(cookie, row, num, attr)
    596 	void *cookie;
    597 	int row, num;
    598 	long attr;
    599 {
    600 	struct rasops_info *ri;
    601 	int32_t *dp, clr;
    602 	int n8, n1, cnt;
    603 
    604 	ri = (struct rasops_info *)cookie;
    605 
    606 #ifdef RASOPS_CLIPPING
    607 	if (row < 0) {
    608 		num += row;
    609 		row = 0;
    610 	}
    611 
    612 	if ((row + num) > ri->ri_rows)
    613 		num = ri->ri_rows - row;
    614 
    615 	if (num <= 0)
    616 		return;
    617 #endif
    618 
    619 	num *= ri->ri_font->fontheight;
    620 	dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
    621 	clr = rasops15_bg_color(ri, attr);
    622 
    623 	n8 = ri->ri_emustride >> 5;
    624 	n1 = (ri->ri_emustride >> 2) & 7;
    625 
    626 	while (num--) {
    627 		for (cnt = n8; cnt; cnt--) {
    628 			dp[0] = clr;
    629 			dp[1] = clr;
    630 			dp[2] = clr;
    631 			dp[3] = clr;
    632 			dp[4] = clr;
    633 			dp[5] = clr;
    634 			dp[6] = clr;
    635 			dp[7] = clr;
    636 			dp += 8;
    637 		}
    638 
    639 		for (cnt = n1; cnt; cnt--)
    640 			*dp++ = clr;
    641 
    642 		DELTA(dp, ri->ri_delta, int32_t *);
    643 	}
    644 }
    645 
    646 #endif /* RASOPS15 */
    647