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;
        }
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to