Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Aug 2014 11:01:36 +0000 (UTC)
From:      Aleksandr Rybalko <ray@svn.freebsd.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r269471 - head/sys/dev/vt/hw/vga
Message-ID:  <53de1690.53ba.64514c82@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ray
Date: Sun Aug  3 11:01:35 2014
New Revision: 269471
URL: http://svnweb.freebsd.org/changeset/base/269471

Log:
  Fix vt_vga driver to draw not-8-bit-aligned fonts correctly.
  Still one bug here: mouse left some gaps on track when moving left.
  
  MFC after:	1 week
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/sys/dev/vt/hw/vga/vt_vga.c

Modified: head/sys/dev/vt/hw/vga/vt_vga.c
==============================================================================
--- head/sys/dev/vt/hw/vga/vt_vga.c	Sun Aug  3 10:47:45 2014	(r269470)
+++ head/sys/dev/vt/hw/vga/vt_vga.c	Sun Aug  3 11:01:35 2014	(r269471)
@@ -87,7 +87,7 @@ static const struct vt_driver vt_vga_dri
 	.vd_init	= vga_init,
 	.vd_blank	= vga_blank,
 	.vd_bitbltchr	= vga_bitbltchr,
-	.vd_maskbitbltchr = vga_maskbitbltchr,
+	.vd_maskbitbltchr = vga_bitbltchr,
 	.vd_drawrect	= vga_drawrect,
 	.vd_setpixel	= vga_setpixel,
 	.vd_putchar	= vga_putchar,
@@ -172,88 +172,83 @@ vga_drawrect(struct vt_device *vd, int x
 	}
 }
 
-static inline void
-vga_bitblt_draw(struct vt_device *vd, const uint8_t *src,
-    u_long ldst, uint8_t shift, unsigned int width, unsigned int height,
-    term_color_t color, int negate)
-{
-	u_long dst;
-	int w;
-	uint8_t b, r, out;
-
-	for (; height > 0; height--) {
-		dst = ldst;
-		ldst += VT_VGA_WIDTH / 8;
-		r = 0;
-		for (w = width; w > 0; w -= 8) {
-			b = *src++;
-			if (negate) {
-				b = ~b;
-				/* Don't go too far. */
-				if (w < 8)
-					b &= 0xff << (8 - w);
-			}
-			/* Reintroduce bits from previous column. */
-			out = (b >> shift) | r;
-			r = b << (8 - shift);
-			vga_bitblt_put(vd, dst++, color, out);
-		}
-		/* Print the remainder. */
-		vga_bitblt_put(vd, dst, color, r);
+/*
+ * Shift bitmap of one row of the glyph.
+ * a - array of bytes with src bitmap and result storage.
+ * m - resulting background color bitmask.
+ * size - number of bytes per glyph row (+ one byte to store shift overflow).
+ * shift - offset for target bitmap.
+ */
+
+static void
+vga_shift_u8array(uint8_t *a, uint8_t *m, int size, int shift)
+{
+	int i;
+
+	for (i = (size - 1); i > 0; i--) {
+		a[i] = (a[i] >> shift) | (a[i-1] << (7 - shift));
+		m[i] = ~a[i];
 	}
+	a[0] = (a[0] >> shift);
+	m[0] = ~a[0] & (0xff >> shift);
+	m[size - 1] = ~a[size - 1] & (0xff << (7 - shift));
 }
 
+/* XXX: fix gaps on mouse track when character size is not rounded to 8. */
 static void
 vga_bitbltchr(struct vt_device *vd, const uint8_t *src, const uint8_t *mask,
     int bpl, vt_axis_t top, vt_axis_t left, unsigned int width,
     unsigned int height, term_color_t fg, term_color_t bg)
 {
-	u_long dst, ldst;
-	int w;
+	uint8_t aa[64], ma[64], *r;
+	int dst, shift, sz, x, y;
+	struct vga_softc *sc;
 
-	/* Don't try to put off screen pixels */
-	if (((left + width) > VT_VGA_WIDTH) || ((top + height) >
-	    VT_VGA_HEIGHT))
+	if ((left + width) > VT_VGA_WIDTH)
+		return;
+	if ((top + height) > VT_VGA_HEIGHT)
 		return;
 
-	dst = (VT_VGA_WIDTH * top + left) / 8;
-
-	for (; height > 0; height--) {
-		ldst = dst;
-		for (w = width; w > 0; w -= 8) {
-			vga_bitblt_put(vd, ldst, fg, *src);
-			vga_bitblt_put(vd, ldst, bg, ~*src);
-			ldst++;
-			src++;
-		}
-		dst += VT_VGA_WIDTH / 8;
-	}
-}
+	sc = vd->vd_softc;
 
-/* Bitblt with mask support. Slow. */
-static void
-vga_maskbitbltchr(struct vt_device *vd, const uint8_t *src, const uint8_t *mask,
-    int bpl, vt_axis_t top, vt_axis_t left, unsigned int width,
-    unsigned int height, term_color_t fg, term_color_t bg)
-{
-	struct vga_softc *sc = vd->vd_softc;
-	u_long dst;
-	uint8_t shift;
+	sz = (width + 7) / 8;
+	shift = left % 8;
 
 	dst = (VT_VGA_WIDTH * top + left) / 8;
-	shift = left % 8;
 
-	/* Don't try to put off screen pixels */
-	if (((left + width) > VT_VGA_WIDTH) || ((top + height) >
-	    VT_VGA_HEIGHT))
-		return;
+	for (y = 0; y < height; y++) {
+		r = (uint8_t *)src + (y * sz);
+		memcpy(aa, r, sz);
+		aa[sz] = 0;
+		vga_shift_u8array(aa, ma, sz + 1, shift);
+
+		vga_setcolor(vd, bg);
+		for (x = 0; x < (sz + 1); x ++) {
+			if (ma[x] == 0)
+				continue;
+			/*
+			 * XXX Only mouse cursor can go out of screen.
+			 * So for mouse it have to just return, but for regular
+			 * characters it have to panic, to indicate error in
+			 * size/coordinates calculations.
+			 */
+			if ((dst + x) >= (VT_VGA_WIDTH * VT_VGA_HEIGHT))
+				return;
+			if (ma[x] != 0xff)
+				MEM_READ1(sc, dst + x);
+			MEM_WRITE1(sc, dst + x, ma[x]);
+		}
 
-	if (sc->vga_curcolor == fg) {
-		vga_bitblt_draw(vd, src, dst, shift, width, height, fg, 0);
-		vga_bitblt_draw(vd, src, dst, shift, width, height, bg, 1);
-	} else {
-		vga_bitblt_draw(vd, src, dst, shift, width, height, bg, 1);
-		vga_bitblt_draw(vd, src, dst, shift, width, height, fg, 0);
+		vga_setcolor(vd, fg);
+		for (x = 0; x < (sz + 1); x ++) {
+			if (aa[x] == 0)
+				continue;
+			if (aa[x] != 0xff)
+				MEM_READ1(sc, dst + x);
+			MEM_WRITE1(sc, dst + x, aa[x]);
+		}
+
+		dst += VT_VGA_WIDTH / 8;
 	}
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53de1690.53ba.64514c82>