Home | History | Annotate | Line # | Download | only in rasops
rasops1.c revision 1.3
      1 /* $NetBSD: rasops1.c,v 1.3 1999/04/13 03:02:40 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.3 1999/04/13 03:02:40 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/wscons/wsconsio.h>
     44 #include <dev/rasops/rasops.h>
     45 
     46 static void	rasops1_putchar __P((void *, int, int col, u_int, long));
     47 static void	rasops1_putchar8 __P((void *, int, int col, u_int, long));
     48 static void	rasops1_putchar16 __P((void *, int, int col, u_int, long));
     49 static void	rasops1_copycols __P((void *, int, int, int, int));
     50 static void	rasops1_erasecols __P((void *, int, int, int, long));
     51 static void	rasops1_erasecols8 __P((void *, int, int, int, long));
     52 static void	rasops1_eraserows __P((void *, int, int, long));
     53 static int32_t	rasops1_fg_color __P((long));
     54 static int32_t	rasops1_bg_color __P((long));
     55 static void	rasops1_do_cursor __P((struct rasops_info *));
     56 static void	rasops1_do_cursor8 __P((struct rasops_info *));
     57 
     58 void	rasops1_init __P((struct rasops_info *ri));
     59 
     60 #if BYTE_ORDER == LITTLE_ENDIAN
     61 static u_int32_t rightmask[32] = {
     62 #else
     63 static u_int32_t leftmask[32] = {
     64 #endif
     65     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
     66     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
     67     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
     68     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
     69     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
     70     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
     71     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
     72     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe,
     73 };
     74 
     75 #if BYTE_ORDER == LITTLE_ENDIAN
     76 static u_int32_t leftmask[32] = {
     77 #else
     78 static u_int32_t rightmask[32] = {
     79 #endif
     80     0x00000000, 0x00000001, 0x00000003, 0x00000007,
     81     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
     82     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
     83     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
     84     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
     85     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
     86     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
     87     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
     88 };
     89 
     90 
     91 /*
     92  * Initalize rasops_info struct for this colordepth.
     93  */
     94 void
     95 rasops1_init(ri)
     96 	struct rasops_info *ri;
     97 {
     98 
     99 	switch (ri->ri_font->fontwidth) {
    100 	case 8:
    101 		ri->ri_ops.putchar = rasops1_putchar8;
    102 		break;
    103 	case 16:
    104 		ri->ri_ops.putchar = rasops1_putchar16;
    105 		break;
    106 	default:
    107 		/*
    108 		 * XXX we don't support anything other than 8 and 16 pel
    109 		 * wide fonts yet. rasops1_copycols needs to be finished, the
    110 		 * other routines will need to be checked.
    111 		 */
    112 		panic("rasops1_init: not completed - see this location in src for details");
    113 		ri->ri_ops.putchar = rasops1_putchar;
    114 		break;
    115 	}
    116 
    117 	if (ri->ri_font->fontwidth & 7) {
    118 		ri->ri_ops.erasecols = rasops1_erasecols;
    119 		ri->ri_ops.copycols = rasops1_copycols;
    120 		ri->ri_do_cursor = rasops1_do_cursor;
    121 	} else {
    122 		ri->ri_ops.erasecols = rasops1_erasecols8;
    123 		/* use default copycols */
    124 		ri->ri_do_cursor = rasops1_do_cursor8;
    125 	}
    126 
    127 	ri->ri_ops.eraserows = rasops1_eraserows;
    128 }
    129 
    130 
    131 /*
    132  * Get foreground color from attribute and copy across all 4 bytes
    133  * in a int32_t.
    134  */
    135 static __inline__ int32_t
    136 rasops1_fg_color(long attr)
    137 {
    138 
    139 	return (attr & 0x0f000000) ? 0xffffffff : 0;
    140 }
    141 
    142 
    143 /*
    144  * Get background color from attribute and copy across all 4 bytes
    145  * in a int32_t.
    146  */
    147 static __inline__ int32_t
    148 rasops1_bg_color(long attr)
    149 {
    150 
    151 	return (attr & 0x000f0000) ? 0xffffffff : 0;
    152 }
    153 
    154 
    155 /*
    156  * Paint a single character. This is the generic version.
    157  */
    158 static void
    159 rasops1_putchar(cookie, row, col, uc, attr)
    160 	void *cookie;
    161 	int row, col;
    162 	u_int uc;
    163 	long attr;
    164 {
    165 
    166 	panic("rasops1_putchar: i need implemention");
    167 }
    168 
    169 
    170 /*
    171  * Paint a single character. This is for 8-pixel wide fonts.
    172  */
    173 static void
    174 rasops1_putchar8(cookie, row, col, uc, attr)
    175 	void *cookie;
    176 	int row, col;
    177 	u_int uc;
    178 	long attr;
    179 {
    180 	int height, fs, rs, bg, fg;
    181 	struct rasops_info *ri;
    182 	u_char *fr, *rp;
    183 
    184 	ri = (struct rasops_info *)cookie;
    185 
    186 #ifdef RASOPS_CLIPPING
    187 	/* Catches 'row < 0' case too */
    188 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    189 		return;
    190 
    191 	if ((unsigned)col >= (unsigned)ri->ri_cols)
    192 		return;
    193 #endif
    194 
    195 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    196 	height = ri->ri_font->fontheight;
    197 	rs = ri->ri_stride;
    198 
    199 	bg = (attr & 0x000f0000) ? 0xff : 0;
    200 	fg = (attr & 0x0f000000) ? 0xff : 0;
    201 
    202 	/* If fg and bg match this becomes a space character */
    203 	if (fg == bg || uc == ' ') {
    204 		while (height--) {
    205 			*rp = bg;
    206 			rp += rs;
    207 		}
    208 	} else {
    209 		uc -= ri->ri_font->firstchar;
    210 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    211 		fs = ri->ri_font->stride;
    212 
    213 		/* NOT fontbits if bg is white */
    214 		if (bg) {
    215 			while (height--) {
    216 				*rp = ~*fr;
    217 				fr += fs;
    218 				rp += rs;
    219 			}
    220 		} else {
    221 			while (height--) {
    222 				*rp = *fr;
    223 				fr += fs;
    224 				rp += rs;
    225 			}
    226 		}
    227 	}
    228 
    229 	/* Do underline */
    230 	if (attr & 1)
    231 		rp[-(ri->ri_stride << 1)] = fg;
    232 }
    233 
    234 
    235 /*
    236  * Paint a single character. This is for 16-pixel wide fonts.
    237  */
    238 static void
    239 rasops1_putchar16(cookie, row, col, uc, attr)
    240 	void *cookie;
    241 	int row, col;
    242 	u_int uc;
    243 	long attr;
    244 {
    245 	int height, fs, rs, bg, fg;
    246 	struct rasops_info *ri;
    247 	u_char *fr, *rp;
    248 
    249 	ri = (struct rasops_info *)cookie;
    250 
    251 #ifdef RASOPS_CLIPPING
    252 	/* Catches 'row < 0' case too */
    253 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    254 		return;
    255 
    256 	if ((unsigned)col >= (unsigned)ri->ri_cols)
    257 		return;
    258 #endif
    259 
    260 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    261 	height = ri->ri_font->fontheight;
    262 	rs = ri->ri_stride;
    263 
    264 	bg = (attr & 0x000f0000) ? 0xffff : 0;
    265 	fg = (attr & 0x0f000000) ? 0xffff : 0;
    266 
    267 	/* If fg and bg match this becomes a space character */
    268 	if (fg == bg || uc == ' ') {
    269 		while (height--) {
    270 			*(int16_t *)rp = bg;
    271 			rp += rs;
    272 		}
    273 	} else {
    274 		uc -= ri->ri_font->firstchar;
    275 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    276 		fs = ri->ri_font->stride;
    277 
    278 		/* NOT fontbits if bg is white */
    279 		if (bg) {
    280 			while (height--) {
    281 				rp[0] = ~fr[0];
    282 				rp[1] = ~fr[1];
    283 				fr += fs;
    284 				rp += rs;
    285 			}
    286 		} else {
    287 			while (height--) {
    288 				rp[0] = fr[0];
    289 				rp[1] = fr[1];
    290 				fr += fs;
    291 				rp += rs;
    292 			}
    293 		}
    294 	}
    295 
    296 	/* Do underline */
    297 	if (attr & 1)
    298 		*(int16_t *)(rp - (ri->ri_stride << 1)) = fg;
    299 }
    300 
    301 
    302 /*
    303  * Erase columns.
    304  */
    305 static void
    306 rasops1_erasecols(cookie, row, col, num, attr)
    307 	void *cookie;
    308 	int row, num;
    309 	long attr;
    310 {
    311 	int32_t *dp, *rp, lmask, rmask, lclr, rclr, clr;
    312 	struct rasops_info *ri;
    313 	int nint, height, cnt;
    314 
    315 	ri = (struct rasops_info *)cookie;
    316 
    317 #ifdef RASOPS_CLIPPING
    318 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    319 		return;
    320 
    321 	if (col < 0) {
    322 		num += col;
    323 		col = 0;
    324 	}
    325 
    326 	if ((col + num) > ri->ri_cols)
    327 		num = ri->ri_cols - col;
    328 
    329 	if (num <= 0)
    330 		return;
    331 #endif
    332 	col *= ri->ri_font->fontwidth;
    333 	num *= ri->ri_font->fontwidth;
    334 
    335 	/*
    336 	 * lmask: mask for leftmost int32
    337 	 * rmask: mask for rightmost int32
    338 	 * nint: number of full int32s
    339 	 */
    340 	lmask = leftmask[col & 31];
    341 	rmask = rightmask[(col + num) & 31];
    342 	nint = (((col + num) & ~31) - ((col + 31) & ~31)) >> 5;
    343 
    344 	/* Merge both masks if the span is encapsulated within one int32 */
    345 	if ((col & ~31) == ((col + num) & ~31)) {
    346 		lmask &= rmask;
    347 		rmask = 0;
    348 	}
    349 
    350 	clr = rasops1_bg_color(attr);
    351 	lclr = clr & lmask;
    352 	rclr = clr & rmask;
    353 	lmask = ~lmask;
    354 	rmask = ~rmask;
    355 	height = ri->ri_font->fontheight;
    356 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3));
    357 
    358 	while (height--) {
    359 		dp = rp;
    360 		DELTA(rp, ri->ri_stride, int32_t *);
    361 
    362 		if (lmask != 0xffffffffU)
    363 			*dp++ = (*dp & lmask) | lclr;
    364 
    365 		for (cnt = nint; cnt; cnt--)
    366 			*dp++ = clr;
    367 
    368 		if (rmask != 0xffffffffU)
    369 			*dp = (*dp & rmask) | rclr;
    370 	}
    371 }
    372 
    373 
    374 /*
    375  * Erase columns for fonts that are a multiple of 8 pels in width.
    376  */
    377 static void
    378 rasops1_erasecols8(cookie, row, col, num, attr)
    379 	void *cookie;
    380 	int row, col, num;
    381 	long attr;
    382 {
    383 	struct rasops_info *ri;
    384 	int32_t *dst;
    385 	u_char *dstb, *rp;
    386 	int clr, height, cnt, slop1, slop2;
    387 
    388 	ri = (struct rasops_info *)cookie;
    389 
    390 #ifdef RASOPS_CLIPPING
    391 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    392 		return;
    393 
    394 	if (col < 0) {
    395 		num += col;
    396 		col = 0;
    397 	}
    398 
    399 	if ((col + num) > ri->ri_cols)
    400 		num = ri->ri_cols - col;
    401 
    402 	if (num <= 0)
    403 		return;
    404 #endif
    405 
    406 	num = num * ri->ri_xscale;
    407 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    408 	clr = rasops1_bg_color(attr);
    409 	height = ri->ri_font->fontheight;
    410 
    411 	slop1 = (int)rp & 3;
    412 	slop2 = (num - slop1) & 3;
    413 	num = (num - slop1 - slop2) >> 2;
    414 
    415 	while (height--) {
    416 		dstb = rp;
    417 		rp += ri->ri_stride;
    418 
    419 		/* Align span to 4 bytes */
    420 		for (cnt = slop1; cnt; cnt--)
    421 			*dstb++ = (u_char)clr;
    422 
    423 		dst = (int32_t *)dstb;
    424 
    425 		/* Write 4 bytes per loop */
    426 		for (cnt = num; cnt; cnt--)
    427 			*dst++ = clr;
    428 
    429 		/* Write unaligned trailing slop */
    430 		if (slop2 == 0)
    431 			continue;
    432 
    433 		dstb = (u_char *)dst;
    434 
    435 		for (cnt = slop2; cnt; cnt--)
    436 			*dstb++ = (u_char)clr;
    437 	}
    438 }
    439 
    440 
    441 /*
    442  * Actually paint the cursor.
    443  */
    444 static void
    445 rasops1_do_cursor(ri)
    446 	struct rasops_info *ri;
    447 {
    448 	int32_t *dp, *rp, lmask, rmask;
    449 	int height, row, col;
    450 
    451 	row = ri->ri_crow;
    452 	col = ri->ri_ccol * ri->ri_font->fontwidth;
    453 
    454 	/*
    455 	 * lmask: mask for leftmost int32
    456 	 * rmask: mask for rightmost int32
    457 	 */
    458 	lmask = leftmask[col & 31];
    459 	rmask = rightmask[(col + ri->ri_font->fontwidth) & 31];
    460 
    461 	/* Merge both masks if the span is encapsulated within one int32 */
    462 	if ((col & ~31) == ((col + ri->ri_font->fontwidth) & ~31)) {
    463 		lmask &= rmask;
    464 		rmask = 0;
    465 	}
    466 
    467 	lmask = ~lmask;
    468 	rmask = ~rmask;
    469 	height = ri->ri_font->fontheight;
    470 	rp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale + ((col >> 3) & ~3));
    471 
    472 	while (height--) {
    473 		dp = rp;
    474 		DELTA(rp, ri->ri_stride, int32_t *);
    475 
    476 		*dp++ = ((*dp & lmask) ^ lmask) | (*dp & ~lmask);
    477 
    478 		if (rmask != 0xffffffffU)
    479 			*dp = ((*dp & rmask) ^ rmask) | (*dp & ~rmask);
    480 	}
    481 }
    482 
    483 
    484 /*
    485  * Paint cursors that are a multiple of 8 pels in size.
    486  */
    487 static void
    488 rasops1_do_cursor8(ri)
    489 	struct rasops_info *ri;
    490 {
    491 	int width, height, cnt;
    492 	u_char *dp, *rp;
    493 
    494 	height = ri->ri_font->fontheight;
    495 	width = ri->ri_font->fontwidth >> 3;
    496 	rp = ri->ri_bits + ri->ri_crow * ri->ri_yscale +
    497 	    ri->ri_ccol * ri->ri_xscale;
    498 
    499 	while (height--) {
    500 		dp = rp;
    501 		rp += ri->ri_stride;
    502 
    503 		for (cnt = width; cnt; cnt--)
    504 			*dp++ ^= 0xff;
    505 	}
    506 }
    507 
    508 
    509 /*
    510  * Erase rows. This is easy.
    511  */
    512 static void
    513 rasops1_eraserows(cookie, row, num, attr)
    514 	void *cookie;
    515 	int row, num;
    516 	long attr;
    517 {
    518 	struct rasops_info *ri;
    519 	int32_t *dp, clr;
    520 	int n8, n1, cnt;
    521 
    522 	ri = (struct rasops_info *)cookie;
    523 
    524 #ifdef RASOPS_CLIPPING
    525 	if (row < 0) {
    526 		num += row;
    527 		row = 0;
    528 	}
    529 
    530 	if ((row + num) > ri->ri_rows)
    531 		num = ri->ri_rows - row;
    532 
    533 	if (num <= 0)
    534 		return;
    535 #endif
    536 
    537 	num *= ri->ri_font->fontheight;
    538 	dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
    539 	clr = rasops1_bg_color(attr);
    540 
    541 	n8 = ri->ri_emustride >> 5;
    542 	n1 = (ri->ri_emustride >> 2) & 7;
    543 
    544 	while (num--) {
    545 		for (cnt = n8; cnt; cnt--) {
    546 			dp[0] = clr;
    547 			dp[1] = clr;
    548 			dp[2] = clr;
    549 			dp[3] = clr;
    550 			dp[4] = clr;
    551 			dp[5] = clr;
    552 			dp[6] = clr;
    553 			dp[7] = clr;
    554 			dp += 8;
    555 		}
    556 
    557 		for (cnt = n1; cnt; cnt--)
    558 			*dp++ = clr;
    559 
    560 		DELTA(dp, ri->ri_delta, int32_t *);
    561 	}
    562 }
    563 
    564 
    565 /*
    566  * Copy columns. This is slow. Ick! You'd better use a font with
    567  * a width that's a multiple of 8 pels, otherwise this is used...
    568  */
    569 static void
    570 rasops1_copycols(cookie, row, src, dst, num)
    571 	void *cookie;
    572 	int row, src, dst, num;
    573 {
    574 
    575 	panic("rasops1_copycols: i need implemention");
    576 }
    577 
    578 #endif /* RASOPS1 */
    579