diff --git a/sys/dev/rasops/Makefile b/sys/dev/rasops/Makefile new file mode 100644 index 000000000000..5a6279f723b6 --- /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 diff --git a/sys/dev/rasops/README b/sys/dev/rasops/README new file mode 100644 index 000000000000..064478d78812 --- /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 , April 1999 diff --git a/sys/dev/rasops/files.rasops b/sys/dev/rasops/files.rasops new file mode 100644 index 000000000000..8af0425ecc7e --- /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 000000000000..29002b0ea051 --- /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 . + * + * 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 +__KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.1 1999/04/13 00:17:58 ad Exp $"); + +#include "opt_rasops.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +/* 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 000000000000..830c7e077eab --- /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 . + * + * 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 000000000000..7b076749d911 --- /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 . + * + * 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 +__KERNEL_RCSID(0, "$NetBSD: rasops1.c,v 1.1 1999/04/13 00:17:59 ad Exp $"); + +#include +#include +#include +#include +#include + +#include +#include + +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 000000000000..c495e7e588b5 --- /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 . + * + * 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 +__KERNEL_RCSID(0, "$NetBSD: rasops15.c,v 1.1 1999/04/13 00:18:00 ad Exp $"); + +#include +#include +#include +#include + +#include +#include +#include + +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 000000000000..2700248c8ee2 --- /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 . + * + * 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 +__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 +#include +#include +#include + +#include +#include +#include + +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 000000000000..0d66b6caf518 --- /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 . + * + * 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 +__KERNEL_RCSID(0, "$NetBSD: rasops32.c,v 1.1 1999/04/13 00:18:01 ad Exp $"); + +#include +#include +#include +#include + +#include +#include +#include + +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 000000000000..831f9ce420f7 --- /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 . + * + * 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 +__KERNEL_RCSID(0, "$NetBSD: rasops8.c,v 1.1 1999/04/13 00:18:01 ad Exp $"); + +#include +#include +#include +#include + +#include +#include +#include + +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 */