Home | History | Annotate | Line # | Download | only in rasops
rasops.c revision 1.2
      1 /* $NetBSD: rasops.c,v 1.2 1999/04/13 00:40:08 ad Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1999 Andy Doran <ad (at) NetBSD.org>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  *
     28  */
     29 
     30 #include <sys/cdefs.h>
     31 __KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.2 1999/04/13 00:40:08 ad Exp $");
     32 
     33 #include "opt_rasops.h"
     34 
     35 #include <sys/types.h>
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/time.h>
     39 
     40 #include <dev/wscons/wsdisplayvar.h>
     41 #include <dev/wscons/wsconsio.h>
     42 #include <dev/wsfont/wsfont.h>
     43 #include <dev/rasops/rasops.h>
     44 
     45 /* ANSI colormap (R,G,B). Upper 8 are high-intensity */
     46 u_char rasops_cmap[256*3] = {
     47 	0x00, 0x00, 0x00, /* black */
     48 	0x7f, 0x00, 0x00, /* red */
     49 	0x00, 0x7f, 0x00, /* green */
     50 	0x7f, 0x7f, 0x00, /* brown */
     51 	0x00, 0x00, 0x7f, /* blue */
     52 	0x7f, 0x00, 0x7f, /* magenta */
     53 	0x00, 0x7f, 0x7f, /* cyan */
     54 	0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
     55 
     56 	0x7f, 0x7f, 0x7f, /* black */
     57 	0xff, 0x00, 0x00, /* red */
     58 	0x00, 0xff, 0x00, /* green */
     59 	0xff, 0xff, 0x00, /* brown */
     60 	0x00, 0x00, 0xff, /* blue */
     61 	0xff, 0x00, 0xff, /* magenta */
     62 	0x00, 0xff, 0xff, /* cyan */
     63 	0xff, 0xff, 0xff, /* white */
     64 };
     65 
     66 /* True if color is gray */
     67 u_char rasops_isgray[16] = {
     68 	1, 0, 0, 0,
     69 	0, 0, 0, 1,
     70 	1, 0, 0, 0,
     71 	0, 0, 0, 1
     72 };
     73 
     74 /* Common functions */
     75 static void	rasops_copycols __P((void *, int, int, int, int));
     76 static void	rasops_copyrows __P((void *, int, int, int));
     77 static int	rasops_mapchar __P((void *, int, u_int *));
     78 static void	rasops_cursor __P((void *, int, int, int));
     79 static int	rasops_alloc_cattr __P((void *, int, int, int, long *));
     80 static int	rasops_alloc_mattr __P((void *, int, int, int, long *));
     81 
     82 /* Per-depth initalization functions */
     83 void	rasops1_init __P((struct rasops_info *));
     84 void	rasops8_init __P((struct rasops_info *));
     85 void	rasops15_init __P((struct rasops_info *));
     86 void	rasops24_init __P((struct rasops_info *));
     87 void	rasops32_init __P((struct rasops_info *));
     88 
     89 /*
     90  * Initalize a 'rasops_info' descriptor.
     91  */
     92 int
     93 rasops_init(ri, wantrows, wantcols, clear, center)
     94 	struct rasops_info *ri;
     95 	int wantrows, wantcols, clear, center;
     96 {
     97 
     98 	/* Select a font if the caller doesn't care */
     99 	if (ri->ri_font == NULL) {
    100 		int cookie;
    101 
    102 		wsfont_init();
    103 
    104 		/* Want 8 pixel wide, don't care about aestethics */
    105 		if ((cookie = wsfont_find(NULL, 8, 0, 0)) < 0)
    106 			cookie = wsfont_find(NULL, 0, 0, 0);
    107 
    108 		if (cookie < 0) {
    109 			printf("rasops_init: font table is empty\n");
    110 			return (-1);
    111 		}
    112 
    113 		if (wsfont_lock(cookie, &ri->ri_font,
    114 		    WSFONT_LITTLE, WSFONT_LITTLE) < 0) {
    115 			printf("rasops_init: couldn't lock font\n");
    116 			return (-1);
    117 		}
    118 	}
    119 
    120 	/* This should never happen in reality... */
    121 #ifdef DEBUG
    122 	if ((int)ri->ri_bits & 3) {
    123 		printf("rasops_init: bits not aligned on 32-bit boundary\n");
    124 		return (-1);
    125 	}
    126 
    127 	if ((int)ri->ri_stride & 3) {
    128 		printf("rasops_init: stride not aligned on 32-bit boundary\n");
    129 		return (-1);
    130 	}
    131 
    132 	if (ri->ri_font->fontwidth > 32) {
    133 		printf("rasops_init: fontwidth > 32\n");
    134 		return (-1);
    135 	}
    136 #endif
    137 
    138 	/* Fix color palette. We need this for the cursor to work. */
    139 	rasops_cmap[255*3+0] = 0xff;
    140 	rasops_cmap[255*3+1] = 0xff;
    141 	rasops_cmap[255*3+2] = 0xff;
    142 
    143 	/* Don't care if the caller wants a hideously small console */
    144 	if (wantrows < 10)
    145 		wantrows = 5000;
    146 
    147 	if (wantcols < 20)
    148 		wantcols = 5000;
    149 
    150 	/* Now constrain what they get */
    151 	ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
    152 	ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
    153 
    154 	if (ri->ri_emuwidth > ri->ri_width)
    155 		ri->ri_emuwidth = ri->ri_width;
    156 
    157 	if (ri->ri_emuheight > ri->ri_height)
    158 		ri->ri_emuheight = ri->ri_height;
    159 
    160 	/* Reduce width until aligned on a 32-bit boundary */
    161 	while ((ri->ri_emuwidth*ri->ri_depth & 31) != 0)
    162 		ri->ri_emuwidth--;
    163 
    164 	ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
    165 	ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
    166 	ri->ri_emustride = ri->ri_emuwidth * ri->ri_depth >> 3;
    167 	ri->ri_delta = ri->ri_stride - ri->ri_emustride;
    168 	ri->ri_ccol = 0;
    169 	ri->ri_crow = 0;
    170 	ri->ri_pelbytes = ri->ri_depth >> 3;
    171 
    172 	ri->ri_xscale = (ri->ri_font->fontwidth * ri->ri_depth) >> 3;
    173 	ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
    174 	ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
    175 
    176 #ifdef DEBUG
    177 	if (ri->ri_delta & 3)
    178 		panic("rasops_init: delta isn't aligned on 32-bit boundary!");
    179 #endif
    180 	/* Clear the entire display */
    181 	if (clear)
    182 		bzero(ri->ri_bits, ri->ri_stride * ri->ri_height);
    183 
    184 	/* Now centre our window if needs be */
    185 	ri->ri_origbits = ri->ri_bits;
    186 
    187 	if (center) {
    188 		ri->ri_bits += ((ri->ri_stride - ri->ri_emustride) >> 1) & ~3;
    189 		ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
    190 		    ri->ri_stride;
    191 	}
    192 
    193 	/* Fill in defaults for operations set */
    194 	ri->ri_ops.mapchar = rasops_mapchar;
    195 	ri->ri_ops.copyrows = rasops_copyrows;
    196 	ri->ri_ops.copycols = rasops_copycols;
    197 	ri->ri_ops.cursor = rasops_cursor;
    198 
    199 	if (ri->ri_depth == 1 || ri->ri_forcemono)
    200 		ri->ri_ops.alloc_attr = rasops_alloc_mattr;
    201 	else
    202 		ri->ri_ops.alloc_attr = rasops_alloc_cattr;
    203 
    204 	switch (ri->ri_depth) {
    205 #ifdef RASOPS1
    206 	case 1:
    207 		rasops1_init(ri);
    208 		break;
    209 #endif
    210 
    211 #ifdef RASOPS8
    212 	case 8:
    213 		rasops8_init(ri);
    214 		break;
    215 #endif
    216 
    217 #if defined(RASOPS15) || defined(RASOPS16)
    218 	case 15:
    219 	case 16:
    220 		rasops15_init(ri);
    221 		break;
    222 #endif
    223 
    224 #ifdef RASOPS24
    225 	case 24:
    226 		rasops24_init(ri);
    227 		break;
    228 #endif
    229 
    230 #ifdef RASOPS24
    231 	case 32:
    232 		rasops32_init(ri);
    233 		break;
    234 #endif
    235 	default:
    236 		ri->ri_flg = 0;
    237 		return (-1);
    238 	}
    239 
    240 	ri->ri_flg = RASOPS_INITTED;
    241 	return (0);
    242 }
    243 
    244 
    245 /*
    246  * Map a character.
    247  */
    248 static int
    249 rasops_mapchar(cookie, c, cp)
    250 	void *cookie;
    251 	int c;
    252 	u_int *cp;
    253 {
    254 	struct rasops_info *ri;
    255 
    256 	ri = (struct rasops_info *)cookie;
    257 
    258 	if (c < ri->ri_font->firstchar) {
    259 		*cp = ' ';
    260 		return (0);
    261 	}
    262 
    263 	if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) {
    264 		*cp = ' ';
    265 		return (0);
    266 	}
    267 
    268 	*cp = c;
    269 	return (5);
    270 }
    271 
    272 
    273 /*
    274  * Allocate a color attribute.
    275  */
    276 static int
    277 rasops_alloc_cattr(cookie, fg, bg, flg, attr)
    278 	void *cookie;
    279 	int fg, bg, flg;
    280 	long *attr;
    281 {
    282 	int swap;
    283 
    284 #ifdef RASOPS_CLIPPING
    285 	fg &= 7;
    286 	bg &= 7;
    287 	flg &= 255;
    288 #endif
    289 	if (flg & WSATTR_BLINK)
    290 		return (EINVAL);
    291 
    292 	if (flg & WSATTR_REVERSE) {
    293 		swap = fg;
    294 		fg = bg;
    295 		bg = swap;
    296 	}
    297 
    298 	if (flg & WSATTR_HILIT)
    299 		fg += 8;
    300 
    301 	flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0);
    302 
    303 	if (rasops_isgray[fg])
    304 		flg |= 2;
    305 
    306 	if (rasops_isgray[bg])
    307 		flg |= 4;
    308 
    309 	*attr = (bg << 16) | (fg << 24) | flg;
    310 	return 0;
    311 }
    312 
    313 
    314 /*
    315  * Allocate a mono attribute.
    316  */
    317 static int
    318 rasops_alloc_mattr(cookie, fg, bg, flg, attr)
    319 	void *cookie;
    320 	int fg, bg, flg;
    321 	long *attr;
    322 {
    323 	int swap;
    324 
    325 #ifdef RASOPS_CLIPPING
    326 	flg &= 255;
    327 #endif
    328 	fg = fg ? 1 : 0;
    329 	bg = bg ? 1 : 0;
    330 
    331 	if (flg & WSATTR_BLINK)
    332 		return (EINVAL);
    333 
    334 	if (!(flg & WSATTR_REVERSE) ^ !(flg & WSATTR_HILIT)) {
    335 		swap = fg;
    336 		fg = bg;
    337 		bg = swap;
    338 	}
    339 
    340 	*attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
    341 	return 0;
    342 }
    343 
    344 
    345 /*
    346  * Copy rows.
    347  */
    348 static void
    349 rasops_copyrows(cookie, src, dst, num)
    350 	void *cookie;
    351 	int src, dst, num;
    352 {
    353 	struct rasops_info *ri;
    354 	int32_t *sp, *dp, *srp, *drp;
    355 	int n8, n1, cnt;
    356 
    357 	ri = (struct rasops_info *)cookie;
    358 
    359 #ifdef RASOPS_CLIPPING
    360 	if (dst == src)
    361 		return;
    362 
    363 	if (src < 0) {
    364 		num += src;
    365 		src = 0;
    366 	}
    367 
    368 	if ((src + num) > ri->ri_rows)
    369 		num = ri->ri_rows - src;
    370 
    371 	if (dst < 0) {
    372 		num += dst;
    373 		dst = 0;
    374 	}
    375 
    376 	if ((dst + num) > ri->ri_rows)
    377 		num = ri->ri_rows - dst;
    378 
    379 	if (num <= 0)
    380 		return;
    381 #endif
    382 
    383 	num *= ri->ri_font->fontheight;
    384 	n8 = ri->ri_emustride >> 5;
    385 	n1 = (ri->ri_emustride >> 2) & 7;
    386 
    387 	if (dst < src) {
    388 		sp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale);
    389 		dp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale);
    390 
    391 		while (num--) {
    392 			for (cnt = n8; cnt; cnt--) {
    393 				dp[0] = sp[0];
    394 				dp[1] = sp[1];
    395 				dp[2] = sp[2];
    396 				dp[3] = sp[3];
    397 				dp[4] = sp[4];
    398 				dp[5] = sp[5];
    399 				dp[6] = sp[6];
    400 				dp[7] = sp[7];
    401 				dp += 8;
    402 				sp += 8;
    403 			}
    404 
    405 			for (cnt = n1; cnt; cnt--)
    406 				*dp++ = *sp++;
    407 
    408 			DELTA(dp, ri->ri_delta, int32_t *);
    409 			DELTA(sp, ri->ri_delta, int32_t *);
    410 		}
    411 	} else {
    412 		src = ri->ri_font->fontheight * src + num - 1;
    413 		dst = ri->ri_font->fontheight * dst + num - 1;
    414 
    415 		srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride);
    416 		drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride);
    417 
    418 		while (num--) {
    419 			dp = drp;
    420 			sp = srp;
    421 			DELTA(srp, -ri->ri_stride, int32_t *);
    422 			DELTA(drp, -ri->ri_stride, int32_t *);
    423 
    424 			for (cnt = n8; cnt; cnt--) {
    425 				dp[0] = sp[0];
    426 				dp[1] = sp[1];
    427 				dp[2] = sp[2];
    428 				dp[3] = sp[3];
    429 				dp[4] = sp[4];
    430 				dp[5] = sp[5];
    431 				dp[6] = sp[6];
    432 				dp[7] = sp[7];
    433 				dp += 8;
    434 				sp += 8;
    435 			}
    436 
    437 			for (cnt = n1; cnt; cnt--)
    438 				*dp++ = *sp++;
    439 		}
    440 	}
    441 }
    442 
    443 
    444 /*
    445  * Copy columns. This is slow, and hard to optimize due to alignment,
    446  * and the fact that we have to copy both left->right and right->left.
    447  * We simply cop-out here and use bcopy(), since it handles all of
    448  * these cases anyway.
    449  */
    450 static void
    451 rasops_copycols(cookie, row, src, dst, num)
    452 	void *cookie;
    453 	int row, src, dst, num;
    454 {
    455 	struct rasops_info *ri;
    456 	u_char *sp, *dp;
    457 	int height;
    458 
    459 	ri = (struct rasops_info *)cookie;
    460 
    461 #ifdef RASOPS_CLIPPING
    462 	if (dst == src)
    463 		return;
    464 
    465 	if (row < 0 || row >= ri->ri_rows)
    466 		return;
    467 
    468 	if (src < 0) {
    469 		num += src;
    470 		src = 0;
    471 	}
    472 
    473 	if ((src + num) > ri->ri_cols)
    474 		num = ri->ri_cols - src;
    475 
    476 	if (dst < 0) {
    477 		num += dst;
    478 		dst = 0;
    479 	}
    480 
    481 	if ((dst + num) > ri->ri_cols)
    482 		num = ri->ri_cols - dst;
    483 
    484 	if (num <= 0)
    485 		return;
    486 #endif
    487 
    488 	num *= ri->ri_xscale;
    489 	row *= ri->ri_yscale;
    490 	height = ri->ri_font->fontheight;
    491 
    492 	sp = ri->ri_bits + row + src * ri->ri_xscale;
    493 	dp = ri->ri_bits + row + dst * ri->ri_xscale;
    494 
    495 	while (height--) {
    496 		bcopy(sp, dp, num);
    497 		dp += ri->ri_stride;
    498 		sp += ri->ri_stride;
    499 	}
    500 }
    501 
    502 
    503 /*
    504  * Turn cursor off/on.
    505  */
    506 static void
    507 rasops_cursor(cookie, on, row, col)
    508 	void *cookie;
    509 	int on, row, col;
    510 {
    511 	struct rasops_info *ri;
    512 
    513 	ri = (struct rasops_info *)cookie;
    514 
    515 	/* Turn old cursor off */
    516 	if (ri->ri_flg & RASOPS_CURSOR)
    517 #ifdef RASOPS_CLIPPING
    518 		if (!(ri->ri_flg & RASOPS_CURSOR_CLIPPED))
    519 #endif
    520 			ri->ri_do_cursor(ri);
    521 
    522 	/* Select new cursor */
    523 #ifdef RASOPS_CLIPPING
    524 	ri->ri_flg &= ~RASOPS_CURSOR_CLIPPED;
    525 
    526 	if (row < 0 || row >= ri->ri_rows)
    527 		ri->ri_flg |= RASOPS_CURSOR_CLIPPED;
    528 	else if (col < 0 || col >= ri->ri_cols)
    529 		ri->ri_flg |= RASOPS_CURSOR_CLIPPED;
    530 #endif
    531 	ri->ri_crow = row;
    532 	ri->ri_ccol = col;
    533 
    534 	if (on) {
    535 		ri->ri_flg |= RASOPS_CURSOR;
    536 #ifdef RASOPS_CLIPPING
    537 		if (!(ri->ri_flg & RASOPS_CURSOR_CLIPPED))
    538 #endif
    539 			ri->ri_do_cursor(ri);
    540 	} else
    541 		ri->ri_flg &= ~RASOPS_CURSOR;
    542 }
    543 
    544 
    545 #if (RASOPS15 + RASOPS16 + RASOPS32)
    546 /*
    547  * Make the device colormap
    548  */
    549 void
    550 rasops_init_devcmap(ri)
    551 	struct rasops_info *ri;
    552 {
    553 	int i, c;
    554 	u_char *p;
    555 
    556 	p = rasops_cmap;
    557 
    558 	for (i = 0; i < 16; i++) {
    559 		if (ri->ri_rnum <= 8)
    560 			c = (*p++ >> (8 - ri->ri_rnum)) << ri->ri_rpos;
    561 		else
    562 			c = (*p++ << (ri->ri_rnum - 8)) << ri->ri_rpos;
    563 
    564 		if (ri->ri_gnum <= 8)
    565 			c = (*p++ >> (8 - ri->ri_gnum)) << ri->ri_gpos;
    566 		else
    567 			c = (*p++ << (ri->ri_gnum - 8)) << ri->ri_gpos;
    568 
    569 		if (ri->ri_bnum <= 8)
    570 			c = (*p++ >> (8 - ri->ri_bnum)) << ri->ri_bpos;
    571 		else
    572 			c = (*p++ << (ri->ri_bnum - 8)) << ri->ri_bpos;
    573 
    574 		ri->ri_devcmap[i] = c;
    575 	}
    576 }
    577 #endif
    578 
    579 
    580 /*
    581  * Unpack a rasops attribute
    582  */
    583 void
    584 rasops_unpack_attr(attr, fg, bg, underline)
    585 	long attr;
    586 	int *fg, *bg, *underline;
    587 {
    588 
    589 	*fg = ((u_int)attr >> 24) & 15;
    590 	*bg = ((u_int)attr >> 16) & 15;
    591 	*underline = (u_int)attr & 1;
    592 }
    593