Home | History | Annotate | Line # | Download | only in rasops
rasops_bitops.h revision 1.23
      1 /* 	$NetBSD: rasops_bitops.h,v 1.23 2019/08/02 04:39:09 rin 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 Andrew 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  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #ifndef _RASOPS_BITOPS_H_
     33 #define _RASOPS_BITOPS_H_ 1
     34 
     35 #define	NAME(name)		NAME1(RASOPS_DEPTH, name)
     36 #define	NAME1(depth, name)	NAME2(depth, name)
     37 #define	NAME2(depth, name)	rasops ## depth ## _ ## name
     38 
     39 #if   RASOPS_DEPTH == 1
     40 #define	PIXEL_SHIFT	0
     41 #elif RASOPS_DEPTH == 2
     42 #define	PIXEL_SHIFT	1
     43 #elif RASOPS_DEPTH == 4
     44 #define	PIXEL_SHIFT	2
     45 #else
     46 #error "Depth not supported"
     47 #endif
     48 
     49 #define	PIXEL_BITS	RASOPS_DEPTH
     50 #define	COLOR_MASK	__BITS(32 - PIXEL_BITS, 31)
     51 
     52 #if RASOPS_DEPTH != 1
     53 /*
     54  * Paint a single character. This function is also applicable to
     55  * monochrome, but that in rasops1.c is much simpler and faster.
     56  */
     57 static void
     58 NAME(putchar)(void *cookie, int row, int col, u_int uc, long attr)
     59 {
     60 	struct rasops_info *ri = (struct rasops_info *)cookie;
     61 	struct wsdisplay_font *font = PICK_FONT(ri, uc);
     62 	int full, cnt, bit;
     63 	uint32_t fs, rs, fb, bg, fg, lmask, rmask, lbg, rbg, clr[2];
     64 	uint32_t height, width;
     65 	uint32_t *rp, *bp, *hp, tmp;
     66 	uint8_t *fr;
     67 	bool space;
     68 
     69 	hp = NULL;	/* XXX GCC */
     70 
     71 #ifdef RASOPS_CLIPPING
     72 	/* Catches 'row < 0' case too */
     73 	if ((unsigned)row >= (unsigned)ri->ri_rows)
     74 		return;
     75 
     76 	if ((unsigned)col >= (unsigned)ri->ri_cols)
     77 		return;
     78 #endif
     79 
     80 	width = font->fontwidth << PIXEL_SHIFT;
     81 	col *= width;
     82 	height = font->fontheight;
     83 	rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale +
     84 	    ((col >> 3) & ~3));
     85 	if (ri->ri_hwbits)
     86 		hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
     87 		    ((col >> 3) & ~3));
     88 	col &= 31;
     89 	rs = ri->ri_stride;
     90 
     91 	bg = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
     92 	fg = ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf];
     93 
     94 	/* If fg and bg match this becomes a space character */
     95 	if (uc == ' ' || __predict_false(fg == bg)) {
     96 		space = true;
     97 		fr = NULL;	/* XXX GCC */
     98 		fs = 0;		/* XXX GCC */
     99 	} else {
    100 		space = false;
    101 		fr = FONT_GLYPH(uc, font, ri);
    102 		fs = font->stride;
    103 	}
    104 
    105 	if (col + width <= 32) {
    106 		/* Single word, only one mask */
    107 
    108 		rmask = rasops_pmask[col][width & 31];
    109 		lmask = ~rmask;
    110 
    111 		if (space) {
    112 			bg &= rmask;
    113 			while (height--) {
    114 				tmp = (*rp & lmask) | bg;
    115 				*rp = tmp;
    116 				DELTA(rp, rs, uint32_t *);
    117 				if (ri->ri_hwbits) {
    118 					*hp = tmp;
    119 					DELTA(hp, rs, uint32_t *);
    120 				}
    121 			}
    122 		} else {
    123 			clr[0] = bg & COLOR_MASK;
    124 			clr[1] = fg & COLOR_MASK;
    125 			while (height--) {
    126 				fb = be32uatoh(fr);
    127 				fr += fs;
    128 				tmp = 0;
    129 				for (bit = col; bit < col + width;
    130 				    bit += PIXEL_BITS) {
    131 					tmp |= clr[(fb >> 31) & 1] >> bit;
    132 					fb <<= 1;
    133 				}
    134 				tmp = (*rp & lmask) | MBE(tmp);
    135 				*rp = tmp;
    136 				DELTA(rp, rs, uint32_t *);
    137 				if (ri->ri_hwbits) {
    138 					*hp = tmp;
    139 					DELTA(hp, rs, uint32_t *);
    140 				}
    141 			}
    142 		}
    143 
    144 		/* Do underline */
    145 		if ((attr & WSATTR_UNDERLINE) != 0) {
    146 			DELTA(rp, -(ri->ri_stride << 1), uint32_t *);
    147 			tmp = (*rp & lmask) | (fg & rmask);
    148 			*rp = tmp;
    149 			if (ri->ri_hwbits) {
    150 				DELTA(hp, -(ri->ri_stride << 1), uint32_t *);
    151 				*hp = tmp;
    152 			}
    153 		}
    154 
    155 		return;
    156 	}
    157 
    158 	/* Word boundary, two masks needed */
    159 
    160 	lmask = ~rasops_lmask[col];
    161 	rmask = ~rasops_rmask[(col + width) & 31];
    162 
    163 	if (lmask != -1)
    164 		width -= 32 - col;
    165 	full = width / 32;
    166 	width -= full * 32;
    167 
    168 	if (space) {
    169 		lbg = bg & ~lmask;
    170 		rbg = bg & ~rmask;
    171 
    172 		while (height--) {
    173 			bp = rp;
    174 
    175 			if (lmask != -1) {
    176 				*bp = (*bp & lmask) | lbg;
    177 				bp++;
    178 			}
    179 
    180 			for (cnt = full; cnt; cnt--)
    181 				*bp++ = bg;
    182 
    183 			if (rmask != -1)
    184 				*bp = (*bp & rmask) | rbg;
    185 
    186 			if (ri->ri_hwbits) {
    187 				memcpy(hp, rp, ((lmask != -1) + full +
    188 				    (rmask != -1)) << 2);
    189 				DELTA(hp, rs, uint32_t *);
    190 			}
    191 			DELTA(rp, rs, uint32_t *);
    192 		}
    193 	} else {
    194 		clr[0] = bg & COLOR_MASK;
    195 		clr[1] = fg & COLOR_MASK;
    196 
    197 		while (height--) {
    198 			bp = rp;
    199 
    200 			fb = be32uatoh(fr);
    201 			fr += fs;
    202 
    203 			if (lmask != -1) {
    204 				tmp = 0;
    205 				for (bit = col; bit < 32; bit += PIXEL_BITS) {
    206 					tmp |= clr[(fb >> 31) & 1] >> bit;
    207 					fb <<= 1;
    208 				}
    209 				*bp = (*bp & lmask) | MBE(tmp);
    210 				bp++;
    211 			}
    212 
    213 			for (cnt = full; cnt; cnt--) {
    214 				tmp = 0;
    215 				for (bit = 0; bit < 32; bit += PIXEL_BITS) {
    216 					tmp |= clr[(fb >> 31) & 1] >> bit;
    217 					fb <<= 1;
    218 				}
    219 				*bp++ = MBE(tmp);
    220 			}
    221 
    222 			if (rmask != -1) {
    223 				tmp = 0;
    224 				for (bit = 0; bit < width; bit += PIXEL_BITS) {
    225 					tmp |= clr[(fb >> 31) & 1] >> bit;
    226 					fb <<= 1;
    227 				}
    228 				*bp = (*bp & rmask) | MBE(tmp);
    229 			}
    230 
    231 			if (ri->ri_hwbits) {
    232 				memcpy(hp, rp, ((lmask != -1) + full +
    233 				    (rmask != -1)) << 2);
    234 				DELTA(hp, rs, uint32_t *);
    235 			}
    236 
    237 			DELTA(rp, rs, uint32_t *);
    238 		}
    239 	}
    240 
    241 	/* Do underline */
    242 	if ((attr & WSATTR_UNDERLINE) != 0) {
    243 		DELTA(rp, -(ri->ri_stride << 1), uint32_t *);
    244 		bp = rp;
    245 		if (lmask != -1) {
    246 			*bp = (*bp & lmask) | (fg & ~lmask);
    247 			bp++;
    248 		}
    249 		for (cnt = full; cnt; cnt--)
    250 			*bp++ = fg;
    251 		if (rmask != -1)
    252 			*bp = (*bp & rmask) | (fg & ~rmask);
    253 		if (ri->ri_hwbits) {
    254 			DELTA(hp, -(ri->ri_stride << 1), uint32_t *);
    255 			memcpy(hp, rp, ((lmask != -1) + full +
    256 			    (rmask != -1)) << 2);
    257 		}
    258 	}
    259 }
    260 #endif /* RASOPS_DEPTH != 1 */
    261 
    262 /*
    263  * Erase columns.
    264  */
    265 static void
    266 NAME(erasecols)(void *cookie, int row, int col, int num, long attr)
    267 {
    268 	struct rasops_info *ri = (struct rasops_info *)cookie;
    269 	uint32_t lclr, rclr, clr;
    270 	uint32_t *dp, *rp, *hp, tmp, lmask, rmask;
    271 	int height, cnt;
    272 
    273 	hp = NULL;	/* XXX GCC */
    274 
    275 #ifdef RASOPS_CLIPPING
    276 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    277 		return;
    278 
    279 	if (col < 0) {
    280 		num += col;
    281 		col = 0;
    282 	}
    283 
    284 	if (col + num > ri->ri_cols)
    285 		num = ri->ri_cols - col;
    286 
    287 	if (num <= 0)
    288 		return;
    289 #endif
    290 
    291 	col *= ri->ri_font->fontwidth << PIXEL_SHIFT;
    292 	num *= ri->ri_font->fontwidth << PIXEL_SHIFT;
    293 	height = ri->ri_font->fontheight;
    294 	clr = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
    295 	rp = (uint32_t *)(ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3));
    296 	if (ri->ri_hwbits)
    297 		hp = (uint32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
    298 		    ((col >> 3) & ~3));
    299 	col &= 31;
    300 
    301 	if (col + num <= 32) {
    302 		lmask = ~rasops_pmask[col][num & 31];
    303 		lclr = clr & ~lmask;
    304 
    305 		while (height--) {
    306 			dp = rp;
    307 			DELTA(rp, ri->ri_stride, uint32_t *);
    308 
    309 			tmp = (*dp & lmask) | lclr;
    310 			*dp = tmp;
    311 			if (ri->ri_hwbits) {
    312 				*hp = tmp;
    313 				DELTA(hp, ri->ri_stride, uint32_t *);
    314 			}
    315 		}
    316 	} else {
    317 		lmask = rasops_rmask[col];
    318 		rmask = rasops_lmask[(col + num) & 31];
    319 
    320 		if (lmask)
    321 			num = (num - (32 - col)) >> 5;
    322 		else
    323 			num = num >> 5;
    324 
    325 		lclr = clr & ~lmask;
    326 		rclr = clr & ~rmask;
    327 
    328 		while (height--) {
    329 			dp = rp;
    330 
    331 			if (lmask) {
    332 				*dp = (*dp & lmask) | lclr;
    333 				dp++;
    334 			}
    335 
    336 			for (cnt = num; cnt > 0; cnt--)
    337 				*dp++ = clr;
    338 
    339 			if (rmask)
    340 				*dp = (*dp & rmask) | rclr;
    341 
    342 			if (ri->ri_hwbits) {
    343 				memcpy(hp, rp, ((lmask != 0) + num +
    344 				    (rmask != 0)) << 2);
    345 				DELTA(hp, ri->ri_stride, uint32_t *);
    346 			}
    347 			DELTA(rp, ri->ri_stride, uint32_t *);
    348 		}
    349 	}
    350 }
    351 
    352 /*
    353  * Actually paint the cursor.
    354  */
    355 static void
    356 NAME(do_cursor)(struct rasops_info *ri)
    357 {
    358 	int height, row, col, num, cnt;
    359 	uint32_t *dp, *rp, *hp, tmp, lmask, rmask;
    360 
    361 	hp = NULL;	/* XXX GCC */
    362 
    363 	row = ri->ri_crow;
    364 	col = ri->ri_ccol * ri->ri_font->fontwidth << PIXEL_SHIFT;
    365 	height = ri->ri_font->fontheight;
    366 	num = ri->ri_font->fontwidth << PIXEL_SHIFT;
    367 	rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale +
    368 	    ((col >> 3) & ~3));
    369 	if (ri->ri_hwbits)
    370 		hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
    371 		    ((col >> 3) & ~3));
    372 	col &= 31;
    373 
    374 	if (col + num <= 32) {
    375 		lmask = rasops_pmask[col][num & 31];
    376 
    377 		while (height--) {
    378 			tmp = *rp ^ lmask;
    379 			*rp = tmp;
    380 			if (ri->ri_hwbits) {
    381 				*hp = tmp;
    382 				DELTA(hp, ri->ri_stride, uint32_t *);
    383 			}
    384 			DELTA(rp, ri->ri_stride, uint32_t *);
    385 		}
    386 	} else {
    387 		lmask = ~rasops_rmask[col];
    388 		rmask = ~rasops_lmask[(col + num) & 31];
    389 
    390 		if (lmask != -1)
    391 			num = (num - (32 - col)) >> 5;
    392 		else
    393 			num = num >> 5;
    394 
    395 		while (height--) {
    396 			dp = rp;
    397 
    398 			if (lmask != -1) {
    399 				*dp = *dp ^ lmask;
    400 				dp++;
    401 			}
    402 
    403 			for (cnt = num; cnt; cnt--) {
    404 				*dp = ~*dp;
    405 				dp++;
    406 			}
    407 
    408 			if (rmask != -1)
    409 				*dp = *dp ^ rmask;
    410 
    411 			if (ri->ri_hwbits) {
    412 				memcpy(hp, rp, ((lmask != -1) + num +
    413 				    (rmask != -1)) << 2);
    414 				DELTA(hp, ri->ri_stride, uint32_t *);
    415 			}
    416 
    417 			DELTA(rp, ri->ri_stride, uint32_t *);
    418 		}
    419 	}
    420 }
    421 
    422 /*
    423  * Copy columns. Ick!
    424  */
    425 static void
    426 NAME(copycols)(void *cookie, int row, int src, int dst, int num)
    427 {
    428 	struct rasops_info *ri = (struct rasops_info *)cookie;
    429 	int height, lnum, rnum, sb, db, cnt, full;
    430 	uint32_t tmp, lmask, rmask;
    431 	uint32_t *sp, *dp, *srp, *drp, *dhp, *hp;
    432 
    433 	dhp = hp = NULL;	/* XXX GCC */
    434 
    435 #ifdef RASOPS_CLIPPING
    436 	if (dst == src)
    437 		return;
    438 
    439 	/* Catches < 0 case too */
    440 	if ((unsigned)row >= (unsigned)ri->ri_rows)
    441 		return;
    442 
    443 	if (src < 0) {
    444 		num += src;
    445 		src = 0;
    446 	}
    447 
    448 	if (src + num > ri->ri_cols)
    449 		num = ri->ri_cols - src;
    450 
    451 	if (dst < 0) {
    452 		num += dst;
    453 		dst = 0;
    454 	}
    455 
    456 	if (dst + num > ri->ri_cols)
    457 		num = ri->ri_cols - dst;
    458 
    459 	if (num <= 0)
    460 		return;
    461 #endif
    462 
    463 	cnt = ri->ri_font->fontwidth << PIXEL_SHIFT;
    464 	src *= cnt;
    465 	dst *= cnt;
    466 	num *= cnt;
    467 	row *= ri->ri_yscale;
    468 	height = ri->ri_font->fontheight;
    469 	db = dst & 31;
    470 
    471 	if (db + num <= 32) {
    472 		/* Destination is contained within a single word */
    473 		srp = (uint32_t *)(ri->ri_bits + row + ((src >> 3) & ~3));
    474 		drp = (uint32_t *)(ri->ri_bits + row + ((dst >> 3) & ~3));
    475 		if (ri->ri_hwbits)
    476 			dhp = (uint32_t *)(ri->ri_hwbits + row +
    477 			    ((dst >> 3) & ~3));
    478 		sb = src & 31;
    479 
    480 		while (height--) {
    481 			GETBITS(srp, sb, num, tmp);
    482 			PUTBITS(tmp, db, num, drp);
    483 			if (ri->ri_hwbits) {
    484 				PUTBITS(tmp, db, num, dhp);
    485 				DELTA(dhp, ri->ri_stride, uint32_t *);
    486 			}
    487 			DELTA(srp, ri->ri_stride, uint32_t *);
    488 			DELTA(drp, ri->ri_stride, uint32_t *);
    489 		}
    490 
    491 		return;
    492 	}
    493 
    494 	lmask = rasops_rmask[db];
    495 	rmask = rasops_lmask[(dst + num) & 31];
    496 	lnum = (32 - db) & 31;
    497 	rnum = (dst + num) & 31;
    498 
    499 	if (lmask)
    500 		full = (num - lnum) >> 5;
    501 	else
    502 		full = num >> 5;
    503 
    504 	if (src < dst && src + num > dst) {
    505 		/* Copy right-to-left */
    506 		bool sbover;
    507 		int sboff;
    508 
    509 		srp = (uint32_t *)(ri->ri_bits + row +
    510 		    (((src + num) >> 3) & ~3));
    511 		drp = (uint32_t *)(ri->ri_bits + row +
    512 		    (((dst + num) >> 3) & ~3));
    513 		if (ri->ri_hwbits)
    514 			dhp = (uint32_t *)(ri->ri_hwbits + row +
    515 			    (((dst + num) >> 3) & ~3));
    516 
    517 		sb = src & 31;
    518 		sbover = (sb + lnum) >= 32;
    519 		sboff = (src + num) & 31;
    520 		if ((sboff -= rnum) < 0) {
    521 			srp--;
    522 			sboff += 32;
    523 		}
    524 
    525 		while (height--) {
    526 			sp = srp;
    527 			dp = drp;
    528 
    529 			if (rnum) {
    530 				GETBITS(sp, sboff, rnum, tmp);
    531 				PUTBITS(tmp, 0, rnum, dp);
    532 			}
    533 
    534 			/* Now aligned to 32-bits wrt dp */
    535 			for (cnt = full; cnt; cnt--) {
    536 				--dp;
    537 				--sp;
    538 				GETBITS(sp, sboff, 32, tmp);
    539 				*dp = tmp;
    540 			}
    541 
    542 			if (lmask) {
    543 				if (sbover)
    544 					--sp;
    545 				--dp;
    546 				GETBITS(sp, sb, lnum, tmp);
    547 				PUTBITS(tmp, db, lnum, dp);
    548  			}
    549 
    550 			if (ri->ri_hwbits) {
    551 				hp = dhp;
    552 				hp -= (lmask != 0) + full;
    553 				memcpy(hp, dp, ((lmask != 0) + full +
    554 				    (rnum != 0)) << 2);
    555 				DELTA(dhp, ri->ri_stride, uint32_t *);
    556 			}
    557 
    558 			DELTA(srp, ri->ri_stride, uint32_t *);
    559 			DELTA(drp, ri->ri_stride, uint32_t *);
    560  		}
    561 	} else {
    562 		/* Copy left-to-right */
    563 		srp = (uint32_t *)(ri->ri_bits + row + ((src >> 3) & ~3));
    564 		drp = (uint32_t *)(ri->ri_bits + row + ((dst >> 3) & ~3));
    565 		if (ri->ri_hwbits)
    566 			dhp = (uint32_t *)(ri->ri_hwbits + row +
    567 			    ((dst >> 3) & ~3));
    568 
    569 		while (height--) {
    570 			sb = src & 31;
    571 			sp = srp;
    572 			dp = drp;
    573 
    574 			if (lmask) {
    575 				GETBITS(sp, sb, lnum, tmp);
    576 				PUTBITS(tmp, db, lnum, dp);
    577 				dp++;
    578 
    579 				sb += lnum;
    580 				if (sb > 31) {
    581 					sp++;
    582 					sb -= 32;
    583 				}
    584 			}
    585 
    586 			/* Now aligned to 32-bits wrt dp */
    587 			for (cnt = full; cnt; cnt--, sp++) {
    588 				GETBITS(sp, sb, 32, tmp);
    589 				*dp++ = tmp;
    590 			}
    591 
    592 			if (rmask) {
    593 				GETBITS(sp, sb, rnum, tmp);
    594 				PUTBITS(tmp, 0, rnum, dp);
    595  			}
    596 
    597 			if (ri->ri_hwbits) {
    598 				memcpy(dhp, drp, ((lmask != 0) + full +
    599 				    (rmask != 0)) << 2);
    600 				DELTA(dhp, ri->ri_stride, uint32_t *);
    601 			}
    602 
    603 			DELTA(srp, ri->ri_stride, uint32_t *);
    604 			DELTA(drp, ri->ri_stride, uint32_t *);
    605  		}
    606  	}
    607 }
    608 
    609 #undef	PIXEL_SHIFT
    610 #undef	PIXEL_BITS
    611 #undef	COLOR_MASK
    612 
    613 #endif /* _RASOPS_BITOPS_H_ */
    614