📄 fbcon.c
字号:
if (delta < 0) { if (softback_curr < softback_top && n < softback_buf) { n += softback_end - softback_buf; if (n < softback_top) { softback_lines -= (softback_top - n) / conp->vc_size_row; n = softback_top; } } else if (softback_curr >= softback_top && n < softback_top) { softback_lines -= (softback_top - n) / conp->vc_size_row; n = softback_top; } } else { if (softback_curr > softback_in && n >= softback_end) { n += softback_buf - softback_end; if (n > softback_in) { n = softback_in; softback_lines = 0; } } else if (softback_curr <= softback_in && n > softback_in) { n = softback_in; softback_lines = 0; } } if (n == softback_curr) return; softback_curr = n; s = (u16 *)softback_curr; if (s == (u16 *)softback_in) s = (u16 *)conp->vc_origin; while (count--) { unsigned short *start; unsigned short *le; unsigned short c; int x = 0; unsigned short attr = 1; start = s; le = advance_row(s, 1); do { c = scr_readw(s); if (attr != (c & 0xff00)) { attr = c & 0xff00; if (s > start) { p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); x += s - start; start = s; } } if (c == scr_readw(d)) { if (s > start) { p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); x += s - start + 1; start = s + 1; } else { x++; start++; } } s++; d++; } while (s < le); if (s > start) p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); line++; if (d == (u16 *)softback_end) d = (u16 *)softback_buf; if (d == (u16 *)softback_in) d = (u16 *)conp->vc_origin; if (s == (u16 *)softback_end) s = (u16 *)softback_buf; if (s == (u16 *)softback_in) s = (u16 *)conp->vc_origin; }}static void fbcon_redraw(struct vc_data *conp, struct display *p, int line, int count, int offset){ unsigned short *d = (unsigned short *) (conp->vc_origin + conp->vc_size_row * line); unsigned short *s = d + offset; 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) { p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); x += s - start; start = s; } } if (c == scr_readw(d)) { if (s > start) { p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); x += s - start + 1; start = s + 1; } else { x++; start++; } } scr_writew(c, d); s++; d++; } while (s < le); if (s > start) p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); if (offset > 0) line++; else { line--; /* NOTE: We subtract two lines from these pointers */ s -= conp->vc_size_row; d -= conp->vc_size_row; } }}/* This cannot be used together with ypan or ywrap */void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h, int w){ if (sy != dy) panic("fbcon_redraw_bmove width sy != dy"); /* h will be always 1, but it does not matter if we are more generic */ while (h-- > 0) { struct vc_data *conp = p->conp; unsigned short *d = (unsigned short *) (conp->vc_origin + conp->vc_size_row * dy + dx * 2); unsigned short *s = d + (dx - sx); unsigned short *start = d; unsigned short *ls = d; unsigned short *le = d + w; unsigned short c; int x = dx; unsigned short attr = 1; do { c = scr_readw(d); if (attr != (c & 0xff00)) { attr = c & 0xff00; if (d > start) { p->dispsw->putcs(conp, p, start, d - start, dy, x); x += d - start; start = d; } } if (s >= ls && s < le && c == scr_readw(s)) { if (d > start) { p->dispsw->putcs(conp, p, start, d - start, dy, x); x += d - start + 1; start = d + 1; } else { x++; start++; } } s++; d++; } while (d < le); if (d > start) p->dispsw->putcs(conp, p, start, d - start, dy, x); sy++; dy++; }}static inline void fbcon_softback_note(struct vc_data *conp, int t, int count){ unsigned short *p = (unsigned short *) (conp->vc_origin + t * conp->vc_size_row); while (count) { scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row); count--; p = advance_row(p, 1); softback_in += conp->vc_size_row; if (softback_in == softback_end) softback_in = softback_buf; if (softback_in == softback_top) { softback_top += conp->vc_size_row; if (softback_top == softback_end) softback_top = softback_buf; } } softback_curr = softback_in;}static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count){ int unit = conp->vc_num; struct display *p = &fb_display[unit]; int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL); if (!p->can_soft_blank && console_blanked) return 0; if (!count || vt_cons[unit]->vc_mode != KD_TEXT) return 0; fbcon_cursor(conp, CM_ERASE); /* * ++Geert: Only use ywrap/ypan if the console is in text mode * ++Andrew: Only use ypan on hardware text mode when scrolling the * whole screen (prevents flicker). */ switch (dir) { case SM_UP: if (count > conp->vc_rows) /* Maximum realistic size */ count = conp->vc_rows; if (softback_top) fbcon_softback_note(conp, t, count); if (logo_shown >= 0) goto redraw_up; switch (p->scrollmode & __SCROLL_YMASK) { case __SCROLL_YMOVE: p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count, conp->vc_cols); p->dispsw->clear(conp, p, b-count, 0, count, conp->vc_cols); break; case __SCROLL_YWRAP: if (b-t-count > 3*conp->vc_rows>>2) { if (t > 0) fbcon_bmove(conp, 0, 0, count, 0, t, conp->vc_cols); ywrap_up(unit, conp, p, count); if (conp->vc_rows-b > 0) fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b, conp->vc_cols); } else if (p->scrollmode & __SCROLL_YPANREDRAW) goto redraw_up; else fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols); fbcon_clear(conp, b-count, 0, count, conp->vc_cols); break; case __SCROLL_YPAN: if (( p->yscroll + count <= 2 * (p->vrows - conp->vc_rows)) && (( !scroll_partial && (b-t == conp->vc_rows)) || ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2)))) { if (t > 0) fbcon_bmove(conp, 0, 0, count, 0, t, conp->vc_cols); ypan_up(unit, conp, p, count); if (conp->vc_rows-b > 0) fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b, conp->vc_cols); } else if (p->scrollmode & __SCROLL_YPANREDRAW) goto redraw_up; else fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols); fbcon_clear(conp, b-count, 0, count, conp->vc_cols); break; case __SCROLL_YREDRAW: redraw_up: fbcon_redraw(conp, p, t, b-t-count, count*conp->vc_cols); p->dispsw->clear(conp, p, real_y(p, b-count), 0, count, conp->vc_cols); scr_memsetw((unsigned short *)(conp->vc_origin + conp->vc_size_row * (b-count)), conp->vc_video_erase_char, conp->vc_size_row * count); return 1; } break; case SM_DOWN: if (count > conp->vc_rows) /* Maximum realistic size */ count = conp->vc_rows; switch (p->scrollmode & __SCROLL_YMASK) { case __SCROLL_YMOVE: p->dispsw->bmove(p, t, 0, t+count, 0, b-t-count, conp->vc_cols); p->dispsw->clear(conp, p, t, 0, count, conp->vc_cols); break; case __SCROLL_YWRAP: if (b-t-count > 3*conp->vc_rows>>2) { if (conp->vc_rows-b > 0) fbcon_bmove(conp, b, 0, b-count, 0, conp->vc_rows-b, conp->vc_cols); ywrap_down(unit, conp, p, count); if (t > 0) fbcon_bmove(conp, count, 0, 0, 0, t, conp->vc_cols); } else if (p->scrollmode & __SCROLL_YPANREDRAW) goto redraw_down; else fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols); fbcon_clear(conp, t, 0, count, conp->vc_cols); break; case __SCROLL_YPAN: if (( count-p->yscroll <= p->vrows-conp->vc_rows) && (( !scroll_partial && (b-t == conp->vc_rows)) || ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2)))) { if (conp->vc_rows-b > 0) fbcon_bmove(conp, b, 0, b-count, 0, conp->vc_rows-b, conp->vc_cols); ypan_down(unit, conp, p, count); if (t > 0) fbcon_bmove(conp, count, 0, 0, 0, t, conp->vc_cols); } else if (p->scrollmode & __SCROLL_YPANREDRAW) goto redraw_down; else fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols); fbcon_clear(conp, t, 0, count, conp->vc_cols); break; case __SCROLL_YREDRAW: redraw_down: fbcon_redraw(conp, p, b - 1, b-t-count, -count*conp->vc_cols); p->dispsw->clear(conp, p, real_y(p, t), 0, count, conp->vc_cols); scr_memsetw((unsigned short *)(conp->vc_origin + conp->vc_size_row * t), conp->vc_video_erase_char, conp->vc_size_row * count); return 1; } } return 0;}static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, int height, int width){ int unit = conp->vc_num; struct display *p = &fb_display[unit]; if (!p->can_soft_blank && console_blanked) return; if (!width || !height) return; if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) && (sx <= p->cursor_x) && (p->cursor_x < sx+width)) || ((dy <= p->cursor_y) && (p->cursor_y < dy+height) && (dx <= p->cursor_x) && (p->cursor_x < dx+width))) fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK); /* Split blits that cross physical y_wrap case. * Pathological case involves 4 blits, better to use recursive * code rather than unrolled case * * Recursive invocations don't need to erase the cursor over and * over again, so we use fbcon_bmove_rec() */ fbcon_bmove_rec(p, sy, sx, dy, dx, height, width, p->vrows-p->yscroll);}static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx, int height, int width, u_int y_break){ u_int b; if (sy < y_break && sy+height > y_break) { b = y_break-sy; if (dy < sy) { /* Avoid trashing self */ fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break); fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break); } else { fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break); fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break); } return; } if (dy < y_break && dy+height > y_break) { b = y_break-dy; if (dy < sy) { /* Avoid trashing self */ fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break); fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break); } else { fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break); fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break); } return; } p->dispsw->bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, width);}static int fbcon_switch(struct vc_data *conp){ int unit = conp->vc_num; struct display *p = &fb_display[unit]; struct fb_info *info = p->fb_info; if (softback_top) { int l = fbcon_softback_size / conp->vc_size_row; if (softback_lines) fbcon_set_origin(conp); softback_top = softback_curr = softback_in = softback_buf; softback_lines = 0; if (l > 5) softback_end = softback_buf + l * conp->vc_size_row; else { /* Smaller scrollback makes no sense, and 0 would screw the operation totally */ softback_top = 0; } } if (logo_shown >= 0) { struct vc_data *conp2 = vc_cons[logo_shown].d; if (conp2->vc_top == logo_lines && conp2->vc_bottom == conp2->vc_rows) conp2->vc_top = 0; logo_shown = -1; } p->var.yoffset = p->yscroll = 0; switch (p->scrollmode & __SCROLL_YMASK) { case __SCROLL_YWRAP: scrollback_phys_max = p->vrows-conp->vc_rows; break; case __SCROLL_YPAN: scrollback_phys_max = p->vrows-2*conp->vc_rows; if (scrollback_phys_max < 0) scrollback_phys_max = 0; break; default: scrollback_phys_max = 0; break; } scrollback_max = 0; scrollback_current = 0; if (info && info->switch_con) (*info->switch_con)(unit, info); if (p->dispsw->clear_margins && vt_cons[unit]->vc_mode == KD_TEXT) p->dispsw->clear_margins(conp, p, 0); if (logo_shown == -2) { logo_shown = fg_console; fbcon_show_logo(); /* This is protected above by initmem_freed */ update_region(fg_console, conp->vc_origin + conp->vc_size_row * conp->vc_top, conp->vc_size_row * (conp->vc_bottom - conp->vc_top) / 2); return 0; } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -