summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-01-02 20:36:20 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-01-02 20:36:20 +0000
commit14f528424baa95c1edc8ccedcd348c62620794e4 (patch)
tree387c3fc04f4c2aec4213c40ff078b9bc5b792bc4 /sys
parentba9f5da24a25d2ffb8d23552059caf231dca463a (diff)
Accelerated routines for solid fills and inverted cursor.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc64/dev/ifb.c229
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);
}