diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-01-02 20:36:20 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-01-02 20:36:20 +0000 |
commit | 14f528424baa95c1edc8ccedcd348c62620794e4 (patch) | |
tree | 387c3fc04f4c2aec4213c40ff078b9bc5b792bc4 /sys | |
parent | ba9f5da24a25d2ffb8d23552059caf231dca463a (diff) |
Accelerated routines for solid fills and inverted cursor.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc64/dev/ifb.c | 229 |
1 files changed, 109 insertions, 120 deletions
diff --git a/sys/arch/sparc64/dev/ifb.c b/sys/arch/sparc64/dev/ifb.c index 17a0ff591da..b665b05e67c 100644 --- a/sys/arch/sparc64/dev/ifb.c +++ b/sys/arch/sparc64/dev/ifb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ifb.c,v 1.12 2009/01/01 19:25:39 miod Exp $ */ +/* $OpenBSD: ifb.c,v 1.13 2009/01/02 20:36:19 miod Exp $ */ /* * Copyright (c) 2007, 2008, 2009 Miodrag Vallat. @@ -204,8 +204,19 @@ #define IFB_REG_DPMS_STANDBY 0x00000002 #define IFB_REG_DPMS_ON 0x00000003 +/* + * (some) ROP codes + */ + +#define IFB_ROP_CLEAR 0x00000000 /* clear bits in rop mask */ +#define IFB_ROP_SRC 0x00330000 /* copy src bits matching rop mask */ +#define IFB_ROP_XOR 0x00cc0000 /* xor src bits with rop mask */ +#define IFB_ROP_SET 0x00ff0000 /* set bits in rop mask */ + #define IFB_COORDS(x, y) ((x) | (y) << 16) +#define IFB_PIXELMASK 0x7f /* 7bpp */ + struct ifb_softc { struct sunfb sc_sunfb; @@ -223,8 +234,7 @@ struct ifb_softc { u_int sc_mode; - struct wsdisplay_emulops sc_old_ops; - void (*sc_old_cursor)(struct rasops_info *); + void (*sc_old_putchar)(void *, int, int, u_int, long); int sc_console; u_int8_t sc_cmap_red[256]; @@ -269,6 +279,11 @@ void ifb_setcolormap(struct sunfb *, void (*)(void *, u_int, u_int8_t, u_int8_t, u_int8_t)); void ifb_copyrect(struct ifb_softc *, int, int, int, int, int, int); +void ifb_fillrect(struct ifb_softc *, int, int, int, int, int); +void ifb_rop(struct ifb_softc *, int, int, int, int, int, int, uint32_t, + int32_t); +void ifb_rop_wait(struct ifb_softc *); + void ifb_putchar(void *, int, int, u_int, long); void ifb_copycols(void *, int, int, int, int); void ifb_erasecols(void *, int, int, int, long); @@ -334,19 +349,20 @@ ifbattach(struct device *parent, struct device *self, void *aux) ri->ri_hw = sc; fbwscons_init(&sc->sc_sunfb, RI_BSWAP, sc->sc_console); - ri->ri_flg &= ~RI_FULLCLEAR; /* due to the way we handle updates */ - if (!sc->sc_console) { - bzero((void *)sc->sc_fb8bank0_vaddr, sc->sc_sunfb.sf_fbsize); - bzero((void *)sc->sc_fb8bank1_vaddr, sc->sc_sunfb.sf_fbsize); - } + /* + * Clear the unwanted pixel planes: all if non console (thus + * white background), and all planes above 7bpp otherwise. + */ + ifb_rop(sc, 0, 0, 0, 0, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height, + IFB_ROP_CLEAR, sc->sc_console ? ~IFB_PIXELMASK : ~0); + ifb_rop_wait(sc); /* pick centering delta */ sc->sc_fb8bank0_vaddr += ri->ri_bits - ri->ri_origbits; sc->sc_fb8bank1_vaddr += ri->ri_bits - ri->ri_origbits; - sc->sc_old_ops = ri->ri_ops; /* structure copy */ - sc->sc_old_cursor = ri->ri_do_cursor; + sc->sc_old_putchar = ri->ri_ops.putchar; ri->ri_ops.copyrows = ifb_copyrows; ri->ri_ops.copycols = ifb_copycols; ri->ri_ops.eraserows = ifb_eraserows; @@ -527,13 +543,13 @@ ifb_setcolormap(struct sunfb *sf, color = &rasops_cmap[(WSCOL_WHITE + 8) * 3]; /* real white */ setcolor(sf, 0, color[0], color[1], color[2]); - setcolor(sf, 0x7f ^ 0, ~color[0], ~color[1], ~color[2]); + setcolor(sf, IFB_PIXELMASK ^ 0, ~color[0], ~color[1], ~color[2]); color = &rasops_cmap[WSCOL_BLACK * 3]; setcolor(sf, 1, color[0], color[1], color[2]); - setcolor(sf, 0x7f ^ 1, ~color[0], ~color[1], ~color[2]); + setcolor(sf, IFB_PIXELMASK ^ 1, ~color[0], ~color[1], ~color[2]); color = &rasops_cmap[WSCOL_RED * 3]; setcolor(sf, 7, color[0], color[1], color[2]); - setcolor(sf, 0x7f ^ 7, ~color[0], ~color[1], ~color[2]); + setcolor(sf, IFB_PIXELMASK ^ 7, ~color[0], ~color[1], ~color[2]); } paddr_t @@ -654,9 +670,9 @@ ifb_putchar(void *cookie, int row, int col, u_int uc, long attr) struct ifb_softc *sc = ri->ri_hw; ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; - sc->sc_old_ops.putchar(cookie, row, col, uc, attr); + sc->sc_old_putchar(cookie, row, col, uc, attr); ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; - sc->sc_old_ops.putchar(cookie, row, col, uc, attr); + sc->sc_old_putchar(cookie, row, col, uc, attr); } void @@ -680,11 +696,16 @@ ifb_erasecols(void *cookie, int row, int col, int num, long attr) { struct rasops_info *ri = cookie; struct ifb_softc *sc = ri->ri_hw; + int bg, fg; - ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; - sc->sc_old_ops.erasecols(cookie, row, col, num, attr); - ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr; - sc->sc_old_ops.erasecols(cookie, row, col, num, attr); + ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); + + row *= ri->ri_font->fontheight; + col *= ri->ri_font->fontwidth; + num *= ri->ri_font->fontwidth; + + ifb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, + num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); } void @@ -706,43 +727,66 @@ ifb_eraserows(void *cookie, int row, int num, long attr) { struct rasops_info *ri = cookie; struct ifb_softc *sc = ri->ri_hw; - int bg, fg, done, cnt; - - /* - * Perform the first line with plain rasops code (adapted below)... - */ + int bg, fg; + int x, y, w; ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); - memset((void *)(sc->sc_fb8bank0_vaddr + row * ri->ri_yscale), - ri->ri_devcmap[bg], ri->ri_emustride); - memset((void *)(sc->sc_fb8bank1_vaddr + row * ri->ri_yscale), - ri->ri_devcmap[bg], ri->ri_emustride); - - /* - * ...then copy it over and over until the whole area is done. - */ + if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { + num = ri->ri_height; + x = y = 0; + w = ri->ri_width; + } else { + num *= ri->ri_font->fontheight; + x = ri->ri_xorigin; + y = ri->ri_yorigin + row * ri->ri_font->fontheight; + w = ri->ri_emuwidth; + } + ifb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); +} - row *= ri->ri_font->fontheight; - num *= ri->ri_font->fontheight; - row += ri->ri_yorigin; +void +ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h) +{ + ifb_rop(sc, sx, sy, dx, dy, w, h, IFB_ROP_SRC, IFB_PIXELMASK); + ifb_rop_wait(sc); +} - for (done = 1, num -= done; num != 0;) { - cnt = min(done, num); +void +ifb_fillrect(struct ifb_softc *sc, int x, int y, int w, int h, int bg) +{ + int32_t mask; - ifb_copyrect(sc, ri->ri_xorigin, row, - ri->ri_xorigin, row + done, ri->ri_emuwidth, cnt); + /* pixels to set... */ + mask = IFB_PIXELMASK & bg; + if (mask != 0) { + ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_SET, mask); + ifb_rop_wait(sc); + } - done += cnt; - num -= cnt; + /* pixels to clear... */ + mask = IFB_PIXELMASK & ~bg; + if (mask != 0) { + ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_CLEAR, mask); + ifb_rop_wait(sc); } } +/* + * Perform a raster operation on both overlay planes. + * Puzzled by all the magic numbers in there? So are we. Isn't a dire + * lack of documentation wonderful? + */ void -ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h) +ifb_rop(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h, + uint32_t rop, int32_t planemask) { - int i, dir = 0; + int dir = 0; + /* + * Compute rop direction. This only really matters for + * screen-to-screen copies. + */ if (sy < dy /* && sy + h > dy */) { sy += h - 1; dy += h; @@ -754,11 +798,12 @@ ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h) dir |= IFB_REG_MAGIC_DIR_BACKWARDS_X; } - /* Lots of magic numbers. */ + /* Which one of those below is your magic number for today? */ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_OFFSET + IFB_REG_MAGIC, 2); bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_OFFSET + IFB_REG_MAGIC, 1); + /* the ``0101'' part is probably a component selection */ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_OFFSET + IFB_REG_MAGIC, 0x540101ff); bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, @@ -770,15 +815,20 @@ ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h) bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_OFFSET + IFB_REG_MAGIC, 0x80000000); bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, - IFB_REG_OFFSET + IFB_REG_MAGIC, 0x00330000); + IFB_REG_OFFSET + IFB_REG_MAGIC, rop); bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, - IFB_REG_OFFSET + IFB_REG_MAGIC, 0xff); + IFB_REG_OFFSET + IFB_REG_MAGIC, planemask); bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_OFFSET + IFB_REG_MAGIC, 0); bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_OFFSET + IFB_REG_MAGIC, 0x64000303); + /* + * This value is a pixel offset within the destination area. It is + * probably used to define complex polygon shapes, with the + * last pixel in the list being back to (0,0). + */ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, - IFB_REG_OFFSET + IFB_REG_MAGIC, 0); + IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(0, 0)); bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_OFFSET + IFB_REG_MAGIC, 0); bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, @@ -794,6 +844,12 @@ ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h) IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(w, h)); bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(sx, sy)); +} + +void +ifb_rop_wait(struct ifb_softc *sc) +{ + int i; for (i = 1000000; i > 0; i--) { if (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h, @@ -803,83 +859,16 @@ ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h) } } -/* - * Similar to rasops_do_cursor(), but using a 7bit pixel mask. - */ - -#define CURSOR_MASK 0x7f7f7f7f - void ifb_do_cursor(struct rasops_info *ri) { struct ifb_softc *sc = ri->ri_hw; - int full1, height, cnt, slop1, slop2, row, col; - int ovl_offset = sc->sc_fb8bank1_vaddr - sc->sc_fb8bank0_vaddr; - u_char *dp0, *dp1, *rp; + int y, x; - row = ri->ri_crow; - col = ri->ri_ccol; + y = ri->ri_yorigin + ri->ri_crow * ri->ri_font->fontheight; + x = ri->ri_xorigin + ri->ri_ccol * ri->ri_font->fontwidth; - ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr; - rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale; - height = ri->ri_font->fontheight; - slop1 = (4 - ((long)rp & 3)) & 3; - - if (slop1 > ri->ri_xscale) - slop1 = ri->ri_xscale; - - slop2 = (ri->ri_xscale - slop1) & 3; - full1 = (ri->ri_xscale - slop1 - slop2) >> 2; - - if ((slop1 | slop2) == 0) { - /* A common case */ - while (height--) { - dp0 = rp; - dp1 = dp0 + ovl_offset; - rp += ri->ri_stride; - - for (cnt = full1; cnt; cnt--) { - *(int32_t *)dp0 ^= CURSOR_MASK; - *(int32_t *)dp1 ^= CURSOR_MASK; - dp0 += 4; - dp1 += 4; - } - } - } else { - /* XXX this is stupid.. use masks instead */ - while (height--) { - dp0 = rp; - dp1 = dp0 + ovl_offset; - rp += ri->ri_stride; - - if (slop1 & 1) { - *dp0++ ^= (u_char)CURSOR_MASK; - *dp1++ ^= (u_char)CURSOR_MASK; - } - - if (slop1 & 2) { - *(int16_t *)dp0 ^= (int16_t)CURSOR_MASK; - *(int16_t *)dp1 ^= (int16_t)CURSOR_MASK; - dp0 += 2; - dp1 += 2; - } - - for (cnt = full1; cnt; cnt--) { - *(int32_t *)dp0 ^= CURSOR_MASK; - *(int32_t *)dp1 ^= CURSOR_MASK; - dp0 += 4; - dp1 += 4; - } - - if (slop2 & 1) { - *dp0++ ^= (u_char)CURSOR_MASK; - *dp1++ ^= (u_char)CURSOR_MASK; - } - - if (slop2 & 2) { - *(int16_t *)dp0 ^= (int16_t)CURSOR_MASK; - *(int16_t *)dp1 ^= (int16_t)CURSOR_MASK; - } - } - } + ifb_rop(sc, x, y, x, y, ri->ri_font->fontwidth, ri->ri_font->fontheight, + IFB_ROP_XOR, IFB_PIXELMASK); + ifb_rop_wait(sc); } |