summaryrefslogtreecommitdiff
path: root/sys/dev/rasops
diff options
context:
space:
mode:
authorad <ad@NetBSD.org>1999-04-13 00:17:57 +0000
committerad <ad@NetBSD.org>1999-04-13 00:17:57 +0000
commit14d2ed835e41af413656a289daf32f2d7b3de646 (patch)
tree17bf7bd2c1728b83e8226716fd2c79e0175b3bc5 /sys/dev/rasops
parent246f73e1a0dfd6398fad5383325706e1c9cc7aa0 (diff)
Initial import of 'rasops', the new raster operations set for wscons/rcons.
Diffstat (limited to 'sys/dev/rasops')
-rw-r--r--sys/dev/rasops/Makefile7
-rw-r--r--sys/dev/rasops/README21
-rw-r--r--sys/dev/rasops/files.rasops11
-rw-r--r--sys/dev/rasops/rasops.c600
-rw-r--r--sys/dev/rasops/rasops.h123
-rw-r--r--sys/dev/rasops/rasops1.c642
-rw-r--r--sys/dev/rasops/rasops15.c646
-rw-r--r--sys/dev/rasops/rasops24.c449
-rw-r--r--sys/dev/rasops/rasops32.c324
-rw-r--r--sys/dev/rasops/rasops8.c634
10 files changed, 3457 insertions, 0 deletions
diff --git a/sys/dev/rasops/Makefile b/sys/dev/rasops/Makefile
new file mode 100644
index 00000000000..5a6279f723b
--- /dev/null
+++ b/sys/dev/rasops/Makefile
@@ -0,0 +1,7 @@
+# $NetBSD: Makefile,v 1.1 1999/04/13 00:17:57 ad Exp $
+
+INCSDIR= /usr/include/dev/rasops
+
+INCS= rasops.h
+
+.include <bsd.kinc.mk>
diff --git a/sys/dev/rasops/README b/sys/dev/rasops/README
new file mode 100644
index 00000000000..064478d7881
--- /dev/null
+++ b/sys/dev/rasops/README
@@ -0,0 +1,21 @@
+$NetBSD: README,v 1.1 1999/04/13 00:17:57 ad Exp $
+
+This directory contains 'rasops', a set of raster operations intended to
+replace the dev/rcons/raster stuff for both wscons and rcons. It yields
+significantly improved performance, supports multiple depths and color.
+
+The stamp_mutex used by some of the colordepths is not fully atomic. It's
+designed to stop stamp corruption in the event that text is printed at
+interrupt time. Even if it fails, >99% of the time text will be white on
+black, so it doesn't really matter. Going to splhigh for each character is
+a Bad Thing.
+
+Status of the various depths. Feel free to complete/test:
+
+ 8 tested, complete
+ 15/16 untested, complete (endainness issues exist?)
+ 32 untested, complete (endainness issues exist?)
+ 1 untested, incomplete for non 8,16 pel fonts
+ 24 untested, incomplete, assumes RGB order
+
+- Andy Doran <ad@NetBSD.org>, April 1999
diff --git a/sys/dev/rasops/files.rasops b/sys/dev/rasops/files.rasops
new file mode 100644
index 00000000000..8af0425ecc7
--- /dev/null
+++ b/sys/dev/rasops/files.rasops
@@ -0,0 +1,11 @@
+# $NetBSD: files.rasops,v 1.1 1999/04/13 00:17:58 ad Exp $
+
+file dev/rasops/rasops.c rasterconsole
+file dev/rasops/rasops1.c rasterconsole
+file dev/rasops/rasops8.c rasterconsole
+file dev/rasops/rasops15.c rasterconsole
+file dev/rasops/rasops24.c rasterconsole
+file dev/rasops/rasops32.c rasterconsole
+
+defopt opt_rasops.h RASOPS1 RASOPS8 RASOPS15 RASOPS16 RASOPS24 RASOPS32
+ RASOPS_CLIPPING
diff --git a/sys/dev/rasops/rasops.c b/sys/dev/rasops/rasops.c
new file mode 100644
index 00000000000..29002b0ea05
--- /dev/null
+++ b/sys/dev/rasops/rasops.c
@@ -0,0 +1,600 @@
+/* $NetBSD: rasops.c,v 1.1 1999/04/13 00:17:58 ad Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andy Doran <ad@NetBSD.org>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.1 1999/04/13 00:17:58 ad Exp $");
+
+#include "opt_rasops.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wscons/wsconsio.h>
+#include <dev/wsfont/wsfont.h>
+#include <dev/rasops/rasops.h>
+
+/* ANSI colormap (R,G,B). Upper 8 are high-intensity */
+u_char rasops_cmap[256*3] = {
+ 0x00, 0x00, 0x00, /* black */
+ 0x7f, 0x00, 0x00, /* red */
+ 0x00, 0x7f, 0x00, /* green */
+ 0x7f, 0x7f, 0x00, /* brown */
+ 0x00, 0x00, 0x7f, /* blue */
+ 0x7f, 0x00, 0x7f, /* magenta */
+ 0x00, 0x7f, 0x7f, /* cyan */
+ 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
+
+ 0x7f, 0x7f, 0x7f, /* black */
+ 0xff, 0x00, 0x00, /* red */
+ 0x00, 0xff, 0x00, /* green */
+ 0xff, 0xff, 0x00, /* brown */
+ 0x00, 0x00, 0xff, /* blue */
+ 0xff, 0x00, 0xff, /* magenta */
+ 0x00, 0xff, 0xff, /* cyan */
+ 0xff, 0xff, 0xff, /* white */
+};
+
+/* True if color is gray */
+u_char rasops_isgray[16] = {
+ 1, 0, 0, 0,
+ 0, 0, 0, 1,
+ 1, 0, 0, 0,
+ 0, 0, 0, 1
+};
+
+/* Common functions */
+static void rasops_copycols __P((void *, int, int, int, int));
+static void rasops_copyrows __P((void *, int, int, int));
+static int rasops_mapchar __P((void *, int, u_int *));
+static void rasops_cursor __P((void *, int, int, int));
+static int rasops_alloc_cattr __P((void *, int, int, int, long *));
+static int rasops_alloc_mattr __P((void *, int, int, int, long *));
+
+/* Per-depth initalization functions */
+void rasops1_init __P((struct rasops_info *));
+void rasops8_init __P((struct rasops_info *));
+void rasops15_init __P((struct rasops_info *));
+void rasops24_init __P((struct rasops_info *));
+void rasops32_init __P((struct rasops_info *));
+
+/*
+ * Initalize a 'rasops_info' descriptor.
+ */
+int
+rasops_init(ri, wantrows, wantcols, clear, center)
+ struct rasops_info *ri;
+ int wantrows, wantcols, clear, center;
+{
+
+ /* Select a font if the caller doesn't care */
+ if (ri->ri_font == NULL) {
+ int cookie;
+
+ wsfont_init();
+
+ /* Want 8 pixel wide, don't care about aestethics */
+ if ((cookie = wsfont_find(NULL, 8, 0, 0)) < 0)
+ cookie = wsfont_find(NULL, 0, 0, 0);
+
+ if (cookie < 0) {
+ printf("rasops_init: font table is empty\n");
+ return (-1);
+ }
+
+ if (wsfont_lock(cookie, &ri->ri_font,
+ WSFONT_LITTLE, WSFONT_LITTLE) < 0) {
+ printf("rasops_init: couldn't lock font\n");
+ return (-1);
+ }
+ }
+
+ /* This should never happen in reality... */
+#ifdef DEBUG
+ if ((int)ri->ri_bits & 3) {
+ printf("rasops_init: bits not aligned on 32-bit boundary\n");
+ return (-1);
+ }
+
+ if ((int)ri->ri_stride & 3) {
+ printf("rasops_init: stride not aligned on 32-bit boundary\n");
+ return (-1);
+ }
+
+ if (ri->ri_font->fontwidth > 32) {
+ printf("rasops_init: fontwidth > 32\n");
+ return (-1);
+ }
+#endif
+
+ /* Fix color palette. We need this for the cursor to work. */
+ rasops_cmap[255*3+0] = 0xff;
+ rasops_cmap[255*3+1] = 0xff;
+ rasops_cmap[255*3+2] = 0xff;
+
+ /* Don't care if the caller wants a hideously small console */
+ if (wantrows < 10)
+ wantrows = 5000;
+
+ if (wantcols < 20)
+ wantcols = 5000;
+
+ /* Now constrain what they get */
+ ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
+ ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
+
+ if (ri->ri_emuwidth > ri->ri_width)
+ ri->ri_emuwidth = ri->ri_width;
+
+ if (ri->ri_emuheight > ri->ri_height)
+ ri->ri_emuheight = ri->ri_height;
+
+ /* Reduce width until aligned on a 32-bit boundary */
+ while ((ri->ri_emuwidth*ri->ri_depth & 31) != 0)
+ ri->ri_emuwidth--;
+
+ ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
+ ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
+ ri->ri_emustride = ri->ri_emuwidth * ri->ri_depth >> 3;
+ ri->ri_delta = ri->ri_stride - ri->ri_emustride;
+ ri->ri_ccol = 0;
+ ri->ri_crow = 0;
+ ri->ri_pelbytes = ri->ri_depth >> 3;
+
+ ri->ri_xscale = (ri->ri_font->fontwidth * ri->ri_depth) >> 3;
+ ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
+ ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
+
+#ifdef DEBUG
+ if (ri->ri_delta & 3)
+ panic("rasops_init: delta isn't aligned on 32-bit boundary!");
+#endif
+ /* Clear the entire display */
+ if (clear)
+ bzero(ri->ri_bits, ri->ri_stride * ri->ri_height);
+
+ /* Now centre our window if needs be */
+ ri->ri_origbits = ri->ri_bits;
+
+ if (center) {
+ ri->ri_bits += ((ri->ri_stride - ri->ri_emustride) >> 1) & ~3;
+ ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
+ ri->ri_stride;
+ }
+
+ /* Fill in defaults for operations set */
+ ri->ri_ops.mapchar = rasops_mapchar;
+ ri->ri_ops.copyrows = rasops_copyrows;
+ ri->ri_ops.copycols = rasops_copycols;
+ ri->ri_ops.cursor = rasops_cursor;
+
+ if (ri->ri_depth == 1 || ri->ri_forcemono)
+ ri->ri_ops.alloc_attr = rasops_alloc_mattr;
+ else
+ ri->ri_ops.alloc_attr = rasops_alloc_cattr;
+
+ switch (ri->ri_depth) {
+#ifdef RASOPS1
+ case 1:
+ rasops1_init(ri);
+ break;
+#endif
+
+#ifdef RASOPS8
+ case 8:
+ rasops8_init(ri);
+ break;
+#endif
+
+#if defined(RASOPS15) || defined(RASOPS16)
+ case 15:
+ case 16:
+ rasops15_init(ri);
+ break;
+#endif
+
+#ifdef RASOPS24
+ case 24:
+ rasops24_init(ri);
+ break;
+#endif
+
+#ifdef RASOPS24
+ case 32:
+ rasops32_init(ri);
+ break;
+#endif
+ default:
+ ri->ri_flg = 0;
+ return (-1);
+ }
+
+ ri->ri_flg = RASOPS_INITTED;
+ return (0);
+}
+
+
+/*
+ * Map a character.
+ */
+static int
+rasops_mapchar(cookie, c, cp)
+ void *cookie;
+ int c;
+ u_int *cp;
+{
+ struct rasops_info *ri;
+
+ ri = (struct rasops_info *)cookie;
+
+ if (c < ri->ri_font->firstchar) {
+ *cp = ' ';
+ return (0);
+ }
+
+ if (c - ri->ri_font->firstchar >= ri->ri_font->numchars) {
+ *cp = ' ';
+ return (0);
+ }
+
+ *cp = c;
+ return (5);
+}
+
+
+/*
+ * Allocate a color attribute.
+ */
+static int
+rasops_alloc_cattr(cookie, fg, bg, flg, attr)
+ void *cookie;
+ int fg, bg, flg;
+ long *attr;
+{
+ int swap;
+
+#ifdef RASOPS_CLIPPING
+ fg &= 7;
+ bg &= 7;
+ flg &= 255;
+#endif
+ if (flg & WSATTR_BLINK)
+ return (EINVAL);
+
+ if (flg & WSATTR_REVERSE) {
+ swap = fg;
+ fg = bg;
+ bg = swap;
+ }
+
+ if (flg & WSATTR_HILIT)
+ fg += 8;
+
+ flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0);
+
+ if (rasops_isgray[fg])
+ flg |= 2;
+
+ if (rasops_isgray[bg])
+ flg |= 4;
+
+ *attr = (bg << 16) | (fg << 24) | flg;
+ return 0;
+}
+
+
+/*
+ * Allocate a mono attribute.
+ */
+static int
+rasops_alloc_mattr(cookie, fg, bg, flg, attr)
+ void *cookie;
+ int fg, bg, flg;
+ long *attr;
+{
+ int swap;
+
+#ifdef RASOPS_CLIPPING
+ flg &= 255;
+#endif
+ fg = fg ? 1 : 0;
+ bg = bg ? 1 : 0;
+
+ if (flg & WSATTR_BLINK)
+ return (EINVAL);
+
+ if (!(flg & WSATTR_REVERSE) ^ !(flg & WSATTR_HILIT)) {
+ swap = fg;
+ fg = bg;
+ bg = swap;
+ }
+
+ *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
+ return 0;
+}
+
+
+/*
+ * Copy rows.
+ */
+static void
+rasops_copyrows(cookie, src, dst, num)
+ void *cookie;
+ int src, dst, num;
+{
+ struct rasops_info *ri;
+ int32_t *sp, *dp, *srp, *drp;
+ int n8, n1, cnt;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (dst == src)
+ return;
+
+ if (src < 0) {
+ num += src;
+ src = 0;
+ }
+
+ if ((src + num) > ri->ri_rows)
+ num = ri->ri_rows - src;
+
+ if (dst < 0) {
+ num += dst;
+ dst = 0;
+ }
+
+ if ((dst + num) > ri->ri_rows)
+ num = ri->ri_rows - dst;
+
+ if (num <= 0)
+ return;
+#endif
+
+ num *= ri->ri_font->fontheight;
+ n8 = ri->ri_emustride >> 5;
+ n1 = (ri->ri_emustride >> 2) & 7;
+
+ if (dst < src) {
+ sp = (int32_t *)(ri->ri_bits + src * ri->ri_yscale);
+ dp = (int32_t *)(ri->ri_bits + dst * ri->ri_yscale);
+
+ while (num--) {
+ for (cnt = n8; cnt; cnt--) {
+ dp[0] = sp[0];
+ dp[1] = sp[1];
+ dp[2] = sp[2];
+ dp[3] = sp[3];
+ dp[4] = sp[4];
+ dp[5] = sp[5];
+ dp[6] = sp[6];
+ dp[7] = sp[7];
+ dp += 8;
+ sp += 8;
+ }
+
+ for (cnt = n1; cnt; cnt--)
+ *dp++ = *sp++;
+
+ DELTA(dp, ri->ri_delta, int32_t *);
+ DELTA(sp, ri->ri_delta, int32_t *);
+ }
+ } else {
+ src = ri->ri_font->fontheight * src + num - 1;
+ dst = ri->ri_font->fontheight * dst + num - 1;
+
+ srp = (int32_t *)(ri->ri_bits + src * ri->ri_stride);
+ drp = (int32_t *)(ri->ri_bits + dst * ri->ri_stride);
+
+ while (num--) {
+ dp = drp;
+ sp = srp;
+ DELTA(srp, -ri->ri_stride, int32_t *);
+ DELTA(drp, -ri->ri_stride, int32_t *);
+
+ for (cnt = n8; cnt; cnt--) {
+ dp[0] = sp[0];
+ dp[1] = sp[1];
+ dp[2] = sp[2];
+ dp[3] = sp[3];
+ dp[4] = sp[4];
+ dp[5] = sp[5];
+ dp[6] = sp[6];
+ dp[7] = sp[7];
+ dp += 8;
+ sp += 8;
+ }
+
+ for (cnt = n1; cnt; cnt--)
+ *dp++ = *sp++;
+ }
+ }
+}
+
+
+/*
+ * Copy columns. This is slow, and hard to optimize due to alignment,
+ * and the fact that we have to copy both left->right and right->left.
+ * We simply cop-out here and use bcopy(), since it handles all of
+ * these cases anyway.
+ */
+static void
+rasops_copycols(cookie, row, src, dst, num)
+ void *cookie;
+ int row, src, dst, num;
+{
+ struct rasops_info *ri;
+ u_char *sp, *dp;
+ int height;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (dst == src)
+ return;
+
+ if (row < 0 || row >= ri->ri_rows)
+ return;
+
+ if (src < 0) {
+ num += src;
+ src = 0;
+ }
+
+ if ((src + num) > ri->ri_cols)
+ num = ri->ri_cols - src;
+
+ if (dst < 0) {
+ num += dst;
+ dst = 0;
+ }
+
+ if ((dst + num) > ri->ri_cols)
+ num = ri->ri_cols - dst;
+
+ if (num <= 0)
+ return;
+#endif
+
+ num *= ri->ri_xscale;
+ row *= ri->ri_yscale;
+ height = ri->ri_font->fontheight;
+
+ sp = ri->ri_bits + row + src * ri->ri_xscale;
+ dp = ri->ri_bits + row + dst * ri->ri_xscale;
+
+ while (height--) {
+ bcopy(sp, dp, num);
+ dp += ri->ri_stride;
+ sp += ri->ri_stride;
+ }
+}
+
+
+/*
+ * Turn cursor off/on.
+ */
+static void
+rasops_cursor(cookie, on, row, col)
+ void *cookie;
+ int on, row, col;
+{
+ struct rasops_info *ri;
+
+ ri = (struct rasops_info *)cookie;
+
+ /* Turn old cursor off */
+ if (ri->ri_flg & RASOPS_CURSOR)
+#ifdef RASOPS_CLIPPING
+ if (!(ri->ri_flg & RASOPS_CURSOR_CLIPPED))
+#endif
+ ri->ri_do_cursor(ri);
+
+ /* Select new cursor */
+#ifdef RASOPS_CLIPPING
+ ri->ri_flg &= ~RASOPS_CURSOR_CLIPPED;
+
+ if (row < 0 || row >= ri->ri_rows)
+ ri->ri_flg |= RASOPS_CURSOR_CLIPPED;
+ else if (col < 0 || col >= ri->ri_cols)
+ ri->ri_flg |= RASOPS_CURSOR_CLIPPED;
+#endif
+ ri->ri_crow = row;
+ ri->ri_ccol = col;
+
+ if (on) {
+ ri->ri_flg |= RASOPS_CURSOR;
+#ifdef RASOPS_CLIPPING
+ if (!(ri->ri_flg & RASOPS_CURSOR_CLIPPED))
+#endif
+ ri->ri_do_cursor(ri);
+ } else
+ ri->ri_flg &= ~RASOPS_CURSOR;
+}
+
+
+#if (RASOPS15 + RASOPS16 + RASOPS32)
+/*
+ * Make the device colormap
+ */
+void
+rasops_init_devcmap(ri)
+ struct rasops_info *ri;
+{
+ int i, c;
+ u_char *p;
+
+ p = rasops_cmap;
+
+ for (i = 0; i < 16; i++) {
+ if (ri->ri_rnum <= 8)
+ c = (*p++ >> (8 - ri->ri_rnum)) << ri->ri_rpos;
+ else
+ c = (*p++ << (ri->ri_rnum - 8)) << ri->ri_rpos;
+
+ if (ri->ri_gnum <= 8)
+ c = (*p++ >> (8 - ri->ri_gnum)) << ri->ri_gpos;
+ else
+ c = (*p++ << (ri->ri_gnum - 8)) << ri->ri_gpos;
+
+ if (ri->ri_bnum <= 8)
+ c = (*p++ >> (8 - ri->ri_bnum)) << ri->ri_bpos;
+ else
+ c = (*p++ << (ri->ri_bnum - 8)) << ri->ri_bpos;
+
+ ri->ri_devcmap[i] = c;
+ }
+}
+#endif
+
+
+/*
+ * Unpack a rasops attribute
+ */
+void
+rasops_unpack_attr(attr, fg, bg, underline)
+ long attr;
+ int *fg, *bg, *underline;
+{
+
+ *fg = ((u_int)attr >> 24) & 15;
+ *bg = ((u_int)attr >> 16) & 15;
+ *underline = (u_int)attr & 1;
+}
diff --git a/sys/dev/rasops/rasops.h b/sys/dev/rasops/rasops.h
new file mode 100644
index 00000000000..830c7e077ea
--- /dev/null
+++ b/sys/dev/rasops/rasops.h
@@ -0,0 +1,123 @@
+/* $NetBSD: rasops.h,v 1.1 1999/04/13 00:17:59 ad Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andy Doran <ad@NetBSD.org>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _RASOPS_H_
+#define _RASOPS_H_ 1
+
+/* Avoid dragging in dev/wscons/wsconsio.h */
+struct wsdisplay_font;
+
+struct rasops_info {
+ /* These must be filled in by the caller */
+ int ri_depth; /* depth in bits */
+ u_char *ri_bits; /* ptr to bits */
+ int ri_width; /* width (pels) */
+ int ri_height; /* height (pels) */
+ int ri_stride; /* stride in bytes */
+
+ /* These can optionally be left NULL */
+ struct wsdisplay_font *ri_font;/* font to use */
+ void *ri_priv; /* driver private data */
+ u_char ri_forcemono; /* force monochrome operation */
+ u_char __pad0;
+
+ /*
+ * These are optional and will default if zero. Meaningless
+ * on depths other than 15, 16, 24 and 32 bits per pel. On
+ * 24 bit displays, ri_{r,g,b}num must be 8.
+ */
+ u_char ri_rnum; /* number of bits for red */
+ u_char ri_gnum; /* number of bits for green */
+ u_char ri_bnum; /* number of bits for blue */
+ u_char ri_rpos; /* which bit red starts at */
+ u_char ri_gpos; /* which bit green starts at */
+ u_char ri_bpos; /* which bit blue starts at */
+
+ /* These are filled in by rasops_init() */
+ int ri_emuwidth; /* width we actually care about */
+ int ri_emuheight; /* height we actually care about */
+ int ri_emustride; /* bytes per row we actually care about */
+ int ri_rows; /* number of rows (characters, not pels) */
+ int ri_cols; /* number of columns (characters, not pels) */
+ int ri_delta; /* row delta in bytes */
+ int ri_flg; /* flags */
+ int ri_crow; /* cursor row */
+ int ri_ccol; /* cursor column */
+ int ri_pelbytes; /* bytes per pel */
+ int ri_fontscale; /* fontheight * fontstride */
+ int ri_xscale; /* fontwidth * pelbytes */
+ int ri_yscale; /* fontheight * stride */
+ u_char *ri_origbits; /* where screen bits actually start */
+
+ /* For 15, 16, 24, 32 bits */
+ int32_t ri_devcmap[16]; /* device colormap (WSCOL_*) */
+
+ /* The emulops you need to use */
+ struct wsdisplay_emulops ri_ops;
+
+ /* Callbacks so we can share some code */
+ void (*ri_do_cursor)(struct rasops_info *);
+};
+
+#define RASOPS_CURSOR (0x01) /* cursor is on */
+#define RASOPS_INITTED (0x02) /* struct is initialized */
+#define RASOPS_CURSOR_CLIPPED (0x04) /* cursor is clipped */
+
+#define DELTA(p, d, cast) ((p) = (cast)((caddr_t)(p) + (d)))
+
+/*
+ * rasops_init().
+ *
+ * Integer parameters are: number of rows we'd like, number of columns we'd
+ * like, whether we should clear the display and whether we should center
+ * the output. Remember that what you'd like is always not what you get.
+ *
+ * In terms of optimization, fonts that are a multiple of 8 pixels wide
+ * work the best: this is important, and will cost you if you don't use 'em.
+ */
+
+/* rasops.c */
+int rasops_init __P((struct rasops_info *, int, int, int, int));
+void rasops_unpack_attr __P((long, int *, int *, int *));
+
+/* This should not be called outside rasops */
+void rasops_init_devcmap __P((struct rasops_info *));
+
+extern u_char rasops_isgray[16];
+extern u_char rasops_cmap[256*3];
+
+#endif /* _RASOPS_H_ */
diff --git a/sys/dev/rasops/rasops1.c b/sys/dev/rasops/rasops1.c
new file mode 100644
index 00000000000..7b076749d91
--- /dev/null
+++ b/sys/dev/rasops/rasops1.c
@@ -0,0 +1,642 @@
+/* $NetBSD: rasops1.c,v 1.1 1999/04/13 00:17:59 ad Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andy Doran <ad@NetBSD.org>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "opt_rasops.h"
+#ifdef RASOPS1
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: rasops1.c,v 1.1 1999/04/13 00:17:59 ad Exp $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <machine/endian.h>
+
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/rasops/rasops.h>
+
+static void rasops1_putchar __P((void *, int, int col, u_int, long));
+static void rasops1_putchar8 __P((void *, int, int col, u_int, long));
+static void rasops1_putchar16 __P((void *, int, int col, u_int, long));
+static void rasops1_copycols __P((void *, int, int, int, int));
+static void rasops1_erasecols __P((void *, int, int, int));
+static void rasops1_erasecols8 __P((void *, int, int, int));
+static void rasops1_eraserows __P((void *, int, int));
+static int32_t rasops1_fg_color __P((long));
+static int32_t rasops1_bg_color __P((long));
+static void rasops1_do_cursor __P((struct rasops_info *));
+static void rasops1_do_cursor8 __P((struct rasops_info *));
+
+void rasops1_init __P((struct rasops_info *ri));
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+static u_int32_t rightmask[32] = {
+#else
+static u_int32_t leftmask[32] = {
+#endif
+ 0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
+ 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
+ 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
+ 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
+ 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
+ 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
+ 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
+ 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe,
+};
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+static u_int32_t leftmask[32] = {
+#else
+static u_int32_t rightmask[32] = {
+#endif
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007,
+ 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
+ 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
+ 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
+ 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
+ 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
+ 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
+ 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+};
+
+
+/*
+ * Initalize rasops_info struct for this colordepth.
+ */
+void
+rasops1_init(ri)
+ struct rasops_info *ri;
+{
+
+ switch (ri->ri_font->fontwidth) {
+ case 8:
+ ri->ri_ops.putchar = rasops1_putchar8;
+ break;
+ case 16:
+ ri->ri_ops.putchar = rasops1_putchar16;
+ break;
+ default:
+ /*
+ * XXX we don't support anything other than 8 and 16 pel
+ * wide fonts yet. rasops1_copycols needs to be finished, the
+ * other routines will need to be checked.
+ */
+ panic("rasops1_init: not completed - see this location in src for details");
+ ri->ri_ops.putchar = rasops1_putchar;
+ break;
+ }
+
+ if (ri->ri_font->fontwidth & 7) {
+ ri->ri_ops.erasecols = rasops1_erasecols;
+ ri->ri_ops.copycols = rasops1_copycols;
+ ri->ri_do_cursor = rasops1_do_cursor;
+ } else {
+ ri->ri_ops.erasecols = rasops1_erasecols8;
+ /* use default copycols */
+ ri->ri_do_cursor = rasops1_do_cursor8;
+ }
+
+ ri->ri_ops.eraserows = rasops1_eraserows;
+}
+
+
+/*
+ * Get foreground color from attribute and copy across all 4 bytes
+ * in a int32_t.
+ */
+static __inline__ int32_t
+rasops1_fg_color(long attr)
+{
+
+ return (attr & 0x0f000000) ? 0xffffffff : 0;
+}
+
+
+/*
+ * Get background color from attribute and copy across all 4 bytes
+ * in a int32_t.
+ */
+static __inline__ int32_t
+rasops1_bg_color(long attr)
+{
+
+ return (attr & 0x000f0000) ? 0xffffffff : 0;
+}
+
+
+/*
+ * Paint a single character. This is the generic version.
+ */
+static void
+rasops1_putchar(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+
+ /* XXX i need implemention */
+}
+
+
+/*
+ * Paint a single character. This is for 8-pixel wide fonts.
+ */
+static void
+rasops1_putchar8(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ int height, fs, rs, bg, fg;
+ struct rasops_info *ri;
+ u_char *fr, *rp;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (row < 0 || row >= ri->ri_rows)
+ return;
+
+ if (col < 0 || col >= ri->ri_cols)
+ return;
+#endif
+
+ rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+ height = ri->ri_font->fontheight;
+ rs = ri->ri_stride;
+
+ bg = (attr & 0x000f0000) ? 0xff : 0;
+ fg = (attr & 0x0f000000) ? 0xff : 0;
+
+ /* If fg and bg match this becomes a space character */
+ if (fg == bg || uc == ' ') {
+ while (height--) {
+ *rp = bg;
+ rp += rs;
+ }
+ } else {
+ uc -= ri->ri_font->firstchar;
+ fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
+ fs = ri->ri_font->stride;
+
+ /* NOT fontbits if bg is white */
+ if (bg) {
+ while (height--) {
+ *rp = ~*fr;
+ fr += fs;
+ rp += rs;
+ }
+ } else {
+ while (height--) {
+ *rp = *fr;
+ fr += fs;
+ rp += rs;
+ }
+ }
+ }
+
+ /* Do underline */
+ if (attr & 1)
+ rp[-(ri->ri_stride << 1)] = fg;
+}
+
+
+/*
+ * Paint a single character. This is for 16-pixel wide fonts.
+ */
+static void
+rasops1_putchar16(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ int height, fs, rs, bg, fg;
+ struct rasops_info *ri;
+ u_char *fr, *rp;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (row < 0 || row >= ri->ri_rows)
+ return;
+
+ if (col < 0 || col >= ri->ri_cols)
+ return;
+#endif
+
+ rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+ height = ri->ri_font->fontheight;
+ rs = ri->ri_stride;
+
+ bg = (attr & 0x000f0000) ? 0xffff : 0;
+ fg = (attr & 0x0f000000) ? 0xffff : 0;
+
+ /* If fg and bg match this becomes a space character */
+ if (fg == bg || uc == ' ') {
+ while (height--) {
+ *(int16_t *)rp = bg;
+ rp += rs;
+ }
+ } else {
+ uc -= ri->ri_font->firstchar;
+ fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
+ fs = ri->ri_font->stride;
+
+ /* NOT fontbits if bg is white */
+ if (bg) {
+ while (height--) {
+ rp[0] = ~fr[0];
+ rp[1] = ~fr[1];
+ fr += fs;
+ rp += rs;
+ }
+ } else {
+ while (height--) {
+ rp[0] = fr[0];
+ rp[1] = fr[1];
+ fr += fs;
+ rp += rs;
+ }
+ }
+ }
+
+ /* Do underline */
+ if (attr & 1)
+ *(int16_t *)(rp - (ri->ri_stride << 1)) = fg;
+}
+
+
+/*
+ * Erase columns.
+ */
+static void
+rasops1_erasecols(cookie, row, col, num, attr)
+ void *cookie;
+ int row, num;
+ long attr;
+{
+ int32_t *dp, *rp, lmask, rmask, lclr, rclr, clr;
+ struct rasops_info *ri;
+ int nint, height, cnt;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (row < 0 || row > ri->ri_rows)
+ return;
+
+ if (col < 0) {
+ num += col;
+ col = 0;
+ }
+
+ if ((col + num) > ri->ri_cols)
+ num = ri->ri_cols - col;
+
+ if (num <= 0)
+ return;
+#endif
+ col *= ri->ri_fontwidth;
+ num *= ri->ri_fontwidth;
+
+ /*
+ * lmask: mask for leftmost int32
+ * rmask: mask for rightmost int32
+ * nint: number of full int32s
+ */
+ lmask = leftmask[col & 31];
+ rmask = rightmask[(col + num) & 31];
+ nint = ((col + num) & ~31) - ((col + 31) & ~31) >> 5;
+
+ /* Merge both masks if the span is encapsulated within one int32 */
+ if (col & ~31 == (col + num) & ~31) {
+ lmask &= rmask;
+ rmask = 0;
+ }
+
+ clr = rasops1_bg_color(attr);
+ lclr = clr & lmask;
+ rclr = clr & rmask;
+ lmask = ~lmask;
+ rmask = ~rmask;
+ height = ri->ri_fontheight;
+ rp = ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3);
+
+ while (height--) {
+ dp = rp;
+ DELTA(rp, ri->ri_stride, int32_t *);
+
+ if (lmask != 0xffffffffU)
+ *dp++ = (*dp & lmask) | lclr;
+
+ for (cnt = nint; cnt; cnt--)
+ *dp++ = clr;
+
+ if (rmask != 0xffffffffU)
+ *dp = (*dp & rmask) | rclr;
+ }
+}
+
+
+/*
+ * Erase columns for fonts that are a multiple of 8 pels in width.
+ */
+static void
+rasops1_erasecols8(cookie, row, col, num, attr)
+ void *cookie;
+ int row, col, num;
+ long attr;
+{
+ struct rasops_info *ri;
+ int32_t *dst;
+ u_char *dstb, *rp;
+ int clr, height, cnt, slop1, slop2;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (row < 0 || row >= ri->ri_rows)
+ return;
+
+ if (col < 0) {
+ num += col;
+ col = 0;
+ }
+
+ if ((col + num) > ri->ri_cols)
+ num = ri->ri_cols - col;
+
+ if (num <= 0)
+ return;
+#endif
+
+ num = num * ri->ri_xscale;
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ clr = rasops1_bg_color(attr);
+ height = ri->ri_font->fontheight;
+
+ slop1 = (int)rp & 3;
+ slop2 = (num - slop1) & 3;
+ num = (num - slop1 - slop2) >> 2;
+
+ while (height--) {
+ dstb = rp;
+ rp += ri->ri_stride;
+
+ /* Align span to 4 bytes */
+ for (cnt = slop1; cnt; cnt--)
+ *dstb++ = (u_char)clr;
+
+ dst = (int32_t *)dstb;
+
+ /* Write 4 bytes per loop */
+ for (cnt = num; cnt; cnt--)
+ *dst++ = clr;
+
+ /* Write unaligned trailing slop */
+ if (slop2 == 0)
+ continue;
+
+ dstb = (u_char *)dst;
+
+ for (cnt = slop2; cnt; cnt--)
+ *dstb++ = (u_char)clr;
+ }
+}
+
+
+/*
+ * Actually paint the cursor.
+ */
+static void
+rasops1_do_cursor(ri)
+ struct rasops_info *ri;
+{
+ int32_t *dp, *rp, lmask, rmask;
+ int height, row, col;
+
+ row = ri->ri_crow;
+ col = ri->ri_ccol * ri->ri_fontwidth;
+
+ /*
+ * lmask: mask for leftmost int32
+ * rmask: mask for rightmost int32
+ */
+ lmask = leftmask[col & 31];
+ rmask = rightmask[(col + ri->ri_fontwidth) & 31];
+
+ /* Merge both masks if the span is encapsulated within one int32 */
+ if (col & ~31 == (col + ri->ri_fontwidth) & ~31) {
+ lmask &= rmask;
+ rmask = 0;
+ }
+
+ lmask = ~lmask;
+ rmask = ~rmask;
+ height = ri->ri_fontheight;
+ rp = ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3);
+
+ while (height--) {
+ dp = rp;
+ DELTA(rp, ri->ri_stride, int32_t *);
+
+ *dp++ = ((*dp & lmask) ^ lmask) | (*dp & ~lmask);
+
+ if (rmask != 0xffffffffU)
+ *dp = ((*dp & rmask) ^ rmask) | (*dp & ~rmask);
+ }
+}
+
+
+/*
+ * Paint cursors that are a multiple of 8 pels in size.
+ */
+static void
+rasops1_do_cursor8(ri)
+ struct rasops_info *ri;
+{
+ int width, height, cnt;
+ u_char *dp, *rp;
+
+ height = ri->ri_fontheight;
+ width = ri->ri_fontwidth >> 3;
+ rp = ri->ri_bits + ri->ri_crow * ri->ri_yscale +
+ ri->ri_ccol * ri->ri_xscale;
+
+ while (height--) {
+ dp = rp;
+ rp += ri->ri_stride;
+
+ for (cnt = width; cnt; cnt--)
+ *dp++ ^= 0xff;
+ }
+}
+
+
+/*
+ * Erase rows.
+ */
+static void
+rasops1_eraserows(cookie, row, num, attr)
+ void *cookie;
+ int row, num;
+ long attr;
+{
+ struct rasops_info *ri;
+ int32_t *dp, clr;
+ int n8, n1, cnt;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (row < 0) {
+ num += row;
+ row = 0;
+ }
+
+ if ((row + num) > ri->ri_rows)
+ num = ri->ri_rows - row;
+
+ if (num <= 0)
+ return;
+#endif
+
+ num *= ri->ri_font->fontheight;
+ dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
+ clr = rasops1_bg_color(attr);
+
+ n8 = ri->ri_emustride >> 5;
+ n1 = (ri->ri_emustride >> 2) & 7;
+
+ while (num--) {
+ for (cnt = n8; cnt; cnt--) {
+ dp[0] = clr;
+ dp[1] = clr;
+ dp[2] = clr;
+ dp[3] = clr;
+ dp[4] = clr;
+ dp[5] = clr;
+ dp[6] = clr;
+ dp[7] = clr;
+ dp += 8;
+ }
+
+ for (cnt = n1; cnt; cnt--)
+ *dp++ = clr;
+
+ DELTA(dp, ri->ri_delta, int32_t *);
+ }
+}
+
+
+/*
+ * Copy columns. This is slow. Ick! You'd better use a font with
+ * a width that's a multiple of 8 pels, otherwise this is used...
+ */
+static void
+rasops1_copycols(cookie, row, src, src)
+ void *cookie;
+ int row, src, dst;
+{
+#ifdef notyet
+ struct rasops_info *ri;
+ int32_t *dp, *drp, *sp, *srp, lmask, rmask;
+ int nint, height, cnt;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (row < 0 || row >= ri->ri_rows)
+ return;
+
+ if (col < 0) {
+ num += col;
+ col = 0;
+ }
+
+ if ((col + num) > ri->ri_cols)
+ num = ri->ri_cols - col;
+
+ if (num <= 0)
+ return;
+#endif
+ src *= ri->ri_fontwidth;
+ dst *= ri->ri_fontwidth;
+ num *= ri->ri_fontwidth;
+
+ /*
+ * lmask: mask for leftmost int32
+ * rmask: mask for rightmost int32
+ * nint: number of full int32s
+ */
+ lmask = leftmask[col & 31];
+ rmask = rightmask[(col + num) & 31];
+ nint = ((col + num) & ~31) - ((col + 31) & ~31) >> 5;
+
+ /* Merge both masks if the span is encapsulated within one int32 */
+ if (col & ~31 == (col + num) & ~31) {
+ lmask &= rmask;
+ rmask = 0;
+ }
+
+ lmask = ~lmask;
+ rmask = ~rmask;
+ height = ri->ri_fontheight;
+ drp = ri->ri_bits + row*ri->ri_yscale + ((dst >> 3) & ~3);
+ srp = ri->ri_bits + row*ri->ri_yscale + ((src >> 3) & ~3);
+
+ while (height--) {
+ dp = rp;
+ DELTA(rp, ri->ri_stride, int32_t *);
+
+ if (lmask != 0xffffffffU)
+ *dp++ = (*dp & lmask) | lclr;
+
+ for (cnt = nint; cnt; cnt--)
+ *dp++ = clr;
+
+ if (rmask != 0xffffffffU)
+ *dp = (*dp & rmask) | rclr;
+ }
+#endif
+}
+
+#endif /* RASOPS1 */
diff --git a/sys/dev/rasops/rasops15.c b/sys/dev/rasops/rasops15.c
new file mode 100644
index 00000000000..c495e7e588b
--- /dev/null
+++ b/sys/dev/rasops/rasops15.c
@@ -0,0 +1,646 @@
+/* $NetBSD: rasops15.c,v 1.1 1999/04/13 00:18:00 ad Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andy Doran <ad@NetBSD.org>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "opt_rasops.h"
+#ifdef RASOPS15
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: rasops15.c,v 1.1 1999/04/13 00:18:00 ad Exp $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wscons/wsconsio.h>
+#include <dev/rasops/rasops.h>
+
+static void rasops15_putchar __P((void *, int, int, u_int, long attr));
+static void rasops15_putchar8 __P((void *, int, int, u_int, long attr));
+static void rasops15_putchar12 __P((void *, int, int, u_int, long attr));
+static void rasops15_putchar16 __P((void *, int, int, u_int, long attr));
+static void rasops15_erasecols __P((void *, int, int, int, long));
+static void rasops15_eraserows __P((void *, int, int, long));
+static void rasops15_makestamp __P((struct rasops_info *, long));
+static int32_t rasops15_bg_color __P((struct rasops_info *, long));
+static void rasops15_do_cursor __P((struct rasops_info *));
+
+void rasops15_init __P((struct rasops_info *ri));
+
+/*
+ * (2x2)x1 stamp for optimized character blitting
+ */
+static int32_t stamp[32];
+static long stamp_attr;
+static int stamp_mutex; /* XXX see note in readme */
+
+/*
+ * XXX this confuses the hell out of gcc2 (not egcs) which always insists
+ * that the shift count is negative.
+ *
+ * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
+ * destination int32_t[0] = STAMP_READ(offset)
+ * destination int32_t[1] = STAMP_READ(offset + 4)
+ */
+#define STAMP_SHIFT(fb,n) ((n*4-3) >= 0 ? (fb)>>(n*4-3):(fb)<<-(n*4-3))
+#define STAMP_MASK (15 << 3)
+#define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o)))
+
+
+/*
+ * Initalize rasops_info struct for this colordepth.
+ */
+void
+rasops15_init(ri)
+ struct rasops_info *ri;
+{
+
+ switch (ri->ri_font->fontwidth) {
+ case 8:
+ ri->ri_ops.putchar = rasops15_putchar8;
+ break;
+
+ case 12:
+ ri->ri_ops.putchar = rasops15_putchar12;
+ break;
+
+ case 16:
+ ri->ri_ops.putchar = rasops15_putchar16;
+ break;
+
+ default:
+ ri->ri_ops.putchar = rasops15_putchar;
+ break;
+ }
+
+ /* Select defaults for color masks if none selected */
+ if (ri->ri_rnum == 0) {
+ ri->ri_rnum = 5;
+ ri->ri_rpos = 0;
+ ri->ri_gnum = 5 + (ri->ri_depth == 16);
+ ri->ri_gpos = 5;
+ ri->ri_bnum = 5;
+ ri->ri_bpos = 10 + (ri->ri_depth == 16);
+ }
+
+ ri->ri_ops.erasecols = rasops15_erasecols;
+ ri->ri_ops.eraserows = rasops15_eraserows;
+ ri->ri_do_cursor = rasops15_do_cursor;
+ rasops_init_devcmap(ri);
+}
+
+
+/*
+ * Get background color from attribute and copy across all 4 bytes
+ * in a int32_t.
+ */
+static __inline__ int32_t
+rasops15_bg_color(ri, attr)
+ struct rasops_info *ri;
+ long attr;
+{
+ int32_t bg;
+
+ bg = ri->ri_devcmap[((u_int)attr >> 16) & 15];
+ return bg | (bg << 16);
+}
+
+
+/*
+ * Actually turn the cursor on or off. This does the dirty work for
+ * rasops_cursor().
+ */
+static void
+rasops15_do_cursor(ri)
+ struct rasops_info *ri;
+{
+ u_char *rp, *dp;
+ int full1, height, cnt, slop1, slop2, row, col;
+ int32_t planemask;
+
+ row = ri->ri_crow;
+ col = ri->ri_ccol;
+
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ height = ri->ri_font->fontheight;
+
+ slop1 = (int)rp & 2;
+ slop2 = (ri->ri_xscale - slop1) & 2;
+ full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
+ planemask = ri->ri_devcmap[15] | (ri->ri_devcmap[15] << 16);
+
+ while (height--) {
+ dp = rp;
+ rp += ri->ri_stride;
+
+ if (slop1) {
+ *(int16_t *)dp ^= (int16_t)planemask;
+ dp += 2;
+ }
+
+ for (cnt = full1; cnt; cnt--) {
+ *(int32_t *)dp ^= planemask;
+ dp += 4;
+ }
+
+ if (slop2)
+ *(int16_t *)dp ^= (int16_t)planemask;
+ }
+}
+
+
+/*
+ * Erase columns.
+ */
+static void
+rasops15_erasecols(cookie, row, col, num, attr)
+ void *cookie;
+ int row, num;
+ long attr;
+{
+ int n8, clr, height, cnt, slop1, slop2;
+ struct rasops_info *ri;
+ int32_t *dp;
+ u_char *rp;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ /* Catches 'row < 0' case too */
+ if ((unsigned)row >= (unsigned)ri->ri_rows)
+ return;
+
+ if (col < 0) {
+ num += col;
+ col = 0;
+ }
+
+ if ((col + num) > ri->ri_cols)
+ num = ri->ri_cols - col;
+
+ if (num <= 0)
+ return;
+#endif
+
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ num *= ri->ri_xscale;
+ clr = rasops15_bg_color(ri, attr);
+ height = ri->ri_font->fontheight;
+
+ slop1 = (int)rp & 2;
+ slop2 = (num - slop1) & 2;
+ num = num - slop1 - slop2;
+ n8 = num >> 5;
+ num = (num >> 2) & 7;
+
+ while (height--) {
+ dp = (u_int32_t *)rp;
+ rp += ri->ri_stride;
+
+ /* Align span to 4 bytes */
+ if (slop1) {
+ *(int16_t *)dp = (int16_t)clr;
+ DELTA(dp, 2, int32_t *);
+ }
+
+ /* Write 32 bytes per loop */
+ for (cnt = n8; cnt; cnt--) {
+ dp[0] = clr;
+ dp[1] = clr;
+ dp[2] = clr;
+ dp[3] = clr;
+ dp[4] = clr;
+ dp[5] = clr;
+ dp[6] = clr;
+ dp[7] = clr;
+ dp += 8;
+ }
+
+ /* Write 4 bytes per loop */
+ for (cnt = num; cnt; cnt--)
+ *dp++ = clr;
+
+ /* Write unaligned trailing slop */
+ if (slop2)
+ *(int16_t *)dp = (int16_t)clr;
+ }
+}
+
+
+/*
+ * Paint a single character.
+ */
+static void
+rasops15_putchar(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ struct rasops_info *ri;
+ int fb, width, height, cnt, clr[2];
+ u_char *dp, *rp, *fr;
+
+ if (uc == (u_int)-1) {
+ rasops15_erasecols(cookie, row, col, 1, attr);
+ return;
+ }
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ /* Catches 'row < 0' case too */
+ if ((unsigned)row >= (unsigned)ri->ri_rows)
+ return;
+
+ if ((unsigned)col >= (unsigned)ri->ri_cols)
+ return;
+#endif
+
+ uc -= ri->ri_font->firstchar;
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
+
+ height = ri->ri_font->fontheight;
+ width = ri->ri_font->fontwidth;
+
+ clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 15];
+ clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 15];
+
+ while (height--) {
+ dp = rp;
+ fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
+ fr += ri->ri_font->stride;
+ rp += ri->ri_stride;
+
+ for (cnt = width; cnt; cnt--) {
+ *(int16_t *)dp = (int16_t)clr[(fb >> 31) & 1];
+ fb <<= 1;
+ dp += 2;
+ }
+ }
+}
+
+
+/*
+ * Recompute the (2x2)x1 blitting stamp.
+ */
+static void
+rasops15_makestamp(ri, attr)
+ struct rasops_info *ri;
+ long attr;
+{
+ int32_t fg, bg;
+ int i;
+
+ fg = ri->ri_devcmap[((u_int)attr >> 24) & 15];
+ bg = ri->ri_devcmap[((u_int)attr >> 16) & 15];
+ stamp_attr = attr;
+
+ for (i = 0; i < 16; i++) {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ stamp[i << 1] = (i & 8 ? fg : bg);
+ stamp[i << 1] |= ((i & 4 ? fg : bg) << 16);
+ stamp[(i << 1) + 1] = (i & 2 ? fg : bg);
+ stamp[(i << 1) + 1] |= ((i & 1 ? fg : bg) << 16);
+#else
+ stamp[i << 1] = (i & 1 ? fg : bg);
+ stamp[i << 1] |= ((i & 2 ? fg : bg) << 16);
+ stamp[(i << 1) + 1] = (i & 4 ? fg : bg);
+ stamp[(i << 1) + 1] |= ((i & 8 ? fg : bg) << 16);
+#endif
+ }
+}
+
+
+/*
+ * Paint a single character. This is for 8-pixel wide fonts.
+ */
+static void
+rasops15_putchar8(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ struct rasops_info *ri;
+ int height, so, fs;
+ int32_t *rp;
+ u_char *fr;
+
+ /* Can't risk remaking the stamp if it's already in use */
+ if (stamp_mutex++) {
+ stamp_mutex--;
+ rasops15_putchar(cookie, row, col, uc, attr);
+ return;
+ }
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if ((unsigned)row >= (unsigned)ri->ri_rows) {
+ stamp_mutex--;
+ return;
+ }
+
+ if ((unsigned)col >= (unsigned)ri->ri_cols) {
+ stamp_mutex--;
+ return;
+ }
+#endif
+
+ /* Recompute stamp? */
+ if (attr != stamp_attr)
+ rasops15_makestamp(ri, attr);
+
+ rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+ height = ri->ri_font->fontheight;
+
+ if (uc == (u_int)-1) {
+ while (height--) {
+ rp[0] = stamp[0];
+ rp[1] = stamp[0];
+ rp[2] = stamp[0];
+ rp[3] = stamp[0];
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ } else {
+ uc -= ri->ri_font->firstchar;
+ fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
+ fs = ri->ri_font->stride;
+
+ while (height--) {
+ so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
+ rp[0] = STAMP_READ(so);
+ rp[1] = STAMP_READ(so + 4);
+
+ so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
+ rp[2] = STAMP_READ(so);
+ rp[3] = STAMP_READ(so + 4);
+
+ fr += fs;
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ }
+
+ stamp_mutex--;
+}
+
+
+/*
+ * Paint a single character. This is for 12-pixel wide fonts.
+ */
+static void
+rasops15_putchar12(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ struct rasops_info *ri;
+ int height, so, fs;
+ int32_t *rp;
+ u_char *fr;
+
+ /* Can't risk remaking the stamp if it's already in use */
+ if (stamp_mutex++) {
+ stamp_mutex--;
+ rasops15_putchar(cookie, row, col, uc, attr);
+ return;
+ }
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if ((unsigned)row >= (unsigned)ri->ri_rows) {
+ stamp_mutex--;
+ return;
+ }
+
+ if ((unsigned)col >= (unsigned)ri->ri_cols) {
+ stamp_mutex--;
+ return;
+ }
+#endif
+
+ /* Recompute stamp? */
+ if (attr != stamp_attr)
+ rasops15_makestamp(ri, attr);
+
+ rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+ height = ri->ri_font->fontheight;
+
+ if (uc == (u_int)-1) {
+ while (height--) {
+ rp[0] = stamp[0];
+ rp[1] = stamp[0];
+ rp[2] = stamp[0];
+ rp[3] = stamp[0];
+ rp[4] = stamp[0];
+ rp[5] = stamp[0];
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ } else {
+ uc -= ri->ri_font->firstchar;
+ fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
+ fs = ri->ri_font->stride;
+
+ while (height--) {
+ so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
+ rp[0] = STAMP_READ(so);
+ rp[1] = STAMP_READ(so + 4);
+
+ so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
+ rp[2] = STAMP_READ(so);
+ rp[3] = STAMP_READ(so + 4);
+
+ so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
+ rp[4] = STAMP_READ(so);
+ rp[5] = STAMP_READ(so + 4);
+
+ fr += fs;
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ }
+
+ stamp_mutex--;
+}
+
+
+/*
+ * Paint a single character. This is for 16-pixel wide fonts.
+ */
+static void
+rasops15_putchar16(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ struct rasops_info *ri;
+ int height, so, fs;
+ int32_t *rp;
+ u_char *fr;
+
+ /* Can't risk remaking the stamp if it's already in use */
+ if (stamp_mutex++) {
+ stamp_mutex--;
+ rasops15_putchar(cookie, row, col, uc, attr);
+ return;
+ }
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if ((unsigned)row >= (unsigned)ri->ri_rows) {
+ stamp_mutex--;
+ return;
+ }
+
+ if ((unsigned)col >= (unsigned)ri->ri_cols) {
+ stamp_mutex--;
+ return;
+ }
+#endif
+
+ /* Recompute stamp? */
+ if (attr != stamp_attr)
+ rasops15_makestamp(ri, attr);
+
+ rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+ height = ri->ri_font->fontheight;
+
+ if (uc == (u_int)-1) {
+ while (height--) {
+ rp[0] = stamp[0];
+ rp[1] = stamp[0];
+ rp[2] = stamp[0];
+ rp[3] = stamp[0];
+ rp[4] = stamp[0];
+ rp[5] = stamp[0];
+ rp[6] = stamp[0];
+ rp[7] = stamp[0];
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ } else {
+ uc -= ri->ri_font->firstchar;
+ fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
+ fs = ri->ri_font->stride;
+
+ while (height--) {
+ so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
+ rp[0] = STAMP_READ(so);
+ rp[1] = STAMP_READ(so + 4);
+
+ so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
+ rp[2] = STAMP_READ(so);
+ rp[3] = STAMP_READ(so + 4);
+
+ so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
+ rp[4] = STAMP_READ(so);
+ rp[5] = STAMP_READ(so + 4);
+
+ so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
+ rp[6] = STAMP_READ(so);
+ rp[7] = STAMP_READ(so + 4);
+
+ DELTA(rp, ri->ri_stride, int32_t *);
+ fr += fs;
+ }
+ }
+
+ stamp_mutex--;
+}
+
+
+/*
+ * Erase rows.
+ */
+static void
+rasops15_eraserows(cookie, row, num, attr)
+ void *cookie;
+ int row, num;
+ long attr;
+{
+ struct rasops_info *ri;
+ int32_t *dp, clr;
+ int n8, n1, cnt;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (row < 0) {
+ num += row;
+ row = 0;
+ }
+
+ if ((row + num) > ri->ri_rows)
+ num = ri->ri_rows - row;
+
+ if (num <= 0)
+ return;
+#endif
+
+ num *= ri->ri_font->fontheight;
+ dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
+ clr = rasops15_bg_color(ri, attr);
+
+ n8 = ri->ri_emustride >> 5;
+ n1 = (ri->ri_emustride >> 2) & 7;
+
+ while (num--) {
+ for (cnt = n8; cnt; cnt--) {
+ dp[0] = clr;
+ dp[1] = clr;
+ dp[2] = clr;
+ dp[3] = clr;
+ dp[4] = clr;
+ dp[5] = clr;
+ dp[6] = clr;
+ dp[7] = clr;
+ dp += 8;
+ }
+
+ for (cnt = n1; cnt; cnt--)
+ *dp++ = clr;
+
+ DELTA(dp, ri->ri_delta, int32_t *);
+ }
+}
+
+#endif /* RASOPS15 */
diff --git a/sys/dev/rasops/rasops24.c b/sys/dev/rasops/rasops24.c
new file mode 100644
index 00000000000..2700248c8ee
--- /dev/null
+++ b/sys/dev/rasops/rasops24.c
@@ -0,0 +1,449 @@
+/* $NetBSD: rasops24.c,v 1.1 1999/04/13 00:18:00 ad Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andy Doran <ad@NetBSD.org>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: rasops24.c,v 1.1 1999/04/13 00:18:00 ad Exp $");
+
+#include "opt_rasops.h"
+#ifdef RASOPS24
+#error This is dangerously incomplete.
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wscons/wsconsio.h>
+#include <dev/rasops/rasops.h>
+
+static void rasops24_putchar __P((void *, int, int, u_int, long attr));
+static void rasops24_erasecols __P((void *, int, int, int, long));
+static void rasops24_eraserows __P((void *, int, int, long));
+static int rasops24_alloc_attr __P((void *, int, int, int, long *));
+static void rasops24_make_bgstamp __P((int, u_char *));
+static int32_t rasops24_fg_color __P((struct rasops_info *, long));
+static int32_t rasops24_bg_color __P((struct rasops_info *, long));
+static void rasops24_do_cursor __P((struct rasops_info *));
+
+void rasops24_init __P((struct rasops_info *ri));
+
+/*
+ * Initalize rasops_info struct for this colordepth.
+ */
+void
+rasops24_init(ri)
+ struct rasops_info *ri;
+{
+
+ switch (ri->ri_font->fontwidth) {
+ case 8:
+ ri->ri_ops.putchar = rasops15_putchar8;
+ break;
+
+ case 12:
+ ri->ri_ops.putchar = rasops15_putchar12;
+ break;
+
+ case 16:
+ ri->ri_ops.putchar = rasops15_putchar16;
+ break;
+
+ default:
+ ri->ri_ops.putchar = rasops15_putchar;
+ break;
+ }
+
+ /* Select defaults for color positions if none selected */
+ if (ri->ri_rnum == 0) {
+ ri->ri_rnum = 8;
+ ri->ri_gnum = 8;
+ ri->ri_bnum = 8;
+ ri->ri_rpos = 0;
+ ri->ri_gpos = 8;
+ ri->ri_bpos = 16;
+ }
+
+ ri->ri_ops.erasecols = rasops25_erasecols;
+ ri->ri_ops.eraserows = rasops25_eraserows;
+ ri->ri_do_cursor = rasops25_do_cursor;
+ rasops_init_devcmap(ri);
+}
+
+/*
+ * Get foreground color from attribute and copy across all 4 bytes
+ * in a int32_t.
+ */
+static __inline__ int32_t
+rasops24_fg_color(ri, attr)
+ struct rasops_info *ri;
+ long attr;
+{
+ int32_t fg;
+
+ fg = ri->ri_devcmap[((u_int)attr >> 24) & 15];
+
+ /* Copy across all 4 bytes if the color is gray */
+ if (attr & 2)
+ fg |= fg << 8;
+
+ return fg;
+}
+
+
+/*
+ * Get background color from attribute and copy across all 4 bytes
+ * in a int32_t.
+ */
+static __inline__ int32_t
+rasops24_bg_color(ri, attr)
+ struct rasops_info *ri;
+ long attr;
+{
+ int32_t bg;
+
+ bg = ri->ri_devcmap[((u_int)attr >> 16) & 15];
+
+ /* Copy across all 4 bytes if the color is gray */
+ if (attr & 4)
+ bg |= bg << 8;
+
+ return bg;
+}
+
+
+/*
+ * Actually turn the cursor on or off. This does the dirty work for
+ * rasops_cursor().
+ */
+static void
+rasops24_do_cursor(ri)
+ struct rasops_info *ri;
+{
+ int full1, height, cnt, slop1, slop2, row, col;
+ u_char *dp, *rp;
+
+ row = ri->ri_crow;
+ col = ri->ri_ccol;
+
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ height = ri->ri_font->fontheight;
+
+ slop1 = (int)rp & 3;
+ slop2 = (ri->ri_xscale - slop1) & 3;
+ full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
+
+ while (height--) {
+ dp = rp;
+ rp += ri->ri_stride;
+
+ for (cnt = slop1; cnt; cnt--)
+ *dp++ ^= 0xff;
+
+ for (cnt = full1; cnt; cnt--) {
+ *(int32_t *)dp ^= 0xffffffff;
+ dp += 4;
+ }
+
+ for (cnt = slop2; cnt; cnt--)
+ *dp++ ^= 0xff;
+ }
+}
+
+
+/*
+ * Erase columns.
+ */
+static void
+rasops24_erasecols(cookie, row, col, num, attr)
+ void *cookie;
+ int row, col, num;
+ long attr;
+{
+ struct rasops_info *ri;
+ int32_t *dp;
+ u_char *rp;
+ int n8, n1, clr, height, cnt, slop1, slop2;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ /* Catches 'row < 0' case too */
+ if ((unsigned)row >= (unsigned)ri->ri_rows)
+ return;
+
+ if (col < 0) {
+ num += col;
+ col = 0;
+ }
+
+ if ((col + num) > ri->ri_cols)
+ num = ri->ri_cols - col;
+
+ if (num <= 0)
+ return;
+#endif
+
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ num *= ri->ri_xscale;
+ clr = rasops24_bg_color(ri, attr);
+ height = ri->ri_font->fontheight;
+
+ slop1 = (int)rp & 2;
+ slop2 = (num - slop1) & 2;
+ n8 = num >> 5;
+ n1 = (num >> 2) & 7;
+
+ while (height--) {
+ cnt = num;
+ dp = (u_int32_t *)rp;
+ rp += ri->ri_stride;
+
+ /* Align span to 4 bytes */
+ if (slop1) {
+ *(int16_t *)dp = (int16_t)clr;
+ DELTA(dp, 2, int32_t *);
+ }
+
+ /* Write 32 bytes per loop */
+ for (cnt = n8; cnt; cnt--) {
+ dp[0] = clr;
+ dp[1] = clr;
+ dp[2] = clr;
+ dp[3] = clr;
+ dp[4] = clr;
+ dp[5] = clr;
+ dp[6] = clr;
+ dp[7] = clr;
+ dp += 8;
+ }
+
+ /* Write 4 bytes per loop */
+ for (cnt = n1; cnt; cnt--)
+ *dp++ = clr;
+
+ /* Write unaligned trailing slop */
+ if (slop2)
+ *(int16_t *)dp = (int16_t)clr;
+ }
+}
+
+
+/*
+ * Paint a single character.
+ */
+static void
+rasops24_putchar(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ struct rasops_info *ri;
+ u_char *dp, *rp;
+ int32_t *fr, clr[16], fb;
+ int width, height, cnt;
+
+ if (uc == (u_int)-1) {
+ rasops24_erasecols(cookie, row, col, 1, attr);
+ return;
+ }
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if ((unsigned)row >= (unsigned)ri->ri_rows)
+ return;
+
+ if ((unsigned)col >= (unsigned)ri->ri_cols)
+ return;
+#endif
+
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ fr = (int32_t *)ri->ri_font->data + uc * ri->ri_font->fontheight;
+
+ height = ri->ri_font->fontheight;
+ width = ri->ri_font->fontwidth;
+
+ clr[1] = ri->ri_devcmap[((u_int)attr >> 24)];
+ clr[0] = ri->ri_devcmap[((u_int)attr >> 16)];
+
+ while (height--) {
+ dp = rp;
+ fb = *fr++;
+ rp += ri->ri_stride;
+
+ for (cnt = width; cnt; cnt--) {
+ *(int16_t *)dp = (int16_t)clr[fb & 1];
+ fb >>= 1;
+ dp += 2;
+ }
+ }
+}
+
+
+/*
+ * Construct a 12 byte by 1 byte blitting stamp. This uses the background
+ * color only (for erasecols()/eraserows()).
+ */
+static void
+rasops24_make_bgstamp(i, bp)
+ int i;
+ u_char *bp;
+{
+ u_char r, g, b;
+
+ i = (i >> 8) & 0xff;
+ i = (i << 1) + i;
+ r = rasops_cmap[i+0];
+ g = rasops_cmap[i+1];
+ b = rasops_cmap[i+2];
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ bp[0] = r; bp[1] = g; bp[2] = b; bp[3] = r;
+ bp[4] = g; bp[5] = b; bp[6] = r; bp[7] = g;
+ bp[8] = b; bp[9] = r; bp[10] = g; bp[11] = b;
+#else
+ bp[3] = r; bp[2] = g; bp[1] = b; bp[0] = r;
+ bp[7] = g; bp[6] = b; bp[5] = r; bp[4] = g;
+ bp[11] = b; bp[10] = r; bp[9] = g; bp[8] = b;
+#endif
+}
+
+
+/*
+ * Erase rows.
+ */
+static void
+rasops24_eraserows(cookie, row, num, attr)
+ void *cookie;
+ int row, num;
+ long attr;
+{
+ struct rasops_info *ri;
+ int32_t *dp, clr, stamp[3];
+ int n9, n3, n1, cnt;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (row < 0) {
+ num += row;
+ row = 0;
+ }
+
+ if ((row + num) > ri->ri_rows)
+ num = ri->ri_rows - row;
+
+ if (num <= 0)
+ return;
+#endif
+
+ num *= ri->ri_font->fontheight;
+ dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
+
+ n9 = ri->ri_emustride / 36;
+ cnt = (n9 << 5) + (n9 << 2); /* (32*n9) + (4*n9) */
+
+ n3 = (ri->ri_emustride - cnt) / 12;
+ cnt += (n3 << 3) + (n3 << 2); /* (8*n3) + (4*n3) */
+
+ n1 = (ri->ri_emustride - cnt) >> 2;
+
+ /* If the color is gray, we can cheat... */
+ if (attr & ATTR_GRAY_BG) {
+ clr = rasops24_bg_color(ri, attr);
+
+ while (num--) {
+ for (cnt = n9; cnt; cnt--) {
+ dp[0] = clr;
+ dp[1] = clr;
+ dp[2] = clr;
+ dp[3] = clr;
+ dp[4] = clr;
+ dp[5] = clr;
+ dp[6] = clr;
+ dp[7] = clr;
+ dp[8] = clr;
+ dp += 9;
+ }
+
+ for (cnt = n3; cnt; cnt--) {
+ dp[0] = clr;
+ dp[1] = clr;
+ dp[2] = clr;
+ dp += 3;
+ }
+
+ for (cnt = n1; cnt; cnt--)
+ *dp++ = clr;
+
+ DELTA(dp, ri->ri_delta, int32_t *);
+ }
+ } else {
+ rasops24_make_bgstamp((int)attr, (u_char *)stamp);
+
+ while (num--) {
+ for (cnt = n9; cnt; cnt--) {
+ dp[0] = stamp[0];
+ dp[1] = stamp[1];
+ dp[2] = stamp[2];
+ dp[3] = stamp[0];
+ dp[4] = stamp[1];
+ dp[5] = stamp[2];
+ dp[6] = stamp[0];
+ dp[7] = stamp[1];
+ dp[8] = stamp[2];
+ dp += 9;
+ }
+
+ for (cnt = n3; cnt; cnt--) {
+ dp[0] = stamp[0];
+ dp[1] = stamp[1];
+ dp[2] = stamp[2];
+ dp += 3;
+ }
+
+ for (cnt = 0; cnt < n1; cnt++)
+ *dp++ = stamp[cnt];
+
+ DELTA(dp, ri->ri_delta, int32_t *);
+ }
+ }
+}
+
+#endif /* RASOPS24 */
diff --git a/sys/dev/rasops/rasops32.c b/sys/dev/rasops/rasops32.c
new file mode 100644
index 00000000000..0d66b6caf51
--- /dev/null
+++ b/sys/dev/rasops/rasops32.c
@@ -0,0 +1,324 @@
+/* $NetBSD: rasops32.c,v 1.1 1999/04/13 00:18:01 ad Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andy Doran <ad@NetBSD.org>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "opt_rasops.h"
+#ifdef RASOPS32
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: rasops32.c,v 1.1 1999/04/13 00:18:01 ad Exp $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wscons/wsconsio.h>
+#include <dev/rasops/rasops.h>
+
+static void rasops32_putchar __P((void *, int, int, u_int, long attr));
+static void rasops32_erasecols __P((void *, int, int, int, long));
+static void rasops32_eraserows __P((void *, int, int, long));
+static int32_t rasops32_fg_color __P((struct rasops_info *, long));
+static int32_t rasops32_bg_color __P((struct rasops_info *, long));
+static void rasops32_do_cursor __P((struct rasops_info *));
+void rasops32_init __P((struct rasops_info *ri));
+
+/*
+ * Initalize a 'rasops_info' descriptor for this depth.
+ */
+void
+rasops32_init(ri)
+ struct rasops_info *ri;
+{
+
+ /*
+ * This sucks. There is little optimization you can do with this
+ * colordepth on 32-bit machines.
+ *
+ * XXX c'mon sparc, alpha ppl?
+ */
+ ri->ri_ops.putchar = rasops32_putchar;
+ ri->ri_ops.erasecols = rasops32_erasecols;
+ ri->ri_ops.eraserows = rasops32_eraserows;
+ ri->ri_do_cursor = rasops32_do_cursor;
+ rasops_init_devcmap(ri);
+}
+
+
+/*
+ * Get background color from attribute.
+ */
+static __inline__ int32_t
+rasops32_bg_color(ri, attr)
+ struct rasops_info *ri;
+ long attr;
+{
+
+ return ri->ri_devcmap[((int32_t)attr >> 24) & 15];
+}
+
+
+/*
+ * Get foreground color from attribute.
+ */
+static __inline__ int32_t
+rasops32_fg_color(ri, attr)
+ struct rasops_info *ri;
+ long attr;
+{
+
+ return ri->ri_devcmap[((int32_t)attr >> 16) & 15];
+}
+
+
+/*
+ * Actually turn the cursor on or off. This does the dirty work for
+ * rasops_cursor().
+ */
+static void
+rasops32_do_cursor(ri)
+ struct rasops_info *ri;
+{
+ u_char *rp;
+ int32_t *dp, planemask;
+ int num, height, cnt, row, col;
+
+ row = ri->ri_crow;
+ col = ri->ri_ccol;
+
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ height = ri->ri_font->fontheight;
+ num = ri->ri_xscale >> 2;
+ planemask = ri->ri_devcmap[15];
+
+ while (height--) {
+ dp = (int32_t *)rp;
+ rp += ri->ri_stride;
+
+ for (cnt = num; cnt; cnt--)
+ *dp++ ^= planemask;
+ }
+}
+
+
+/*
+ * Paint a single character.
+ */
+static void
+rasops32_putchar(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ struct rasops_info *ri;
+ int32_t *dp, *rp, clr[2];
+ u_char *fr;
+ int width, height, cnt, fs, fb;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ /* Catches 'row < 0' case too */
+ if ((unsigned)row >= (unsigned)ri->ri_rows)
+ return;
+
+ if ((unsigned)col >= (unsigned)ri->ri_cols)
+ return;
+#endif
+
+ rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+
+ height = ri->ri_font->fontheight;
+ width = ri->ri_font->fontwidth;
+ clr[0] = rasops32_bg_color(ri, attr);
+ clr[1] = rasops32_fg_color(ri, attr);
+
+ if (uc == ' ') {
+ while (height--) {
+ dp = rp;
+ DELTA(rp, ri->ri_stride, int32_t *);
+
+ for (cnt = width; cnt; cnt--)
+ *dp++ = clr[0];
+ }
+ } else {
+ uc -= ri->ri_font->firstchar;
+ fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
+ fs = ri->ri_font->stride;
+
+ while (height--) {
+ dp = rp;
+ fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
+ fr += fs;
+ DELTA(rp, ri->ri_stride, int32_t *);
+
+ for (cnt = width; cnt; cnt--) {
+ *dp++ = clr[(fb >> 31) & 1];
+ fb <<= 1;
+ }
+ }
+ }
+
+ /* Do underline */
+ if (attr & 1) {
+ DELTA(rp, -(ri->ri_stride << 1), int32_t *);
+
+ while (width--)
+ *rp++ = clr[1];
+ }
+}
+
+
+/*
+ * Erase rows.
+ */
+static void
+rasops32_eraserows(cookie, row, num, attr)
+ void *cookie;
+ int row, num;
+ long attr;
+{
+ struct rasops_info *ri;
+ int32_t *dp, clr;
+ int n8, n1, cnt;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (row < 0) {
+ num += row;
+ row = 0;
+ }
+
+ if ((row + num) > ri->ri_rows)
+ num = ri->ri_rows - row;
+
+ if (num <= 0)
+ return;
+#endif
+
+ num *= ri->ri_font->fontheight;
+ dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
+ clr = rasops32_bg_color(ri, attr);
+
+ n8 = ri->ri_emustride >> 5;
+ n1 = (ri->ri_emustride >> 2) & 7;
+
+ while (num--) {
+ for (cnt = n8; cnt; cnt--) {
+ dp[0] = clr;
+ dp[1] = clr;
+ dp[2] = clr;
+ dp[3] = clr;
+ dp[4] = clr;
+ dp[5] = clr;
+ dp[6] = clr;
+ dp[7] = clr;
+ dp += 8;
+ }
+
+ for (cnt = n1; cnt; cnt--)
+ *dp++ = clr;
+
+ DELTA(dp, ri->ri_delta, int32_t *);
+ }
+}
+
+
+/*
+ * Erase columns.
+ */
+static void
+rasops32_erasecols(cookie, row, col, num, attr)
+ void *cookie;
+ int row, col, num;
+ long attr;
+{
+ int n8, clr, height, cnt;
+ struct rasops_info *ri;
+ int32_t *dst;
+ u_char *rp;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if ((unsigned)row >= (unsigned)ri->ri_rows)
+ return;
+
+ if (col < 0) {
+ num += col;
+ col = 0;
+ }
+
+ if ((col + num) > ri->ri_cols)
+ num = ri->ri_cols - col;
+
+ if (num <= 0)
+ return;
+#endif
+
+ num = num * ri->ri_xscale;
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ clr = rasops32_bg_color(ri, attr);
+ height = ri->ri_font->fontheight;
+ n8 = num >> 5;
+ num = (num >> 2) & 7;
+
+ while (height--) {
+ dst = (int32_t *)rp;
+ rp += ri->ri_stride;
+
+ for (cnt = n8; cnt; cnt--) {
+ dst[0] = clr;
+ dst[1] = clr;
+ dst[2] = clr;
+ dst[3] = clr;
+ dst[4] = clr;
+ dst[5] = clr;
+ dst[6] = clr;
+ dst[7] = clr;
+ dst += 8;
+ }
+
+ for (cnt = num; cnt; cnt--)
+ *dst++ = clr;
+ }
+}
+
+#endif /* RASOPS32 */
diff --git a/sys/dev/rasops/rasops8.c b/sys/dev/rasops/rasops8.c
new file mode 100644
index 00000000000..831f9ce420f
--- /dev/null
+++ b/sys/dev/rasops/rasops8.c
@@ -0,0 +1,634 @@
+/* $NetBSD: rasops8.c,v 1.1 1999/04/13 00:18:01 ad Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andy Doran <ad@NetBSD.org>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "opt_rasops.h"
+#ifdef RASOPS8
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.1 1999/04/13 00:18:01 ad Exp $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wscons/wsconsio.h>
+#include <dev/rasops/rasops.h>
+
+static void rasops8_putchar __P((void *, int, int, u_int, long attr));
+static void rasops8_putchar8 __P((void *, int, int, u_int, long attr));
+static void rasops8_putchar12 __P((void *, int, int, u_int, long attr));
+static void rasops8_putchar16 __P((void *, int, int, u_int, long attr));
+static void rasops8_erasecols __P((void *, int, int, int, long));
+static void rasops8_eraserows __P((void *, int, int, long));
+static void rasops8_makestamp __P((long));
+static int32_t rasops8_bg_color __P((long));
+static void rasops8_do_cursor __P((struct rasops_info *));
+void rasops8_init __P((struct rasops_info *ri));
+
+/*
+ * 4x1 stamp for optimized character blitting
+ */
+static int32_t stamp[16];
+static long stamp_attr;
+static int stamp_mutex; /* XXX see note in README */
+
+/*
+ * XXX this confuses the hell out of gcc2 (not egcs) which always insists
+ * that the shift count is negative.
+ *
+ * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
+ * destination = STAMP_READ(offset)
+ */
+#define STAMP_SHIFT(fb,n) ((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
+#define STAMP_MASK (15 << 2)
+#define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o)))
+
+
+/*
+ * Initalize a 'rasops_info' descriptor for this depth.
+ */
+void
+rasops8_init(ri)
+ struct rasops_info *ri;
+{
+
+ switch (ri->ri_font->fontwidth) {
+ case 8:
+ ri->ri_ops.putchar = rasops8_putchar8;
+ break;
+
+ case 12:
+ ri->ri_ops.putchar = rasops8_putchar12;
+ break;
+
+ case 16:
+ ri->ri_ops.putchar = rasops8_putchar16;
+ break;
+
+ default:
+ ri->ri_ops.putchar = rasops8_putchar;
+ break;
+ }
+
+ ri->ri_ops.erasecols = rasops8_erasecols;
+ ri->ri_ops.eraserows = rasops8_eraserows;
+ ri->ri_do_cursor = rasops8_do_cursor;
+}
+
+
+/*
+ * Get background color from attribute and copy across all 4 bytes
+ * of an int32_t.
+ */
+static __inline__ int32_t
+rasops8_bg_color(attr)
+ long attr;
+{
+ int32_t bg;
+
+ bg = ((int32_t)attr >> 16) & 15;
+ return bg | (bg << 8) | (bg << 16) | (bg << 24);
+}
+
+
+/*
+ * Actually turn the cursor on or off. This does the dirty work for
+ * rasops_cursor().
+ */
+static void
+rasops8_do_cursor(ri)
+ struct rasops_info *ri;
+{
+ u_char *dp, *rp;
+ int full1, height, cnt, slop1, slop2, row, col;
+
+ row = ri->ri_crow;
+ col = ri->ri_ccol;
+
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ height = ri->ri_font->fontheight;
+
+ slop1 = (int)rp & 3;
+ slop2 = (ri->ri_xscale - slop1) & 3;
+ full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
+
+ while (height--) {
+ dp = rp;
+ rp += ri->ri_stride;
+
+ for (cnt = slop1; cnt; cnt--)
+ *dp++ ^= 0xff;
+
+ for (cnt = full1; cnt; cnt--) {
+ *(int32_t *)dp ^= 0xffffffff;
+ dp += 4;
+ }
+
+ for (cnt = slop2; cnt; cnt--)
+ *dp++ ^= 0xff;
+ }
+}
+
+
+/*
+ * Paint a single character.
+ */
+static void
+rasops8_putchar(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ struct rasops_info *ri;
+ u_char *dp, *rp, *fr, clr[2];
+ int width, height, cnt, fs, fb;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ /* Catches 'row < 0' case too */
+ if ((unsigned)row >= (unsigned)ri->ri_rows)
+ return;
+
+ if ((unsigned)col >= (unsigned)ri->ri_cols)
+ return;
+#endif
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+
+ height = ri->ri_font->fontheight;
+ width = ri->ri_font->fontwidth;
+ clr[0] = (u_char)(attr >> 16);
+ clr[1] = (u_char)(attr >> 24);
+
+ if (uc == ' ') {
+ while (height--) {
+ dp = rp;
+ rp += ri->ri_stride;
+
+ for (cnt = width; cnt; cnt--)
+ *dp++ = clr[0];
+ }
+ } else {
+ uc -= ri->ri_font->firstchar;
+ fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
+ fs = ri->ri_font->stride;
+
+ while (height--) {
+ dp = rp;
+ fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
+ fr += fs;
+ rp += ri->ri_stride;
+
+ for (cnt = width; cnt; cnt--) {
+ *dp++ = clr[(fb >> 31) & 1];
+ fb <<= 1;
+ }
+ }
+ }
+
+ /* Do underline */
+ if (attr & 1) {
+ rp -= (ri->ri_stride << 1);
+
+ while (width--)
+ *rp++ = clr[1];
+ }
+
+}
+
+
+/*
+ * Recompute the 4x1 blitting stamp.
+ */
+static void
+rasops8_makestamp(long attr)
+{
+ int i;
+ int32_t fg, bg;
+
+ fg = (attr >> 24) & 15;
+ bg = (attr >> 16) & 15;
+ stamp_attr = attr;
+
+ for (i = 0; i < 16; i++) {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ stamp[i] = (i & 8 ? fg : bg);
+ stamp[i] |= ((i & 4 ? fg : bg) << 8);
+ stamp[i] |= ((i & 2 ? fg : bg) << 16);
+ stamp[i] |= ((i & 1 ? fg : bg) << 24);
+#else
+ stamp[i] = (i & 1 ? fg : bg);
+ stamp[i] |= ((i & 2 ? fg : bg) << 8);
+ stamp[i] |= ((i & 4 ? fg : bg) << 16);
+ stamp[i] |= ((i & 8 ? fg : bg) << 24);
+#endif
+ }
+}
+
+
+/*
+ * Paint a single character. This is for 8-pixel wide fonts.
+ */
+static void
+rasops8_putchar8(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ struct rasops_info *ri;
+ int height, fs;
+ int32_t *rp;
+ u_char *fr;
+
+ /* Can't risk remaking the stamp if it's already in use */
+ if (stamp_mutex++) {
+ stamp_mutex--;
+ rasops8_putchar(cookie, row, col, uc, attr);
+ return;
+ }
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if ((unsigned)row >= (unsigned)ri->ri_rows) {
+ stamp_mutex--;
+ return;
+ }
+
+ if ((unsigned)col >= (unsigned)ri->ri_cols) {
+ stamp_mutex--;
+ return;
+ }
+#endif
+
+ /* Recompute stamp? */
+ if (attr != stamp_attr)
+ rasops8_makestamp(attr);
+
+ rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+ height = ri->ri_font->fontheight;
+
+ if (uc == ' ') {
+ while (height--) {
+ rp[0] = stamp[0];
+ rp[1] = stamp[0];
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ } else {
+ uc -= ri->ri_font->firstchar;
+ fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
+ fs = ri->ri_font->stride;
+
+ while (height--) {
+ rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
+ rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
+
+ fr += fs;
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ }
+
+ /* Do underline */
+ if (attr & 1) {
+ DELTA(rp, -(ri->ri_stride << 1), int32_t *);
+ rp[0] = stamp[15];
+ rp[1] = stamp[15];
+ }
+
+ stamp_mutex--;
+}
+
+
+/*
+ * Paint a single character. This is for 12-pixel wide fonts.
+ */
+static void
+rasops8_putchar12(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ struct rasops_info *ri;
+ int height, fs;
+ int32_t *rp;
+ u_char *fr;
+
+ /* Can't risk remaking the stamp if it's already in use */
+ if (stamp_mutex++) {
+ stamp_mutex--;
+ rasops8_putchar(cookie, row, col, uc, attr);
+ return;
+ }
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if ((unsigned)row >= (unsigned)ri->ri_rows) {
+ stamp_mutex--;
+ return;
+ }
+
+ if ((unsigned)col >= (unsigned)ri->ri_cols) {
+ stamp_mutex--;
+ return;
+ }
+#endif
+
+ /* Recompute stamp? */
+ if (attr != stamp_attr)
+ rasops8_makestamp(attr);
+
+ rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+ height = ri->ri_font->fontheight;
+
+ if (uc == ' ') {
+ while (height--) {
+ rp[0] = stamp[0];
+ rp[1] = stamp[0];
+ rp[2] = stamp[0];
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ } else {
+ uc -= ri->ri_font->firstchar;
+ fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
+ fs = ri->ri_font->stride;
+
+ while (height--) {
+ rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
+ rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
+ rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
+
+ fr += fs;
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ }
+
+ /* Do underline */
+ if (attr & 1) {
+ DELTA(rp, -(ri->ri_stride << 1), int32_t *);
+ rp[0] = stamp[15];
+ rp[1] = stamp[15];
+ rp[2] = stamp[15];
+ }
+
+ stamp_mutex--;
+}
+
+
+/*
+ * Paint a single character. This is for 16-pixel wide fonts.
+ */
+static void
+rasops8_putchar16(cookie, row, col, uc, attr)
+ void *cookie;
+ int row, col;
+ u_int uc;
+ long attr;
+{
+ struct rasops_info *ri;
+ int height, fs;
+ int32_t *rp;
+ u_char *fr;
+
+ /* Can't risk remaking the stamp if it's already in use */
+ if (stamp_mutex++) {
+ stamp_mutex--;
+ rasops8_putchar(cookie, row, col, uc, attr);
+ return;
+ }
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if ((unsigned)row >= (unsigned)ri->ri_rows) {
+ stamp_mutex--;
+ return;
+ }
+
+ if ((unsigned)col >= (unsigned)ri->ri_cols) {
+ stamp_mutex--;
+ return;
+ }
+#endif
+
+ /* Recompute stamp? */
+ if (attr != stamp_attr)
+ rasops8_makestamp(attr);
+
+ rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+ height = ri->ri_font->fontheight;
+
+ if (uc == ' ') {
+ while (height--) {
+ rp[0] = stamp[0];
+ rp[1] = stamp[0];
+ rp[2] = stamp[0];
+ rp[3] = stamp[0];
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ } else {
+ uc -= ri->ri_font->firstchar;
+ fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
+ fs = ri->ri_font->stride;
+
+ while (height--) {
+ rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
+ rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
+ rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
+ rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
+
+ fr += fs;
+ DELTA(rp, ri->ri_stride, int32_t *);
+ }
+ }
+
+ /* Do underline */
+ if (attr & 1) {
+ DELTA(rp, -(ri->ri_stride << 1), int32_t *);
+ rp[0] = stamp[15];
+ rp[1] = stamp[15];
+ rp[2] = stamp[15];
+ rp[3] = stamp[15];
+ }
+
+ stamp_mutex--;
+}
+
+
+/*
+ * Erase rows.
+ */
+static void
+rasops8_eraserows(cookie, row, num, attr)
+ void *cookie;
+ int row, num;
+ long attr;
+{
+ struct rasops_info *ri;
+ int32_t *dp, clr;
+ int n8, n1, cnt;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if (row < 0) {
+ num += row;
+ row = 0;
+ }
+
+ if ((row + num) > ri->ri_rows)
+ num = ri->ri_rows - row;
+
+ if (num <= 0)
+ return;
+#endif
+
+ num *= ri->ri_font->fontheight;
+ dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
+ clr = rasops8_bg_color(attr);
+
+ n8 = ri->ri_emustride >> 5;
+ n1 = (ri->ri_emustride >> 2) & 7;
+
+ while (num--) {
+ for (cnt = n8; cnt; cnt--) {
+ dp[0] = clr;
+ dp[1] = clr;
+ dp[2] = clr;
+ dp[3] = clr;
+ dp[4] = clr;
+ dp[5] = clr;
+ dp[6] = clr;
+ dp[7] = clr;
+ dp += 8;
+ }
+
+ for (cnt = n1; cnt; cnt--)
+ *dp++ = clr;
+
+ DELTA(dp, ri->ri_delta, int32_t *);
+ }
+}
+
+
+/*
+ * Erase columns.
+ */
+static void
+rasops8_erasecols(cookie, row, col, num, attr)
+ void *cookie;
+ int row, col, num;
+ long attr;
+{
+ int n8, clr, height, cnt, slop1, slop2;
+ struct rasops_info *ri;
+ int32_t *dst;
+ u_char *dstb, *rp;
+
+ ri = (struct rasops_info *)cookie;
+
+#ifdef RASOPS_CLIPPING
+ if ((unsigned)row >= (unsigned)ri->ri_rows)
+ return;
+
+ if (col < 0) {
+ num += col;
+ col = 0;
+ }
+
+ if ((col + num) > ri->ri_cols)
+ num = ri->ri_cols - col;
+
+ if (num <= 0)
+ return;
+#endif
+
+ num = num * ri->ri_xscale;
+ rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
+ clr = rasops8_bg_color(attr);
+ height = ri->ri_font->fontheight;
+
+ slop1 = (int)rp & 3;
+ slop2 = (num - slop1) & 3;
+ num -= slop1 + slop2;
+ n8 = num >> 5;
+ num = (num >> 2) & 7;
+
+ while (height--) {
+ dstb = rp;
+ rp += ri->ri_stride;
+
+ /* Align span to 4 bytes */
+ for (cnt = slop1; cnt; cnt--)
+ *dstb++ = (u_char)clr;
+
+ dst = (int32_t *)dstb;
+
+ /* Write 32 bytes per loop */
+ for (cnt = n8; cnt; cnt--) {
+ dst[0] = clr;
+ dst[1] = clr;
+ dst[2] = clr;
+ dst[3] = clr;
+ dst[4] = clr;
+ dst[5] = clr;
+ dst[6] = clr;
+ dst[7] = clr;
+ dst += 8;
+ }
+
+ /* Write 4 bytes per loop */
+ for (cnt = num; cnt; cnt--)
+ *dst++ = clr;
+
+ /* Write unaligned trailing slop */
+ if (slop2 == 0)
+ continue;
+
+ dstb = (u_char *)dst;
+
+ for (cnt = slop2; cnt; cnt--)
+ *dstb++ = (u_char)clr;
+ }
+}
+
+#endif /* RASOPS8 */