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