📄 fbcon.c
字号:
/* * ++guenther: console.c:vc_allocate() relies on initializing * vc_{cols,rows}, but we must not set those if we are only * resizing the console. */ if (!init) { vc->vc_cols = new_cols; vc->vc_rows = new_rows; } if (logo) fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows); if (vc == svc && softback_buf) fbcon_update_softback(vc); if (ops->rotate_font && ops->rotate_font(info, vc)) { ops->rotate = FB_ROTATE_UR; set_blitting_type(vc, info); } ops->p = &fb_display[fg_console];}static void fbcon_free_font(struct display *p){ if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); p->fontdata = NULL; p->userfont = 0;}static void fbcon_deinit(struct vc_data *vc){ struct display *p = &fb_display[vc->vc_num]; struct fb_info *info; struct fbcon_ops *ops; int idx; fbcon_free_font(p); idx = con2fb_map[vc->vc_num]; if (idx == -1) goto finished; info = registered_fb[idx]; if (!info) goto finished; ops = info->fbcon_par; if (!ops) goto finished; if (CON_IS_VISIBLE(vc)) fbcon_del_cursor_timer(info); ops->flags &= ~FBCON_FLAGS_INIT;finished: if (!con_is_bound(&fb_con)) fbcon_exit(); return;}/* ====================================================================== *//* 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 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; int y; int c = scr_readw((u16 *) vc->vc_pos); if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1) return; ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1; if (mode & CM_SOFTBACK) { mode &= ~CM_SOFTBACK; y = softback_lines; } else { if (softback_lines) fbcon_set_origin(vc); y = 0; } ops->cursor(vc, info, mode, y, 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;/* * If no vc is existent yet, just set struct display */static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var, int unit){ struct display *p = &fb_display[unit]; struct display *t = &fb_display[fg_console]; if (var_to_display(p, 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 fb_var_screeninfo *var, 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; struct fbcon_ops *ops = info->fbcon_par; int rows, cols, charcnt = 256; if (var_to_display(p, var, info)) return; t = &fb_display[svc->vc_num]; if (!vc->vc_font.data) { vc->vc_font.data = (void *)(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); var->activate = FB_ACTIVATE_NOW; info->var.activate = var->activate; var->yoffset = info->var.yoffset; var->xoffset = info->var.xoffset; fb_set_var(info, var); ops->var = info->var; vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=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(svc); if (!*vc->vc_uni_pagedir_loc) con_copy_unimap(vc, svc); cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); cols /= vc->vc_font.width; rows /= vc->vc_font.height; vc_resize(vc, cols, rows); if (CON_IS_VISIBLE(vc)) { update_screen(vc); if (softback_buf) fbcon_update_softback(vc); }}static __inline__ void ywrap_up(struct vc_data *vc, int count){ 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]; p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ p->yscroll -= p->vrows; ops->var.xoffset = 0; ops->var.yoffset = p->yscroll * vc->vc_font.height; ops->var.vmode |= FB_VMODE_YWRAP; ops->update_start(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 fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ p->yscroll += p->vrows; ops->var.xoffset = 0; ops->var.yoffset = p->yscroll * vc->vc_font.height; ops->var.vmode |= FB_VMODE_YWRAP; ops->update_start(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; } ops->var.xoffset = 0; ops->var.yoffset = p->yscroll * vc->vc_font.height; ops->var.vmode &= ~FB_VMODE_YWRAP; ops->update_start(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 fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll += count; if (p->yscroll > p->vrows - vc->vc_rows) { p->yscroll -= p->vrows - vc->vc_rows; fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t); } ops->var.xoffset = 0; ops->var.yoffset = p->yscroll * vc->vc_font.height; ops->var.vmode &= ~FB_VMODE_YWRAP; ops->update_start(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; } ops->var.xoffset = 0; ops->var.yoffset = p->yscroll * vc->vc_font.height; ops->var.vmode &= ~FB_VMODE_YWRAP; ops->update_start(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 fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll -= count; if (p->yscroll < 0) { p->yscroll += p->vrows - vc->vc_rows; fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count); } ops->var.xoffset = 0; ops->var.yoffset = p->yscroll * vc->vc_font.height; ops->var.vmode &= ~FB_VMODE_YWRAP; ops->update_start(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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -