📄 fbcon.c
字号:
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;}static int fbcon_blank(struct vc_data *conp, int blank){ struct display *p = &fb_display[conp->vc_num]; struct fb_info *info = p->fb_info; if (blank < 0) /* Entering graphics mode */ return 0; fbcon_cursor(p->conp, blank ? CM_ERASE : CM_DRAW); if (!p->can_soft_blank) { if (blank) { if (p->visual == FB_VISUAL_MONO01) { if (p->screen_base) fb_memset255(p->screen_base, p->var.xres_virtual*p->var.yres_virtual* p->var.bits_per_pixel>>3); } else { unsigned short oldc; u_int height; u_int y_break; oldc = conp->vc_video_erase_char; conp->vc_video_erase_char &= p->charmask; height = conp->vc_rows; y_break = p->vrows-p->yscroll; if (height > y_break) { p->dispsw->clear(conp, p, real_y(p, 0), 0, y_break, conp->vc_cols); p->dispsw->clear(conp, p, real_y(p, y_break), 0, height-y_break, conp->vc_cols); } else p->dispsw->clear(conp, p, real_y(p, 0), 0, height, conp->vc_cols); conp->vc_video_erase_char = oldc; } return 0; } else { /* Tell console.c that it has to restore the screen itself */ return 1; } } (*info->blank)(blank, info); return 0;}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 inline int fbcon_get_font(int unit, struct console_font_op *op){ struct display *p = &fb_display[unit]; u8 *data = op->data; u8 *fontdata = p->fontdata; int i, j;#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY if (fontwidth(p) != 8) return -EINVAL;#endif op->width = fontwidth(p); op->height = fontheight(p); op->charcount = (p->charmask == 0x1ff) ? 512 : 256; if (!op->data) return 0; if (op->width <= 8) { j = fontheight(p); for (i = 0; i < op->charcount; i++) { memcpy(data, fontdata, j); memset(data+j, 0, 32-j); data += 32; fontdata += j; } }#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY else if (op->width <= 16) { j = fontheight(p) * 2; for (i = 0; i < op->charcount; i++) { memcpy(data, fontdata, j); memset(data+j, 0, 64-j); data += 64; fontdata += j; } } else if (op->width <= 24) { for (i = 0; i < op->charcount; i++) { for (j = 0; j < fontheight(p); j++) { *data++ = fontdata[0]; *data++ = fontdata[1]; *data++ = fontdata[2]; fontdata += sizeof(u32); } memset(data, 0, 3*(32-j)); data += 3 * (32 - j); } } else { j = fontheight(p) * 4; for (i = 0; i < op->charcount; i++) { memcpy(data, fontdata, j); memset(data+j, 0, 128-j); data += 128; fontdata += j; } }#endif return 0;}static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int userfont){ struct display *p = &fb_display[unit]; int resize; int w = op->width; int h = op->height; int cnt; char *old_data = NULL; if (!fontwidthvalid(p,w)) { if (userfont && op->op != KD_FONT_OP_COPY) kfree(data - FONT_EXTRA_WORDS*sizeof(int)); return -ENXIO; } if (CON_IS_VISIBLE(p->conp) && softback_lines) fbcon_set_origin(p->conp); resize = (w != fontwidth(p)) || (h != fontheight(p)); if (p->userfont) old_data = p->fontdata; if (userfont) cnt = FNTCHARCNT(data); else cnt = 256; p->fontdata = data; if ((p->userfont = userfont)) REFCOUNT(data)++; p->_fontwidth = w; p->_fontheight = h; if (p->conp->vc_hi_font_mask && cnt == 256) { p->conp->vc_hi_font_mask = 0; if (p->conp->vc_can_do_color) p->conp->vc_complement_mask >>= 1; p->fgshift--; p->bgshift--; p->charmask = 0xff; /* ++Edmund: reorder the attribute bits */ if (p->conp->vc_can_do_color) { struct vc_data *conp = p->conp; unsigned short *cp = (unsigned short *) conp->vc_origin; int count = conp->vc_screenbuf_size/2; unsigned short c; for (; count > 0; count--, cp++) { c = scr_readw(cp); scr_writew(((c & 0xfe00) >> 1) | (c & 0xff), cp); } c = conp->vc_video_erase_char; conp->vc_video_erase_char = ((c & 0xfe00) >> 1) | (c & 0xff); conp->vc_attr >>= 1; } } else if (!p->conp->vc_hi_font_mask && cnt == 512) { p->conp->vc_hi_font_mask = 0x100; if (p->conp->vc_can_do_color) p->conp->vc_complement_mask <<= 1; p->fgshift++; p->bgshift++; p->charmask = 0x1ff; /* ++Edmund: reorder the attribute bits */ { struct vc_data *conp = p->conp; unsigned short *cp = (unsigned short *) conp->vc_origin; int count = conp->vc_screenbuf_size/2; unsigned short c; for (; count > 0; count--, cp++) { unsigned short newc; c = scr_readw(cp); if (conp->vc_can_do_color) newc = ((c & 0xff00) << 1) | (c & 0xff); else newc = c & ~0x100; scr_writew(newc, cp); } c = conp->vc_video_erase_char; if (conp->vc_can_do_color) { conp->vc_video_erase_char = ((c & 0xff00) << 1) | (c & 0xff); conp->vc_attr <<= 1; } else conp->vc_video_erase_char = c & ~0x100; } } fbcon_font_widths(p); if (resize) { struct vc_data *conp = p->conp; /* reset wrap/pan */ p->var.xoffset = p->var.yoffset = p->yscroll = 0; p->vrows = p->var.yres_virtual/h; if ((p->var.yres % h) && (p->var.yres_virtual % h < p->var.yres % h)) p->vrows--; updatescrollmode(p); vc_resize_con( p->var.yres/h, p->var.xres/w, unit ); if (CON_IS_VISIBLE(conp) && 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; } } } else if (CON_IS_VISIBLE(p->conp) && vt_cons[unit]->vc_mode == KD_TEXT) { if (p->dispsw->clear_margins) p->dispsw->clear_margins(p->conp, p, 0); update_screen(unit); } if (old_data && (--REFCOUNT(old_data) == 0)) kfree(old_data - FONT_EXTRA_WORDS*sizeof(int)); return 0;}static inline int fbcon_copy_font(int unit, struct console_font_op *op){ struct display *od, *p = &fb_display[unit]; int h = op->height; if (h < 0 || !vc_cons_allocated( h )) return -ENOTTY; if (h == unit) return 0; /* nothing to do */ od = &fb_display[h]; if (od->fontdata == p->fontdata) return 0; /* already the same font... */ op->width = fontwidth(od); op->height = fontheight(od); return fbcon_do_set_font(unit, op, od->fontdata, od->userfont);}static inline int fbcon_set_font(int unit, struct console_font_op *op){ int w = op->width; int h = op->height; int size = h; int i, k; u8 *new_data, *data = op->data, *p;#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY if (w != 8) return -EINVAL;#endif if ((w <= 0) || (w > 32) || (op->charcount != 256 && op->charcount != 512)) return -EINVAL; if (w > 8) { if (w <= 16) size *= 2; else size *= 4; } size *= op->charcount; if (!(new_data = kmalloc(FONT_EXTRA_WORDS*sizeof(int)+size, GFP_USER))) return -ENOMEM; new_data += FONT_EXTRA_WORDS*sizeof(int); FNTSIZE(new_data) = size; FNTCHARCNT(new_data) = op->charcount; REFCOUNT(new_data) = 0; /* usage counter */ p = new_data; if (w <= 8) { for (i = 0; i < op->charcount; i++) { memcpy(p, data, h); data += 32; p += h; } }#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY else if (w <= 16) { h *= 2; for (i = 0; i < op->charcount; i++) { memcpy(p, data, h); data += 64; p += h;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -