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