diff options
author | emaste <emaste@FreeBSD.org> | 2015-04-29 20:30:11 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2015-04-29 20:30:11 +0000 |
commit | 40a5e702ecaa604813d983965508c6f958493fd9 (patch) | |
tree | a25dd868ffb1c57bd77dc0ca9372f829fb9db751 /sys/dev/vt | |
parent | ac98f0f74657de04f4189781ec4765beade82e9f (diff) | |
download | FreeBSD-src-40a5e702ecaa604813d983965508c6f958493fd9.zip FreeBSD-src-40a5e702ecaa604813d983965508c6f958493fd9.tar.gz |
vt: fix vt_fb_bitblt_bitmap mask corruption
Previously the mask wrapped when one or more of the mask bytes extended
past the right edge of the window. Simplify the logic and use the same
byte offset and bit in both the pattern and mask.
PR: 199648
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D2360
Diffstat (limited to 'sys/dev/vt')
-rw-r--r-- | sys/dev/vt/hw/fb/vt_fb.c | 54 |
1 files changed, 23 insertions, 31 deletions
diff --git a/sys/dev/vt/hw/fb/vt_fb.c b/sys/dev/vt/hw/fb/vt_fb.c index 40f56fc..b2babd1 100644 --- a/sys/dev/vt/hw/fb/vt_fb.c +++ b/sys/dev/vt/hw/fb/vt_fb.c @@ -264,46 +264,40 @@ vt_fb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw, { struct fb_info *info; uint32_t fgc, bgc, cc, o; - int c, l, bpp, bpl; - u_long line; - uint8_t b, m; - const uint8_t *ch; + int bpp, bpl, xi, yi; + int bit, byte; info = vd->vd_softc; bpp = FBTYPE_GET_BYTESPP(info); fgc = info->fb_cmap[fg]; bgc = info->fb_cmap[bg]; - b = m = 0; - bpl = (width + 7) >> 3; /* Bytes per source line. */ + bpl = (width + 7) / 8; /* Bytes per source line. */ if (info->fb_flags & FB_FLAG_NOWRITE) return; KASSERT((info->fb_vbase != 0), ("Unmapped framebuffer")); - line = (info->fb_stride * y) + (x * bpp); - for (l = 0; - l < height && y + l < vw->vw_draw_area.tr_end.tp_row; - l++) { - ch = pattern; - for (c = 0; - c < width && x + c < vw->vw_draw_area.tr_end.tp_col; - c++) { - if (c % 8 == 0) - b = *ch++; - else - b <<= 1; - if (mask != NULL) { - if (c % 8 == 0) - m = *mask++; - else - m <<= 1; - /* Skip pixel write, if mask has no bit set. */ - if ((m & 0x80) == 0) - continue; - } - o = line + (c * bpp); - cc = b & 0x80 ? fgc : bgc; + /* Bound by right and bottom edges. */ + if (y + height > vw->vw_draw_area.tr_end.tp_row) { + if (y >= vw->vw_draw_area.tr_end.tp_row) + return; + height = vw->vw_draw_area.tr_end.tp_row - y; + } + if (x + width > vw->vw_draw_area.tr_end.tp_col) { + if (x >= vw->vw_draw_area.tr_end.tp_col) + return; + width = vw->vw_draw_area.tr_end.tp_col - x; + } + for (yi = 0; yi < height; yi++) { + for (xi = 0; xi < width; xi++) { + byte = yi * bpl + xi / 8; + bit = 0x80 >> (xi % 8); + /* Skip pixel write, if mask bit not set. */ + if (mask != NULL && (mask[byte] & bit) == 0) + continue; + o = (y + yi) * info->fb_stride + (x + xi) * bpp; + cc = pattern[byte] & bit ? fgc : bgc; switch(bpp) { case 1: @@ -326,8 +320,6 @@ vt_fb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw, break; } } - line += info->fb_stride; - pattern += bpl; } } |