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