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