Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bad07ff7 authored by Krzysztof Helt's avatar Krzysztof Helt Committed by Linus Torvalds
Browse files

fbcon: smart blitter usage for scrolling



This patch replaces the current SCROLL_MOVE method with smarter method using
the same logic as the SCROLL_REDRAW method.  This brings these two methods
much closer in performance and benefits all framebuffers which uses the
SCROLL_MOVE method.

[adaplas]
- remove unnecessary char attribute checking
- whitespace cleanups and 80-column line fixes

Signed-off-by: default avatarKrzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: default avatarAntonino Daplas <adaplas@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5d2b56c6
Loading
Loading
Loading
Loading
+68 −8
Original line number Diff line number Diff line
@@ -1704,6 +1704,56 @@ static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
	}
}

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;

		do {
			c = scr_readw(s);

			if (c == scr_readw(d)) {
				if (s > start) {
					ops->bmove(vc, info, line + ycount, x,
						   line, x, 1, s-start);
					x += s - start + 1;
					start = s + 1;
				} else {
					x++;
					start++;
				}
			}

			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)
{
@@ -1789,7 +1839,6 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
{
	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
	struct display *p = &fb_display[vc->vc_num];
	struct fbcon_ops *ops = info->fbcon_par;
	int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;

	if (fbcon_is_inactive(vc, info))
@@ -1813,10 +1862,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
			goto redraw_up;
		switch (p->scrollmode) {
		case SCROLL_MOVE:
			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);
			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;
			break;

		case SCROLL_WRAP_MOVE:
@@ -1899,9 +1953,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
			goto redraw_down;
		switch (p->scrollmode) {
		case SCROLL_MOVE:
			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);
			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;
			break;

		case SCROLL_WRAP_MOVE: