Home | History | Annotate | Line # | Download | only in rasops
rasops8.c revision 1.14
      1 /* 	$NetBSD: rasops8.c,v 1.14 2002/01/31 11:18:07 uwe 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.14 2002/01/31 11:18:07 uwe 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 #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 		if ((ri->ri_flg & RI_BSWAP) != 0)
    204 			stamp[i] = bswap32(stamp[i]);
    205 	}
    206 }
    207 
    208 /*
    209  * Put a single character. This is for 8-pixel wide fonts.
    210  */
    211 static void
    212 rasops8_putchar8(cookie, row, col, uc, attr)
    213 	void *cookie;
    214 	int row, col;
    215 	u_int uc;
    216 	long attr;
    217 {
    218 	struct rasops_info *ri;
    219 	int height, fs;
    220 	int32_t *rp;
    221 	u_char *fr;
    222 
    223 	/* Can't risk remaking the stamp if it's already in use */
    224 	if (stamp_mutex++) {
    225 		stamp_mutex--;
    226 		rasops8_putchar(cookie, row, col, uc, attr);
    227 		return;
    228 	}
    229 
    230 	ri = (struct rasops_info *)cookie;
    231 
    232 #ifdef RASOPS_CLIPPING
    233 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    234 		stamp_mutex--;
    235 		return;
    236 	}
    237 
    238 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    239 		stamp_mutex--;
    240 		return;
    241 	}
    242 #endif
    243 
    244 	/* Recompute stamp? */
    245 	if (attr != stamp_attr)
    246 		rasops8_makestamp(ri, attr);
    247 
    248 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    249 	height = ri->ri_font->fontheight;
    250 
    251 	if (uc == ' ') {
    252 		while (height--) {
    253 			rp[0] = rp[1] = stamp[0];
    254 			DELTA(rp, ri->ri_stride, int32_t *);
    255 		}
    256 	} else {
    257 		uc -= ri->ri_font->firstchar;
    258 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    259 		fs = ri->ri_font->stride;
    260 
    261 		while (height--) {
    262 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    263 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    264 
    265 			fr += fs;
    266 			DELTA(rp, ri->ri_stride, int32_t *);
    267 		}
    268 	}
    269 
    270 	/* Do underline */
    271 	if ((attr & 1) != 0) {
    272 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    273 		rp[0] = rp[1] = stamp[15];
    274 	}
    275 
    276 	stamp_mutex--;
    277 }
    278 
    279 /*
    280  * Put a single character. This is for 12-pixel wide fonts.
    281  */
    282 static void
    283 rasops8_putchar12(cookie, row, col, uc, attr)
    284 	void *cookie;
    285 	int row, col;
    286 	u_int uc;
    287 	long attr;
    288 {
    289 	struct rasops_info *ri;
    290 	int height, fs;
    291 	int32_t *rp;
    292 	u_char *fr;
    293 
    294 	/* Can't risk remaking the stamp if it's already in use */
    295 	if (stamp_mutex++) {
    296 		stamp_mutex--;
    297 		rasops8_putchar(cookie, row, col, uc, attr);
    298 		return;
    299 	}
    300 
    301 	ri = (struct rasops_info *)cookie;
    302 
    303 #ifdef RASOPS_CLIPPING
    304 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    305 		stamp_mutex--;
    306 		return;
    307 	}
    308 
    309 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    310 		stamp_mutex--;
    311 		return;
    312 	}
    313 #endif
    314 
    315 	/* Recompute stamp? */
    316 	if (attr != stamp_attr)
    317 		rasops8_makestamp(ri, attr);
    318 
    319 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    320 	height = ri->ri_font->fontheight;
    321 
    322 	if (uc == ' ') {
    323 		while (height--) {
    324 			int32_t c = stamp[0];
    325 
    326 			rp[0] = rp[1] = rp[2] = c;
    327 			DELTA(rp, ri->ri_stride, int32_t *);
    328 		}
    329 	} else {
    330 		uc -= ri->ri_font->firstchar;
    331 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    332 		fs = ri->ri_font->stride;
    333 
    334 		while (height--) {
    335 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    336 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    337 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    338 
    339 			fr += fs;
    340 			DELTA(rp, ri->ri_stride, int32_t *);
    341 		}
    342 	}
    343 
    344 	/* Do underline */
    345 	if ((attr & 1) != 0) {
    346 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    347 		rp[0] = rp[1] = rp[2] = stamp[15];
    348 	}
    349 
    350 	stamp_mutex--;
    351 }
    352 
    353 /*
    354  * Put a single character. This is for 16-pixel wide fonts.
    355  */
    356 static void
    357 rasops8_putchar16(cookie, row, col, uc, attr)
    358 	void *cookie;
    359 	int row, col;
    360 	u_int uc;
    361 	long attr;
    362 {
    363 	struct rasops_info *ri;
    364 	int height, fs;
    365 	int32_t *rp;
    366 	u_char *fr;
    367 
    368 	/* Can't risk remaking the stamp if it's already in use */
    369 	if (stamp_mutex++) {
    370 		stamp_mutex--;
    371 		rasops8_putchar(cookie, row, col, uc, attr);
    372 		return;
    373 	}
    374 
    375 	ri = (struct rasops_info *)cookie;
    376 
    377 #ifdef RASOPS_CLIPPING
    378 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    379 		stamp_mutex--;
    380 		return;
    381 	}
    382 
    383 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    384 		stamp_mutex--;
    385 		return;
    386 	}
    387 #endif
    388 
    389 	/* Recompute stamp? */
    390 	if (attr != stamp_attr)
    391 		rasops8_makestamp(ri, attr);
    392 
    393 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    394 	height = ri->ri_font->fontheight;
    395 
    396 	if (uc == ' ') {
    397 		while (height--)
    398 			rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
    399 	} else {
    400 		uc -= ri->ri_font->firstchar;
    401 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    402 		fs = ri->ri_font->stride;
    403 
    404 		while (height--) {
    405 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
    406 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
    407 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
    408 			rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
    409 
    410 			fr += fs;
    411 			DELTA(rp, ri->ri_stride, int32_t *);
    412 		}
    413 	}
    414 
    415 	/* Do underline */
    416 	if ((attr & 1) != 0) {
    417 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    418 		rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
    419 	}
    420 
    421 	stamp_mutex--;
    422 }
    423 #endif /* !RASOPS_SMALL */
    424