Module Name: src Committed By: macallan Date: Wed Jan 25 03:49:12 UTC 2012
Modified Files: src/sys/dev/pci: voodoofb.c Log Message: add a simple glyph cacheing scheme Glyphs which use the default attribute will be saved into offscreen video memory the first time they're used and subsequent uses will just copy them from there instead of rendering them every time. This should give a nice speedup especially on slow CPUs. To generate a diff of this commit: cvs rdiff -u -r1.36 -r1.37 src/sys/dev/pci/voodoofb.c 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/voodoofb.c diff -u src/sys/dev/pci/voodoofb.c:1.36 src/sys/dev/pci/voodoofb.c:1.37 --- src/sys/dev/pci/voodoofb.c:1.36 Wed Jan 25 02:04:35 2012 +++ src/sys/dev/pci/voodoofb.c Wed Jan 25 03:49:12 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: voodoofb.c,v 1.36 2012/01/25 02:04:35 macallan Exp $ */ +/* $NetBSD: voodoofb.c,v 1.37 2012/01/25 03:49:12 macallan Exp $ */ /* * Copyright (c) 2005, 2006 Michael Lorenz @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: voodoofb.c,v 1.36 2012/01/25 02:04:35 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: voodoofb.c,v 1.37 2012/01/25 03:49:12 macallan Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -90,6 +90,15 @@ struct voodoofb_softc { int sc_width, sc_height, sc_linebytes; const struct videomode *sc_videomode; + /* glyph cache */ + long sc_defattr, sc_kernattr; + uint32_t sc_glyphs_defattr[256]; + uint32_t sc_glyphs_kernattr[256]; + int sc_numglyphs, sc_usedglyphs; + uint32_t sc_cache; /* offset where cache starts */ + uint32_t sc_fmt; /* *fmt register */ + void *sc_font; + /* i2c stuff */ struct i2c_controller sc_i2c; uint8_t sc_edid_data[128]; @@ -160,6 +169,8 @@ static void voodoofb_setup_mono(struct v static void voodoofb_feed_line(struct voodoofb_softc *, int, uint8_t *); static void voodoofb_wait_idle(struct voodoofb_softc *); +static void voodoofb_init_glyphcache(struct voodoofb_softc *, + struct rasops_info *); #ifdef VOODOOFB_ENABLE_INTR static int voodoofb_intr(void *); @@ -421,6 +432,8 @@ voodoofb_attach(device_t parent, device_ voodoofb_set_videomode(sc, sc->sc_videomode); + sc->sc_font = NULL; + vcons_init(&sc->vd, sc, &voodoofb_defaultscreen, &voodoofb_accessops); sc->vd.init_screen = voodoofb_init_screen; @@ -758,7 +771,7 @@ voodoofb_putchar_aa(void *cookie, int ro struct vcons_screen *scr = ri->ri_hw; struct voodoofb_softc *sc = scr->scr_cookie; uint8_t *data; - uint32_t bg, latch = 0, bg8, fg8, pixel; + uint32_t bg, latch = 0, bg8, fg8, pixel, save_offset = 0; int i, x, y, wi, he, r, g, b, aval; int r1, g1, b1, r0, g0, b0, fgo, bgo, j; @@ -778,9 +791,33 @@ voodoofb_putchar_aa(void *cookie, int ro voodoofb_rectfill(sc, x, y, wi, he, bg); return; } + + /* first, see if it's in the cache */ + if ((attr == sc->sc_defattr) && (c < 256)) { + uint32_t offset = sc->sc_glyphs_defattr[c]; + if (offset != 0) { + voodoo3_make_room(sc, 8); + voodoo3_write32(sc, SRCBASE, offset); + voodoo3_write32(sc, DSTBASE, 0); + voodoo3_write32(sc, SRCFORMAT, sc->sc_fmt); + voodoo3_write32(sc, DSTFORMAT, sc->sc_linebytes | FMT_8BIT); + voodoo3_write32(sc, DSTSIZE, wi | (he << 16)); + voodoo3_write32(sc, DSTXY, x | (y << 16)); + voodoo3_write32(sc, SRCXY, 0); + voodoo3_write32(sc, COMMAND_2D, COMMAND_2D_S2S_BITBLT | + (ROP_COPY << 24) | SST_2D_GO); + return; + } else { + int slot = sc->sc_usedglyphs; + sc->sc_usedglyphs++; + save_offset = sc->sc_cache + (slot * ri->ri_fontscale); + sc->sc_glyphs_defattr[c] = save_offset; + } + } data = WSFONT_GLYPH(c, font); - voodoo3_make_room(sc, 6); + voodoo3_make_room(sc, 7); + voodoo3_write32(sc, DSTBASE, 0); voodoo3_write32(sc, SRCFORMAT, FMT_8BIT | FMT_PAD_BYTE); voodoo3_write32(sc, DSTFORMAT, sc->sc_linebytes | FMT_8BIT); voodoo3_write32(sc, DSTSIZE, wi | (he << 16)); @@ -848,6 +885,19 @@ voodoofb_putchar_aa(void *cookie, int ro latch = latch << ((4 - (i & 3)) << 3); voodoo3_write32s(sc, LAUNCH_2D, latch); } + if (save_offset != 0) { + /* save the glyph we just drew */ + voodoo3_make_room(sc, 8); + voodoo3_write32(sc, SRCBASE, 0); + voodoo3_write32(sc, DSTBASE, save_offset); + voodoo3_write32(sc, SRCFORMAT, sc->sc_linebytes | FMT_8BIT); + voodoo3_write32(sc, DSTFORMAT, sc->sc_fmt); + voodoo3_write32(sc, DSTSIZE, wi | (he << 16)); + voodoo3_write32(sc, DSTXY, 0); + voodoo3_write32(sc, SRCXY, x | (y << 16)); + voodoo3_write32(sc, COMMAND_2D, COMMAND_2D_S2S_BITBLT | + (ROP_COPY << 24) | SST_2D_GO); + } } static void @@ -950,8 +1000,10 @@ voodoofb_bitblt(struct voodoofb_softc *s ys += (height - 1); yd += (height - 1); } - voodoo3_make_room(sc, 6); + voodoo3_make_room(sc, 8); + voodoo3_write32(sc, SRCBASE, 0); + voodoo3_write32(sc, DSTBASE, 0); voodoo3_write32(sc, SRCFORMAT, fmt); voodoo3_write32(sc, DSTFORMAT, fmt); voodoo3_write32(sc, DSTSIZE, width | (height << 16)); @@ -970,8 +1022,9 @@ voodoofb_rectfill(struct voodoofb_softc fmt = sc->sc_linebytes | ((sc->sc_bits_per_pixel + ((sc->sc_bits_per_pixel == 8) ? 0 : 8)) << 13); - voodoo3_make_room(sc, 6); + voodoo3_make_room(sc, 7); voodoo3_write32(sc, DSTFORMAT, fmt); + voodoo3_write32(sc, DSTBASE, 0); voodoo3_write32(sc, COLORFORE, colour); voodoo3_write32(sc, COLORBACK, colour); voodoo3_write32(sc, COMMAND_2D, COMMAND_2D_FILLRECT | (ROP_COPY << 24)); @@ -988,7 +1041,9 @@ voodoofb_rectinvert(struct voodoofb_soft fmt = sc->sc_linebytes | ((sc->sc_bits_per_pixel + ((sc->sc_bits_per_pixel == 8) ? 0 : 8)) << 13); - voodoo3_make_room(sc, 6); + voodoo3_make_room(sc, 8); + voodoo3_write32(sc, SRCBASE, 0); + voodoo3_write32(sc, DSTBASE, 0); voodoo3_write32(sc, DSTFORMAT, fmt); voodoo3_write32(sc, COMMAND_2D, COMMAND_2D_FILLRECT | (ROP_INVERT << 24)); @@ -1006,9 +1061,10 @@ voodoofb_setup_mono(struct voodoofb_soft dfmt = sc->sc_linebytes | ((sc->sc_bits_per_pixel + ((sc->sc_bits_per_pixel == 8) ? 0 : 8)) << 13); - voodoo3_make_room(sc, 9); + voodoo3_make_room(sc, 10); voodoo3_write32(sc, SRCFORMAT, sfmt); voodoo3_write32(sc, DSTFORMAT, dfmt); + voodoo3_write32(sc, DSTBASE, 0); voodoo3_write32(sc, COLORFORE, fg); voodoo3_write32(sc, COLORBACK, bg); voodoo3_write32(sc, DSTSIZE, width | (height << 16)); @@ -1207,6 +1263,10 @@ voodoofb_init_screen(void *cookie, struc ri->ri_ops.cursor = voodoofb_cursor; if (FONT_IS_ALPHA(ri->ri_font)) { ri->ri_ops.putchar = voodoofb_putchar_aa; + ri->ri_ops.allocattr(ri, WS_DEFAULT_FG, WS_DEFAULT_BG, + 0, &sc->sc_defattr); + sc->sc_kernattr = (WS_KERNEL_FG << 24) | (WS_KERNEL_BG << 16); + voodoofb_init_glyphcache(sc, ri); } else { ri->ri_ops.putchar = voodoofb_putchar; } @@ -1541,6 +1601,7 @@ voodoofb_set_videomode(struct voodoofb_s voodoofb_wait_idle(sc); printf("%s: switched to %dx%d, %d bit\n", device_xname(sc->sc_dev), sc->sc_width, sc->sc_height, sc->sc_bits_per_pixel); + sc->sc_numglyphs = 0; /* invalidate the glyph cache */ } static void @@ -1750,3 +1811,27 @@ voodoofb_i2c_write_byte(void *cookie, ui { return (i2c_bitbang_write_byte(cookie, val, flags, &voodoofb_i2cbb_ops)); } + +/* glyph cache */ +static void +voodoofb_init_glyphcache(struct voodoofb_softc *sc, struct rasops_info *ri) +{ + int bufsize, i; + + if (sc->sc_numglyphs != 0) { + /* re-initialize */ + if (ri->ri_font == sc->sc_font) { + /* nothing to do, keep using the same cache */ + return; + } + } + sc->sc_cache = (ri->ri_width * ri->ri_stride + 3) & 0xfffffffc; + bufsize = sc->sc_memsize - sc->sc_cache; + sc->sc_numglyphs = bufsize / ri->ri_fontscale; + sc->sc_usedglyphs = 0; + for (i = 0; i < 256; i++) { + sc->sc_glyphs_kernattr[i] = 0; + sc->sc_glyphs_defattr[i] = 0; + } + sc->sc_fmt = ri->ri_font->fontwidth | FMT_8BIT; +}