📄 fbcon.c
字号:
if (!softback_buf) { fbcon_softback_size = 0; softback_top = 0; } } } else { if (softback_buf) { kfree((void *)softback_buf); softback_buf = 0; softback_top = 0; } } if (softback_buf) softback_in = softback_top = softback_curr = softback_buf; softback_lines = 0; } for (i = 0; i < MAX_NR_CONSOLES; i++) if (i != con && fb_display[i].fb_info == p->fb_info && fb_display[i].conp && fb_display[i].fontdata) break; fbcon_free_font(p); if (i < MAX_NR_CONSOLES) { struct display *q = &fb_display[i]; if (fontwidthvalid(p,fontwidth(q))) { /* If we are not the first console on this fb, copy the font from that console */ p->_fontwidth = q->_fontwidth; p->_fontheight = q->_fontheight; p->_fontwidthlog = q->_fontwidthlog; p->_fontheightlog = q->_fontheightlog; p->fontdata = q->fontdata; p->userfont = q->userfont; if (p->userfont) { REFCOUNT(p->fontdata)++; charcnt = FNTCHARCNT(p->fontdata); } con_copy_unimap(con, i); } } if (!p->fontdata) { if (!p->fb_info->fontname[0] || !(font = fbcon_find_font(p->fb_info->fontname))) font = fbcon_get_default_font(p->var.xres, p->var.yres); p->_fontwidth = font->width; p->_fontheight = font->height; p->fontdata = font->data; fbcon_font_widths(p); } if (!fontwidthvalid(p,fontwidth(p))) {#ifdef CONFIG_MAC if (MACH_IS_MAC) /* ++Geert: hack to make 6x11 fonts work on mac */ p->dispsw = &fbcon_mac; else#endif { /* ++Geert: changed from panic() to `correct and continue' */ printk(KERN_ERR "fbcon_setup: No support for fontwidth %d\n", fontwidth(p)); p->dispsw = &fbcon_dummy; } } if (p->dispsw->set_font) p->dispsw->set_font(p, fontwidth(p), fontheight(p)); updatescrollmode(p); old_cols = conp->vc_cols; old_rows = conp->vc_rows; nr_cols = p->var.xres/fontwidth(p); nr_rows = p->var.yres/fontheight(p); if (logo) { /* Need to make room for the logo */ int cnt; int step;#if defined(CONFIG_MY_LOGO) && (MY_LOGO_H > LOGO_H) logo_lines = (MY_LOGO_H + fontheight(p) - 1) / fontheight(p);#else logo_lines = (LOGO_H + fontheight(p) - 1) / fontheight(p);#endif q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows); step = logo_lines * old_cols; for (r = q - logo_lines * old_cols; r < q; r++) if (*r != conp->vc_video_erase_char) break; if (r != q && nr_rows >= old_rows + logo_lines) { save = kmalloc(logo_lines * nr_cols * 2, GFP_KERNEL); if (save) { int i = old_cols < nr_cols ? old_cols : nr_cols; scr_memsetw(save, conp->vc_video_erase_char, logo_lines * nr_cols * 2); r = q - step; for (cnt = 0; cnt < logo_lines; cnt++, r += i) scr_memcpyw_to(save + cnt * nr_cols, r, 2 * i); r = q; } } if (r == q) { /* We can scroll screen down */ r = q - step - old_cols; for (cnt = old_rows - logo_lines; cnt > 0; cnt--) { scr_memcpyw(r + step, r, conp->vc_size_row); r -= old_cols; } if (!save) { conp->vc_y += logo_lines; conp->vc_pos += logo_lines * conp->vc_size_row; } } scr_memsetw((unsigned short *)conp->vc_origin, conp->vc_video_erase_char, conp->vc_size_row * logo_lines); } /* * ++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) { conp->vc_cols = nr_cols; conp->vc_rows = nr_rows; } p->vrows = p->var.yres_virtual/fontheight(p); if ((p->var.yres % fontheight(p)) && (p->var.yres_virtual % fontheight(p) < p->var.yres % fontheight(p))) p->vrows--; conp->vc_can_do_color = p->var.bits_per_pixel != 1; conp->vc_complement_mask = conp->vc_can_do_color ? 0x7700 : 0x0800; if (charcnt == 256) { conp->vc_hi_font_mask = 0; p->fgshift = 8; p->bgshift = 12; p->charmask = 0xff; } else { conp->vc_hi_font_mask = 0x100; if (conp->vc_can_do_color) conp->vc_complement_mask <<= 1; p->fgshift = 9; p->bgshift = 13; p->charmask = 0x1ff; } if (p->dispsw == &fbcon_dummy) printk(KERN_WARNING "fbcon_setup: type %d (aux %d, depth %d) not " "supported\n", p->type, p->type_aux, p->var.bits_per_pixel); p->dispsw->setup(p); p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1; p->bgcol = 0; if (!init) { if (conp->vc_cols != nr_cols || conp->vc_rows != nr_rows) vc_resize_con(nr_rows, nr_cols, con); else if (CON_IS_VISIBLE(conp) && vt_cons[conp->vc_num]->vc_mode == KD_TEXT) { if (p->dispsw->clear_margins) p->dispsw->clear_margins(conp, p, 0); update_screen(con); } if (save) { q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows); scr_memcpyw_from(q, save, logo_lines * nr_cols * 2); conp->vc_y += logo_lines; conp->vc_pos += logo_lines * conp->vc_size_row; kfree(save); } } if (logo) { logo_shown = -2; conp->vc_top = logo_lines; } if (con == fg_console && softback_buf) { int l = fbcon_softback_size / conp->vc_size_row; 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; } }}/* ====================================================================== *//* 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() * * 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() -- (fontwidth != 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 *conp, int sy, int sx, int height, int width){ int unit = conp->vc_num; struct display *p = &fb_display[unit]; u_int y_break; int redraw_cursor = 0; if (!p->can_soft_blank && console_blanked) return; if (!height || !width) return; if ((sy <= p->cursor_y) && (p->cursor_y < sy+height) && (sx <= p->cursor_x) && (p->cursor_x < sx+width)) { cursor_undrawn(); redraw_cursor = 1; } /* 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; p->dispsw->clear(conp, p, real_y(p, sy), sx, b, width); p->dispsw->clear(conp, p, real_y(p, sy+b), sx, height-b, width); } else p->dispsw->clear(conp, p, real_y(p, sy), sx, height, width); if (redraw_cursor) vbl_cursor_cnt = CURSOR_DRAW_DELAY;}static void fbcon_putc(struct vc_data *conp, int c, int ypos, int xpos){ int unit = conp->vc_num; struct display *p = &fb_display[unit]; int redraw_cursor = 0; if (!p->can_soft_blank && console_blanked) return; if (vt_cons[unit]->vc_mode != KD_TEXT) return; if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) { cursor_undrawn(); redraw_cursor = 1; } p->dispsw->putc(conp, p, c, real_y(p, ypos), xpos); if (redraw_cursor) vbl_cursor_cnt = CURSOR_DRAW_DELAY;}static void fbcon_putcs(struct vc_data *conp, const unsigned short *s, int count, int ypos, int xpos){ int unit = conp->vc_num; struct display *p = &fb_display[unit]; int redraw_cursor = 0; if (!p->can_soft_blank && console_blanked) return; if (vt_cons[unit]->vc_mode != KD_TEXT) return; if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) && (p->cursor_x < (xpos + count))) { cursor_undrawn(); redraw_cursor = 1; } p->dispsw->putcs(conp, p, s, count, real_y(p, ypos), xpos); if (redraw_cursor) vbl_cursor_cnt = CURSOR_DRAW_DELAY;}static void fbcon_cursor(struct vc_data *conp, int mode){ int unit = conp->vc_num; struct display *p = &fb_display[unit]; int y = conp->vc_y; if (mode & CM_SOFTBACK) { mode &= ~CM_SOFTBACK; if (softback_lines) { if (y + softback_lines >= conp->vc_rows) mode = CM_ERASE; else y += softback_lines; } } else if (softback_lines) fbcon_set_origin(conp); /* do we have a hardware cursor ? */ if (p->dispsw->cursor) { p->cursor_x = conp->vc_x; p->cursor_y = y; p->dispsw->cursor(p, mode, p->cursor_x, real_y(p, p->cursor_y)); return; } /* Avoid flickering if there's no real change. */ if (p->cursor_x == conp->vc_x && p->cursor_y == y && (mode == CM_ERASE) == !cursor_on) return; cursor_on = 0; if (cursor_drawn) p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); p->cursor_x = conp->vc_x; p->cursor_y = y; switch (mode) { case CM_ERASE: cursor_drawn = 0; break; case CM_MOVE: case CM_DRAW: if (cursor_drawn) p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); vbl_cursor_cnt = CURSOR_DRAW_DELAY; cursor_on = 1; break; }}static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp){ struct display *p; if (!cursor_on) return; if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) { p = &fb_display[fg_console]; if (p->dispsw->revc) p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); cursor_drawn ^= 1; vbl_cursor_cnt = cursor_blink_rate; }}static int scrollback_phys_max = 0;static int scrollback_max = 0;static int scrollback_current = 0;static __inline__ void ywrap_up(int unit, struct vc_data *conp, struct display *p, int count){ p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ p->yscroll -= p->vrows; p->var.xoffset = 0; p->var.yoffset = p->yscroll*fontheight(p); p->var.vmode |= FB_VMODE_YWRAP; p->fb_info->updatevar(unit, p->fb_info); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; scrollback_current = 0;}static __inline__ void ywrap_down(int unit, struct vc_data *conp, struct display *p, int count){ p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ p->yscroll += p->vrows; p->var.xoffset = 0; p->var.yoffset = p->yscroll*fontheight(p); p->var.vmode |= FB_VMODE_YWRAP; p->fb_info->updatevar(unit, p->fb_info); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; scrollback_current = 0;}static __inline__ void ypan_up(int unit, struct vc_data *conp, struct display *p, int count){ p->yscroll += count; if (p->yscroll > p->vrows-conp->vc_rows) { p->dispsw->bmove(p, p->vrows-conp->vc_rows, 0, 0, 0, conp->vc_rows, conp->vc_cols); p->yscroll -= p->vrows-conp->vc_rows; } p->var.xoffset = 0; p->var.yoffset = p->yscroll*fontheight(p); p->var.vmode &= ~FB_VMODE_YWRAP; p->fb_info->updatevar(unit, p->fb_info); if (p->dispsw->clear_margins) p->dispsw->clear_margins(conp, p, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; scrollback_current = 0;}static __inline__ void ypan_down(int unit, struct vc_data *conp, struct display *p, int count){ p->yscroll -= count; if (p->yscroll < 0) { p->dispsw->bmove(p, 0, 0, p->vrows-conp->vc_rows, 0, conp->vc_rows, conp->vc_cols); p->yscroll += p->vrows-conp->vc_rows; } p->var.xoffset = 0; p->var.yoffset = p->yscroll*fontheight(p); p->var.vmode &= ~FB_VMODE_YWRAP; p->fb_info->updatevar(unit, p->fb_info); if (p->dispsw->clear_margins) p->dispsw->clear_margins(conp, p, 1); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; scrollback_current = 0;}static void fbcon_redraw_softback(struct vc_data *conp, struct display *p, long delta){ unsigned short *d, *s; unsigned long n; int line = 0; int count = conp->vc_rows; d = (u16 *)softback_curr; if (d == (u16 *)softback_in) d = (u16 *)conp->vc_origin; n = softback_curr + delta * conp->vc_size_row; softback_lines -= delta;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -