Home | History | Annotate | Line # | Download | only in rasops
rasops8.c revision 1.17
      1 /* 	$NetBSD: rasops8.c,v 1.17 2004/03/05 08:33:53 petrov 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  * 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 
     39 #include <sys/cdefs.h>
     40 __KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.17 2004/03/05 08:33:53 petrov Exp $");
     41 
     42 #include "opt_rasops.h"
     43 
     44 #include <sys/param.h>
     45 #include <sys/systm.h>
     46 #include <sys/time.h>
     47 #include <sys/bswap.h>
     48 
     49 #include <dev/wscons/wsdisplayvar.h>
     50 #include <dev/wscons/wsconsio.h>
     51 #include <dev/rasops/rasops.h>
     52 
     53 static void 	rasops8_putchar __P((void *, int, int, u_int, long attr));
     54 #ifndef RASOPS_SMALL
     55 static void 	rasops8_putchar8 __P((void *, int, int, u_int, long attr));
     56 static void 	rasops8_putchar12 __P((void *, int, int, u_int, long attr));
     57 static void 	rasops8_putchar16 __P((void *, int, int, u_int, long attr));
     58 static void	rasops8_makestamp __P((struct rasops_info *ri, long));
     59 
     60 /*
     61  * 4x1 stamp for optimized character blitting
     62  */
     63 static int32_t	stamp[16];
     64 static long	stamp_attr;
     65 static int	stamp_mutex;	/* XXX see note in README */
     66 #endif
     67 
     68 /*
     69  * XXX this confuses the hell out of gcc2 (not egcs) which always insists
     70  * that the shift count is negative.
     71  *
     72  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
     73  * destination = STAMP_READ(offset)
     74  */
     75 #define STAMP_SHIFT(fb,n)	((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
     76 #define STAMP_MASK		(0xf << 2)
     77 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
     78 
     79 /*
     80  * Initialize a 'rasops_info' descriptor for this depth.
     81  */
     82 void
     83 rasops8_init(ri)
     84 	struct rasops_info *ri;
     85 {
     86 
     87 	switch (ri->ri_font->fontwidth) {
     88 #ifndef RASOPS_SMALL
     89 	case 8:
     90 		ri->ri_ops.putchar = rasops8_putchar8;
     91 		break;
     92 	case 12:
     93 		ri->ri_ops.putchar = rasops8_putchar12;
     94 		break;
     95 	case 16:
     96 		ri->ri_ops.putchar = rasops8_putchar16;
     97 		break;
     98 #endif /* !RASOPS_SMALL */
     99 	default:
    100 		ri->ri_ops.putchar = rasops8_putchar;
    101 		break;
    102 	}
    103 }
    104 
    105 /*
    106  * Put a single character.
    107  */
    108 static void
    109 rasops8_putchar(cookie, row, col, uc, attr)
    110 	void *cookie;
    111 	int row, col;
    112 	u_int uc;
    113 	long attr;
    114 {
    115 	int width, height, cnt, fs, fb;
    116 	u_char *dp, *rp, *fr, clr[2];
    117 	struct rasops_info *ri;
    118 
    119 	ri = (struct rasops_info *)cookie;
    120 
    121 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    122 		return;
    123 
    124 #ifdef RASOPS_CLIPPING
    125 	/* Catches 'row < 0' case too */
    126 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    127 		return;
    128 
    129 	if ((unsigned)col >= (unsigned)ri->ri_cols)
    130 		return;
    131 #endif
    132 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    133 
    134 	height = ri->ri_font->fontheight;
    135 	width = ri->ri_font->fontwidth;
    136 	clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
    137 	clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
    138 
    139 	if (uc == ' ') {
    140 		u_char c = clr[0];
    141 
    142 		while (height--) {
    143 			dp = rp;
    144 			rp += ri->ri_stride;
    145 
    146 			for (cnt = width; cnt; cnt--)
    147 				*dp++ = c;
    148 		}
    149 	} else {
    150 		uc -= ri->ri_font->firstchar;
    151 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    152 		fs = ri->ri_font->stride;
    153 
    154 		while (height--) {
    155 			dp = rp;
    156 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
    157 			fr += fs;
    158 			rp += ri->ri_stride;
    159 
    160 			for (cnt = width; cnt; cnt--) {
    161 				*dp++ = clr[(fb >> 31) & 1];
    162 				fb <<= 1;
    163 			}
    164 		}
    165 	}
    166 
    167 	/* Do underline */
    168 	if ((attr & 1) != 0) {
    169 		u_char c = clr[1];
    170 
    171 		rp -= (ri->ri_stride << 1);
    172 
    173 		while (width--)
    174 			*rp++ = c;
    175 	}
    176 }
    177 
    178 #ifndef RASOPS_SMALL
    179 /*
    180  * Recompute the 4x1 blitting stamp.
    181  */
    182 static void
    183 rasops8_makestamp(ri, attr)
    184 	struct rasops_info *ri;
    185 	long attr;
    186 {
    187 	int32_t fg, bg;
    188 	int i;
    189 
    190 	fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
    191 	bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
    192 	stamp_attr = attr;
    193 
    194 	for (i = 0; i < 16; i++) {
    195 #if BYTE_ORDER == BIG_ENDIAN
    196 #define NEED_LITTLE_ENDIAN_STAMP RI_BSWAP
    197 #else
    198 #define NEED_LITTLE_ENDIAN_STAMP 0
    199 #endif
    200 		if ((ri->ri_flg & RI_BSWAP) == NEED_LITTLE_ENDIAN_STAMP) {
    201 			/* little endian */
    202 			stamp[i] = (i & 8 ? fg : bg);
    203 			stamp[i] |= ((i & 4 ? fg : bg) << 8);
    204 			stamp[i] |= ((i & 2 ? fg : bg) << 16);
    205 			stamp[i] |= ((i & 1 ? fg : bg) << 24);
    206 		} else {
    207 			/* big endian */
    208 			stamp[i] = (i & 1 ? fg : bg);
    209 			stamp[i] |= ((i & 2 ? fg : bg) << 8);
    210 			stamp[i] |= ((i & 4 ? fg : bg) << 16);
    211 			stamp[i] |= ((i & 8 ? fg : bg) << 24);
    212 		}
    213 	}
    214 }
    215 
    216 /*
    217  * Put a single character. This is for 8-pixel wide fonts.
    218  */
    219 static void
    220 rasops8_putchar8(cookie, row, col, uc, attr)
    221 	void *cookie;
    222 	int row, col;
    223 	u_int uc;
    224 	long attr;
    225 {
    226 	struct rasops_info *ri;
    227 	int height, fs;
    228 	int32_t *rp;
    229 	u_char *fr;
    230 
    231 	/* Can't risk remaking the stamp if it's already in use */
    232 	if (stamp_mutex++) {
    233 		stamp_mutex--;
    234 		rasops8_putchar(cookie, row, col, uc, attr);
    235 		return;
    236 	}
    237 
    238 	ri = (struct rasops_info *)cookie;
    239 
    240 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    241 		return;
    242 
    243 #ifdef RASOPS_CLIPPING
    244 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    245 		stamp_mutex--;
    246 		return;
    247 	}
    248 
    249 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    250 		stamp_mutex--;
    251 		return;
    252 	}
    253 #endif
    254 
    255 	/* Recompute stamp? */
    256 	if (attr != stamp_attr)
    257 		rasops8_makestamp(ri, attr);
    258 
    259 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    260 	height = ri->ri_font->fontheight;
    261 
    262 	if (uc == ' ') {
    263 		while (height--) {
    264 			rp[0] = rp[1] = stamp[0];
    265 			DELTA(rp, ri->ri_stride, int32_t *);
    266 		}
    267 	} else {
    268 		uc -= ri->ri_font->firstchar;
    269 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    270 		fs = ri->ri_font->stride;
    271 
    272 		while (height--) {
    273 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    274 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    275 
    276 			fr += fs;
    277 			DELTA(rp, ri->ri_stride, int32_t *);
    278 		}
    279 	}
    280 
    281 	/* Do underline */
    282 	if ((attr & 1) != 0) {
    283 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    284 		rp[0] = rp[1] = stamp[15];
    285 	}
    286 
    287 	stamp_mutex--;
    288 }
    289 
    290 /*
    291  * Put a single character. This is for 12-pixel wide fonts.
    292  */
    293 static void
    294 rasops8_putchar12(cookie, row, col, uc, attr)
    295 	void *cookie;
    296 	int row, col;
    297 	u_int uc;
    298 	long attr;
    299 {
    300 	struct rasops_info *ri;
    301 	int height, fs;
    302 	int32_t *rp;
    303 	u_char *fr;
    304 
    305 	/* Can't risk remaking the stamp if it's already in use */
    306 	if (stamp_mutex++) {
    307 		stamp_mutex--;
    308 		rasops8_putchar(cookie, row, col, uc, attr);
    309 		return;
    310 	}
    311 
    312 	ri = (struct rasops_info *)cookie;
    313 
    314 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    315 	    return;
    316 
    317 #ifdef RASOPS_CLIPPING
    318 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    319 		stamp_mutex--;
    320 		return;
    321 	}
    322 
    323 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    324 		stamp_mutex--;
    325 		return;
    326 	}
    327 #endif
    328 
    329 	/* Recompute stamp? */
    330 	if (attr != stamp_attr)
    331 		rasops8_makestamp(ri, attr);
    332 
    333 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    334 	height = ri->ri_font->fontheight;
    335 
    336 	if (uc == ' ') {
    337 		while (height--) {
    338 			int32_t c = stamp[0];
    339 
    340 			rp[0] = rp[1] = rp[2] = c;
    341 			DELTA(rp, ri->ri_stride, int32_t *);
    342 		}
    343 	} else {
    344 		uc -= ri->ri_font->firstchar;
    345 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    346 		fs = ri->ri_font->stride;
    347 
    348 		while (height--) {
    349 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    350 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    351 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    352 
    353 			fr += fs;
    354 			DELTA(rp, ri->ri_stride, int32_t *);
    355 		}
    356 	}
    357 
    358 	/* Do underline */
    359 	if ((attr & 1) != 0) {
    360 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    361 		rp[0] = rp[1] = rp[2] = stamp[15];
    362 	}
    363 
    364 	stamp_mutex--;
    365 }
    366 
    367 /*
    368  * Put a single character. This is for 16-pixel wide fonts.
    369  */
    370 static void
    371 rasops8_putchar16(cookie, row, col, uc, attr)
    372 	void *cookie;
    373 	int row, col;
    374 	u_int uc;
    375 	long attr;
    376 {
    377 	struct rasops_info *ri;
    378 	int height, fs;
    379 	int32_t *rp;
    380 	u_char *fr;
    381 
    382 	/* Can't risk remaking the stamp if it's already in use */
    383 	if (stamp_mutex++) {
    384 		stamp_mutex--;
    385 		rasops8_putchar(cookie, row, col, uc, attr);
    386 		return;
    387 	}
    388 
    389 	ri = (struct rasops_info *)cookie;
    390 
    391 	if (!CHAR_IN_FONT(uc, ri->ri_font))
    392 		return;
    393 
    394 #ifdef RASOPS_CLIPPING
    395 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    396 		stamp_mutex--;
    397 		return;
    398 	}
    399 
    400 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    401 		stamp_mutex--;
    402 		return;
    403 	}
    404 #endif
    405 
    406 	/* Recompute stamp? */
    407 	if (attr != stamp_attr)
    408 		rasops8_makestamp(ri, attr);
    409 
    410 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    411 	height = ri->ri_font->fontheight;
    412 
    413 	if (uc == ' ') {
    414 		while (height--)
    415 			rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
    416 	} else {
    417 		uc -= ri->ri_font->firstchar;
    418 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    419 		fs = ri->ri_font->stride;
    420 
    421 		while (height--) {
    422 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    423 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    424 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    425 			rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
    426 
    427 			fr += fs;
    428 			DELTA(rp, ri->ri_stride, int32_t *);
    429 		}
    430 	}
    431 
    432 	/* Do underline */
    433 	if ((attr & 1) != 0) {
    434 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    435 		rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
    436 	}
    437 
    438 	stamp_mutex--;
    439 }
    440 #endif /* !RASOPS_SMALL */
    441