Skip to content

Commit 40faaf8

Browse files
Thomas Zimmermannairlied
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 <[email protected]> Fixes: 6f29e04 ("fbdev: Improve performance of sys_imageblit()") Cc: Thomas Zimmermann <[email protected]> Cc: Javier Martinez Canillas <[email protected]> Cc: Sam Ravnborg <[email protected]> Tested-by: Geert Uytterhoeven <[email protected]> Reviewed-by: Javier Martinez Canillas <[email protected]> Signed-off-by: Dave Airlie <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent c73c357 commit 40faaf8

File tree

1 file changed

+25
-4
lines changed

1 file changed

+25
-4
lines changed

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)