static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx,
int dy, int dx, int height, int width, u_int y_break);
static void fbcon_set_disp(struct fb_info *info, struct vc_data *vc);
+static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
+ int line, int count, int dy);
#ifdef CONFIG_MAC
/*
if ((cap & FBINFO_HWACCEL_COPYAREA) &&
!(cap & FBINFO_HWACCEL_DISABLED))
- p->scrollmode = SCROLL_ACCEL;
+ p->scrollmode = SCROLL_MOVE;
else /* default to something safe */
p->scrollmode = SCROLL_REDRAW;
scrollback_current = 0;
}
+static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count)
+{
+ struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+ struct display *p = &fb_display[vc->vc_num];
+ int redraw = 0;
+
+ p->yscroll += count;
+ if (p->yscroll > p->vrows - vc->vc_rows) {
+ p->yscroll -= p->vrows - vc->vc_rows;
+ redraw = 1;
+ }
+
+ info->var.xoffset = 0;
+ info->var.yoffset = p->yscroll * vc->vc_font.height;
+ info->var.vmode &= ~FB_VMODE_YWRAP;
+ if (redraw)
+ fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t);
+ update_var(vc->vc_num, info);
+ accel_clear_margins(vc, info, 1);
+ scrollback_max += count;
+ if (scrollback_max > scrollback_phys_max)
+ scrollback_max = scrollback_phys_max;
+ scrollback_current = 0;
+}
+
static __inline__ void ypan_down(struct vc_data *vc, int count)
{
struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
scrollback_current = 0;
}
+static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
+{
+ struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+ struct display *p = &fb_display[vc->vc_num];
+ int redraw = 0;
+
+ p->yscroll -= count;
+ if (p->yscroll < 0) {
+ p->yscroll += p->vrows - vc->vc_rows;
+ redraw = 1;
+ }
+ info->var.xoffset = 0;
+ info->var.yoffset = p->yscroll * vc->vc_font.height;
+ info->var.vmode &= ~FB_VMODE_YWRAP;
+ if (redraw)
+ fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count);
+ update_var(vc->vc_num, info);
+ accel_clear_margins(vc, info, 1);
+ scrollback_max -= count;
+ if (scrollback_max < 0)
+ scrollback_max = 0;
+ scrollback_current = 0;
+}
+
static void fbcon_redraw_softback(struct vc_data *vc, struct display *p,
long delta)
{
}
}
+static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
+ int line, int count, int dy)
+{
+ struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+ unsigned short *s = (unsigned short *)
+ (vc->vc_origin + vc->vc_size_row * line);
+
+ while (count--) {
+ unsigned short *start = s;
+ unsigned short *le = advance_row(s, 1);
+ unsigned short c;
+ int x = 0;
+ unsigned short attr = 1;
+
+ do {
+ c = scr_readw(s);
+ if (attr != (c & 0xff00)) {
+ attr = c & 0xff00;
+ if (s > start) {
+ accel_putcs(vc, info, start, s - start,
+ real_y(p, dy), x);
+ x += s - start;
+ start = s;
+ }
+ }
+ console_conditional_schedule();
+ s++;
+ } while (s < le);
+ if (s > start)
+ accel_putcs(vc, info, start, s - start,
+ real_y(p, dy), x);
+ console_conditional_schedule();
+ dy++;
+ }
+}
+
static void fbcon_redraw(struct vc_data *vc, struct display *p,
int line, int count, int offset)
{
if (logo_shown >= 0)
goto redraw_up;
switch (p->scrollmode) {
- case SCROLL_ACCEL:
+ case SCROLL_MOVE:
accel_bmove(vc, info, t + count, 0, t, 0,
b - t - count, vc->vc_cols);
accel_clear(vc, info, b - count, 0, count,
vc->vc_cols);
break;
- case SCROLL_WRAP:
+ case SCROLL_WRAP_MOVE:
if (b - t - count > 3 * vc->vc_rows >> 2) {
if (t > 0)
fbcon_bmove(vc, 0, 0, count, 0, t,
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
break;
- case SCROLL_PAN:
+ case SCROLL_PAN_REDRAW:
+ if ((p->yscroll + count <=
+ 2 * (p->vrows - vc->vc_rows))
+ && ((!scroll_partial && (b - t == vc->vc_rows))
+ || (scroll_partial
+ && (b - t - count >
+ 3 * vc->vc_rows >> 2)))) {
+ if (t > 0)
+ fbcon_redraw_move(vc, p, 0, t, count);
+ ypan_up_redraw(vc, t, count);
+ if (vc->vc_rows - b > 0)
+ fbcon_redraw_move(vc, p, b - count,
+ vc->vc_rows - b, b);
+ } else
+ fbcon_redraw_move(vc, p, t + count, b - t - count, t);
+ fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+ break;
+
+ case SCROLL_PAN_MOVE:
if ((p->yscroll + count <=
2 * (p->vrows - vc->vc_rows))
&& ((!scroll_partial && (b - t == vc->vc_rows))
if (count > vc->vc_rows) /* Maximum realistic size */
count = vc->vc_rows;
switch (p->scrollmode) {
- case SCROLL_ACCEL:
+ case SCROLL_MOVE:
accel_bmove(vc, info, t, 0, t + count, 0,
b - t - count, vc->vc_cols);
accel_clear(vc, info, t, 0, count, vc->vc_cols);
break;
- case SCROLL_WRAP:
+ case SCROLL_WRAP_MOVE:
if (b - t - count > 3 * vc->vc_rows >> 2) {
if (vc->vc_rows - b > 0)
fbcon_bmove(vc, b, 0, b - count, 0,
fbcon_clear(vc, t, 0, count, vc->vc_cols);
break;
- case SCROLL_PAN:
+ case SCROLL_PAN_MOVE:
if ((count - p->yscroll <= p->vrows - vc->vc_rows)
&& ((!scroll_partial && (b - t == vc->vc_rows))
|| (scroll_partial
fbcon_clear(vc, t, 0, count, vc->vc_cols);
break;
+ case SCROLL_PAN_REDRAW:
+ if ((count - p->yscroll <= p->vrows - vc->vc_rows)
+ && ((!scroll_partial && (b - t == vc->vc_rows))
+ || (scroll_partial
+ && (b - t - count >
+ 3 * vc->vc_rows >> 2)))) {
+ if (vc->vc_rows - b > 0)
+ fbcon_redraw_move(vc, p, b, vc->vc_rows - b,
+ b - count);
+ ypan_down_redraw(vc, t, count);
+ if (t > 0)
+ fbcon_redraw_move(vc, p, count, t, 0);
+ } else
+ fbcon_redraw_move(vc, p, t, b - t - count, t + count);
+ fbcon_clear(vc, t, 0, count, vc->vc_cols);
+ break;
+
case SCROLL_REDRAW:
redraw_down:
fbcon_redraw(vc, p, b - 1, b - t - count,
int cap = info->flags;
int good_pan = (cap & FBINFO_HWACCEL_YPAN)
&& divides(info->fix.ypanstep, vc->vc_font.height)
- && info->var.yres_virtual >= 2*info->var.yres;
+ && info->var.yres_virtual > info->var.yres;
int good_wrap = (cap & FBINFO_HWACCEL_YWRAP)
&& divides(info->fix.ywrapstep, vc->vc_font.height)
&& divides(vc->vc_font.height, info->var.yres_virtual);
int reading_fast = cap & FBINFO_READS_FAST;
int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED);
+ int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && !(cap & FBINFO_HWACCEL_DISABLED);
p->vrows = info->var.yres_virtual/fh;
if (info->var.yres > (fh * (vc->vc_rows + 1)))
if (good_wrap || good_pan) {
if (reading_fast || fast_copyarea)
- p->scrollmode = good_wrap ? SCROLL_WRAP : SCROLL_PAN;
+ p->scrollmode = good_wrap ? SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE;
else
- p->scrollmode = SCROLL_REDRAW;
+ p->scrollmode = good_wrap ? SCROLL_REDRAW :
+ SCROLL_PAN_REDRAW;
} else {
- if (reading_fast || fast_copyarea)
- p->scrollmode = SCROLL_ACCEL;
+ if (reading_fast || (fast_copyarea && !fast_imageblit))
+ p->scrollmode = SCROLL_MOVE;
else
p->scrollmode = SCROLL_REDRAW;
}
}
switch (p->scrollmode) {
- case SCROLL_WRAP:
+ case SCROLL_WRAP_MOVE:
scrollback_phys_max = p->vrows - vc->vc_rows;
break;
- case SCROLL_PAN:
+ case SCROLL_PAN_MOVE:
+ case SCROLL_PAN_REDRAW:
scrollback_phys_max = p->vrows - 2 * vc->vc_rows;
if (scrollback_phys_max < 0)
scrollback_phys_max = 0;
offset = p->yscroll - scrollback_current;
limit = p->vrows;
switch (p->scrollmode) {
- case SCROLL_WRAP:
+ case SCROLL_WRAP_MOVE:
info->var.vmode |= FB_VMODE_YWRAP;
break;
- case SCROLL_PAN:
+ case SCROLL_PAN_MOVE:
+ case SCROLL_PAN_REDRAW:
limit -= vc->vc_rows;
info->var.vmode &= ~FB_VMODE_YWRAP;
break;