fbcon.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,412 行 · 第 1/5 页

C
2,412
字号
	dst = fb_get_buffer_offset(info, &info->pixmap, size);	image.data = dst;	if (info->pixmap.outbuf)		fb_iomove_buf_aligned(info, &info->pixmap, dst, pitch, src, width, image.height);	else		fb_sysmove_buf_aligned(info, &info->pixmap, dst, pitch, src, width, image.height);	info->fbops->fb_imageblit(info, &image);}static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,			int count, int ypos, int xpos){	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];	struct display *p = &fb_display[vc->vc_num];	if (!info->fbops->fb_blank && console_blanked)		return;	if (info->state != FBINFO_STATE_RUNNING)		return;	if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT)		return;	accel_putcs(vc, info, s, count, real_y(p, ypos), xpos);}static void fbcon_cursor(struct vc_data *vc, int mode){	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;	struct display *p = &fb_display[vc->vc_num];	int w = (vc->vc_font.width + 7) >> 3, c;	int y = real_y(p, vc->vc_y);	struct fb_cursor cursor;		if (mode & CM_SOFTBACK) {		mode &= ~CM_SOFTBACK;		if (softback_lines) {			if (y + softback_lines >= vc->vc_rows)				mode = CM_ERASE;			else				y += softback_lines;		}	} else if (softback_lines)		fbcon_set_origin(vc); 	c = scr_readw((u16 *) vc->vc_pos);	cursor.image.data = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));	cursor.set = FB_CUR_SETCUR;	cursor.image.depth = 1;		switch (mode) {	case CM_ERASE:		if (info->cursor.rop == ROP_XOR) {			info->cursor.enable = 0;			info->cursor.rop = ROP_COPY;			info->fbops->fb_cursor(info, &cursor);		}			break;	case CM_MOVE:	case CM_DRAW:		info->cursor.enable = 1;				if (info->cursor.image.fg_color != attr_fgcol(fgshift, c) ||	    	    info->cursor.image.bg_color != attr_bgcol(bgshift, c)) {			cursor.image.fg_color = attr_fgcol(fgshift, c);			cursor.image.bg_color = attr_bgcol(bgshift, c);			cursor.set |= FB_CUR_SETCMAP;		}				if ((info->cursor.image.dx != (vc->vc_font.width * vc->vc_x)) ||		    (info->cursor.image.dy != (vc->vc_font.height * y))) {			cursor.image.dx = vc->vc_font.width * vc->vc_x;			cursor.image.dy = vc->vc_font.height * y;			cursor.set |= FB_CUR_SETPOS;		}		if (info->cursor.image.height != vc->vc_font.height ||		    info->cursor.image.width != vc->vc_font.width) {			cursor.image.height = vc->vc_font.height;			cursor.image.width = vc->vc_font.width;			cursor.set |= FB_CUR_SETSIZE;		}		if (info->cursor.hot.x || info->cursor.hot.y) {			cursor.hot.x = cursor.hot.y = 0;			cursor.set |= FB_CUR_SETHOT;		}		if ((cursor.set & FB_CUR_SETSIZE) || ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)		    || info->cursor.mask == NULL) {			char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);			int cur_height, size, i = 0;			if (!mask)	return;						if (info->cursor.mask)				kfree(info->cursor.mask);			info->cursor.mask = mask;				p->cursor_shape = vc->vc_cursor_type & 0x0f;			cursor.set |= FB_CUR_SETSHAPE;			switch (vc->vc_cursor_type & 0x0f) {			case CUR_NONE:				cur_height = 0;				break;			case CUR_UNDERLINE:				cur_height = (vc->vc_font.height < 10) ? 1 : 2;				break;			case CUR_LOWER_THIRD:				cur_height = vc->vc_font.height/3;				break;			case CUR_LOWER_HALF:				cur_height = vc->vc_font.height >> 1;				break;			case CUR_TWO_THIRDS:				cur_height = (vc->vc_font.height << 1)/3;				break;			case CUR_BLOCK:			default:				cur_height = vc->vc_font.height;				break;			}			size = (vc->vc_font.height - cur_height) * w;			while (size--)				mask[i++] = 0;			size = cur_height * w;			while (size--)				mask[i++] = 0xff;		}        	info->cursor.rop = ROP_XOR;		info->fbops->fb_cursor(info, &cursor);		vbl_cursor_cnt = CURSOR_DRAW_DELAY;		break;	}}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 == info->currcon) 		return fb_pan_display(info, &info->var);	return 0;}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;	int display_fg = (*default_mode)->vc_num;	int rows, cols, charcnt = 256;	info->var.xoffset = info->var.yoffset = p->yscroll = 0;	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)++;		con_copy_unimap(vc->vc_num, display_fg);	}	if (p->userfont)		charcnt = FNTCHARCNT(p->fontdata);	vc->vc_can_do_color = info->var.bits_per_pixel != 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;	}	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;			}		}	}	switch_screen(fg_console);}static __inline__ void ywrap_up(struct vc_data *vc, int count){	struct fb_info *info = registered_fb[(int) 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[(int) 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[(int) con2fb_map[vc->vc_num]];	struct display *p = &fb_display[vc->vc_num];		p->yscroll += count;	if (p->yscroll > p->vrows - vc->vc_rows) {		accel_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);	accel_clear_margins(vc, info, 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[(int) 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);	accel_clear_margins(vc, info, 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[(int) con2fb_map[vc->vc_num]];	struct display *p = &fb_display[vc->vc_num];		p->yscroll -= count;	if (p->yscroll < 0) {		accel_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);	accel_clear_margins(vc, info, 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[(int) 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);	accel_clear_margins(vc, info, 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){	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];	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) {					accel_putcs(vc, info, start, s - start,						    real_y(p, line), x);					x += s - start;					start = s;				}			}			if (c == scr_readw(d)) {				if (s > start) {					accel_putcs(vc, info, 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)			accel_putcs(vc, info, 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 *) 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){	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];	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) {					accel_putcs(vc, info, start, s - start,						    real_y(p, dy), x);					x += s - start;					start = s;				}			}			console_conditional_schedule();			s++;		} while (s < le);		if (s > start)			accel_putcs(vc, info, start, s - start,				    real_y(p, 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);	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];	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)) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?