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