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