Skip to content

Commit 40faaf8

Browse files
tdzairlied
authored andcommitted
fbdev: Fix sys_imageblit() for arbitrary image widths
Commit 6f29e04 ("fbdev: Improve performance of sys_imageblit()") broke sys_imageblit() for image width that are not aligned to 8-bit boundaries. Fix this by handling the trailing pixels on each line separately. The performance improvements in the original commit do not regress by this change. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Fixes: 6f29e04 ("fbdev: Improve performance of sys_imageblit()") Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: Javier Martinez Canillas <javierm@redhat.com> Cc: Sam Ravnborg <sam@ravnborg.org> Tested-by: Geert Uytterhoeven <geert@linux-m68k.org> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220313192952.12058-2-tzimmermann@suse.de
1 parent c73c357 commit 40faaf8

1 file changed

Lines changed: 25 additions & 4 deletions

File tree

drivers/video/fbdev/core/sysimgblt.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
188188
{
189189
u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
190190
u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
191-
u32 bit_mask, eorx;
191+
u32 bit_mask, eorx, shift;
192192
const char *s = image->data, *src;
193193
u32 *dst;
194194
const u32 *tab;
@@ -229,25 +229,31 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
229229

230230
for (i = image->height; i--; ) {
231231
dst = dst1;
232+
shift = 8;
232233
src = s;
233234

235+
/*
236+
* Manually unroll the per-line copying loop for better
237+
* performance. This works until we processed the last
238+
* completely filled source byte (inclusive).
239+
*/
234240
switch (ppw) {
235241
case 4: /* 8 bpp */
236-
for (j = k; j; j -= 2, ++src) {
242+
for (j = k; j >= 2; j -= 2, ++src) {
237243
*dst++ = colortab[(*src >> 4) & bit_mask];
238244
*dst++ = colortab[(*src >> 0) & bit_mask];
239245
}
240246
break;
241247
case 2: /* 16 bpp */
242-
for (j = k; j; j -= 4, ++src) {
248+
for (j = k; j >= 4; j -= 4, ++src) {
243249
*dst++ = colortab[(*src >> 6) & bit_mask];
244250
*dst++ = colortab[(*src >> 4) & bit_mask];
245251
*dst++ = colortab[(*src >> 2) & bit_mask];
246252
*dst++ = colortab[(*src >> 0) & bit_mask];
247253
}
248254
break;
249255
case 1: /* 32 bpp */
250-
for (j = k; j; j -= 8, ++src) {
256+
for (j = k; j >= 8; j -= 8, ++src) {
251257
*dst++ = colortab[(*src >> 7) & bit_mask];
252258
*dst++ = colortab[(*src >> 6) & bit_mask];
253259
*dst++ = colortab[(*src >> 5) & bit_mask];
@@ -259,6 +265,21 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
259265
}
260266
break;
261267
}
268+
269+
/*
270+
* For image widths that are not a multiple of 8, there
271+
* are trailing pixels left on the current line. Print
272+
* them as well.
273+
*/
274+
for (; j--; ) {
275+
shift -= ppw;
276+
*dst++ = colortab[(*src >> shift) & bit_mask];
277+
if (!shift) {
278+
shift = 8;
279+
++src;
280+
}
281+
}
282+
262283
dst1 += p->fix.line_length;
263284
s += spitch;
264285
}

0 commit comments

Comments
 (0)