Module Name:    src
Committed By:   macallan
Date:           Wed Sep 12 12:07:04 UTC 2012

Modified Files:
        src/sys/dev/pci: pm2fb.c pm2reg.h

Log Message:
support anti-aliased fonts in 8 bit
while there, fix pm2fb_bitblt() packed mode, for real this time
TODO:
- use packed mode when uploading glyphs
- let the hardware do the alpha blending if possible
- mode setting


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/pci/pm2fb.c
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/pci/pm2reg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/pm2fb.c
diff -u src/sys/dev/pci/pm2fb.c:1.16 src/sys/dev/pci/pm2fb.c:1.17
--- src/sys/dev/pci/pm2fb.c:1.16	Wed Sep  5 23:19:13 2012
+++ src/sys/dev/pci/pm2fb.c	Wed Sep 12 12:07:04 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: pm2fb.c,v 1.16 2012/09/05 23:19:13 macallan Exp $	*/
+/*	$NetBSD: pm2fb.c,v 1.17 2012/09/12 12:07:04 macallan Exp $	*/
 
 /*
  * Copyright (c) 2009 Michael Lorenz
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pm2fb.c,v 1.16 2012/09/05 23:19:13 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pm2fb.c,v 1.17 2012/09/12 12:07:04 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -55,6 +55,7 @@ __KERNEL_RCSID(0, "$NetBSD: pm2fb.c,v 1.
 #include <dev/wsfont/wsfont.h>
 #include <dev/rasops/rasops.h>
 #include <dev/wscons/wsdisplay_vconsvar.h>
+#include <dev/wscons/wsdisplay_glyphcachevar.h>
 #include <dev/pci/wsdisplay_pci.h>
 
 #include <dev/i2c/i2cvar.h>
@@ -104,6 +105,7 @@ struct pm2fb_softc {
 	uint8_t sc_edid_data[128];
 	struct edid_info sc_ei;
 	struct videomode *sc_videomode;
+	glyphcache sc_gc;
 };
 
 static int	pm2fb_match(device_t, cfdata_t, void *);
@@ -129,11 +131,11 @@ static void	pm2fb_init(struct pm2fb_soft
 static void	pm2fb_flush_engine(struct pm2fb_softc *);
 static void	pm2fb_rectfill(struct pm2fb_softc *, int, int, int, int,
 			    uint32_t);
-static void	pm2fb_bitblt(struct pm2fb_softc *, int, int, int, int, int,
-			    int, int);
+static void	pm2fb_bitblt(void *, int, int, int, int, int, int, int);
 
 static void	pm2fb_cursor(void *, int, int, int);
 static void	pm2fb_putchar(void *, int, int, u_int, long);
+static void	pm2fb_putchar_aa(void *, int, int, u_int, long);
 static void	pm2fb_copycols(void *, int, int, int, int);
 static void	pm2fb_erasecols(void *, int, int, int, long);
 static void	pm2fb_copyrows(void *, int, int, int);
@@ -222,7 +224,10 @@ pm2fb_match(device_t parent, cfdata_t ma
 	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_3DLABS)
 		return 0;
 
-	/* only cards tested on so far - likely need a list */
+	/*
+	 * only card tested on so far is a TechSource Raptor GFX 8P 
+	 * Sun PGX32, which happens to be a Permedia 2v
+	 */
 	if ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3DLABS_PERMEDIA2) ||
 	    (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3DLABS_PERMEDIA2V))
 		return 100;
@@ -323,6 +328,18 @@ pm2fb_attach(device_t parent, device_t s
 
 	ri = &sc->sc_console_screen.scr_ri;
 
+	sc->sc_gc.gc_bitblt = pm2fb_bitblt;
+	sc->sc_gc.gc_blitcookie = sc;
+	sc->sc_gc.gc_rop = 3;
+
+#ifdef PM2FB_DEBUG
+	/*
+	 * leave some room at the bottom of the screen for various blitter
+	 * tests and in order to make the glyph cache visible
+	 */
+	sc->sc_height -= 200;
+#endif
+
 	if (is_console) {
 		vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
 		    &defattr);
@@ -334,12 +351,25 @@ pm2fb_attach(device_t parent, device_t s
 		sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
 		sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
 		sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
+		/* XXX use actual memory size instead of assuming 8MB */
+		glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
+				(0x800000 / sc->sc_stride) - sc->sc_height - 5,
+				sc->sc_width,
+				ri->ri_font->fontwidth,
+				ri->ri_font->fontheight,
+				defattr);
 		wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
 		    defattr);
 		vcons_replay_msgbuf(&sc->sc_console_screen);
 	} else {
 		if (sc->sc_console_screen.scr_ri.ri_rows == 0) {
 			/* do some minimal setup to avoid weirdnesses later */
+			glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
+				(0x800000 / sc->sc_stride) - sc->sc_height - 5,
+				sc->sc_width,
+				ri->ri_font->fontwidth,
+				ri->ri_font->fontheight,
+				defattr);
 			vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, 
 			   &defattr);
 		}
@@ -360,7 +390,25 @@ pm2fb_attach(device_t parent, device_t s
 	aa.accessops = &pm2fb_accessops;
 	aa.accesscookie = &sc->vd;
 
-	config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);	
+	config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
+
+#ifdef PM2FB_DEBUG
+	/*
+	 * draw a pattern to check if pm2fb_bitblt() gets the alignment stuff
+	 * right
+	 */
+	pm2fb_rectfill(sc, 0, sc->sc_height, sc->sc_width, 200, 0xffffffff);
+	pm2fb_rectfill(sc, 0, sc->sc_height, 300, 10, 0);
+	pm2fb_rectfill(sc, 10, sc->sc_height, 200, 10, 0xe0e0e0e0);
+	for (i = 1; i < 20; i++) {
+		pm2fb_bitblt(sc, 0, sc->sc_height, 
+			i, sc->sc_height + 10 * i,
+			300, 10, 3);
+		pm2fb_bitblt(sc, i, sc->sc_height, 
+			400, sc->sc_height + 10 * i,
+			300, 10, 3);
+	}
+#endif
 }
 
 static int
@@ -414,7 +462,9 @@ pm2fb_ioctl(void *v, void *vs, u_long cm
 		if (new_mode != sc->sc_mode) {
 			sc->sc_mode = new_mode;
 			if(new_mode == WSDISPLAYIO_MODE_EMUL) {
+				pm2fb_init(sc);
 				pm2fb_restore_palette(sc);
+				glyphcache_wipe(&sc->sc_gc);
 				vcons_redraw_screen(ms);
 			} else
 				pm2fb_flush_engine(sc);
@@ -497,7 +547,7 @@ pm2fb_init_screen(void *cookie, struct v
 	ri->ri_stride = sc->sc_stride;
 	ri->ri_flg = RI_CENTER;
 	if (sc->sc_depth == 8)
-		ri->ri_flg |= RI_8BIT_IS_RGB /*| RI_ENABLE_ALPHA*/;
+		ri->ri_flg |= RI_8BIT_IS_RGB | RI_ENABLE_ALPHA;
 
 	rasops_init(ri, 0, 0);
 	ri->ri_caps = WSSCREEN_WSCOLORS;
@@ -511,7 +561,10 @@ pm2fb_init_screen(void *cookie, struct v
 	ri->ri_ops.cursor = pm2fb_cursor;
 	ri->ri_ops.eraserows = pm2fb_eraserows;
 	ri->ri_ops.erasecols = pm2fb_erasecols;
-	ri->ri_ops.putchar = pm2fb_putchar;
+	if (FONT_IS_ALPHA(ri->ri_font)) {
+		ri->ri_ops.putchar = pm2fb_putchar_aa;
+	} else
+		ri->ri_ops.putchar = pm2fb_putchar;
 }
 
 static int
@@ -694,6 +747,13 @@ pm2fb_init(struct pm2fb_softc *sc)
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SCISSOR_MINYX, 0);
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SCISSOR_MAXYX,
 	    0x0fff0fff);
+	/*
+	 * another scissor we need to disable in order to blit into off-screen
+	 * memory
+	 */
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SCREENSIZE,
+	    0x0fff0fff);
+
 	switch(sc->sc_depth) {
 		case 8:
 			bus_space_write_4(sc->sc_memt, sc->sc_regh,
@@ -709,7 +769,8 @@ pm2fb_init(struct pm2fb_softc *sc)
 			break;
 	}
 	pm2fb_flush_engine(sc);
-	DPRINTF("pixel size: %08x\n", bus_space_read_4(sc->sc_memt, sc->sc_regh, PM2_RE_PIXEL_SIZE));
+	DPRINTF("pixel size: %08x\n", 
+	    bus_space_read_4(sc->sc_memt, sc->sc_regh, PM2_RE_PIXEL_SIZE));
 }
 
 static void
@@ -733,11 +794,12 @@ pm2fb_rectfill(struct pm2fb_softc *sc, i
 }
 
 static void
-pm2fb_bitblt(struct pm2fb_softc *sc, int xs, int ys, int xd, int yd,
+pm2fb_bitblt(void *cookie, int xs, int ys, int xd, int yd,
     int wi, int he, int rop)
 {
+	struct pm2fb_softc *sc = cookie;
 	uint32_t dir = 0;
-	int rxs, rxd, rwi;
+	int rxs, rxd, rwi, rxdelta;
 
 	if (yd <= ys) {
 		dir |= PM2RE_INC_Y;
@@ -771,12 +833,14 @@ pm2fb_bitblt(struct pm2fb_softc *sc, int
 		}
 		rxs = xs >> 2;
 		rxd = xd >> 2;
-		rwi = wi >> 2;
+		rwi = (wi + 7) >> 2;
+		rxdelta = (xs & 0xffc) - (xd & 0xffc);
 		/* adjust for non-aligned x */
-		adjust = (xs & 3) - (xd & 3);
+		adjust = ((xd & 3) - (xs & 3));
 		bus_space_write_4(sc->sc_memt, sc->sc_regh,
 		    PM2_RE_PACKEDDATA_LIMIT,
 		    (xd << 16) | (xd + wi) | (adjust << 29));
+		
 	} else {
 		/* we're in 16 or 32bit mode */
 		if (rop == 3) {
@@ -794,13 +858,14 @@ pm2fb_bitblt(struct pm2fb_softc *sc, int
 		rxs = xs;
 		rxd = xd;
 		rwi = wi;
+		rxdelta = xs - xd;
 	}		
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_RECT_START,
 	    (yd << 16) | rxd);
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_RECT_SIZE,
 	    (he << 16) | rwi);
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SOURCE_DELTA,
-	    (((ys - yd) & 0xfff) << 16) | ((rxs - rxd) & 0xfff));
+	    (((ys - yd) & 0xfff) << 16) | (rxdelta & 0xfff));
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_RENDER,
 	    PM2RE_RECTANGLE | dir);
 }
@@ -934,6 +999,138 @@ pm2fb_putchar(void *cookie, int row, int
 }
 
 static void
+pm2fb_putchar_aa(void *cookie, int row, int col, u_int c, long attr)
+{
+	struct rasops_info *ri = cookie;
+	struct wsdisplay_font *font = PICK_FONT(ri, c);
+	struct vcons_screen *scr = ri->ri_hw;
+	struct pm2fb_softc *sc = scr->scr_cookie;
+	uint32_t bg, /*latch = 0,*/ bg8, fg8, pixel;
+	int i, x, y, wi, he, r, g, b, aval;
+	int r1, g1, b1, r0, g0, b0, fgo, bgo;
+	uint8_t *data8;
+	int rv = GC_NOPE, cnt = 0;
+
+	if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 
+		return;
+
+	if (!CHAR_IN_FONT(c, font))
+		return;
+
+	wi = font->fontwidth;
+	he = font->fontheight;
+
+	bg = ri->ri_devcmap[(attr >> 16) & 0xf];
+	x = ri->ri_xorigin + col * wi;
+	y = ri->ri_yorigin + row * he;
+	if (c == 0x20) {
+		pm2fb_rectfill(sc, x, y, wi, he, bg);
+		return;
+	}
+
+	rv = glyphcache_try(&sc->sc_gc, c, x, y, attr);
+	if (rv == GC_OK)
+		return;
+
+	data8 = WSFONT_GLYPH(c, font);
+
+	pm2fb_wait(sc, 5);
+#if 0
+	/*
+	 * TODO:
+	 * - use packed mode here as well, instead of writing each pixel separately
+	 * - support 32bit colour
+	 * - see if we can trick the chip into doing the alpha blending for us
+	 */
+	x = x >> 2;
+	wi = (wi + 3) >> 2;
+#endif
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_MODE, 0);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_CONFIG,
+			    PM2RECFG_WRITE_EN /*| PM2RECFG_PACKED*/);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, 
+			    PM2_RE_RECT_START, (y << 16) | x);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, 
+			    PM2_RE_RECT_SIZE, (he << 16) | wi);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, 
+			    PM2_RE_RENDER,
+			    PM2RE_RECTANGLE | PM2RE_SYNC_ON_HOST |
+			    PM2RE_INC_X | PM2RE_INC_Y);
+	/*
+	 * we need the RGB colours here, so get offsets into rasops_cmap
+	 */
+	fgo = ((attr >> 24) & 0xf) * 3;
+	bgo = ((attr >> 16) & 0xf) * 3;
+
+	r0 = rasops_cmap[bgo];
+	r1 = rasops_cmap[fgo];
+	g0 = rasops_cmap[bgo + 1];
+	g1 = rasops_cmap[fgo + 1];
+	b0 = rasops_cmap[bgo + 2];
+	b1 = rasops_cmap[fgo + 2];
+#define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6))
+	bg8 = R3G3B2(r0, g0, b0);
+	fg8 = R3G3B2(r1, g1, b1);
+
+	pm2fb_wait(sc, 200);
+
+	for (i = 0; i < ri->ri_fontscale; i++) {
+		aval = *data8;
+		if (aval == 0) {
+			pixel = bg8;
+		} else if (aval == 255) {
+			pixel = fg8;
+		} else {
+			r = aval * r1 + (255 - aval) * r0;
+			g = aval * g1 + (255 - aval) * g0;
+			b = aval * b1 + (255 - aval) * b0;
+			pixel = ((r & 0xe000) >> 8) |
+				((g & 0xe000) >> 11) |
+				((b & 0xc000) >> 14);
+		}
+#if 0
+		latch = (latch << 8) | pixel;
+		/* write in 32bit chunks */
+		if ((i & 3) == 3) {
+			bus_space_write_stream_4(sc->sc_memt, sc->sc_regh,
+			    PM2_RE_DATA, latch);
+			/*
+			 * not strictly necessary, old data should be shifted 
+			 * out 
+			 */
+			latch = 0;
+			cnt++;
+			if (cnt > 190) {
+				pm2fb_wait(sc, 200);
+				cnt = 0;
+			}
+		}
+#else
+		bus_space_write_4(sc->sc_memt, sc->sc_regh,
+			    PM2_RE_COLOUR, pixel);
+
+		if (cnt > 190) {
+			pm2fb_wait(sc, 200);
+			cnt = 0;
+		}		
+#endif
+		data8++;
+	}
+#if 0
+	/* if we have pixels left in latch write them out */
+	if ((i & 3) != 0) {
+		latch = latch << ((4 - (i & 3)) << 3);	
+		bus_space_write_stream_4(sc->sc_memt, sc->sc_regh,
+				    PM2_RE_DATA, latch);
+	}
+#endif
+
+	if (rv == GC_ADD) {
+		glyphcache_add(&sc->sc_gc, c, x, y);
+	}
+}
+
+static void
 pm2fb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
 {
 	struct rasops_info *ri = cookie;

Index: src/sys/dev/pci/pm2reg.h
diff -u src/sys/dev/pci/pm2reg.h:1.7 src/sys/dev/pci/pm2reg.h:1.8
--- src/sys/dev/pci/pm2reg.h:1.7	Wed Sep  5 01:32:01 2012
+++ src/sys/dev/pci/pm2reg.h	Wed Sep 12 12:07:04 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: pm2reg.h,v 1.7 2012/09/05 01:32:01 macallan Exp $	*/
+/*	$NetBSD: pm2reg.h,v 1.8 2012/09/12 12:07:04 macallan Exp $	*/
 
 /*
  * Copyright (c) 2009 Michael Lorenz
@@ -322,6 +322,8 @@
 #define PM2_RE_STENCIL_MODE	0x00008988
 #define PM2_RE_ROP_MODE		0x00008828
 #define PM2_RE_PACKEDDATA_LIMIT	0x00008150
+#define PM2_RE_DATA		0x00008aa0	/* pixel data */
+#define PM2_RE_SOURCEDATA	0x00008aa8	/* raw data */
 
 
 #endif /* PM2_REG_H */

Reply via email to