Home | History | Annotate | Line # | Download | only in rasops
rasops.c revision 1.4
      1 /*	 $NetBSD: rasops.c,v 1.4 1999/04/26 04:27:47 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 <sys/cdefs.h>
     31 __KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.4 1999/04/26 04:27:47 ad Exp $");
     32 
     33 #include "rasops_glue.h"
     34 
     35 #include <sys/types.h>
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/time.h>
     39 
     40 #include <machine/bswap.h>
     41 #include <machine/endian.h>
     42 
     43 #include <dev/wscons/wsdisplayvar.h>
     44 #include <dev/wscons/wsconsio.h>
     45 #include <dev/wsfont/wsfont.h>
     46 #include <dev/rasops/rasops.h>
     47 
     48 /* ANSI colormap (R,G,B). Upper 8 are high-intensity */
     49 u_char rasops_cmap[256*3] = {
     50 	0x00, 0x00, 0x00, /* black */
     51 	0x7f, 0x00, 0x00, /* red */
     52 	0x00, 0x7f, 0x00, /* green */
     53 	0x7f, 0x7f, 0x00, /* brown */
     54 	0x00, 0x00, 0x7f, /* blue */
     55 	0x7f, 0x00, 0x7f, /* magenta */
     56 	0x00, 0x7f, 0x7f, /* cyan */
     57 	0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
     58 
     59 	0x7f, 0x7f, 0x7f, /* black */
     60 	0xff, 0x00, 0x00, /* red */
     61 	0x00, 0xff, 0x00, /* green */
     62 	0xff, 0xff, 0x00, /* brown */
     63 	0x00, 0x00, 0xff, /* blue */
     64 	0xff, 0x00, 0xff, /* magenta */
     65 	0x00, 0xff, 0xff, /* cyan */
     66 	0xff, 0xff, 0xff, /* white */
     67 };
     68 
     69 /* True if color is gray */
     70 u_char rasops_isgray[16] = {
     71 	1, 0, 0, 0,
     72 	0, 0, 0, 1,
     73 	1, 0, 0, 0,
     74 	0, 0, 0, 1
     75 };
     76 
     77 /* Generic functions */
     78 static void	rasops_copyrows __P((void *, int, int, int));
     79 static int	rasops_mapchar __P((void *, int, u_int *));
     80 static void	rasops_cursor __P((void *, int, int, int));
     81 static int	rasops_alloc_cattr __P((void *, int, int, int, long *));
     82 static int	rasops_alloc_mattr __P((void *, int, int, int, long *));
     83 static void	rasops_do_cursor __P((struct rasops_info *));
     84 static void	rasops_init_devcmap __P((struct rasops_info *));
     85 
     86 /* Per-depth initalization functions */
     87 void	rasops1_init __P((struct rasops_info *));
     88 void	rasops2_init __P((struct rasops_info *));
     89 void	rasops8_init __P((struct rasops_info *));
     90 void	rasops15_init __P((struct rasops_info *));
     91 void	rasops24_init __P((struct rasops_info *));
     92 void	rasops32_init __P((struct rasops_info *));
     93 
     94 /*
     95  * Initalize a 'rasops_info' descriptor.
     96  */
     97 int
     98 rasops_init(ri, wantrows, wantcols, clear, center)
     99 	struct rasops_info *ri;
    100 	int wantrows, wantcols, clear, center;
    101 {
    102 #ifdef _KERNEL
    103 	/* Select a font if the caller doesn't care */
    104 	if (ri->ri_font == NULL) {
    105 		int cookie;
    106 
    107 		wsfont_init();
    108 
    109 		/* Want 8 pixel wide, don't care about aestethics */
    110 		if ((cookie = wsfont_find(NULL, 8, 0, 0)) < 0)
    111 			cookie = wsfont_find(NULL, 0, 0, 0);
    112 
    113 		if (cookie < 0) {
    114 			printf("rasops_init: font table is empty\n");
    115 			return (-1);
    116 		}
    117 
    118 		if (wsfont_lock(cookie, &ri->ri_font,
    119 		    WSFONT_L2R, WSFONT_L2R) < 0) {
    120 			printf("rasops_init: couldn't lock font\n");
    121 			return (-1);
    122 		}
    123 	}
    124 #endif
    125 
    126 	/* This should never happen in reality... */
    127 #ifdef DEBUG
    128 	if ((int)ri->ri_bits & 3) {
    129 		printf("rasops_init: bits not aligned on 32-bit boundary\n");
    130 		return (-1);
    131 	}
    132 
    133 	if ((int)ri->ri_stride & 3) {
    134 		printf("rasops_init: stride not aligned on 32-bit boundary\n");
    135 		return (-1);
    136 	}
    137 #endif
    138 
    139 	/* Fix color palette. We need this for the cursor to work. */
    140 	rasops_cmap[255*3+0] = 0xff;
    141 	rasops_cmap[255*3+1] = 0xff;
    142 	rasops_cmap[255*3+2] = 0xff;
    143 
    144 	/* setfont does most of the work */
    145 	if (rasops_setfont(ri, wantrows, wantcols, clear, center))
    146 		return (-1);
    147 
    148 	rasops_init_devcmap(ri);
    149 	ri->ri_flg = RASOPS_INITTED;
    150 	return (0);
    151 }
    152 
    153 
    154 /*
    155  * Choose a different font. The new font will already be set in ri_font.
    156  */
    157 int
    158 rasops_setfont(ri, wantrows, wantcols, clear, center)
    159 	struct rasops_info *ri;
    160 	int wantrows, wantcols, clear, center;
    161 {
    162 	int bpp;
    163 
    164 	if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4)
    165 		panic("rasops_init: fontwidth assumptions botched!\n");
    166 
    167 	/* Need this to frob the setup below */
    168 	bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth);
    169 
    170 	if (ri->ri_flg & RASOPS_INITTED)
    171 		ri->ri_bits = ri->ri_origbits;
    172 
    173 	/* Don't care if the caller wants a hideously small console */
    174 	if (wantrows < 10)
    175 		wantrows = 5000;
    176 
    177 	if (wantcols < 20)
    178 		wantcols = 5000;
    179 
    180 	/* Now constrain what they get */
    181 	ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
    182 	ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
    183 
    184 	if (ri->ri_emuwidth > ri->ri_width)
    185 		ri->ri_emuwidth = ri->ri_width;
    186 
    187 	if (ri->ri_emuheight > ri->ri_height)
    188 		ri->ri_emuheight = ri->ri_height;
    189 
    190 	/* Reduce width until aligned on a 32-bit boundary */
    191 	while ((ri->ri_emuwidth*bpp & 31) != 0)
    192 		ri->ri_emuwidth--;
    193 
    194 	ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
    195 	ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
    196 	ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
    197 	ri->ri_delta = ri->ri_stride - ri->ri_emustride;
    198 	ri->ri_ccol = 0;
    199 	ri->ri_crow = 0;
    200 	ri->ri_pelbytes = bpp >> 3;
    201 
    202 	ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
    203 	ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
    204 	ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
    205 
    206 #ifdef DEBUG
    207 	if (ri->ri_delta & 3)
    208 		panic("rasops_init: delta isn't aligned on 32-bit boundary!");
    209 #endif
    210 	/* Clear the entire display */
    211 	if (clear)
    212 		bzero(ri->ri_bits, ri->ri_stride * ri->ri_height);
    213 
    214 	/* Now centre our window if needs be */
    215 	ri->ri_origbits = ri->ri_bits;
    216 
    217 	if (center) {
    218 		ri->ri_bits += ((ri->ri_stride - ri->ri_emustride) >> 1) & ~3;
    219 		ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
    220 		    ri->ri_stride;
    221 	}
    222 
    223 	/*
    224 	 * Fill in defaults for operations set.  XXX this nukes private
    225 	 * routines used by accelerated fb drivers.
    226 	 */
    227 	ri->ri_ops.mapchar = rasops_mapchar;
    228 	ri->ri_ops.copyrows = rasops_copyrows;
    229 	ri->ri_ops.copycols = rasops_copycols;
    230 	ri->ri_ops.erasecols = rasops_erasecols;
    231 	ri->ri_ops.eraserows = rasops_eraserows;
    232 	ri->ri_ops.cursor = rasops_cursor;
    233 	ri->ri_do_cursor = rasops_do_cursor;
    234 
    235 	if (ri->ri_depth < 8 || ri->ri_forcemono) {
    236 		ri->ri_ops.alloc_attr = rasops_alloc_mattr;
    237 		ri->ri_caps = WSATTR_UNDERLINE;
    238 	} else {
    239 		ri->ri_ops.alloc_attr = rasops_alloc_cattr;
    240 		ri->ri_caps = WSATTR_UNDERLINE | WSATTR_HILIT |
    241 		    WSATTR_WSCOLORS;
    242 	}
    243 
    244 	switch (ri->ri_depth) {
    245 #if NRASOPS1
    246 	case 1:
    247 		rasops1_init(ri);
    248 		break;
    249 #endif
    250 
    251 #if NRASOPS2
    252 	case 2:
    253 		rasops2_init(ri);
    254 		break;
    255 #endif
    256 
    257 #if NRASOPS8
    258 	case 8:
    259 		rasops8_init(ri);
    260 		break;
    261 #endif
    262 
    263 #if NRASOPS15 || NRASOPS16
    264 	case 15:
    265 	case 16:
    266 		rasops15_init(ri);
    267 		break;
    268 #endif
    269 
    270 #if NRASOPS24
    271 	case 24:
    272 		rasops24_init(ri);
    273 		break;
    274 #endif
    275 
    276 #if NRASOPS32
    277 	case 32:
    278 		rasops32_init(ri);
    279 		break;
    280 #endif
    281 	default:
    282 		ri->ri_flg = 0;
    283 		return (-1);
    284 	}
    285 
    286 	return (0);
    287 }
    288 
    289 
    290 /*
    291  * Map a character.
    292  */
    293 static int
    294 rasops_mapchar(cookie, c, cp)
    295 	void *cookie;
    296 	int c;
    297 	u_int *cp;
    298 {
    299 	struct rasops_info *ri;
    300 
    301 	ri = (struct rasops_info *)cookie;
    302 
    303 	if (c < ri->ri_font->firstchar) {
    304 		*cp = ' ';
    305 		return (0);
    306 	}
    307 
    308 	if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) {
    309 		*cp = ' ';
    310 		return (0);
    311 	}
    312 
    313 	*cp = c;
    314 	return (5);
    315 }
    316 
    317 
    318 /*
    319  * Allocate a color attribute.
    320  */
    321 static int
    322 rasops_alloc_cattr(cookie, fg, bg, flg, attr)
    323 	void *cookie;
    324 	int fg, bg, flg;
    325 	long *attr;
    326 {
    327 	int swap;
    328 
    329 #ifdef RASOPS_CLIPPING
    330 	fg &= 7;
    331 	bg &= 7;
    332 	flg &= 255;
    333 #endif
    334 	if (flg & WSATTR_BLINK)
    335 		return (EINVAL);
    336 
    337 	if (flg & WSATTR_REVERSE) {
    338 		swap = fg;
    339 		fg = bg;
    340 		bg = swap;
    341 	}
    342 
    343 	if (flg & WSATTR_HILIT)
    344 		fg += 8;
    345 
    346 	flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0);
    347 
    348 	if (rasops_isgray[fg])
    349 		flg |= 2;
    350 
    351 	if (rasops_isgray[bg])
    352 		flg |= 4;
    353 
    354 	*attr = (bg << 16) | (fg << 24) | flg;
    355 	return 0;
    356 }
    357 
    358 
    359 /*
    360  * Allocate a mono attribute.
    361  */
    362 static int
    363 rasops_alloc_mattr(cookie, fg, bg, flg, attr)
    364 	void *cookie;
    365 	int fg, bg, flg;
    366 	long *attr;
    367 {
    368 	int swap;
    369 
    370 #ifdef RASOPS_CLIPPING
    371 	flg &= 255;
    372 #endif
    373 	fg = fg ? 1 : 0;
    374 	bg = bg ? 1 : 0;
    375 
    376 	if (flg & WSATTR_BLINK)
    377 		return (EINVAL);
    378 
    379 	if (!(flg & WSATTR_REVERSE) ^ !(flg & WSATTR_HILIT)) {
    380 		swap = fg;
    381 		fg = bg;
    382 		bg = swap;
    383 	}
    384 
    385 	*attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
    386 	return 0;
    387 }
    388 
    389 
    390 /*
    391  * Copy rows.
    392  */
    393 static void
    394 rasops_copyrows(cookie, src, dst, num)
    395 	void *cookie;
    396 	int src, dst, num;
    397 {
    398 	struct rasops_info *ri;
    399 	int32_t *sp, *dp, *srp, *drp;
    400 	int n8, n1, cnt;
    401 
    402 	ri = (struct rasops_info *)cookie;
    403 
    404 #ifdef RASOPS_CLIPPING
    405 	if (dst == src)
    406 		return;
    407 
    408 	if (src < 0) {
    409 		num += src;
    410 		src = 0;
    411 	}
    412 
    413 	if ((src + num) > ri->ri_rows)
    414 		num = ri->ri_rows - src;
    415 
    416 	if (dst < 0) {
    417 		num += dst;
    418 		dst = 0;
    419 	}
    420 
    421 	if ((dst + num) > ri->ri_rows)
    422 		num = ri->ri_rows - dst;
    423 
    424 	if (num <= 0)
    425 		return;
    426 #endif
    427 
    428 	num *= ri->ri_font->fontheight;
    429 	n8 = ri->ri_emustride >> 5;
    430 	n1 = (ri->ri_emustride >> 2) & 7;
    431 
    432 	if (dst < src) {
    433 		sp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale);
    434 		dp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale);
    435 
    436 		while (num--) {
    437 			for (cnt = n8; cnt; cnt--) {
    438 				dp[0] = sp[0];
    439 				dp[1] = sp[1];
    440 				dp[2] = sp[2];
    441 				dp[3] = sp[3];
    442 				dp[4] = sp[4];
    443 				dp[5] = sp[5];
    444 				dp[6] = sp[6];
    445 				dp[7] = sp[7];
    446 				dp += 8;
    447 				sp += 8;
    448 			}
    449 
    450 			for (cnt = n1; cnt; cnt--)
    451 				*dp++ = *sp++;
    452 
    453 			DELTA(dp, ri->ri_delta, int32_t *);
    454 			DELTA(sp, ri->ri_delta, int32_t *);
    455 		}
    456 	} else {
    457 		src = ri->ri_font->fontheight * src + num - 1;
    458 		dst = ri->ri_font->fontheight * dst + num - 1;
    459 
    460 		srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride);
    461 		drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride);
    462 
    463 		while (num--) {
    464 			dp = drp;
    465 			sp = srp;
    466 			DELTA(srp, -ri->ri_stride, int32_t *);
    467 			DELTA(drp, -ri->ri_stride, int32_t *);
    468 
    469 			for (cnt = n8; cnt; cnt--) {
    470 				dp[0] = sp[0];
    471 				dp[1] = sp[1];
    472 				dp[2] = sp[2];
    473 				dp[3] = sp[3];
    474 				dp[4] = sp[4];
    475 				dp[5] = sp[5];
    476 				dp[6] = sp[6];
    477 				dp[7] = sp[7];
    478 				dp += 8;
    479 				sp += 8;
    480 			}
    481 
    482 			for (cnt = n1; cnt; cnt--)
    483 				*dp++ = *sp++;
    484 		}
    485 	}
    486 }
    487 
    488 
    489 /*
    490  * Copy columns. This is slow, and hard to optimize due to alignment,
    491  * and the fact that we have to copy both left->right and right->left.
    492  * We simply cop-out here and use bcopy(), since it handles all of
    493  * these cases anyway.
    494  */
    495 void
    496 rasops_copycols(cookie, row, src, dst, num)
    497 	void *cookie;
    498 	int row, src, dst, num;
    499 {
    500 	struct rasops_info *ri;
    501 	u_char *sp, *dp;
    502 	int height;
    503 
    504 	ri = (struct rasops_info *)cookie;
    505 
    506 #ifdef RASOPS_CLIPPING
    507 	if (dst == src)
    508 		return;
    509 
    510 	/* Catches < 0 case too */
    511 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    512 		return;
    513 
    514 	if (src < 0) {
    515 		num += src;
    516 		src = 0;
    517 	}
    518 
    519 	if ((src + num) > ri->ri_cols)
    520 		num = ri->ri_cols - src;
    521 
    522 	if (dst < 0) {
    523 		num += dst;
    524 		dst = 0;
    525 	}
    526 
    527 	if ((dst + num) > ri->ri_cols)
    528 		num = ri->ri_cols - dst;
    529 
    530 	if (num <= 0)
    531 		return;
    532 #endif
    533 
    534 	num *= ri->ri_xscale;
    535 	row *= ri->ri_yscale;
    536 	height = ri->ri_font->fontheight;
    537 
    538 	sp = ri->ri_bits + row + src * ri->ri_xscale;
    539 	dp = ri->ri_bits + row + dst * ri->ri_xscale;
    540 
    541 	while (height--) {
    542 		bcopy(sp, dp, num);
    543 		dp += ri->ri_stride;
    544 		sp += ri->ri_stride;
    545 	}
    546 }
    547 
    548 
    549 /*
    550  * Turn cursor off/on.
    551  */
    552 static void
    553 rasops_cursor(cookie, on, row, col)
    554 	void *cookie;
    555 	int on, row, col;
    556 {
    557 	struct rasops_info *ri;
    558 
    559 	ri = (struct rasops_info *)cookie;
    560 
    561 	/* Turn old cursor off */
    562 	if (ri->ri_flg & RASOPS_CURSOR)
    563 #ifdef RASOPS_CLIPPING
    564 		if (!(ri->ri_flg & RASOPS_CURSOR_CLIPPED))
    565 #endif
    566 			ri->ri_do_cursor(ri);
    567 
    568 	/* Select new cursor */
    569 #ifdef RASOPS_CLIPPING
    570 	ri->ri_flg &= ~RASOPS_CURSOR_CLIPPED;
    571 
    572 	if (row < 0 || row >= ri->ri_rows)
    573 		ri->ri_flg |= RASOPS_CURSOR_CLIPPED;
    574 	else if (col < 0 || col >= ri->ri_cols)
    575 		ri->ri_flg |= RASOPS_CURSOR_CLIPPED;
    576 #endif
    577 	ri->ri_crow = row;
    578 	ri->ri_ccol = col;
    579 
    580 	if (on) {
    581 		ri->ri_flg |= RASOPS_CURSOR;
    582 #ifdef RASOPS_CLIPPING
    583 		if (!(ri->ri_flg & RASOPS_CURSOR_CLIPPED))
    584 #endif
    585 			ri->ri_do_cursor(ri);
    586 	} else
    587 		ri->ri_flg &= ~RASOPS_CURSOR;
    588 }
    589 
    590 
    591 /*
    592  * Make the device colormap
    593  */
    594 static void
    595 rasops_init_devcmap(ri)
    596 	struct rasops_info *ri;
    597 {
    598 	u_char *p;
    599 	int i, c;
    600 
    601 	switch (ri->ri_depth) {
    602 	case 1:
    603 		ri->ri_devcmap[0] = 0;
    604 		for (i = 1; i < 16; i++)
    605 			ri->ri_devcmap[i] = -1;
    606 		return;
    607 
    608 	case 2:
    609 		for (i = 1; i < 15; i++)
    610 			ri->ri_devcmap[i] = 0xaaaaaaaa;
    611 
    612 		ri->ri_devcmap[0] = 0;
    613 		ri->ri_devcmap[8] = 0x55555555;
    614 		ri->ri_devcmap[15] = -1;
    615 		return;
    616 
    617 	case 8:
    618 		for (i = 0; i < 16; i++)
    619 			ri->ri_devcmap[i] = i | (i<<8) | (i<<16) | (i<<24);
    620 		return;
    621 	}
    622 
    623 	p = rasops_cmap;
    624 
    625 	for (i = 0; i < 16; i++) {
    626 		if (ri->ri_rnum <= 8)
    627 			c = (*p++ >> (8 - ri->ri_rnum)) << ri->ri_rpos;
    628 		else
    629 			c = (*p++ << (ri->ri_rnum - 8)) << ri->ri_rpos;
    630 
    631 		if (ri->ri_gnum <= 8)
    632 			c |= (*p++ >> (8 - ri->ri_gnum)) << ri->ri_gpos;
    633 		else
    634 			c |= (*p++ << (ri->ri_gnum - 8)) << ri->ri_gpos;
    635 
    636 		if (ri->ri_bnum <= 8)
    637 			c |= (*p++ >> (8 - ri->ri_bnum)) << ri->ri_bpos;
    638 		else
    639 			c |= (*p++ << (ri->ri_bnum - 8)) << ri->ri_bpos;
    640 
    641 		/* Fill the word for generic routines, which want this */
    642 		if (ri->ri_depth == 24)
    643 			c = c | ((c & 0xff) << 24);
    644 		else if (ri->ri_depth <= 16)
    645 			c = c | (c << 16);
    646 
    647 		/* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
    648 		if (!ri->ri_swab)
    649 			ri->ri_devcmap[i] = c;
    650 		else if (ri->ri_depth == 32)
    651 			ri->ri_devcmap[i] = bswap32(c);
    652 		else if (ri->ri_depth == 16 || ri->ri_depth == 15)
    653 			ri->ri_devcmap[i] = bswap16(c);
    654 		else
    655 			ri->ri_devcmap[i] = c;
    656 	}
    657 }
    658 
    659 
    660 /*
    661  * Unpack a rasops attribute
    662  */
    663 void
    664 rasops_unpack_attr(attr, fg, bg, underline)
    665 	long attr;
    666 	int *fg, *bg, *underline;
    667 {
    668 
    669 	*fg = ((u_int)attr >> 24) & 15;
    670 	*bg = ((u_int)attr >> 16) & 15;
    671 	*underline = (u_int)attr & 1;
    672 }
    673 
    674 
    675 /*
    676  * Erase rows. This isn't static, since 24-bpp uses it in special cases.
    677  */
    678 void
    679 rasops_eraserows(cookie, row, num, attr)
    680 	void *cookie;
    681 	int row, num;
    682 	long attr;
    683 {
    684 	struct rasops_info *ri;
    685 	int np, nw, cnt;
    686 	int32_t *dp, clr;
    687 
    688 	ri = (struct rasops_info *)cookie;
    689 
    690 #ifdef RASOPS_CLIPPING
    691 	if (row < 0) {
    692 		num += row;
    693 		row = 0;
    694 	}
    695 
    696 	if ((row + num) > ri->ri_rows)
    697 		num = ri->ri_rows - row;
    698 
    699 	if (num <= 0)
    700 		return;
    701 #endif
    702 
    703 	clr = ri->ri_devcmap[(attr >> 16) & 15];
    704 	num *= ri->ri_font->fontheight;
    705 	dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
    706 
    707 	np = ri->ri_emustride >> 5;
    708 	nw = (ri->ri_emustride >> 2) & 7;
    709 
    710 	while (num--) {
    711 		for (cnt = np; cnt; cnt--) {
    712 			dp[0] = clr;
    713 			dp[1] = clr;
    714 			dp[2] = clr;
    715 			dp[3] = clr;
    716 			dp[4] = clr;
    717 			dp[5] = clr;
    718 			dp[6] = clr;
    719 			dp[7] = clr;
    720 			dp += 8;
    721 		}
    722 
    723 		for (cnt = nw; cnt; cnt--) {
    724 			*(int32_t *)dp = clr;
    725 			DELTA(dp, 4, int32_t *);
    726 		}
    727 
    728 		DELTA(dp, ri->ri_delta, int32_t *);
    729 	}
    730 }
    731 
    732 
    733 /*
    734  * Actually turn the cursor on or off. This does the dirty work for
    735  * rasops_cursor().
    736  */
    737 static void
    738 rasops_do_cursor(ri)
    739 	struct rasops_info *ri;
    740 {
    741 	int full1, height, cnt, slop1, slop2, row, col, mask;
    742 	u_char *dp, *rp;
    743 
    744 	row = ri->ri_crow;
    745 	col = ri->ri_ccol;
    746 
    747 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    748 	height = ri->ri_font->fontheight;
    749 	mask = ri->ri_devcmap[15];
    750 
    751 	slop1 = (int)rp & 3;
    752 
    753 	if (slop1 > ri->ri_xscale)
    754 		slop1 = ri->ri_xscale;
    755 
    756 	slop2 = (ri->ri_xscale - slop1) & 3;
    757 	full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
    758 
    759 	if ((slop1 | slop2) == 0) {
    760 		/* A common case */
    761 		while (height--) {
    762 			dp = rp;
    763 			rp += ri->ri_stride;
    764 
    765 			for (cnt = full1; cnt; cnt--) {
    766 				*(int32_t *)dp ^= mask;
    767 				dp += 4;
    768 			}
    769 		}
    770 	} else {
    771 		/* XXX this is stupid.. use masks instead */
    772 		while (height--) {
    773 			dp = rp;
    774 			rp += ri->ri_stride;
    775 
    776 			if (slop1 & 1)
    777 				*dp++ ^= mask;
    778 
    779 			if (slop1 & 2) {
    780 				*(int16_t *)dp ^= mask;
    781 				dp += 2;
    782 			}
    783 
    784 			for (cnt = full1; cnt; cnt--) {
    785 				*(int32_t *)dp ^= mask;
    786 				dp += 4;
    787 			}
    788 
    789 			if (slop2 & 1)
    790 				*dp++ ^= mask;
    791 
    792 			if (slop2 & 2)
    793 				*(int16_t *)dp ^= mask;
    794 		}
    795 	}
    796 }
    797 
    798 
    799 /*
    800  * Erase columns.
    801  */
    802 void
    803 rasops_erasecols(cookie, row, col, num, attr)
    804 	void *cookie;
    805 	int row, col, num;
    806 	long attr;
    807 {
    808 	int n8, height, cnt, slop1, slop2, clr;
    809 	struct rasops_info *ri;
    810 	int32_t *rp, *dp;
    811 
    812 	ri = (struct rasops_info *)cookie;
    813 
    814 #ifdef RASOPS_CLIPPING
    815 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    816 		return;
    817 
    818 	if (col < 0) {
    819 		num += col;
    820 		col = 0;
    821 	}
    822 
    823 	if ((col + num) > ri->ri_cols)
    824 		num = ri->ri_cols - col;
    825 
    826 	if (num <= 0)
    827 		return;
    828 #endif
    829 
    830 	num = num * ri->ri_xscale;
    831 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    832 	height = ri->ri_font->fontheight;
    833 	clr = ri->ri_devcmap[(attr >> 16) & 15];
    834 
    835 	/* Don't bother using the full loop for <= 32 pels */
    836 	if (num <= 32) {
    837 		if (((num | ri->ri_xscale) & 1) == 0) {
    838 			/*
    839 			 * Halfword aligned blt. This is needed so the
    840 			 * 15/16 bit ops can use this function.
    841 			 */
    842 			num >>= 1;
    843 
    844 			while (height--) {
    845 				dp = rp;
    846 				DELTA(rp, ri->ri_stride, int32_t *);
    847 
    848 				for (cnt = num; cnt; cnt--) {
    849 					*(int16_t *)dp = clr;
    850 					DELTA(dp, 2, int32_t *);
    851 				}
    852 			}
    853 		} else if (((num | ri->ri_xscale) & 3) == 0) {
    854 			/* Word aligned blt */
    855 			num >>= 2;
    856 
    857 			while (height--) {
    858 				dp = rp;
    859 				DELTA(rp, ri->ri_stride, int32_t *);
    860 
    861 				for (cnt = num; cnt; cnt--)
    862 					*dp++ = clr;
    863 			}
    864 		} else {
    865 			while (height--) {
    866 				dp = rp;
    867 				DELTA(rp, ri->ri_stride, int32_t *);
    868 
    869 				for (cnt = num; cnt; cnt--) {
    870 					*(u_char *)dp = clr;
    871 					DELTA(dp, 1, int32_t *);
    872 				}
    873 			}
    874 		}
    875 
    876 		return;
    877 	}
    878 
    879 	slop1 = (int)rp & 3;
    880 	slop2 = (num - slop1) & 3;
    881 	num -= slop1 + slop2;
    882 	n8 = num >> 5;
    883 	num = (num >> 2) & 7;
    884 
    885 	while (height--) {
    886 		dp = rp;
    887 		DELTA(rp, ri->ri_stride, int32_t *);
    888 
    889 		/* Align span to 4 bytes */
    890 		if (slop1 & 1) {
    891 			*(u_char *)dp = clr;
    892 			DELTA(dp, 1, int32_t *);
    893 		}
    894 
    895 		if (slop1 & 2) {
    896 			*(int16_t *)dp = clr;
    897 			DELTA(dp, 2, int32_t *);
    898 		}
    899 
    900 		/* Write 32 bytes per loop */
    901 		for (cnt = n8; cnt; cnt--) {
    902 			dp[0] = clr;
    903 			dp[1] = clr;
    904 			dp[2] = clr;
    905 			dp[3] = clr;
    906 			dp[4] = clr;
    907 			dp[5] = clr;
    908 			dp[6] = clr;
    909 			dp[7] = clr;
    910 			dp += 8;
    911 		}
    912 
    913 		/* Write 4 bytes per loop */
    914 		for (cnt = num; cnt; cnt--)
    915 			*dp++ = clr;
    916 
    917 		/* Write unaligned trailing slop */
    918 		if (slop2 & 1) {
    919 			*(u_char *)dp = clr;
    920 			DELTA(dp, 1, int32_t *);
    921 		}
    922 
    923 		if (slop2 & 2)
    924 			*(int16_t *)dp = clr;
    925 	}
    926 }
    927