Home | History | Annotate | Line # | Download | only in rasops
rasops24.c revision 1.5
      1 /* 	$NetBSD: rasops24.c,v 1.5 1999/04/26 04:29:12 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 #include <sys/cdefs.h>
     32 __KERNEL_RCSID(0, "$NetBSD: rasops24.c,v 1.5 1999/04/26 04:29:12 ad Exp $");
     33 
     34 #include <sys/types.h>
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/time.h>
     38 
     39 #include <machine/endian.h>
     40 #include <machine/bswap.h>
     41 
     42 #include <dev/wscons/wsdisplayvar.h>
     43 #include <dev/wscons/wsconsio.h>
     44 #include <dev/rasops/rasops.h>
     45 
     46 static void 	rasops24_putchar __P((void *, int, int, u_int, long attr));
     47 static void 	rasops24_putchar8 __P((void *, int, int, u_int, long attr));
     48 static void 	rasops24_putchar12 __P((void *, int, int, u_int, long attr));
     49 static void 	rasops24_putchar16 __P((void *, int, int, u_int, long attr));
     50 static void 	rasops24_erasecols __P((void *, int, int, int, long));
     51 static void 	rasops24_eraserows __P((void *, int, int, long));
     52 static void	rasops24_makestamp __P((struct rasops_info *, long));
     53 
     54 void	rasops24_init __P((struct rasops_info *ri));
     55 
     56 /*
     57  * 4x1 stamp for optimized character blitting
     58  */
     59 static int32_t	stamp[64];
     60 static long	stamp_attr;
     61 static int	stamp_mutex;	/* XXX see note in readme */
     62 
     63 /*
     64  * XXX this confuses the hell out of gcc2 (not egcs) which always insists
     65  * that the shift count is negative.
     66  *
     67  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
     68  * destination int32_t[0] = STAMP_READ(offset)
     69  * destination int32_t[1] = STAMP_READ(offset + 4)
     70  * destination int32_t[2] = STAMP_READ(offset + 8)
     71  */
     72 #define STAMP_SHIFT(fb,n)	((n*4-4) >= 0 ? (fb)>>(n*4-4):(fb)<<-(n*4-4))
     73 #define STAMP_MASK		(15 << 4)
     74 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
     75 
     76 
     77 /*
     78  * Initalize rasops_info struct for this colordepth.
     79  */
     80 void
     81 rasops24_init(ri)
     82 	struct rasops_info *ri;
     83 {
     84 
     85 	switch (ri->ri_font->fontwidth) {
     86 	case 8:
     87 		ri->ri_ops.putchar = rasops24_putchar8;
     88 		break;
     89 
     90 	case 12:
     91 		ri->ri_ops.putchar = rasops24_putchar12;
     92 		break;
     93 
     94 	case 16:
     95 		ri->ri_ops.putchar = rasops24_putchar16;
     96 		break;
     97 
     98 	default:
     99 		ri->ri_ops.putchar = rasops24_putchar;
    100 		break;
    101 	}
    102 
    103 	if (ri->ri_rnum == 0) {
    104 		ri->ri_rnum = 8;
    105 		ri->ri_rpos = 0;
    106 		ri->ri_gnum = 8;
    107 		ri->ri_gpos = 8;
    108 		ri->ri_bnum = 8;
    109 		ri->ri_bpos = 16;
    110 	}
    111 
    112 	ri->ri_ops.erasecols = rasops24_erasecols;
    113 	ri->ri_ops.eraserows = rasops24_eraserows;
    114 }
    115 
    116 
    117 /*
    118  * Recompute the blitting stamp.
    119  */
    120 static void
    121 rasops24_makestamp(ri, attr)
    122 	struct rasops_info *ri;
    123 	long attr;
    124 {
    125 	u_int32_t fg, bg, c1, c2, c3, c4;
    126 	int i;
    127 
    128 	fg = ri->ri_devcmap[((u_int)attr >> 24) & 15] & 0xffffff;
    129 	bg = ri->ri_devcmap[((u_int)attr >> 16) & 15] & 0xffffff;
    130 	stamp_attr = attr;
    131 
    132 	for (i = 0; i < 64; i += 4) {
    133 #if BYTE_ORDER == LITTLE_ENDIAN
    134 		c1 = (i & 32 ? fg : bg);
    135 		c2 = (i & 16 ? fg : bg);
    136 		c3 = (i & 8 ? fg : bg);
    137 		c4 = (i & 4 ? fg : bg);
    138 #else
    139 		c1 = (i & 8 ? fg : bg);
    140 		c2 = (i & 4 ? fg : bg);
    141 		c3 = (i & 16 ? fg : bg);
    142 		c4 = (i & 32 ? fg : bg);
    143 #endif
    144 		stamp[i+0] = (c1 <<  8) | (c2 >> 16);
    145 		stamp[i+1] = (c2 << 16) | (c3 >>  8);
    146 		stamp[i+2] = (c3 << 24) | c4;
    147 
    148 #if BYTE_ORDER == LITTLE_ENDIAN
    149 		if (!ri->ri_swab) {
    150 #else
    151 		if (ri->ri_swab) {
    152 #endif
    153 			stamp[i+0] = bswap32(stamp[i+0]);
    154 			stamp[i+1] = bswap32(stamp[i+1]);
    155 			stamp[i+2] = bswap32(stamp[i+2]);
    156 		}
    157 	}
    158 }
    159 
    160 
    161 /*
    162  * Put a single character. This is the generic version.
    163  * XXX this bites - we should use masks.
    164  */
    165 static void
    166 rasops24_putchar(cookie, row, col, uc, attr)
    167 	void *cookie;
    168 	int row, col;
    169 	u_int uc;
    170 	long attr;
    171 {
    172 	struct rasops_info *ri;
    173 	int fb, width, height, cnt, clr[2];
    174 	u_char *dp, *rp, *fr;
    175 
    176 	ri = (struct rasops_info *)cookie;
    177 
    178 #ifdef RASOPS_CLIPPING
    179 	/* Catches 'row < 0' case too */
    180 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    181 		return;
    182 
    183 	if ((unsigned)col >= (unsigned)ri->ri_cols)
    184 		return;
    185 #endif
    186 
    187 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
    188 	height = ri->ri_font->fontheight;
    189 	width = ri->ri_font->fontwidth;
    190 
    191 	clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 15];
    192 	clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 15];
    193 
    194 	if (uc == ' ') {
    195 		while (height--) {
    196 			dp = rp;
    197 			rp += ri->ri_stride;
    198 
    199 			for (cnt = width; cnt; cnt--) {
    200 				*dp++ = clr[0] >> 16;
    201 				*dp++ = clr[0] >> 8;
    202 				*dp++ = clr[0];
    203 			}
    204 		}
    205 	} else {
    206 		uc -= ri->ri_font->firstchar;
    207 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
    208 
    209 		while (height--) {
    210 			dp = rp;
    211 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
    212 			fr += ri->ri_font->stride;
    213 			rp += ri->ri_stride;
    214 
    215 			for (cnt = width; cnt; cnt--, fb <<= 1) {
    216 				if ((fb >> 31) & 1) {
    217 					*dp++ = clr[1] >> 16;
    218 					*dp++ = clr[1] >> 8;
    219 					*dp++ = clr[1];
    220 				} else {
    221 					*dp++ = clr[0] >> 16;
    222 					*dp++ = clr[0] >> 8;
    223 					*dp++ = clr[0];
    224 				}
    225 			}
    226 		}
    227 	}
    228 
    229 	/* Do underline */
    230 	if (attr & 1) {
    231 		rp -= ri->ri_stride << 1;
    232 
    233 		while (width--) {
    234 			*rp++ = clr[1] >> 16;
    235 			*rp++ = clr[1] >> 8;
    236 			*rp++ = clr[1];
    237 		}
    238 	}
    239 }
    240 
    241 
    242 /*
    243  * Put a single character. This is for 8-pixel wide fonts.
    244  */
    245 static void
    246 rasops24_putchar8(cookie, row, col, uc, attr)
    247 	void *cookie;
    248 	int row, col;
    249 	u_int uc;
    250 	long attr;
    251 {
    252 	struct rasops_info *ri;
    253 	int height, so, fs;
    254 	int32_t *rp;
    255 	u_char *fr;
    256 
    257 	/* Can't risk remaking the stamp if it's already in use */
    258 	if (stamp_mutex++) {
    259 		stamp_mutex--;
    260 		rasops24_putchar(cookie, row, col, uc, attr);
    261 		return;
    262 	}
    263 
    264 	ri = (struct rasops_info *)cookie;
    265 
    266 #ifdef RASOPS_CLIPPING
    267 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    268 		stamp_mutex--;
    269 		return;
    270 	}
    271 
    272 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    273 		stamp_mutex--;
    274 		return;
    275 	}
    276 #endif
    277 
    278 	/* Recompute stamp? */
    279 	if (attr != stamp_attr)
    280 		rasops24_makestamp(ri, attr);
    281 
    282 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    283 	height = ri->ri_font->fontheight;
    284 
    285 	if (uc == (u_int)-1) {
    286 		while (height--) {
    287 			rp[0] = stamp[0];
    288 			rp[1] = stamp[0];
    289 			rp[2] = stamp[0];
    290 			rp[3] = stamp[0];
    291 			rp[4] = stamp[0];
    292 			rp[5] = stamp[0];
    293 			DELTA(rp, ri->ri_stride, int32_t *);
    294 		}
    295 	} else {
    296 		uc -= ri->ri_font->firstchar;
    297 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
    298 		fs = ri->ri_font->stride;
    299 
    300 		while (height--) {
    301 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
    302 			rp[0] = STAMP_READ(so);
    303 			rp[1] = STAMP_READ(so + 4);
    304 			rp[2] = STAMP_READ(so + 8);
    305 
    306 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
    307 			rp[3] = STAMP_READ(so);
    308 			rp[4] = STAMP_READ(so + 4);
    309 			rp[5] = STAMP_READ(so + 8);
    310 
    311 			fr += fs;
    312 			DELTA(rp, ri->ri_stride, int32_t *);
    313 		}
    314 	}
    315 
    316 	/* Do underline */
    317 	if (attr & 1) {
    318 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    319 		rp[0] = STAMP_READ(30);
    320 		rp[1] = STAMP_READ(30);
    321 		rp[2] = STAMP_READ(30);
    322 		rp[3] = STAMP_READ(30);
    323 		rp[4] = STAMP_READ(30);
    324 		rp[5] = STAMP_READ(30);
    325 	}
    326 
    327 	stamp_mutex--;
    328 }
    329 
    330 
    331 /*
    332  * Put a single character. This is for 12-pixel wide fonts.
    333  */
    334 static void
    335 rasops24_putchar12(cookie, row, col, uc, attr)
    336 	void *cookie;
    337 	int row, col;
    338 	u_int uc;
    339 	long attr;
    340 {
    341 	struct rasops_info *ri;
    342 	int height, so, fs;
    343 	int32_t *rp;
    344 	u_char *fr;
    345 
    346 	/* Can't risk remaking the stamp if it's already in use */
    347 	if (stamp_mutex++) {
    348 		stamp_mutex--;
    349 		rasops24_putchar(cookie, row, col, uc, attr);
    350 		return;
    351 	}
    352 
    353 	ri = (struct rasops_info *)cookie;
    354 
    355 #ifdef RASOPS_CLIPPING
    356 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    357 		stamp_mutex--;
    358 		return;
    359 	}
    360 
    361 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    362 		stamp_mutex--;
    363 		return;
    364 	}
    365 #endif
    366 
    367 	/* Recompute stamp? */
    368 	if (attr != stamp_attr)
    369 		rasops24_makestamp(ri, attr);
    370 
    371 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    372 	height = ri->ri_font->fontheight;
    373 
    374 	if (uc == (u_int)-1) {
    375 		while (height--) {
    376 			rp[0] = stamp[0];
    377 			rp[1] = stamp[0];
    378 			rp[2] = stamp[0];
    379 			rp[3] = stamp[0];
    380 			rp[4] = stamp[0];
    381 			rp[5] = stamp[0];
    382 			rp[6] = stamp[0];
    383 			rp[7] = stamp[0];
    384 			rp[8] = stamp[0];
    385 			DELTA(rp, ri->ri_stride, int32_t *);
    386 		}
    387 	} else {
    388 		uc -= ri->ri_font->firstchar;
    389 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
    390 		fs = ri->ri_font->stride;
    391 
    392 		while (height--) {
    393 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
    394 			rp[0] = STAMP_READ(so);
    395 			rp[1] = STAMP_READ(so + 4);
    396 			rp[2] = STAMP_READ(so + 8);
    397 
    398 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
    399 			rp[3] = STAMP_READ(so);
    400 			rp[4] = STAMP_READ(so + 4);
    401 			rp[5] = STAMP_READ(so + 8);
    402 
    403 			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
    404 			rp[6] = STAMP_READ(so);
    405 			rp[7] = STAMP_READ(so + 4);
    406 			rp[8] = STAMP_READ(so + 8);
    407 
    408 			fr += fs;
    409 			DELTA(rp, ri->ri_stride, int32_t *);
    410 		}
    411 	}
    412 
    413 	/* Do underline */
    414 	if (attr & 1) {
    415 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    416 		rp[0] = STAMP_READ(30);
    417 		rp[1] = STAMP_READ(30);
    418 		rp[2] = STAMP_READ(30);
    419 		rp[3] = STAMP_READ(30);
    420 		rp[4] = STAMP_READ(30);
    421 		rp[5] = STAMP_READ(30);
    422 		rp[6] = STAMP_READ(30);
    423 		rp[7] = STAMP_READ(30);
    424 		rp[8] = STAMP_READ(30);
    425 	}
    426 
    427 	stamp_mutex--;
    428 }
    429 
    430 
    431 /*
    432  * Put a single character. This is for 16-pixel wide fonts.
    433  */
    434 static void
    435 rasops24_putchar16(cookie, row, col, uc, attr)
    436 	void *cookie;
    437 	int row, col;
    438 	u_int uc;
    439 	long attr;
    440 {
    441 	struct rasops_info *ri;
    442 	int height, so, fs;
    443 	int32_t *rp;
    444 	u_char *fr;
    445 
    446 	/* Can't risk remaking the stamp if it's already in use */
    447 	if (stamp_mutex++) {
    448 		stamp_mutex--;
    449 		rasops24_putchar(cookie, row, col, uc, attr);
    450 		return;
    451 	}
    452 
    453 	ri = (struct rasops_info *)cookie;
    454 
    455 #ifdef RASOPS_CLIPPING
    456 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
    457 		stamp_mutex--;
    458 		return;
    459 	}
    460 
    461 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
    462 		stamp_mutex--;
    463 		return;
    464 	}
    465 #endif
    466 
    467 	/* Recompute stamp? */
    468 	if (attr != stamp_attr)
    469 		rasops24_makestamp(ri, attr);
    470 
    471 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    472 	height = ri->ri_font->fontheight;
    473 
    474 	if (uc == (u_int)-1) {
    475 		while (height--) {
    476 			rp[0] = stamp[0];
    477 			rp[1] = stamp[0];
    478 			rp[2] = stamp[0];
    479 			rp[3] = stamp[0];
    480 			rp[4] = stamp[0];
    481 			rp[5] = stamp[0];
    482 			rp[6] = stamp[0];
    483 			rp[7] = stamp[0];
    484 			rp[8] = stamp[0];
    485 			rp[9] = stamp[0];
    486 			rp[10] = stamp[0];
    487 			rp[11] = stamp[0];
    488 			DELTA(rp, ri->ri_stride, int32_t *);
    489 		}
    490 	} else {
    491 		uc -= ri->ri_font->firstchar;
    492 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
    493 		fs = ri->ri_font->stride;
    494 
    495 		while (height--) {
    496 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
    497 			rp[0] = STAMP_READ(so);
    498 			rp[1] = STAMP_READ(so + 4);
    499 			rp[2] = STAMP_READ(so + 8);
    500 
    501 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
    502 			rp[3] = STAMP_READ(so);
    503 			rp[4] = STAMP_READ(so + 4);
    504 			rp[5] = STAMP_READ(so + 8);
    505 
    506 			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
    507 			rp[6] = STAMP_READ(so);
    508 			rp[7] = STAMP_READ(so + 4);
    509 			rp[8] = STAMP_READ(so + 8);
    510 
    511 			so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
    512 			rp[9] = STAMP_READ(so);
    513 			rp[10] = STAMP_READ(so + 4);
    514 			rp[11] = STAMP_READ(so + 8);
    515 
    516 			DELTA(rp, ri->ri_stride, int32_t *);
    517 			fr += fs;
    518 		}
    519 	}
    520 
    521 	/* Do underline */
    522 	if (attr & 1) {
    523 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
    524 		rp[0] = STAMP_READ(30);
    525 		rp[1] = STAMP_READ(30);
    526 		rp[2] = STAMP_READ(30);
    527 		rp[3] = STAMP_READ(30);
    528 		rp[4] = STAMP_READ(30);
    529 		rp[5] = STAMP_READ(30);
    530 		rp[6] = STAMP_READ(30);
    531 		rp[7] = STAMP_READ(30);
    532 		rp[8] = STAMP_READ(30);
    533 		rp[9] = STAMP_READ(30);
    534 		rp[10] = STAMP_READ(30);
    535 		rp[11] = STAMP_READ(30);
    536 	}
    537 
    538 	stamp_mutex--;
    539 }
    540 
    541 
    542 /*
    543  * Erase rows. This is nice and easy due to alignment.
    544  */
    545 static void
    546 rasops24_eraserows(cookie, row, num, attr)
    547 	void *cookie;
    548 	int row, num;
    549 	long attr;
    550 {
    551 	struct rasops_info *ri;
    552 	u_int32_t *dp, clr, stamp[3];
    553 	int n9, n3, n1, cnt;
    554 
    555 	/*
    556 	 * If the color is gray, we can cheat and use the generic routines
    557 	 * (which are faster, hopefully) since the r,g,b values are the same.
    558 	 */
    559 	if (attr & 4) {
    560 		rasops_eraserows(cookie, row, num, attr);
    561 		return;
    562 	}
    563 
    564 	ri = (struct rasops_info *)cookie;
    565 
    566 #ifdef RASOPS_CLIPPING
    567 	if (row < 0) {
    568 		num += row;
    569 		row = 0;
    570 	}
    571 
    572 	if ((row + num) > ri->ri_rows)
    573 		num = ri->ri_rows - row;
    574 
    575 	if (num <= 0)
    576 		return;
    577 #endif
    578 
    579 	clr = ri->ri_devcmap[(attr >> 16) & 15] & 0xffffff;
    580 	stamp[0] = (clr <<  8) | (clr >> 16);
    581 	stamp[1] = (clr << 16) | (clr >>  8);
    582 	stamp[2] = (clr << 24) | clr;
    583 
    584 #if BYTE_ORDER == LITTLE_ENDIAN
    585 	if (!ri->ri_swab) {
    586 #else
    587 	if (ri->ri_swab) {
    588 #endif
    589 		stamp[0] = bswap32(stamp[0]);
    590 		stamp[1] = bswap32(stamp[1]);
    591 		stamp[2] = bswap32(stamp[2]);
    592 	}
    593 
    594 	num *= ri->ri_font->fontheight;
    595 	dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
    596 
    597 	n9 = ri->ri_emustride / 36;
    598 	cnt = (n9 << 5) + (n9 << 2); /* (32*n9) + (4*n9) */
    599 	n3 = (ri->ri_emustride - cnt) / 12;
    600 	cnt += (n3 << 3) + (n3 << 2); /* (8*n3) + (4*n3) */
    601 	n1 = (ri->ri_emustride - cnt) >> 2;
    602 
    603 	while (num--) {
    604 		for (cnt = n9; cnt; cnt--) {
    605 			dp[0] = stamp[0];
    606 			dp[1] = stamp[1];
    607 			dp[2] = stamp[2];
    608 			dp[3] = stamp[0];
    609 			dp[4] = stamp[1];
    610 			dp[5] = stamp[2];
    611 			dp[6] = stamp[0];
    612 			dp[7] = stamp[1];
    613 			dp[8] = stamp[2];
    614 			dp += 9;
    615 		}
    616 
    617 		for (cnt = n3; cnt; cnt--) {
    618 			dp[0] = stamp[0];
    619 			dp[1] = stamp[1];
    620 			dp[2] = stamp[2];
    621 			dp += 3;
    622 		}
    623 
    624 		for (cnt = 0; cnt < n1; cnt++)
    625 			*dp++ = stamp[cnt];
    626 
    627 		DELTA(dp, ri->ri_delta, int32_t *);
    628 	}
    629 }
    630 
    631 
    632 /*
    633  * Erase columns.
    634  */
    635 static void
    636 rasops24_erasecols(cookie, row, col, num, attr)
    637 	void *cookie;
    638 	int row, col, num;
    639 	long attr;
    640 {
    641 	int n12, n4, height, cnt, slop, clr, stamp[3];
    642 	struct rasops_info *ri;
    643 	int32_t *dp, *rp;
    644 	u_char *dbp;
    645 
    646 	/*
    647 	 * If the color is gray, we can cheat and use the generic routines
    648 	 * (which are faster, hopefully) since the r,g,b values are the same.
    649 	 */
    650 	if (attr & 4) {
    651 		rasops_erasecols(cookie, row, col, num, attr);
    652 		return;
    653 	}
    654 
    655 	ri = (struct rasops_info *)cookie;
    656 
    657 #ifdef RASOPS_CLIPPING
    658 	/* Catches 'row < 0' case too */
    659 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    660 		return;
    661 
    662 	if (col < 0) {
    663 		num += col;
    664 		col = 0;
    665 	}
    666 
    667 	if ((col + num) > ri->ri_cols)
    668 		num = ri->ri_cols - col;
    669 
    670 	if (num <= 0)
    671 		return;
    672 #endif
    673 
    674 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
    675 	num *= ri->ri_font->fontwidth;
    676 	height = ri->ri_font->fontheight;
    677 
    678 	clr = ri->ri_devcmap[(attr >> 16) & 15] & 0xffffff;
    679 	stamp[0] = (clr <<  8) | (clr >> 16);
    680 	stamp[1] = (clr << 16) | (clr >>  8);
    681 	stamp[2] = (clr << 24) | clr;
    682 
    683 #if BYTE_ORDER == LITTLE_ENDIAN
    684 	if (!ri->ri_swab) {
    685 #else
    686 	if (ri->ri_swab) {
    687 #endif
    688 		stamp[0] = bswap32(stamp[0]);
    689 		stamp[1] = bswap32(stamp[1]);
    690 		stamp[2] = bswap32(stamp[2]);
    691 	}
    692 
    693 	/*
    694 	 * The current byte offset mod 4 tells us the number of 24-bit pels
    695 	 * we need to write for alignment to 32-bits. Once we're aligned on
    696 	 * a 32-bit boundary, we're also aligned on a 4 pixel boundary, so
    697 	 * the stamp does not need to be rotated. The following shows the
    698 	 * layout of 4 pels (a, b, and c) in a 3 word region and illustrates
    699 	 * this:
    700 	 *
    701 	 *	aaab bbcc cddd
    702 	 */
    703 	slop = (int)rp & 3;	num -= slop;
    704 	n12 = num / 12;		num -= (n12 << 3) + (n12 << 2);
    705 	n4 = num >> 2;		num &= 3;
    706 
    707 	while (height--) {
    708 		dbp = (u_char *)rp;
    709 		DELTA(rp, ri->ri_stride, int32_t *);
    710 
    711 		/* Align to 4 bytes */
    712 		/* XXX handle with masks, bring under control of ri_swab */
    713 		for (cnt = slop; cnt; cnt--) {
    714 			*dbp++ = (clr >> 16);
    715 			*dbp++ = (clr >> 8);
    716 			*dbp++ = clr;
    717 		}
    718 
    719 		dp = (int32_t *)dbp;
    720 
    721 		/* 12 pels per loop */
    722 		for (cnt = n12; cnt; cnt--) {
    723 			dp[0] = stamp[0];
    724 			dp[1] = stamp[1];
    725 			dp[2] = stamp[2];
    726 			dp[3] = stamp[0];
    727 			dp[4] = stamp[1];
    728 			dp[5] = stamp[2];
    729 			dp[6] = stamp[0];
    730 			dp[7] = stamp[1];
    731 			dp[8] = stamp[2];
    732 			dp += 9;
    733 		}
    734 
    735 		/* 4 pels per loop */
    736 		for (cnt = n4; cnt; cnt--) {
    737 			dp[0] = stamp[0];
    738 			dp[1] = stamp[1];
    739 			dp[2] = stamp[2];
    740 			dp += 3;
    741 		}
    742 
    743 		/* Trailing slop */
    744 		/* XXX handle with masks, bring under control of ri_swab */
    745 		dbp = (u_char *)dp;
    746 		for (cnt = num; cnt; cnt--) {
    747 			*dbp++ = (clr >> 16);
    748 			*dbp++ = (clr >> 8);
    749 			*dbp++ = clr;
    750 		}
    751 	}
    752 }
    753