📄 fbcon.c
字号:
fbcon_free_font(p);}/* ====================================================================== *//* fbcon_XXX routines - interface used by the world * * This system is now divided into two levels because of complications * caused by hardware scrolling. Top level functions: * * fbcon_bmove(), fbcon_clear(), fbcon_putc(), fbcon_clear_margins() * * handles y values in range [0, scr_height-1] that correspond to real * screen positions. y_wrap shift means that first line of bitmap may be * anywhere on this display. These functions convert lineoffsets to * bitmap offsets and deal with the wrap-around case by splitting blits. * * fbcon_bmove_physical_8() -- These functions fast implementations * fbcon_clear_physical_8() -- of original fbcon_XXX fns. * fbcon_putc_physical_8() -- (font width != 8) may be added later * * WARNING: * * At the moment fbcon_putc() cannot blit across vertical wrap boundary * Implies should only really hardware scroll in rows. Only reason for * restriction is simplicity & efficiency at the moment. */static __inline__ int real_y(struct display *p, int ypos){ int rows = p->vrows; ypos += p->yscroll; return ypos < rows ? ypos : ypos - rows;}static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, int width){ struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; u_int y_break; if (fbcon_is_inactive(vc, info)) return; if (!height || !width) return; /* Split blits that cross physical y_wrap boundary */ y_break = p->vrows - p->yscroll; if (sy < y_break && sy + height - 1 >= y_break) { u_int b = y_break - sy; ops->clear(vc, info, real_y(p, sy), sx, b, width); ops->clear(vc, info, real_y(p, sy + b), sx, height - b, width); } else ops->clear(vc, info, real_y(p, sy), sx, height, width);}static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, int count, int ypos, int xpos){ 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; if (!fbcon_is_inactive(vc, info)) ops->putcs(vc, info, s, count, real_y(p, ypos), xpos, get_color(vc, info, scr_readw(s), 1), get_color(vc, info, scr_readw(s), 0));}static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos){ unsigned short chr; scr_writew(c, &chr); fbcon_putcs(vc, &chr, 1, ypos, xpos);}static void fbcon_clear_margins(struct vc_data *vc, int bottom_only){ struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_ops *ops = info->fbcon_par; if (!fbcon_is_inactive(vc, info)) ops->clear_margins(vc, info, bottom_only);}static void fbcon_cursor(struct vc_data *vc, int mode){ struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int y = real_y(p, vc->vc_y); int c = scr_readw((u16 *) vc->vc_pos); if (fbcon_is_inactive(vc, info)) return; ops->cursor_flash = 1; if (mode & CM_SOFTBACK) { mode &= ~CM_SOFTBACK; if (softback_lines) { if (y + softback_lines >= vc->vc_rows) { mode = CM_ERASE; ops->cursor_flash = 0; } else y += softback_lines; } } else if (softback_lines) fbcon_set_origin(vc); ops->cursor(vc, info, p, mode, get_color(vc, info, c, 1), get_color(vc, info, c, 0)); vbl_cursor_cnt = CURSOR_DRAW_DELAY;}static int scrollback_phys_max = 0;static int scrollback_max = 0;static int scrollback_current = 0;int update_var(int con, struct fb_info *info){ if (con == ((struct fbcon_ops *)info->fbcon_par)->currcon) return fb_pan_display(info, &info->var); return 0;}/* * If no vc is existent yet, just set struct display */static void fbcon_preset_disp(struct fb_info *info, int unit){ struct display *p = &fb_display[unit]; struct display *t = &fb_display[fg_console]; info->var.xoffset = info->var.yoffset = p->yscroll = 0; if (var_to_display(p, &info->var, info)) return; p->fontdata = t->fontdata; p->userfont = t->userfont; if (p->userfont) REFCOUNT(p->fontdata)++;}static void fbcon_set_disp(struct fb_info *info, struct vc_data *vc){ struct display *p = &fb_display[vc->vc_num], *t; struct vc_data **default_mode = vc->vc_display_fg; struct vc_data *svc = *default_mode; int display_fg = (*default_mode)->vc_num; int rows, cols, charcnt = 256; info->var.xoffset = info->var.yoffset = p->yscroll = 0; if (var_to_display(p, &info->var, info)) return; t = &fb_display[display_fg]; if (!vc->vc_font.data) { vc->vc_font.data = p->fontdata = t->fontdata; vc->vc_font.width = (*default_mode)->vc_font.width; vc->vc_font.height = (*default_mode)->vc_font.height; p->userfont = t->userfont; if (p->userfont) REFCOUNT(p->fontdata)++; } if (p->userfont) charcnt = FNTCHARCNT(p->fontdata); vc->vc_can_do_color = (fb_get_color_depth(info) != 1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; if (charcnt == 256) { vc->vc_hi_font_mask = 0; } else { vc->vc_hi_font_mask = 0x100; if (vc->vc_can_do_color) vc->vc_complement_mask <<= 1; } if (!*svc->vc_uni_pagedir_loc) con_set_default_unimap(display_fg); if (!*vc->vc_uni_pagedir_loc) con_copy_unimap(vc->vc_num, display_fg); cols = info->var.xres / vc->vc_font.width; rows = info->var.yres / vc->vc_font.height; vc_resize(vc->vc_num, cols, rows); if (CON_IS_VISIBLE(vc)) { update_screen(vc->vc_num); if (softback_buf) { int l = fbcon_softback_size / vc->vc_size_row; if (l > 5) softback_end = softback_buf + l * vc->vc_size_row; else { /* Smaller scrollback makes no sense, and 0 would screw the operation totally */ softback_top = 0; } } }}static __inline__ void ywrap_up(struct vc_data *vc, int count){ struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct display *p = &fb_display[vc->vc_num]; p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ p->yscroll -= p->vrows; info->var.xoffset = 0; info->var.yoffset = p->yscroll * vc->vc_font.height; info->var.vmode |= FB_VMODE_YWRAP; update_var(vc->vc_num, info); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; scrollback_current = 0;}static __inline__ void ywrap_down(struct vc_data *vc, int count){ struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct display *p = &fb_display[vc->vc_num]; p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ p->yscroll += p->vrows; info->var.xoffset = 0; info->var.yoffset = p->yscroll * vc->vc_font.height; info->var.vmode |= FB_VMODE_YWRAP; update_var(vc->vc_num, info); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; scrollback_current = 0;}static __inline__ void ypan_up(struct vc_data *vc, int count){ 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; p->yscroll += count; if (p->yscroll > p->vrows - vc->vc_rows) { ops->bmove(vc, info, p->vrows - vc->vc_rows, 0, 0, 0, vc->vc_rows, vc->vc_cols); p->yscroll -= p->vrows - vc->vc_rows; } info->var.xoffset = 0; info->var.yoffset = p->yscroll * vc->vc_font.height; info->var.vmode &= ~FB_VMODE_YWRAP; update_var(vc->vc_num, info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; scrollback_current = 0;}static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count){ struct fb_info *info = registered_fb[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); fbcon_clear_margins(vc, 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[con2fb_map[vc->vc_num]]; struct display *p = &fb_display[vc->vc_num]; struct fbcon_ops *ops = info->fbcon_par; p->yscroll -= count; if (p->yscroll < 0) { ops->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows, 0, vc->vc_rows, vc->vc_cols); p->yscroll += p->vrows - vc->vc_rows; } info->var.xoffset = 0; info->var.yoffset = p->yscroll * vc->vc_font.height; info->var.vmode &= ~FB_VMODE_YWRAP; update_var(vc->vc_num, info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; scrollback_current = 0;}static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count){ struct fb_info *info = registered_fb[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); fbcon_clear_margins(vc, 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){ int count = vc->vc_rows; unsigned short *d, *s; unsigned long n; int line = 0; d = (u16 *) softback_curr; if (d == (u16 *) softback_in) d = (u16 *) vc->vc_origin; n = softback_curr + delta * vc->vc_size_row; softback_lines -= delta; 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) / vc->vc_size_row; n = softback_top; } } else if (softback_curr >= softback_top && n < softback_top) { softback_lines -= (softback_top - n) / vc->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 *) vc->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) { fbcon_putcs(vc, start, s - start, line, x); x += s - start; start = s; } } if (c == scr_readw(d)) { if (s > start) { fbcon_putcs(vc, start, s - start, line, x); x += s - start + 1; start = s + 1; } else { x++; start++; } } s++; d++; } while (s < le); if (s > start) fbcon_putcs(vc, start, s - start, line, x); line++; if (d == (u16 *) softback_end) d = (u16 *) softback_buf; if (d == (u16 *) softback_in) d = (u16 *) vc->vc_origin; if (s == (u16 *) softback_end) s = (u16 *) softback_buf; if (s == (u16 *) softback_in) s = (u16 *) vc->vc_origin; }}static void fbcon_redraw_move(struct vc_data *vc, struct display *p, int line, int count, int dy){ 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) { fbcon_putcs(vc, start, s - start, dy, x); x += s - start; start = s; } } console_conditional_schedule(); s++; } while (s < le); if (s > start) fbcon_putcs(vc, start, s - start, dy, x); console_conditional_schedule(); dy++; }}static void fbcon_redraw(struct vc_data *vc, struct display *p, int line, int count, int offset){ unsigned short *d = (unsigned short *) (vc->vc_origin + vc->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) { fbcon_putcs(vc, start, s - start, line, x); x += s - start; start = s; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -