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 */