Home | History | Annotate | Line # | Download | only in dev
omrasops.c revision 1.5
      1 /* $NetBSD: omrasops.c,v 1.5 2007/03/04 12:48:38 tsutsui Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Tohru Nishimura.
      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 <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     40 
     41 __KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.5 2007/03/04 12:48:38 tsutsui Exp $");
     42 
     43 /*
     44  * Designed speficically for 'm68k bitorder';
     45  *	- most significant byte is stored at lower address,
     46  *	- most significant bit is displayed at left most on screen.
     47  * Implementation relys on;
     48  *	- every memory references is done in aligned 32bit chunk,
     49  *	- font glyphs are stored in 32bit padded.
     50  */
     51 
     52 #include <sys/param.h>
     53 #include <sys/systm.h>
     54 #include <sys/device.h>
     55 
     56 #include <dev/rcons/raster.h>
     57 #include <dev/wscons/wscons_raster.h>
     58 #include <dev/wscons/wscons_rfont.h>
     59 #include <dev/wscons/wsdisplayvar.h>
     60 
     61 void rcons_init __P((struct rcons *, int, int));
     62 
     63 /* wscons emulator operations */
     64 static void	om_cursor __P((void *, int, int, int));
     65 static int	om_mapchar __P((void *, int, unsigned int *));
     66 static void	om_putchar __P((void *, int, int, u_int, long));
     67 static void	om_copycols __P((void *, int, int, int, int));
     68 static void	om_copyrows __P((void *, int, int, int num));
     69 static void	om_erasecols __P((void *, int, int, int, long));
     70 static void	om_eraserows __P((void *, int, int, long));
     71 static int	om_allocattr __P((void *, int, int, int, long *));
     72 
     73 struct wsdisplay_emulops omfb_emulops = {
     74 	om_cursor,
     75 	om_mapchar,
     76 	om_putchar,
     77 	om_copycols,
     78 	om_erasecols,
     79 	om_copyrows,
     80 	om_eraserows,
     81 	om_allocattr
     82 };
     83 
     84 #define	ALL1BITS	(~0U)
     85 #define	ALL0BITS	(0U)
     86 #define	BLITWIDTH	(32)
     87 #define	ALIGNMASK	(0x1f)
     88 #define	BYTESDONE	(4)
     89 
     90 #define	W(p) (*(u_int32_t *)(p))
     91 #define	R(p) (*(u_int32_t *)((uint8_t *)(p) + 0x40000))
     92 
     93 /*
     94  * Blit a character at the specified co-ordinates.
     95  */
     96 static void
     97 om_putchar(cookie, row, startcol, uc, attr)
     98 	void *cookie;
     99 	int row, startcol;
    100 	u_int uc;
    101 	long attr;
    102 {
    103 	struct rcons *rc = cookie;
    104 	struct raster *rap = rc->rc_sp;
    105 	uint8_t *p;
    106 	int scanspan, startx, height, width, align, y;
    107 	u_int32_t lmask, rmask, glyph, inverse;
    108 	u_int32_t *g;
    109 
    110 	scanspan = rap->linelongs * 4;
    111 	y = rc->rc_yorigin + rc->rc_font->height * row;
    112 	startx = rc->rc_xorigin + rc->rc_font->width * startcol;
    113 	height = rc->rc_font->height;
    114 	g = rc->rc_font->chars[uc].r->pixels;
    115 	inverse = (attr != 0) ? ALL1BITS : ALL0BITS;
    116 
    117 	p = (uint8_t *)rap->pixels + y * scanspan + ((startx / 32) * 4);
    118 	align = startx & ALIGNMASK;
    119 	width = rc->rc_font->width + align;
    120 	lmask = ALL1BITS >> align;
    121 	rmask = ALL1BITS << (-width & ALIGNMASK);
    122 	if (width <= BLITWIDTH) {
    123 		lmask &= rmask;
    124 		while (height > 0) {
    125 			glyph = *g;
    126 			glyph = (glyph >> align) ^ inverse;
    127 			W(p) = (R(p) & ~lmask) | (glyph & lmask);
    128 			p += scanspan;
    129 			g += 1;
    130 			height--;
    131 		}
    132 	}
    133 	else {
    134 		uint8_t *q = p;
    135 		u_int32_t lhalf, rhalf;
    136 
    137 		while (height > 0) {
    138 			glyph = *g;
    139 			lhalf = (glyph >> align) ^ inverse;
    140 			W(p) = (R(p) & ~lmask) | (lhalf & lmask);
    141 			p += BYTESDONE;
    142 			rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
    143 			W(p) = (rhalf & rmask) | (R(p) & ~rmask);
    144 
    145 			p = (q += scanspan);
    146 			g += 1;
    147 			height--;
    148 		}
    149 	}
    150 }
    151 
    152 static void
    153 om_erasecols(cookie, row, startcol, ncols, attr)
    154 	void *cookie;
    155 	int row, startcol, ncols;
    156 	long attr;
    157 {
    158         struct rcons *rc = cookie;
    159         struct raster *rap = rc->rc_sp;
    160         uint8_t *p;
    161         int scanspan, startx, height, width, align, w, y;
    162         u_int32_t lmask, rmask, fill;
    163 
    164         scanspan = rap->linelongs * 4;
    165         y = rc->rc_yorigin + rc->rc_font->height * row;
    166         startx = rc->rc_xorigin + rc->rc_font->width * startcol;
    167         height = rc->rc_font->height;
    168         w = rc->rc_font->width * ncols;
    169 	fill = (attr != 0) ? ALL1BITS : ALL0BITS;
    170 
    171 	p = (uint8_t *)rap->pixels + y * scanspan + ((startx / 32) * 4);
    172 	align = startx & ALIGNMASK;
    173 	width = w + align;
    174 	lmask = ALL1BITS >> align;
    175 	rmask = ALL1BITS << (-width & ALIGNMASK);
    176 	if (width <= BLITWIDTH) {
    177 		lmask &= rmask;
    178 		fill &= lmask;
    179 		while (height > 0) {
    180 			W(p) = (R(p) & ~lmask) | fill;
    181 			p += scanspan;
    182 			height--;
    183 		}
    184 	}
    185 	else {
    186 		uint8_t *q = p;
    187 		while (height > 0) {
    188 			W(p) = (R(p) & ~lmask) | (fill & lmask);
    189 			width -= 2 * BLITWIDTH;
    190 			while (width > 0) {
    191 				p += BYTESDONE;
    192 				W(p) = fill;
    193 				width -= BLITWIDTH;
    194 			}
    195 			p += BYTESDONE;
    196 			W(p) = (fill & rmask) | (R(p) & ~rmask);
    197 
    198 			p = (q += scanspan);
    199 			width = w + align;
    200 			height--;
    201 		}
    202 	}
    203 }
    204 
    205 static void
    206 om_eraserows(cookie, startrow, nrows, attr)
    207 	void *cookie;
    208 	int startrow, nrows;
    209 	long attr;
    210 {
    211 	struct rcons *rc = cookie;
    212 	struct raster *rap = rc->rc_sp;
    213 	uint8_t *p, *q;
    214 	int scanspan, starty, height, width, w;
    215 	u_int32_t rmask, fill;
    216 
    217 	scanspan = rap->linelongs * 4;
    218 	starty = rc->rc_yorigin + rc->rc_font->height * startrow;
    219 	height = rc->rc_font->height * nrows;
    220 	w = rc->rc_font->width * rc->rc_maxcol;
    221 	fill = (attr == 1) ? ALL1BITS : ALL0BITS;
    222 
    223 	p = (uint8_t *)rap->pixels + starty * scanspan;
    224 	p += (rc->rc_xorigin / 32) * 4;
    225 	width = w;
    226         rmask = ALL1BITS << (-width & ALIGNMASK);
    227 	q = p;
    228 	while (height > 0) {
    229 		W(p) = fill;				/* always aligned */
    230 		width -= 2 * BLITWIDTH;
    231 		while (width > 0) {
    232 			p += BYTESDONE;
    233 			W(p) = fill;
    234 			width -= BLITWIDTH;
    235 		}
    236 		p += BYTESDONE;
    237 		W(p) = (fill & rmask) | (R(p) & ~rmask);
    238 		p = (q += scanspan);
    239 		width = w;
    240 		height--;
    241 	}
    242 }
    243 
    244 static void
    245 om_copyrows(cookie, srcrow, dstrow, nrows)
    246 	void *cookie;
    247 	int srcrow, dstrow, nrows;
    248 {
    249         struct rcons *rc = cookie;
    250         struct raster *rap = rc->rc_sp;
    251         uint8_t *p, *q;
    252 	int scanspan, offset, srcy, height, width, w;
    253         u_int32_t rmask;
    254 
    255 	scanspan = rap->linelongs * 4;
    256 	height = rc->rc_font->height * nrows;
    257 	offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
    258 	srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
    259 	if (srcrow < dstrow && srcrow + nrows > dstrow) {
    260 		scanspan = -scanspan;
    261 		srcy += height;
    262 	}
    263 
    264 	p = (uint8_t *)rap->pixels + srcy * (rap->linelongs * 4);
    265 	p += (rc->rc_xorigin / 32) * 4;
    266 	w = rc->rc_font->width * rc->rc_maxcol;
    267 	width = w;
    268 	rmask = ALL1BITS << (-width & ALIGNMASK);
    269 	q = p;
    270 	while (height > 0) {
    271 		W(p + offset) = R(p);			/* always aligned */
    272 		width -= 2 * BLITWIDTH;
    273 		while (width > 0) {
    274 			p += BYTESDONE;
    275 			W(p + offset) = R(p);
    276 			width -= BLITWIDTH;
    277 		}
    278 		p += BYTESDONE;
    279 		W(p + offset) = (R(p) & rmask) | (R(p + offset) & ~rmask);
    280 
    281 		p = (q += scanspan);
    282 		width = w;
    283 		height--;
    284 	}
    285 }
    286 
    287 static void
    288 om_copycols(cookie, startrow, srccol, dstcol, ncols)
    289 	void *cookie;
    290 	int startrow, srccol, dstcol, ncols;
    291 {
    292 	struct rcons *rc = cookie;
    293 	struct raster *rap = rc->rc_sp;
    294 	uint8_t *sp, *dp, *basep;
    295 	int scanspan, height, width, align, shift, w, y, srcx, dstx;
    296 	u_int32_t lmask, rmask;
    297 
    298 	scanspan = rap->linelongs * 4;
    299 	y = rc->rc_yorigin + rc->rc_font->height * startrow;
    300 	srcx = rc->rc_xorigin + rc->rc_font->width * srccol;
    301 	dstx = rc->rc_xorigin + rc->rc_font->width * dstcol;
    302 	height = rc->rc_font->height;
    303 	w = rc->rc_font->width * ncols;
    304 	basep = (uint8_t *)rap->pixels + y * scanspan;
    305 
    306 	align = shift = srcx & ALIGNMASK;
    307 	width = w + align;
    308 	align = dstx & ALIGNMASK;
    309 	lmask = ALL1BITS >> align;
    310 	rmask = ALL1BITS << (-(w + align) & ALIGNMASK);
    311 	shift = align - shift;
    312 	sp = basep + (srcx / 32) * 4;
    313 	dp = basep + (dstx / 32) * 4;
    314 
    315 	if (shift != 0)
    316 		goto hardluckalignment;
    317 
    318 	/* alignments comfortably match */
    319 	if (width <= BLITWIDTH) {
    320 		lmask &= rmask;
    321 		while (height > 0) {
    322 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
    323 			dp += scanspan;
    324 			sp += scanspan;
    325 			height--;
    326 		}
    327 	}
    328 	/* copy forward (left-to-right) */
    329 	else if (dstcol < srccol || srccol + ncols < dstcol) {
    330 		uint8_t *sq = sp, *dq = dp;
    331 
    332 		w = width;
    333 		while (height > 0) {
    334 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
    335 			width -= 2 * BLITWIDTH;
    336 			while (width > 0) {
    337 				sp += BYTESDONE;
    338 				dp += BYTESDONE;
    339 				W(dp) = R(sp);
    340 				width -= BLITWIDTH;
    341 			}
    342 			sp += BYTESDONE;
    343 			dp += BYTESDONE;
    344 			W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask);
    345 			sp = (sq += scanspan);
    346 			dp = (dq += scanspan);
    347 			width = w;
    348 			height--;
    349 		}
    350 	}
    351 	/* copy backward (right-to-left) */
    352 	else {
    353 		uint8_t *sq, *dq;
    354 
    355 		sq = (sp += width / 32 * 4);
    356 		dq = (dp += width / 32 * 4);
    357 		w = width;
    358 		while (height > 0) {
    359 			W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask);
    360 			width -= 2 * BLITWIDTH;
    361 			while (width > 0) {
    362 				sp -= BYTESDONE;
    363 				dp -= BYTESDONE;
    364 				W(dp) = R(sp);
    365 				width -= BLITWIDTH;
    366 			}
    367 			sp -= BYTESDONE;
    368 			dp -= BYTESDONE;
    369 			W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
    370 
    371 			sp = (sq += scanspan);
    372 			dp = (dq += scanspan);
    373 			width = w;
    374 			height--;
    375 		}
    376 	}
    377 	return;
    378 
    379     hardluckalignment:
    380 	/* alignments painfully disagree */
    381 	return;
    382 }
    383 
    384 /*
    385  * Map a character.
    386  */
    387 static int
    388 om_mapchar(cookie, c, cp)
    389 	void *cookie;
    390 	int c;
    391 	u_int *cp;
    392 {
    393 	if (c < 128) {
    394 		*cp = c;
    395 		return (5);
    396 	}
    397 	*cp = ' ';
    398 	return (0);
    399 }
    400 
    401 /*
    402  * Position|{enable|disable} the cursor at the specified location.
    403  */
    404 static void
    405 om_cursor(cookie, on, row, col)
    406 	void *cookie;
    407 	int on, row, col;
    408 {
    409 	struct rcons *rc = cookie;
    410 	struct raster *rap = rc->rc_sp;
    411 	uint8_t *p;
    412 	int scanspan, startx, height, width, align, y;
    413 	u_int32_t lmask, rmask, image;
    414 
    415 	if (!on) {
    416 		/* make sure it's on */
    417 		if ((rc->rc_bits & RC_CURSOR) == 0)
    418 			return;
    419 
    420 		row = *rc->rc_crowp;
    421 		col = *rc->rc_ccolp;
    422 	} else {
    423 		/* unpaint the old copy. */
    424 		*rc->rc_crowp = row;
    425 		*rc->rc_ccolp = col;
    426 	}
    427 
    428 	scanspan = rap->linelongs * 4;
    429 	y = rc->rc_yorigin + rc->rc_font->height * row;
    430 	startx = rc->rc_xorigin + rc->rc_font->width * col;
    431 	height = rc->rc_font->height;
    432 
    433 	p = (uint8_t *)rap->pixels + y * scanspan + ((startx / 32) * 4);
    434 	align = startx & ALIGNMASK;
    435 	width = rc->rc_font->width + align;
    436 	lmask = ALL1BITS >> align;
    437 	rmask = ALL1BITS << (-width & ALIGNMASK);
    438 	if (width <= BLITWIDTH) {
    439 		lmask &= rmask;
    440 		while (height > 0) {
    441 			image = R(p);
    442 			W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
    443 			p += scanspan;
    444 			height--;
    445 		}
    446 	}
    447 	else {
    448 		uint8_t *q = p;
    449 
    450 		while (height > 0) {
    451 			image = R(p);
    452 			W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
    453 			p += BYTESDONE;
    454 			image = R(p);
    455 			W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
    456 
    457 			p = (q += scanspan);
    458 			height--;
    459 		}
    460 	}
    461 	rc->rc_bits ^= RC_CURSOR;
    462 }
    463 
    464 /*
    465  * Allocate attribute. We just pack these into an integer.
    466  */
    467 static int
    468 om_allocattr(id, fg, bg, flags, attrp)
    469 	void *id;
    470 	int fg, bg, flags;
    471 	long *attrp;
    472 {
    473 	if (flags & (WSATTR_HILIT | WSATTR_BLINK |
    474 		     WSATTR_UNDERLINE | WSATTR_WSCOLORS))
    475 		return (EINVAL);
    476 	if (flags & WSATTR_REVERSE)
    477 		*attrp = 1;
    478 	else
    479 		*attrp = 0;
    480 	return (0);
    481 }
    482 
    483 void
    484 rcons_init(rc, mrow, mcol)
    485 	struct rcons *rc;
    486 	int mrow, mcol;
    487 {
    488 	struct raster *rp = rc->rc_sp;
    489 	int i;
    490 
    491 	rc->rc_font = &gallant19; /* 12x22 monospacing font */
    492 
    493 	/* Get distance to top and bottom of font from font origin */
    494 	rc->rc_font_ascent = -(rc->rc_font->chars)['a'].homey;
    495 
    496 	i = rp->height / rc->rc_font->height;
    497 	rc->rc_maxrow = min(i, mrow);
    498 
    499 	i = rp->width / rc->rc_font->width;
    500 	rc->rc_maxcol = min(i, mcol);
    501 
    502 	/* Center emulator screen (but align x origin to 32 bits) */
    503 	rc->rc_xorigin =
    504 	    ((rp->width - rc->rc_maxcol * rc->rc_font->width) / 2) & ~ALIGNMASK;
    505 	rc->rc_yorigin =
    506 	    (rp->height - rc->rc_maxrow * rc->rc_font->height) / 2;
    507 #if 0
    508 	/* Raster width used for row copies */
    509 	rc->rc_raswidth = rc->rc_maxcol * rc->rc_font->width;
    510 	if (rc->rc_raswidth & ALIGNMASK) {
    511 		/* Pad to 32 bits */
    512 		i = (rc->rc_raswidth + ALIGNMASK) & ~ALIGNMASK;
    513 		/* Make sure width isn't too wide */
    514 		if (rc->rc_xorigin + i <= rp->width)
    515 			rc->rc_raswidth = i;
    516 	}
    517 #endif
    518 	rc->rc_bits = 0;
    519 }
    520