Home | History | Annotate | Line # | Download | only in rasops
rasops1.c revision 1.2
      1 /* $NetBSD: rasops1.c,v 1.2 1999/04/13 00:40:09 ad Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1999 Andy Doran <ad (at) NetBSD.org>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  *
     28  */
     29 
     30 #include "opt_rasops.h"
     31 #ifdef RASOPS1
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: rasops1.c,v 1.2 1999/04/13 00:40:09 ad Exp $");
     35 
     36 #include <sys/types.h>
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/time.h>
     40 #include <machine/endian.h>
     41 
     42 #include <dev/wscons/wsdisplayvar.h>
     43 #include <dev/rasops/rasops.h>
     44 
     45 static void	rasops1_putchar __P((void *, int, int col, u_int, long));
     46 static void	rasops1_putchar8 __P((void *, int, int col, u_int, long));
     47 static void	rasops1_putchar16 __P((void *, int, int col, u_int, long));
     48 static void	rasops1_copycols __P((void *, int, int, int, int));
     49 static void	rasops1_erasecols __P((void *, int, int, int));
     50 static void	rasops1_erasecols8 __P((void *, int, int, int));
     51 static void	rasops1_eraserows __P((void *, int, int));
     52 static int32_t	rasops1_fg_color __P((long));
     53 static int32_t	rasops1_bg_color __P((long));
     54 static void	rasops1_do_cursor __P((struct rasops_info *));
     55 static void	rasops1_do_cursor8 __P((struct rasops_info *));
     56 
     57 void	rasops1_init __P((struct rasops_info *ri));
     58 
     59 #if BYTE_ORDER == LITTLE_ENDIAN
     60 static u_int32_t rightmask[32] = {
     61 #else
     62 static u_int32_t leftmask[32] = {
     63 #endif
     64     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
     65     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
     66     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
     67     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
     68     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
     69     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
     70     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
     71     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe,
     72 };
     73 
     74 #if BYTE_ORDER == LITTLE_ENDIAN
     75 static u_int32_t leftmask[32] = {
     76 #else
     77 static u_int32_t rightmask[32] = {
     78 #endif
     79     0x00000000, 0x00000001, 0x00000003, 0x00000007,
     80     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
     81     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
     82     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
     83     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
     84     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
     85     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
     86     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
     87 };
     88 
     89 
     90 /*
     91  * Initalize rasops_info struct for this colordepth.
     92  */
     93 void
     94 rasops1_init(ri)
     95 	struct rasops_info *ri;
     96 {
     97 
     98 	switch (ri->ri_font->fontwidth) {
     99 	case 8:
    100 		ri->ri_ops.putchar = rasops1_putchar8;
    101 		break;
    102 	case 16:
    103 		ri->ri_ops.putchar = rasops1_putchar16;
    104 		break;
    105 	default:
    106 		/*
    107 		 * XXX we don't support anything other than 8 and 16 pel
    108 		 * wide fonts yet. rasops1_copycols needs to be finished, the
    109 		 * other routines will need to be checked.
    110 		 */
    111 		panic("rasops1_init: not completed - see this location in src for details");
    112 		ri->ri_ops.putchar = rasops1_putchar;
    113 		break;
    114 	}
    115 
    116 	if (ri->ri_font->fontwidth & 7) {
    117 		ri->ri_ops.erasecols = rasops1_erasecols;
    118 		ri->ri_ops.copycols = rasops1_copycols;
    119 		ri->ri_do_cursor = rasops1_do_cursor;
    120 	} else {
    121 		ri->ri_ops.erasecols = rasops1_erasecols8;
    122 		/* use default copycols */
    123 		ri->ri_do_cursor = rasops1_do_cursor8;
    124 	}
    125 
    126 	ri->ri_ops.eraserows = rasops1_eraserows;
    127 }
    128 
    129 
    130 /*
    131  * Get foreground color from attribute and copy across all 4 bytes
    132  * in a int32_t.
    133  */
    134 static __inline__ int32_t
    135 rasops1_fg_color(long attr)
    136 {
    137 
    138 	return (attr & 0x0f000000) ? 0xffffffff : 0;
    139 }
    140 
    141 
    142 /*
    143  * Get background color from attribute and copy across all 4 bytes
    144  * in a int32_t.
    145  */
    146 static __inline__ int32_t
    147 rasops1_bg_color(long attr)
    148 {
    149 
    150 	return (attr & 0x000f0000) ? 0xffffffff : 0;
    151 }
    152 
    153 
    154 /*
    155  * Paint a single character. This is the generic version.
    156  */
    157 static void
    158 rasops1_putchar(cookie, row, col, uc, attr)
    159 	void *cookie;
    160 	int row, col;
    161 	u_int uc;
    162 	long attr;
    163 {
    164 
    165 	/* XXX i need implemention */
    166 }
    167 
    168 
    169 /*
    170  * Paint a single character. This is for 8-pixel wide fonts.
    171  */
    172 static void
    173 rasops1_putchar8(cookie, row, col, uc, attr)
    174 	void *cookie;
    175 	int row, col;
    176 	u_int uc;
    177 	long attr;
    178 {
    179 	int height, fs, rs, bg, fg;
    180 	struct rasops_info *ri;
    181 	u_char *fr, *rp;
    182 
    183 	ri = (struct rasops_info *)cookie;
    184 
    185 #ifdef RASOPS_CLIPPING
    186 	if (row < 0 || row >= ri->ri_rows)
    187 		return;
    188 
    189 	if (col < 0 || col >= ri->ri_cols)
    190 		return;
    191 #endif
    192 
    193 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    194 	height = ri->ri_font->fontheight;
    195 	rs = ri->ri_stride;
    196 
    197 	bg = (attr & 0x000f0000) ? 0xff : 0;
    198 	fg = (attr & 0x0f000000) ? 0xff : 0;
    199 
    200 	/* If fg and bg match this becomes a space character */
    201 	if (fg == bg || uc == ' ') {
    202 		while (height--) {
    203 			*rp = bg;
    204 			rp += rs;
    205 		}
    206 	} else {
    207 		uc -= ri->ri_font->firstchar;
    208 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    209 		fs = ri->ri_font->stride;
    210 
    211 		/* NOT fontbits if bg is white */
    212 		if (bg) {
    213 			while (height--) {
    214 				*rp = ~*fr;
    215 				fr += fs;
    216 				rp += rs;
    217 			}
    218 		} else {
    219 			while (height--) {
    220 				*rp = *fr;
    221 				fr += fs;
    222 				rp += rs;
    223 			}
    224 		}
    225 	}
    226 
    227 	/* Do underline */
    228 	if (attr & 1)
    229 		rp[-(ri->ri_stride << 1)] = fg;
    230 }
    231 
    232 
    233 /*
    234  * Paint a single character. This is for 16-pixel wide fonts.
    235  */
    236 static void
    237 rasops1_putchar16(cookie, row, col, uc, attr)
    238 	void *cookie;
    239 	int row, col;
    240 	u_int uc;
    241 	long attr;
    242 {
    243 	int height, fs, rs, bg, fg;
    244 	struct rasops_info *ri;
    245 	u_char *fr, *rp;
    246 
    247 	ri = (struct rasops_info *)cookie;
    248 
    249 #ifdef RASOPS_CLIPPING
    250 	if (row < 0 || row >= ri->ri_rows)
    251 		return;
    252 
    253 	if (col < 0 || col >= ri->ri_cols)
    254 		return;
    255 #endif
    256 
    257 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    258 	height = ri->ri_font->fontheight;
    259 	rs = ri->ri_stride;
    260 
    261 	bg = (attr & 0x000f0000) ? 0xffff : 0;
    262 	fg = (attr & 0x0f000000) ? 0xffff : 0;
    263 
    264 	/* If fg and bg match this becomes a space character */
    265 	if (fg == bg || uc == ' ') {
    266 		while (height--) {
    267 			*(int16_t *)rp = bg;
    268 			rp += rs;
    269 		}
    270 	} else {
    271 		uc -= ri->ri_font->firstchar;
    272 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    273 		fs = ri->ri_font->stride;
    274 
    275 		/* NOT fontbits if bg is white */
    276 		if (bg) {
    277 			while (height--) {
    278 				rp[0] = ~fr[0];
    279 				rp[1] = ~fr[1];
    280 				fr += fs;
    281 				rp += rs;
    282 			}
    283 		} else {
    284 			while (height--) {
    285 				rp[0] = fr[0];
    286 				rp[1] = fr[1];
    287 				fr += fs;
    288 				rp += rs;
    289 			}
    290 		}
    291 	}
    292 
    293 	/* Do underline */
    294 	if (attr & 1)
    295 		*(int16_t *)(rp - (ri->ri_stride << 1)) = fg;
    296 }
    297 
    298 
    299 /*
    300  * Erase columns.
    301  */
    302 static void
    303 rasops1_erasecols(cookie, row, col, num, attr)
    304 	void *cookie;
    305 	int row, num;
    306 	long attr;
    307 {
    308 	int32_t *dp, *rp, lmask, rmask, lclr, rclr, clr;
    309 	struct rasops_info *ri;
    310 	int nint, height, cnt;
    311 
    312 	ri = (struct rasops_info *)cookie;
    313 
    314 #ifdef RASOPS_CLIPPING
    315 	if (row < 0 || row > ri->ri_rows)
    316 		return;
    317 
    318 	if (col < 0) {
    319 		num += col;
    320 		col = 0;
    321 	}
    322 
    323 	if ((col + num) > ri->ri_cols)
    324 		num = ri->ri_cols - col;
    325 
    326 	if (num <= 0)
    327 		return;
    328 #endif
    329 	col *= ri->ri_fontwidth;
    330 	num *= ri->ri_fontwidth;
    331 
    332 	/*
    333 	 * lmask: mask for leftmost int32
    334 	 * rmask: mask for rightmost int32
    335 	 * nint: number of full int32s
    336 	 */
    337 	lmask = leftmask[col & 31];
    338 	rmask = rightmask[(col + num) & 31];
    339 	nint = ((col + num) & ~31) - ((col + 31) & ~31) >> 5;
    340 
    341 	/* Merge both masks if the span is encapsulated within one int32 */
    342 	if (col & ~31 == (col + num) & ~31) {
    343 		lmask &= rmask;
    344 		rmask = 0;
    345 	}
    346 
    347 	clr = rasops1_bg_color(attr);
    348 	lclr = clr & lmask;
    349 	rclr = clr & rmask;
    350 	lmask = ~lmask;
    351 	rmask = ~rmask;
    352 	height = ri->ri_fontheight;
    353 	rp = ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3);
    354 
    355 	while (height--) {
    356 		dp = rp;
    357 		DELTA(rp, ri->ri_stride, int32_t *);
    358 
    359 		if (lmask != 0xffffffffU)
    360 			*dp++ = (*dp & lmask) | lclr;
    361 
    362 		for (cnt = nint; cnt; cnt--)
    363 			*dp++ = clr;
    364 
    365 		if (rmask != 0xffffffffU)
    366 			*dp = (*dp & rmask) | rclr;
    367 	}
    368 }
    369 
    370 
    371 /*
    372  * Erase columns for fonts that are a multiple of 8 pels in width.
    373  */
    374 static void
    375 rasops1_erasecols8(cookie, row, col, num, attr)
    376 	void *cookie;
    377 	int row, col, num;
    378 	long attr;
    379 {
    380 	struct rasops_info *ri;
    381 	int32_t *dst;
    382 	u_char *dstb, *rp;
    383 	int clr, height, cnt, slop1, slop2;
    384 
    385 	ri = (struct rasops_info *)cookie;
    386 
    387 #ifdef RASOPS_CLIPPING
    388 	if (row < 0 || row >= ri->ri_rows)
    389 		return;
    390 
    391 	if (col < 0) {
    392 		num += col;
    393 		col = 0;
    394 	}
    395 
    396 	if ((col + num) > ri->ri_cols)
    397 		num = ri->ri_cols - col;
    398 
    399 	if (num <= 0)
    400 		return;
    401 #endif
    402 
    403 	num = num * ri->ri_xscale;
    404 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    405 	clr = rasops1_bg_color(attr);
    406 	height = ri->ri_font->fontheight;
    407 
    408 	slop1 = (int)rp & 3;
    409 	slop2 = (num - slop1) & 3;
    410 	num = (num - slop1 - slop2) >> 2;
    411 
    412 	while (height--) {
    413 		dstb = rp;
    414 		rp += ri->ri_stride;
    415 
    416 		/* Align span to 4 bytes */
    417 		for (cnt = slop1; cnt; cnt--)
    418 			*dstb++ = (u_char)clr;
    419 
    420 		dst = (int32_t *)dstb;
    421 
    422 		/* Write 4 bytes per loop */
    423 		for (cnt = num; cnt; cnt--)
    424 			*dst++ = clr;
    425 
    426 		/* Write unaligned trailing slop */
    427 		if (slop2 == 0)
    428 			continue;
    429 
    430 		dstb = (u_char *)dst;
    431 
    432 		for (cnt = slop2; cnt; cnt--)
    433 			*dstb++ = (u_char)clr;
    434 	}
    435 }
    436 
    437 
    438 /*
    439  * Actually paint the cursor.
    440  */
    441 static void
    442 rasops1_do_cursor(ri)
    443 	struct rasops_info *ri;
    444 {
    445 	int32_t *dp, *rp, lmask, rmask;
    446 	int height, row, col;
    447 
    448 	row = ri->ri_crow;
    449 	col = ri->ri_ccol * ri->ri_fontwidth;
    450 
    451 	/*
    452 	 * lmask: mask for leftmost int32
    453 	 * rmask: mask for rightmost int32
    454 	 */
    455 	lmask = leftmask[col & 31];
    456 	rmask = rightmask[(col + ri->ri_fontwidth) & 31];
    457 
    458 	/* Merge both masks if the span is encapsulated within one int32 */
    459 	if (col & ~31 == (col + ri->ri_fontwidth) & ~31) {
    460 		lmask &= rmask;
    461 		rmask = 0;
    462 	}
    463 
    464 	lmask = ~lmask;
    465 	rmask = ~rmask;
    466 	height = ri->ri_fontheight;
    467 	rp = ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3);
    468 
    469 	while (height--) {
    470 		dp = rp;
    471 		DELTA(rp, ri->ri_stride, int32_t *);
    472 
    473 		*dp++ = ((*dp & lmask) ^ lmask) | (*dp & ~lmask);
    474 
    475 		if (rmask != 0xffffffffU)
    476 			*dp = ((*dp & rmask) ^ rmask) | (*dp & ~rmask);
    477 	}
    478 }
    479 
    480 
    481 /*
    482  * Paint cursors that are a multiple of 8 pels in size.
    483  */
    484 static void
    485 rasops1_do_cursor8(ri)
    486 	struct rasops_info *ri;
    487 {
    488 	int width, height, cnt;
    489 	u_char *dp, *rp;
    490 
    491 	height = ri->ri_fontheight;
    492 	width = ri->ri_fontwidth >> 3;
    493 	rp = ri->ri_bits + ri->ri_crow * ri->ri_yscale +
    494 	    ri->ri_ccol * ri->ri_xscale;
    495 
    496 	while (height--) {
    497 		dp = rp;
    498 		rp += ri->ri_stride;
    499 
    500 		for (cnt = width; cnt; cnt--)
    501 			*dp++ ^= 0xff;
    502 	}
    503 }
    504 
    505 
    506 /*
    507  * Erase rows.
    508  */
    509 static void
    510 rasops1_eraserows(cookie, row, num, attr)
    511 	void *cookie;
    512 	int row, num;
    513 	long attr;
    514 {
    515 	struct rasops_info *ri;
    516 	int32_t *dp, clr;
    517 	int n8, n1, cnt;
    518 
    519 	ri = (struct rasops_info *)cookie;
    520 
    521 #ifdef RASOPS_CLIPPING
    522 	if (row < 0) {
    523 		num += row;
    524 		row = 0;
    525 	}
    526 
    527 	if ((row + num) > ri->ri_rows)
    528 		num = ri->ri_rows - row;
    529 
    530 	if (num <= 0)
    531 		return;
    532 #endif
    533 
    534 	num *= ri->ri_font->fontheight;
    535 	dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
    536 	clr = rasops1_bg_color(attr);
    537 
    538 	n8 = ri->ri_emustride >> 5;
    539 	n1 = (ri->ri_emustride >> 2) & 7;
    540 
    541 	while (num--) {
    542 		for (cnt = n8; cnt; cnt--) {
    543 			dp[0] = clr;
    544 			dp[1] = clr;
    545 			dp[2] = clr;
    546 			dp[3] = clr;
    547 			dp[4] = clr;
    548 			dp[5] = clr;
    549 			dp[6] = clr;
    550 			dp[7] = clr;
    551 			dp += 8;
    552 		}
    553 
    554 		for (cnt = n1; cnt; cnt--)
    555 			*dp++ = clr;
    556 
    557 		DELTA(dp, ri->ri_delta, int32_t *);
    558 	}
    559 }
    560 
    561 
    562 /*
    563  * Copy columns. This is slow. Ick! You'd better use a font with
    564  * a width that's a multiple of 8 pels, otherwise this is used...
    565  */
    566 static void
    567 rasops1_copycols(cookie, row, src, src)
    568 	void *cookie;
    569 	int row, src, dst;
    570 {
    571 #ifdef notyet
    572 	struct rasops_info *ri;
    573 	int32_t *dp, *drp, *sp, *srp, lmask, rmask;
    574 	int nint, height, cnt;
    575 
    576 	ri = (struct rasops_info *)cookie;
    577 
    578 #ifdef RASOPS_CLIPPING
    579 	if (row < 0 || row >= ri->ri_rows)
    580 		return;
    581 
    582 	if (col < 0) {
    583 		num += col;
    584 		col = 0;
    585 	}
    586 
    587 	if ((col + num) > ri->ri_cols)
    588 		num = ri->ri_cols - col;
    589 
    590 	if (num <= 0)
    591 		return;
    592 #endif
    593 	src *= ri->ri_fontwidth;
    594 	dst *= ri->ri_fontwidth;
    595 	num *= ri->ri_fontwidth;
    596 
    597 	/*
    598 	 * lmask: mask for leftmost int32
    599 	 * rmask: mask for rightmost int32
    600 	 * nint: number of full int32s
    601 	 */
    602 	lmask = leftmask[col & 31];
    603 	rmask = rightmask[(col + num) & 31];
    604 	nint = ((col + num) & ~31) - ((col + 31) & ~31) >> 5;
    605 
    606 	/* Merge both masks if the span is encapsulated within one int32 */
    607 	if (col & ~31 == (col + num) & ~31) {
    608 		lmask &= rmask;
    609 		rmask = 0;
    610 	}
    611 
    612 	lmask = ~lmask;
    613 	rmask = ~rmask;
    614 	height = ri->ri_fontheight;
    615 	drp = ri->ri_bits + row*ri->ri_yscale + ((dst >> 3) & ~3);
    616 	srp = ri->ri_bits + row*ri->ri_yscale + ((src >> 3) & ~3);
    617 
    618 	while (height--) {
    619 		dp = rp;
    620 		DELTA(rp, ri->ri_stride, int32_t *);
    621 
    622 		if (lmask != 0xffffffffU)
    623 			*dp++ = (*dp & lmask) | lclr;
    624 
    625 		for (cnt = nint; cnt; cnt--)
    626 			*dp++ = clr;
    627 
    628 		if (rmask != 0xffffffffU)
    629 			*dp = (*dp & rmask) | rclr;
    630 	}
    631 #endif
    632 }
    633 
    634 #endif /* RASOPS1 */
    635