summaryrefslogtreecommitdiffstats
path: root/sys/dev/vt
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2015-04-29 20:30:11 +0000
committeremaste <emaste@FreeBSD.org>2015-04-29 20:30:11 +0000
commit40a5e702ecaa604813d983965508c6f958493fd9 (patch)
treea25dd868ffb1c57bd77dc0ca9372f829fb9db751 /sys/dev/vt
parentac98f0f74657de04f4189781ec4765beade82e9f (diff)
downloadFreeBSD-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.c54
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;
}
}
OpenPOWER on IntegriCloud