diff -urp linux-2.6.21/drivers/video/Kconfig linux-2.6.21.mod/drivers/video/Kconfig --- linux-2.6.21/drivers/video/Kconfig 2007-05-08 23:38:34.055228990 +0200 +++ linux-2.6.21.mod/drivers/video/Kconfig 2007-05-09 00:13:34.910949935 +0200 @@ -139,6 +139,23 @@ config FB_TILEBLITTING This is particularly important to one driver, matroxfb. If unsure, say N. +config FB_SMALL_BLITS + bool "Enable Enhanced Blitting Support (EXPERIMENTAL)" + depends on FB && EXPERIMENTAL + default n + ---help--- + This enables smart usage of blitter to sroll screen. A standard + way is to use blitter to move almost whole screen. The enhanced + blitting moves only characters which have to be moved. The same + logic is used for redrawing characters during scroll if the + blitting is not used to scroll. + It may or may not speed up scrolling of your framebuffer. It + depends on relative speed of your CPU and GPU. If you have + fast CPU and slow GPU this option may slow down scrolling. + If the opposite is true this may speed up scrolling for you. + + If unsure, say N. + comment "Frame buffer hardware drivers" depends on FB diff -urp linux-2.6.21/drivers/video/console/fbcon.c linux-2.6.21.mod/drivers/video/console/fbcon.c --- linux-2.6.21/drivers/video/console/fbcon.c 2007-04-26 05:08:32.000000000 +0200 +++ linux-2.6.21.mod/drivers/video/console/fbcon.c 2007-05-09 00:15:37.501935997 +0200 @@ -1663,6 +1663,81 @@ static void fbcon_redraw_move(struct vc_ } } +static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, + struct display *p, int line, int count, int ycount) +{ + int offset = ycount * vc->vc_cols; + unsigned short *d = (unsigned short *) + (vc->vc_origin + vc->vc_size_row * line); + unsigned short *s = d + offset; + struct fbcon_ops *ops = info->fbcon_par; + + while (count--) { + unsigned short *start = s; + unsigned short *le = advance_row(s, 1); + unsigned short c; + int x = 0; + unsigned short attr = 1; +#ifdef MERGE_BLITS + int was_blit = 1; +#endif + + do { + c = scr_readw(s); + if (attr != (c & 0xff00)) { + attr = c & 0xff00; + if (s > start) { + ops->bmove(vc, info, line + ycount, x, line, x, 1, s-start); +#ifdef MERGE_BLITS + was_blit = 1; +#endif + x += s - start; + start = s; + } + } + if (c == scr_readw(d)) { + if (s > start) { +#ifdef MERGE_BLITS + if (!was_blit) { +#endif + ops->bmove(vc, info, line + ycount, x, line, x, 1, s-start); + x += s - start + 1; + start = s + 1; +#ifdef MERGE_BLITS + } + was_blit = !was_blit; +#endif + } else { +#ifdef MERGE_BLITS + if (was_blit) { +#endif + x++; + start++; +#ifdef MERGE_BLITS + } +#endif + } + } + scr_writew(c, d); + console_conditional_schedule(); + s++; + d++; + } while (s < le); + if (s > start) { + ops->bmove(vc, info, line + ycount, x, line, x, 1, s-start); + } + console_conditional_schedule(); + if (ycount > 0) + line++; + else { + line--; + /* NOTE: We subtract two lines from these pointers */ + s -= vc->vc_size_row; + d -= vc->vc_size_row; + } + } +} + static void fbcon_redraw(struct vc_data *vc, struct display *p, int line, int count, int offset) { @@ -1748,7 +1823,9 @@ static int fbcon_scroll(struct vc_data * { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct display *p = &fb_display[vc->vc_num]; +#ifndef CONFIG_FB_SMALL_BLITS struct fbcon_ops *ops = info->fbcon_par; +#endif int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; if (fbcon_is_inactive(vc, info)) @@ -1772,10 +1849,22 @@ static int fbcon_scroll(struct vc_data * goto redraw_up; switch (p->scrollmode) { case SCROLL_MOVE: +#ifndef CONFIG_FB_SMALL_BLITS ops->bmove(vc, info, t + count, 0, t, 0, b - t - count, vc->vc_cols); ops->clear(vc, info, b - count, 0, count, vc->vc_cols); +#else + fbcon_redraw_blit(vc, info, p, t, b - t - count, + count); + fbcon_clear(vc, b - count, 0, count, vc->vc_cols); + scr_memsetw((unsigned short *) (vc->vc_origin + + vc->vc_size_row * + (b - count)), + vc->vc_video_erase_char, + vc->vc_size_row * count); + return 1; +#endif break; case SCROLL_WRAP_MOVE: @@ -1858,9 +1947,21 @@ static int fbcon_scroll(struct vc_data * goto redraw_down; switch (p->scrollmode) { case SCROLL_MOVE: +#ifndef CONFIG_FB_SMALL_BLITS ops->bmove(vc, info, t, 0, t + count, 0, b - t - count, vc->vc_cols); ops->clear(vc, info, t, 0, count, vc->vc_cols); +#else + fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, + -count); + fbcon_clear(vc, t, 0, count, vc->vc_cols); + scr_memsetw((unsigned short *) (vc->vc_origin + + vc->vc_size_row * + t), + vc->vc_video_erase_char, + vc->vc_size_row * count); + return 1; +#endif break; case SCROLL_WRAP_MOVE: