From 7255f43132acdab3ba6ccb12e863d77aca804463 Mon Sep 17 00:00:00 2001 From: emaste Date: Tue, 12 May 2015 18:08:07 +0000 Subject: [PATCH] MFC r282247: 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 git-svn-id: svn://svn.freebsd.org/base/stable/10@282822 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/vt/hw/fb/vt_fb.c | 54 +++++++++++++++++----------------------- 1 file 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 c170547de..9028fb04e 100644 --- a/sys/dev/vt/hw/fb/vt_fb.c +++ b/sys/dev/vt/hw/fb/vt_fb.c @@ -250,43 +250,37 @@ 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. */ 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: @@ -309,8 +303,6 @@ vt_fb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw, break; } } - line += info->fb_stride; - pattern += bpl; } } -- 2.45.0