Module Name:    src
Committed By:   macallan
Date:           Mon Jul 15 10:26:09 UTC 2024

Modified Files:
        src/sys/arch/hppa/dev: hyperfb.c

Log Message:
we have a blitter - use it


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/hppa/dev/hyperfb.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/arch/hppa/dev/hyperfb.c
diff -u src/sys/arch/hppa/dev/hyperfb.c:1.1 src/sys/arch/hppa/dev/hyperfb.c:1.2
--- src/sys/arch/hppa/dev/hyperfb.c:1.1	Fri Jul 12 08:43:08 2024
+++ src/sys/arch/hppa/dev/hyperfb.c	Mon Jul 15 10:26:09 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: hyperfb.c,v 1.1 2024/07/12 08:43:08 macallan Exp $	*/
+/*	$NetBSD: hyperfb.c,v 1.2 2024/07/15 10:26:09 macallan Exp $	*/
 
 /*
  * Copyright (c) 2024 Michael Lorenz
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hyperfb.c,v 1.1 2024/07/12 08:43:08 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hyperfb.c,v 1.2 2024/07/15 10:26:09 macallan Exp $");
 
 #include "opt_cputype.h"
 #include "opt_hyperfb.h"
@@ -133,6 +133,52 @@ static int 	hyperfb_putpalreg(struct hyp
 void 	hyperfb_setup(struct hyperfb_softc *);
 static void	hyperfb_set_video(struct hyperfb_softc *, int);
 
+static void	hyperfb_rectfill(struct hyperfb_softc *, int, int, int, int,
+			    uint32_t);
+static void	hyperfb_bitblt(void *, int, int, int, int, int,
+			    int, int);
+
+static void	hyperfb_cursor(void *, int, int, int);
+static void	hyperfb_putchar(void *, int, int, u_int, long);
+static void	hyperfb_copycols(void *, int, int, int, int);
+static void	hyperfb_erasecols(void *, int, int, int, long);
+static void	hyperfb_copyrows(void *, int, int, int);
+static void	hyperfb_eraserows(void *, int, int, long);
+
+#if 0
+static void	hyperfb_move_cursor(struct hyperfb_softc *, int, int);
+static int	hyperfb_do_cursor(struct hyperfb_softc *, struct wsdisplay_cursor *);
+#endif
+
+#define BA(F,C,S,A,J,B,I)						\
+	(((F)<<31)|((C)<<27)|((S)<<24)|((A)<<21)|((J)<<16)|((B)<<12)|(I))
+	/* FCCCCSSSAAAJJJJJBBBBIIIIIIIIIIII */
+
+#define IBOvals(R,M,X,S,D,L,B,F)					\
+	(((R)<<8)|((M)<<16)|((X)<<24)|((S)<<29)|((D)<<28)|((L)<<31)|((B)<<1)|(F))
+	/* LSSDXXXXMMMMMMMMRRRRRRRRBBBBBBBF */
+
+#define	    IndexedDcd	0	/* Pixel data is indexed (pseudo) color */
+#define	    Otc04	2	/* Pixels in each longword transfer (4) */
+#define	    Otc32	5	/* Pixels in each longword transfer (32) */
+#define	    Ots08	3	/* Each pixel is size (8)d transfer (1) */
+#define	    OtsIndirect	6	/* Each bit goes through FG/BG color(8) */
+#define	    AddrLong	5	/* FB address is Long aligned (pixel) */
+#define	    BINovly	0x2	/* 8 bit overlay */
+#define	    BINapp0I	0x0	/* Application Buffer 0, Indexed */
+#define	    BINapp1I	0x1	/* Application Buffer 1, Indexed */
+#define	    BINapp0F8	0xa	/* Application Buffer 0, Fractional 8-8-8 */
+#define	    BINattr	0xd	/* Attribute Bitmap */
+#define	    RopSrc 	0x3
+#define	    RopInv 	0xc
+#define	    BitmapExtent08  3	/* Each write hits ( 8) bits in depth */
+#define	    BitmapExtent32  5	/* Each write hits (32) bits in depth */
+#define	    DataDynamic	    0	/* Data register reloaded by direct access */
+#define	    MaskDynamic	    1	/* Mask register reloaded by direct access */
+#define	    MaskOtc	    0	/* Mask contains Object Count valid bits */
+
+static inline void hyperfb_wait_fifo(struct hyperfb_softc *, uint32_t);
+
 #define	ngle_bt458_write(sc, r, v) \
 	hyperfb_write4(sc, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
 
@@ -183,6 +229,16 @@ hyperfb_wait(struct hyperfb_softc *sc)
 	} while (stat != 0);
 }
 
+static inline void
+hyperfb_wait_fifo(struct hyperfb_softc *sc, uint32_t slots)
+{
+	uint32_t reg;
+
+	do {
+		reg = hyperfb_read4(sc, NGLE_REG_34);
+	} while (reg < slots);
+}
+
 void
 hyperfb_setup_fb(struct hyperfb_softc *sc)
 {
@@ -395,10 +451,10 @@ hyperfb_attach(device_t parent, device_t
 #endif
 		wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
 		    defattr);
-#if 0
+
 		hyperfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
 		    ri->ri_devcmap[(defattr >> 16) & 0xff]);
-#endif
+
 		vcons_replay_msgbuf(&sc->sc_console_screen);
 	} else {
 		/*
@@ -456,21 +512,20 @@ hyperfb_init_screen(void *cookie, struct
 	rasops_init(ri, 0, 0);
 	ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
 		      WSSCREEN_RESIZE;
-	scr->scr_flags |= VCONS_LOADFONT | VCONS_DONT_READ;
+	scr->scr_flags |= VCONS_LOADFONT;
 
 	rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
 		    sc->sc_width / ri->ri_font->fontwidth);
 
 	ri->ri_hw = scr;
-#if 0
+
 	sc->sc_putchar = ri->ri_ops.putchar;
-	ri->ri_ops.copyrows = gftfb_copyrows;
-	ri->ri_ops.copycols = gftfb_copycols;
-	ri->ri_ops.eraserows = gftfb_eraserows;
-	ri->ri_ops.erasecols = gftfb_erasecols;
-	ri->ri_ops.cursor = gftfb_cursor;
-	ri->ri_ops.putchar = gftfb_putchar;
-#endif
+	ri->ri_ops.copyrows = hyperfb_copyrows;
+	ri->ri_ops.copycols = hyperfb_copycols;
+	ri->ri_ops.eraserows = hyperfb_eraserows;
+	ri->ri_ops.erasecols = hyperfb_erasecols;
+	ri->ri_ops.cursor = hyperfb_cursor;
+	ri->ri_ops.putchar = hyperfb_putchar;
 }
 
 static int
@@ -517,10 +572,10 @@ hyperfb_ioctl(void *v, void *vs, u_long 
 				hyperfb_restore_palette(sc);
 #if 0
 				glyphcache_wipe(&sc->sc_gc);
+#endif
 				hyperfb_rectfill(sc, 0, 0, sc->sc_width,
 				    sc->sc_height, ms->scr_ri.ri_devcmap[
 				    (ms->scr_defattr >> 16) & 0xff]);
-#endif
 				vcons_redraw_screen(ms);
 				hyperfb_set_video(sc, 1);
 			}
@@ -552,7 +607,7 @@ hyperfb_ioctl(void *v, void *vs, u_long 
 		{
 			struct wsdisplay_curpos *cp = (void *)data;
 
-			gftfb_move_cursor(sc, cp->x, cp->y);
+			hyperfb_move_cursor(sc, cp->x, cp->y);
 		}
 		return 0;
 
@@ -569,7 +624,7 @@ hyperfb_ioctl(void *v, void *vs, u_long 
 		{
 			struct wsdisplay_cursor *cursor = (void *)data;
 
-			return gftfb_do_cursor(sc, cursor);
+			return hyperfb_do_cursor(sc, cursor);
 		}
 #endif
 
@@ -719,10 +774,8 @@ hyperfb_setup(struct hyperfb_softc *sc)
 	sc->sc_enabled = 0;
 	sc->sc_video_on = 1;
 
-#if 0
 	sc->sc_rect_colour = 0xf0000000;
 	sc->sc_rect_height = 0;
-#endif
 
 	/* set Bt458 read mask register to all planes */
 	/* XXX I'm not sure HCRX even has one of these */
@@ -818,7 +871,7 @@ hyperfb_setup(struct hyperfb_softc *sc)
 
 	//hyperfb_write4(sc, NGLE_REG_29, 0x80200020);
 
-	//gftfb_move_cursor(sc, 100, 100);
+	//hyperfb_move_cursor(sc, 100, 100);
 
 }
 
@@ -841,3 +894,260 @@ hyperfb_set_video(struct hyperfb_softc *
 		hyperfb_write4(sc, NGLE_REG_33, reg & ~0x0a000000);
 	}
 }
+
+static void
+hyperfb_rectfill(struct hyperfb_softc *sc, int x, int y, int wi, int he,
+		      uint32_t bg)
+{
+	/*
+	 * XXX
+	 * HCRX has the same problem as VisEG drawing rectangles less than 32
+	 * pixels wide, but here we don't seem to have any usable offscreen 
+	 * memory, at least not as long as we're using the overlay planes.
+	 * As a workaround, fall back to memset()-based fills for rectangles
+	 * less than 32 pixels wide
+	 */
+	if (wi < 32) {
+		int i;
+		uint8_t *ptr = (uint8_t *)sc->sc_fb + (y << 11) + x;
+
+		if (sc->sc_hwmode != HW_FB)
+			hyperfb_setup_fb(sc);
+
+		for (i = 0; i < he; i++) {
+			memset(ptr, bg, wi);
+			ptr += 2048;
+		}
+		return;
+	}
+	if (sc->sc_hwmode != HW_FILL) {
+		hyperfb_wait_fifo(sc, 4);
+		/* transfer data */
+		hyperfb_write4(sc, NGLE_REG_8, 0xffffffff);
+		/* plane mask */
+		hyperfb_write4(sc, NGLE_REG_13, 0xff);
+		/* bitmap op */
+		hyperfb_write4(sc, NGLE_REG_14, 
+		    IBOvals(RopSrc, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 0, 0));
+		/* dst bitmap access */
+		hyperfb_write4(sc, NGLE_REG_11,
+		    BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINovly, 0));
+		sc->sc_hwmode = HW_FILL;
+	}
+	hyperfb_wait_fifo(sc, 3);
+	hyperfb_write4(sc, NGLE_REG_35, bg);
+	/* dst XY */
+	hyperfb_write4(sc, NGLE_REG_6, (x << 16) | y);
+	/* len XY start */
+	hyperfb_write4(sc, NGLE_REG_9, (wi << 16) | he);
+}
+
+static void
+hyperfb_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi,
+			    int he, int rop)
+{
+	struct hyperfb_softc *sc = cookie;
+
+	if (sc->sc_hwmode != HW_BLIT) {
+		hyperfb_wait(sc);
+		hyperfb_write4(sc, NGLE_REG_10, 0x13a02000);
+		hyperfb_write4(sc, NGLE_REG_13, 0xff);
+		sc->sc_hwmode = HW_BLIT;
+	}
+	hyperfb_wait_fifo(sc, 4);
+	hyperfb_write4(sc, NGLE_REG_14, ((rop << 8) & 0xf00) | 0x23000000);
+	/* IBOvals(rop, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 0, 0) */
+	hyperfb_write4(sc, NGLE_REG_24, (xs << 16) | ys);
+	hyperfb_write4(sc, NGLE_REG_7, (wi << 16) | he);
+	hyperfb_write4(sc, NGLE_REG_25, (xd << 16) | yd);
+}
+
+static void
+hyperfb_nuke_cursor(struct rasops_info *ri)
+{
+	struct vcons_screen *scr = ri->ri_hw;
+	struct hyperfb_softc *sc = scr->scr_cookie;
+	int wi, he, x, y;
+		
+	if (ri->ri_flg & RI_CURSOR) {
+		wi = ri->ri_font->fontwidth;
+		he = ri->ri_font->fontheight;
+		x = ri->ri_ccol * wi + ri->ri_xorigin;
+		y = ri->ri_crow * he + ri->ri_yorigin;
+		hyperfb_bitblt(sc, x, y, x, y, wi, he, RopInv);
+		ri->ri_flg &= ~RI_CURSOR;
+	}
+}
+
+static void
+hyperfb_cursor(void *cookie, int on, int row, int col)
+{
+	struct rasops_info *ri = cookie;
+	struct vcons_screen *scr = ri->ri_hw;
+	struct hyperfb_softc *sc = scr->scr_cookie;
+	int x, y, wi, he;
+	
+	wi = ri->ri_font->fontwidth;
+	he = ri->ri_font->fontheight;
+	
+	if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
+		if (on) {
+			if (ri->ri_flg & RI_CURSOR) {
+				hyperfb_nuke_cursor(ri);
+			}
+			x = col * wi + ri->ri_xorigin;
+			y = row * he + ri->ri_yorigin;
+			hyperfb_bitblt(sc, x, y, x, y, wi, he, RopInv);
+			ri->ri_flg |= RI_CURSOR;
+		}
+		ri->ri_crow = row;
+		ri->ri_ccol = col;
+	} else
+	{
+		ri->ri_crow = row;
+		ri->ri_ccol = col;
+		ri->ri_flg &= ~RI_CURSOR;
+	}
+
+}
+
+static void
+hyperfb_putchar(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 hyperfb_softc *sc = scr->scr_cookie;
+	int x, y, wi, he/*, rv = GC_NOPE*/;
+	uint32_t bg;
+
+	if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
+		return;
+
+	if (!CHAR_IN_FONT(c, font))
+		return;
+
+	if (row == ri->ri_crow && col == ri->ri_ccol) {
+		ri->ri_flg &= ~RI_CURSOR;
+	}
+
+	wi = font->fontwidth;
+	he = font->fontheight;
+
+	x = ri->ri_xorigin + col * wi;
+	y = ri->ri_yorigin + row * he;
+
+	bg = ri->ri_devcmap[(attr >> 16) & 0xf];
+
+	if (c == 0x20) {
+		hyperfb_rectfill(sc, x, y, wi, he, bg);
+		return;
+	}
+
+#if 0
+	rv = glyphcache_try(&sc->sc_gc, c, x, y, attr);
+	if (rv == GC_OK)
+		return;
+#endif
+	if (sc->sc_hwmode != HW_FB) hyperfb_setup_fb(sc);
+	sc->sc_putchar(cookie, row, col, c, attr);
+#if 0
+	if (rv == GC_ADD)
+		glyphcache_add(&sc->sc_gc, c, x, y);
+#endif
+}
+
+static void
+hyperfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
+{
+	struct rasops_info *ri = cookie;
+	struct vcons_screen *scr = ri->ri_hw;
+	struct hyperfb_softc *sc = scr->scr_cookie;
+	int32_t xs, xd, y, width, height;
+	
+	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
+		if (ri->ri_crow == row && 
+		   (ri->ri_ccol >= srccol && ri->ri_ccol < (srccol + ncols)) &&
+		   (ri->ri_flg & RI_CURSOR)) {
+			hyperfb_nuke_cursor(ri);
+		}
+
+		xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
+		xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
+		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
+		width = ri->ri_font->fontwidth * ncols;
+		height = ri->ri_font->fontheight;
+		hyperfb_bitblt(sc, xs, y, xd, y, width, height, RopSrc);
+		if (ri->ri_crow == row && 
+		   (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols)))
+			ri->ri_flg &= ~RI_CURSOR;
+	}
+}
+
+static void
+hyperfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
+{
+	struct rasops_info *ri = cookie;
+	struct vcons_screen *scr = ri->ri_hw;
+	struct hyperfb_softc *sc = scr->scr_cookie;
+	int32_t x, y, width, height, fg, bg, ul;
+	
+	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
+		x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
+		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
+		width = ri->ri_font->fontwidth * ncols;
+		height = ri->ri_font->fontheight;
+		rasops_unpack_attr(fillattr, &fg, &bg, &ul);
+
+		hyperfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
+		if (ri->ri_crow == row && 
+		   (ri->ri_ccol >= startcol && ri->ri_ccol < (startcol + ncols)))
+			ri->ri_flg &= ~RI_CURSOR;
+	}
+}
+
+static void
+hyperfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
+{
+	struct rasops_info *ri = cookie;
+	struct vcons_screen *scr = ri->ri_hw;
+	struct hyperfb_softc *sc = scr->scr_cookie;
+	int32_t x, ys, yd, width, height;
+
+	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
+		if ((ri->ri_crow >= srcrow && ri->ri_crow < (srcrow + nrows)) &&
+		   (ri->ri_flg & RI_CURSOR)) {
+			hyperfb_nuke_cursor(ri);
+		}
+		x = ri->ri_xorigin;
+		ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
+		yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
+		width = ri->ri_emuwidth;
+		height = ri->ri_font->fontheight * nrows;
+		hyperfb_bitblt(sc, x, ys, x, yd, width, height, RopSrc);
+		if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows))
+			ri->ri_flg &= ~RI_CURSOR;
+	}
+}
+
+static void
+hyperfb_eraserows(void *cookie, int row, int nrows, long fillattr)
+{
+	struct rasops_info *ri = cookie;
+	struct vcons_screen *scr = ri->ri_hw;
+	struct hyperfb_softc *sc = scr->scr_cookie;
+	int32_t x, y, width, height, fg, bg, ul;
+	
+	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
+		x = ri->ri_xorigin;
+		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
+		width = ri->ri_emuwidth;
+		height = ri->ri_font->fontheight * nrows;
+		rasops_unpack_attr(fillattr, &fg, &bg, &ul);
+
+		hyperfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
+
+		if (ri->ri_crow >= row && ri->ri_crow < (row + nrows))
+			ri->ri_flg &= ~RI_CURSOR;
+	}
+}

Reply via email to