Home | History | Annotate | Line # | Download | only in rasops
rasops8.c revision 1.12
      1 /* 	$NetBSD: rasops8.c,v 1.12 2001/11/13 07:00:23 lukem 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.12 2001/11/13 07:00:23 lukem Exp $");
     41 
     42 #include "opt_rasops.h"
     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 	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 #ifdef RASOPS_CLIPPING
    122 	/* Catches 'row < 0' case too */
    123 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    124 		return;
    125 
    126 	if ((unsigned)col >= (unsigned)ri->ri_cols)
    127 		return;
    128 #endif
    129 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    130 
    131 	height = ri->ri_font->fontheight;
    132 	width = ri->ri_font->fontwidth;
    133 	clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
    134 	clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
    135 
    136 	if (uc == ' ') {
    137 		u_char c = clr[0];
    138 
    139 		while (height--) {
    140 			dp = rp;
    141 			rp += ri->ri_stride;
    142 
    143 			for (cnt = width; cnt; cnt--)
    144 				*dp++ = c;
    145 		}
    146 	} else {
    147 		uc -= ri->ri_font->firstchar;
    148 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    149 		fs = ri->ri_font->stride;
    150 
    151 		while (height--) {
    152 			dp = rp;
    153 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
    154 			fr += fs;
    155 			rp += ri->ri_stride;
    156 
    157 			for (cnt = width; cnt; cnt--) {
    158 				*dp++ = clr[(fb >> 31) & 1];
    159 				fb <<= 1;
    160 			}
    161 		}
    162 	}
    163 
    164 	/* Do underline */
    165 	if ((attr & 1) != 0) {
    166 		u_char c = clr[1];
    167 
    168 		rp -= (ri->ri_stride << 1);
    169 
    170 		while (width--)
    171 			*rp++ = c;
    172 	}
    173 }
    174 
    175 #ifndef RASOPS_SMALL
    176 /*
    177  * Recompute the 4x1 blitting stamp.
    178  */
    179 static void
    180 rasops8_makestamp(ri, attr)
    181 	struct rasops_info *ri;
    182 	long attr;
    183 {
    184 	int32_t fg, bg;
    185 	int i;
    186 
    187 	fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
    188 	bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
    189 	stamp_attr = attr;
    190 
    191 	for (i = 0; i < 16; i++) {
    192 #if BYTE_ORDER == LITTLE_ENDIAN
    193 		stamp[i] = (i & 8 ? fg : bg);
    194 		stamp[i] |= ((i & 4 ? fg : bg) << 8);
    195 		stamp[i] |= ((i & 2 ? fg : bg) << 16);
    196 		stamp[i] |= ((i & 1 ? fg : bg) << 24);
    197 #else
    198 		stamp[i] = (i & 1 ? fg : bg);
    199 		stamp[i] |= ((i & 2 ? fg : bg) << 8);
    200 		stamp[i] |= ((i & 4 ? fg : bg) << 16);
    201 		stamp[i] |= ((i & 8 ? fg : bg) << 24);
    202 #endif
    203 	}
    204 }
    205 
    206 /*
    207  * Put a single character. This is for 8-pixel wide fonts.
    208  */
    209 static void
    210 rasops8_putchar8(cookie, row, col, uc, attr)
    211 	void *cookie;
    212 	int row, col;
    213 	u_int uc;
    214 	long attr;
    215 {
    216 	struct rasops_info *ri;
    217 	int height, fs;
    218 	int32_t *rp;
    219 	u_char *fr;
    220 
    221 	/* Can't risk remaking the stamp if it's already in use */
    222 	if (stamp_mutex++) {
    223 		stamp_mutex--;
    224 		rasops8_putchar(cookie, row, col, uc, attr);
    225 		return;
    226 	}
    227 
    228 	ri = (struct rasops_info *)cookie;
    229 
    230 #ifdef RASOPS_CLIPPING
    231 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    232 		stamp_mutex--;
    233 		return;
    234 	}
    235 
    236 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    237 		stamp_mutex--;
    238 		return;
    239 	}
    240 #endif
    241 
    242 	/* Recompute stamp? */
    243 	if (attr != stamp_attr)
    244 		rasops8_makestamp(ri, attr);
    245 
    246 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    247 	height = ri->ri_font->fontheight;
    248 
    249 	if (uc == ' ') {
    250 		while (height--) {
    251 			rp[0] = rp[1] = stamp[0];
    252 			DELTA(rp, ri->ri_stride, int32_t *);
    253 		}
    254 	} else {
    255 		uc -= ri->ri_font->firstchar;
    256 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    257 		fs = ri->ri_font->stride;
    258 
    259 		while (height--) {
    260 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    261 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    262 
    263 			fr += fs;
    264 			DELTA(rp, ri->ri_stride, int32_t *);
    265 		}
    266 	}
    267 
    268 	/* Do underline */
    269 	if ((attr & 1) != 0) {
    270 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    271 		rp[0] = rp[1] = stamp[15];
    272 	}
    273 
    274 	stamp_mutex--;
    275 }
    276 
    277 /*
    278  * Put a single character. This is for 12-pixel wide fonts.
    279  */
    280 static void
    281 rasops8_putchar12(cookie, row, col, uc, attr)
    282 	void *cookie;
    283 	int row, col;
    284 	u_int uc;
    285 	long attr;
    286 {
    287 	struct rasops_info *ri;
    288 	int height, fs;
    289 	int32_t *rp;
    290 	u_char *fr;
    291 
    292 	/* Can't risk remaking the stamp if it's already in use */
    293 	if (stamp_mutex++) {
    294 		stamp_mutex--;
    295 		rasops8_putchar(cookie, row, col, uc, attr);
    296 		return;
    297 	}
    298 
    299 	ri = (struct rasops_info *)cookie;
    300 
    301 #ifdef RASOPS_CLIPPING
    302 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    303 		stamp_mutex--;
    304 		return;
    305 	}
    306 
    307 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    308 		stamp_mutex--;
    309 		return;
    310 	}
    311 #endif
    312 
    313 	/* Recompute stamp? */
    314 	if (attr != stamp_attr)
    315 		rasops8_makestamp(ri, attr);
    316 
    317 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    318 	height = ri->ri_font->fontheight;
    319 
    320 	if (uc == ' ') {
    321 		while (height--) {
    322 			int32_t c = stamp[0];
    323 
    324 			rp[0] = rp[1] = rp[2] = c;
    325 			DELTA(rp, ri->ri_stride, int32_t *);
    326 		}
    327 	} else {
    328 		uc -= ri->ri_font->firstchar;
    329 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    330 		fs = ri->ri_font->stride;
    331 
    332 		while (height--) {
    333 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    334 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    335 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    336 
    337 			fr += fs;
    338 			DELTA(rp, ri->ri_stride, int32_t *);
    339 		}
    340 	}
    341 
    342 	/* Do underline */
    343 	if ((attr & 1) != 0) {
    344 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    345 		rp[0] = rp[1] = rp[2] = stamp[15];
    346 	}
    347 
    348 	stamp_mutex--;
    349 }
    350 
    351 /*
    352  * Put a single character. This is for 16-pixel wide fonts.
    353  */
    354 static void
    355 rasops8_putchar16(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, 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 		rasops8_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 		rasops8_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 == ' ') {
    395 		while (height--)
    396 			rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
    397 	} else {
    398 		uc -= ri->ri_font->firstchar;
    399 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    400 		fs = ri->ri_font->stride;
    401 
    402 		while (height--) {
    403 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    404 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    405 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    406 			rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
    407 
    408 			fr += fs;
    409 			DELTA(rp, ri->ri_stride, int32_t *);
    410 		}
    411 	}
    412 
    413 	/* Do underline */
    414 	if ((attr & 1) != 0) {
    415 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    416 		rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
    417 	}
    418 
    419 	stamp_mutex--;
    420 }
    421 #endif /* !RASOPS_SMALL */
    422