diff -Naur linux-2.5.61-fbdev/drivers/video/console/Kconfig linux-2.5.61/drivers/video/console/Kconfig --- linux-2.5.61-fbdev/drivers/video/console/Kconfig 2003-02-16 00:49:23.000000000 +0000 +++ linux-2.5.61/drivers/video/console/Kconfig 2003-02-23 06:42:26.000000000 +0000 @@ -136,6 +136,16 @@ If unsure, say N. +config FBCON_ADVANCED_TILEBLIT + bool "Support for Tile Blitting Operations" + depends on FBCON_ADVANCED + ---help--- + If you say Y, Tile Blitting support will be added. Tile blitting is + a drawing operation, but its basic operating unit is a bitmap (in + contrast to Classic Blitting which operate on pixels). This is + necessary for drivers with Text Mode support. + + If unsure, say N. # Guess what we need config FONT_SUN8x16 diff -Naur linux-2.5.61-fbdev/drivers/video/console/Makefile linux-2.5.61/drivers/video/console/Makefile --- linux-2.5.61-fbdev/drivers/video/console/Makefile 2003-02-16 00:49:23.000000000 +0000 +++ linux-2.5.61/drivers/video/console/Makefile 2003-02-23 07:01:01.000000000 +0000 @@ -16,6 +16,10 @@ font-objs += $(font-objs-y) +fbcon_adv-objs := fbcon_accelops.o +fbcon_adv-objs-$(CONFIG_FBCON_ADVANCED_TILEBLIT) += fbcon_tileops.o +fbcon_adv-objs += $(fbcon_adv-objs-y) + # Each configuration option enables a list of files. obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o @@ -24,7 +28,7 @@ obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o obj-$(CONFIG_MDA_CONSOLE) += mdacon.o -obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o font.o +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o font.o fbcon_adv.o obj-$(CONFIG_FB_STI) += sticore.o diff -Naur linux-2.5.61-fbdev/drivers/video/console/fbcon.c linux-2.5.61/drivers/video/console/fbcon.c --- linux-2.5.61-fbdev/drivers/video/console/fbcon.c 2003-02-22 02:34:26.000000000 +0000 +++ linux-2.5.61/drivers/video/console/fbcon.c 2003-02-23 06:45:15.000000000 +0000 @@ -295,136 +295,7 @@ take_over_console(&fb_con, unit, unit, fbcon_is_default); } -/* - * Accelerated handlers. - */ -void accel_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - struct fb_info *info = p->fb_info; - struct vc_data *vc = p->conp; - struct fb_copyarea area; - - area.sx = sx * vc->vc_font.width; - area.sy = sy * vc->vc_font.height; - area.dx = dx * vc->vc_font.width; - area.dy = dy * vc->vc_font.height; - area.height = height * vc->vc_font.height; - area.width = width * vc->vc_font.width; - - info->fbops->fb_copyarea(info, &area); -} - -void accel_clear(struct vc_data *vc, struct display *p, int sy, - int sx, int height, int width) -{ - struct fb_info *info = p->fb_info; - struct fb_fillrect region; - - region.color = attr_bgcol_ec(p, vc); - region.dx = sx * vc->vc_font.width; - region.dy = sy * vc->vc_font.height; - region.width = width * vc->vc_font.width; - region.height = height * vc->vc_font.height; - region.rop = ROP_COPY; - - info->fbops->fb_fillrect(info, ®ion); -} - -#define FB_PIXMAPSIZE 8192 -void accel_putcs(struct vc_data *vc, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - struct fb_info *info = p->fb_info; - unsigned short charmask = p->charmask; - unsigned int width = ((vc->vc_font.width + 7)/8); - unsigned int cellsize = vc->vc_font.height * width; - struct fb_image image; - u16 c = scr_readw(s); - static u8 pixmap[FB_PIXMAPSIZE]; - - image.fg_color = attr_fgcol(p, c); - image.bg_color = attr_bgcol(p, c); - image.dx = xx * vc->vc_font.width; - image.dy = yy * vc->vc_font.height; - image.height = vc->vc_font.height; - image.depth = 0; - - if (!(vc->vc_font.width & 7)) { - unsigned int pitch, cnt, i, j, k; - unsigned int maxcnt = FB_PIXMAPSIZE/cellsize; - char *src, *dst, *dst0; - - image.data = pixmap; - while (count) { - if (count > maxcnt) - cnt = k = maxcnt; - else - cnt = k = count; - - dst0 = pixmap; - pitch = width * cnt; - image.width = vc->vc_font.width * cnt; - while (k--) { - src = p->fontdata + (scr_readw(s++)&charmask)* - cellsize; - dst = dst0; - for (i = image.height; i--; ) { - for (j = 0; j < width; j++) - dst[j] = *src++; - dst += pitch; - } - dst0 += width; - } - - info->fbops->fb_imageblit(info, &image); - image.dx += cnt * vc->vc_font.width; - count -= cnt; - } - } else { - image.width = vc->vc_font.width; - while (count--) { - image.data = p->fontdata + - (scr_readw(s++) & charmask) * cellsize; - info->fbops->fb_imageblit(info, &image); - image.dx += vc->vc_font.width; - } - } -} - -void accel_clear_margins(struct vc_data *vc, struct display *p, - int bottom_only) -{ - struct fb_info *info = p->fb_info; - unsigned int cw = vc->vc_font.width; - unsigned int ch = vc->vc_font.height; - unsigned int rw = info->var.xres % cw; - unsigned int bh = info->var.yres % ch; - unsigned int rs = info->var.xres - rw; - unsigned int bs = info->var.yres - bh; - struct fb_fillrect region; - - region.color = attr_bgcol_ec(p, vc); - region.rop = ROP_COPY; - - if (rw & !bottom_only) { - region.dx = info->var.xoffset + rs; - region.dy = 0; - region.width = rw; - region.height = info->var.yres_virtual; - info->fbops->fb_fillrect(info, ®ion); - } - - if (bh) { - region.dx = info->var.xoffset; - region.dy = info->var.yoffset + bs; - region.width = rs; - region.height = bh; - info->fbops->fb_fillrect(info, ®ion); - } -} - -void accel_cursor(struct display *p, int flags, int xx, int yy) +void fb_cursor(struct display *p, int flags, int xx, int yy) { static char mask[64], image[64], *dest; struct vc_data *vc = p->conp; @@ -743,6 +614,13 @@ int i, charcnt = 256; struct font_desc *font; +#ifdef CONFIG_FBCON_ADVANCED_TILEBLIT + if (info->tileops) + p->dispsw = &tile_switch; + else +#endif + p->dispsw = &accel_switch; + if (con != fg_console || (info->flags & FBINFO_FLAG_MODULE) || info->fix.type == FB_TYPE_TEXT) logo = 0; @@ -880,7 +758,7 @@ vc_resize(con, nr_cols, nr_rows); else if (CON_IS_VISIBLE(vc) && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) { - accel_clear_margins(vc, p, 0); + p->dispsw->clear_margins(vc, p, 0); update_screen(con); } if (save) { @@ -977,11 +855,11 @@ y_break = p->vrows - p->yscroll; if (sy < y_break && sy + height - 1 >= y_break) { u_int b = y_break - sy; - accel_clear(vc, p, real_y(p, sy), sx, b, width); - accel_clear(vc, p, real_y(p, sy + b), sx, height - b, + p->dispsw->clear(vc, p, real_y(p, sy), sx, b, width); + p->dispsw->clear(vc, p, real_y(p, sy + b), sx, height - b, width); } else - accel_clear(vc, p, real_y(p, sy), sx, height, width); + p->dispsw->clear(vc, p, real_y(p, sy), sx, height, width); if (redraw_cursor) vbl_cursor_cnt = CURSOR_DRAW_DELAY; @@ -991,10 +869,6 @@ static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos) { struct display *p = &fb_display[vc->vc_num]; - struct fb_info *info = p->fb_info; - unsigned short charmask = p->charmask; - unsigned int width = ((vc->vc_font.width + 7) >> 3); - struct fb_image image; int redraw_cursor = 0; if (!p->can_soft_blank && console_blanked) @@ -1008,16 +882,7 @@ redraw_cursor = 1; } - image.fg_color = attr_fgcol(p, c); - image.bg_color = attr_bgcol(p, c); - image.dx = xpos * vc->vc_font.width; - image.dy = real_y(p, ypos) * vc->vc_font.height; - image.width = vc->vc_font.width; - image.height = vc->vc_font.height; - image.depth = 1; - image.data = p->fontdata + (c & charmask) * vc->vc_font.height * width; - - info->fbops->fb_imageblit(info, &image); + p->dispsw->putc(vc, p, c, real_y(p, ypos), xpos); if (redraw_cursor) vbl_cursor_cnt = CURSOR_DRAW_DELAY; @@ -1042,7 +907,7 @@ cursor_undrawn(); redraw_cursor = 1; } - accel_putcs(vc, p, s, count, real_y(p, ypos), xpos); + p->dispsw->putcs(vc, p, s, count, real_y(p, ypos), xpos); if (redraw_cursor) vbl_cursor_cnt = CURSOR_DRAW_DELAY; } @@ -1070,7 +935,7 @@ cursor_on = 0; if (cursor_drawn) - accel_cursor(p, 0, p->cursor_x, + fb_cursor(p, 0, p->cursor_x, real_y(p, p->cursor_y)); p->cursor_x = vc->vc_x; @@ -1084,7 +949,7 @@ case CM_MOVE: case CM_DRAW: if (cursor_drawn) - accel_cursor(p, FB_CUR_SETCUR, p->cursor_x, + fb_cursor(p, FB_CUR_SETCUR, p->cursor_x, real_y(p, p->cursor_y)); vbl_cursor_cnt = CURSOR_DRAW_DELAY; cursor_on = 1; @@ -1106,7 +971,7 @@ flag = 0; if (!cursor_drawn) flag = FB_CUR_SETCUR; - accel_cursor(p, flag, p->cursor_x, + fb_cursor(p, flag, p->cursor_x, real_y(p, p->cursor_y)); cursor_drawn ^= 1; vbl_cursor_cnt = cursor_blink_rate; @@ -1168,7 +1033,7 @@ p->yscroll += count; if (p->yscroll > p->vrows - vc->vc_rows) { - accel_bmove(p, p->vrows - vc->vc_rows, 0, 0, 0, + p->dispsw->bmove(p, p->vrows - vc->vc_rows, 0, 0, 0, vc->vc_rows, vc->vc_cols); p->yscroll -= p->vrows - vc->vc_rows; } @@ -1176,7 +1041,7 @@ 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, p, 1); + p->dispsw->clear_margins(vc, p, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; @@ -1191,7 +1056,7 @@ p->yscroll -= count; if (p->yscroll < 0) { - accel_bmove(p, 0, 0, p->vrows - vc->vc_rows, 0, + p->dispsw->bmove(p, 0, 0, p->vrows - vc->vc_rows, 0, vc->vc_rows, vc->vc_cols); p->yscroll += p->vrows - vc->vc_rows; } @@ -1199,7 +1064,7 @@ 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, p, 1); + p->dispsw->clear_margins(vc, p, 1); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; @@ -1265,7 +1130,7 @@ if (attr != (c & 0xff00)) { attr = c & 0xff00; if (s > start) { - accel_putcs(vc, p, start, + p->dispsw->putcs(vc, p, start, s - start, real_y(p, line), x); @@ -1275,7 +1140,7 @@ } if (c == scr_readw(d)) { if (s > start) { - accel_putcs(vc, p, start, + p->dispsw->putcs(vc, p, start, s - start, real_y(p, line), x); @@ -1290,7 +1155,7 @@ d++; } while (s < le); if (s > start) - accel_putcs(vc, p, start, s - start, + p->dispsw->putcs(vc, p, start, s - start, real_y(p, line), x); line++; if (d == (u16 *) softback_end) @@ -1323,7 +1188,7 @@ if (attr != (c & 0xff00)) { attr = c & 0xff00; if (s > start) { - accel_putcs(vc, p, start, + p->dispsw->putcs(vc, p, start, s - start, real_y(p, line), x); @@ -1333,7 +1198,7 @@ } if (c == scr_readw(d)) { if (s > start) { - accel_putcs(vc, p, start, + p->dispsw->putcs(vc, p, start, s - start, real_y(p, line), x); @@ -1350,7 +1215,7 @@ d++; } while (s < le); if (s > start) - accel_putcs(vc, p, start, s - start, + p->dispsw->putcs(vc, p, start, s - start, real_y(p, line), x); console_conditional_schedule(); if (offset > 0) @@ -1420,9 +1285,9 @@ goto redraw_up; switch (p->scrollmode & __SCROLL_YMASK) { case __SCROLL_YMOVE: - accel_bmove(p, t + count, 0, t, 0, + p->dispsw->bmove(p, t + count, 0, t, 0, b - t - count, vc->vc_cols); - accel_clear(vc, p, b - count, 0, count, + p->dispsw->clear(vc, p, b - count, 0, count, vc->vc_cols); break; @@ -1471,7 +1336,7 @@ redraw_up: fbcon_redraw(vc, p, t, b - t - count, count * vc->vc_cols); - accel_clear(vc, p, real_y(p, b - count), 0, + p->dispsw->clear(vc, p, real_y(p, b - count), 0, count, vc->vc_cols); scr_memsetw((unsigned short *) (vc->vc_origin + vc->vc_size_row * @@ -1487,9 +1352,9 @@ count = vc->vc_rows; switch (p->scrollmode & __SCROLL_YMASK) { case __SCROLL_YMOVE: - accel_bmove(p, t, 0, t + count, 0, + p->dispsw->bmove(p, t, 0, t + count, 0, b - t - count, vc->vc_cols); - accel_clear(vc, p, t, 0, count, vc->vc_cols); + p->dispsw->clear(vc, p, t, 0, count, vc->vc_cols); break; case __SCROLL_YWRAP: @@ -1536,7 +1401,7 @@ redraw_down: fbcon_redraw(vc, p, b - 1, b - t - count, -count * vc->vc_cols); - accel_clear(vc, p, real_y(p, t), 0, count, + p->dispsw->clear(vc, p, real_y(p, t), 0, count, vc->vc_cols); scr_memsetw((unsigned short *) (vc->vc_origin + vc->vc_size_row * @@ -1615,7 +1480,7 @@ } return; } - accel_bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, + p->dispsw->bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, width); } @@ -1643,8 +1508,8 @@ DPRINTK("resize now %ix%i\n", var.xres, var.yres); var.activate = FB_ACTIVATE_NOW; fb_set_var(&var, info); - p->vrows = info->var.yres_virtual/fh; } + p->vrows = info->var.yres_virtual/fh; return 0; } @@ -1654,6 +1519,13 @@ struct display *p = &fb_display[unit]; struct fb_info *info = p->fb_info; +#ifdef CONFIG_FBCON_ADVANCED_TILEBLIT + if (info->tileops) + p->dispsw = &tile_switch; + else +#endif + p->dispsw = &accel_switch; + if (softback_top) { int l = fbcon_softback_size / vc->vc_size_row; if (softback_lines) @@ -1679,6 +1551,9 @@ } if (info) info->var.yoffset = p->yscroll = 0; + + fbcon_resize(vc, vc->vc_cols, vc->vc_rows); + switch (p->scrollmode & __SCROLL_YMASK) { case __SCROLL_YWRAP: scrollback_phys_max = p->vrows - vc->vc_rows; @@ -1695,14 +1570,39 @@ scrollback_max = 0; scrollback_current = 0; +#ifdef CONFIG_FBCON_ADVANCED_TILEBLIT + if (info->tileops) { + struct fb_tiledata tile; + int err, cnt, size; + u8 *tiledata; + + cnt = FNTCHARCNT(p->fontdata); + if (!cnt) + cnt = 256; + size = vc->vc_font.height * ((vc->vc_font.width + 7)/8) * cnt; + tiledata = kmalloc(size, GFP_KERNEL); + if (tiledata == NULL) + return 0; + memcpy(tiledata, p->fontdata, size); + tile.tile.width = vc->vc_font.width; + tile.tile.height = vc->vc_font.height; + tile.tile.depth = 1; + tile.len = cnt; + tile.data = tiledata; + err = info->tileops->fb_loadtiles(info, &tile); + kfree(tiledata); + + if (err) return 0; + } +#endif + info->currcon = unit; - fbcon_resize(vc, vc->vc_cols, vc->vc_rows); update_var(unit, info); fbcon_set_palette(vc, color_table); if (vt_cons[unit]->vc_mode == KD_TEXT) - accel_clear_margins(vc, p, 0); + p->dispsw->clear_margins(vc, p, 0); if (logo_shown == -2) { logo_shown = fg_console; /* This is protected above by initmem_freed */ @@ -1737,18 +1637,18 @@ height = vc->vc_rows; y_break = p->vrows - p->yscroll; if (height > y_break) { - accel_clear(vc, p, + p->dispsw->clear(vc, p, real_y(p, 0), 0, y_break, vc->vc_cols); - accel_clear(vc, p, + p->dispsw->clear(vc, p, real_y(p, y_break), 0, height - y_break, vc->vc_cols); } else - accel_clear(vc, p, + p->dispsw->clear(vc, p, real_y(p, 0), 0, height, vc->vc_cols); @@ -1913,6 +1813,29 @@ } +#ifdef CONFIG_FBCON_ADVANCED_TILEBLIT + if (info->tileops) { + struct fb_tiledata tile; + int err, size; + u8 *tiledata; + + size = vc->vc_font.height * ((vc->vc_font.width + 7)/8) * cnt; + tiledata = kmalloc(size, GFP_KERNEL); + if (tiledata == NULL) + return 1; + memcpy(tiledata, p->fontdata, size); + tile.tile.width = vc->vc_font.width; + tile.tile.height = vc->vc_font.height; + tile.tile.depth = 1; + tile.len = cnt; + tile.data = tiledata; + + err = info->tileops->fb_loadtiles(info, &tile); + kfree(tiledata); + if (err) return err; + } +#endif + if (resize) { /* reset wrap/pan */ info->var.xoffset = info->var.yoffset = p->yscroll = 0; @@ -1935,7 +1858,7 @@ } } else if (CON_IS_VISIBLE(vc) && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) { - accel_clear_margins(vc, p, 0); + p->dispsw->clear_margins(vc, p, 0); update_screen(vc->vc_num); } diff -Naur linux-2.5.61-fbdev/drivers/video/console/fbcon.h linux-2.5.61/drivers/video/console/fbcon.h --- linux-2.5.61-fbdev/drivers/video/console/fbcon.h 2003-02-22 02:34:26.000000000 +0000 +++ linux-2.5.61/drivers/video/console/fbcon.h 2003-02-23 06:45:15.000000000 +0000 @@ -46,6 +46,20 @@ unsigned int fontwidthmask; /* 1 at (1 << (width - 1)) if width is supported */ }; +struct display_switch { + void (*bmove)(struct display *p, int sy, int sx, + int dy, int dx, int height, int width); + void (*clear)(struct vc_data *vc, struct display *p, int sy, + int sx, int height, int width); + void (*putcs)(struct vc_data *vc, struct display *p, + const unsigned short *s, int count, + int yy, int xx); + void (*putc)(struct vc_data *vc, struct display *p, + int c, int ypos, int xpos); + void (*clear_margins)(struct vc_data *vc, struct display *p, + int bottom_only); +}; + /* drivers/video/console/fbcon.c */ extern struct display fb_display[MAX_NR_CONSOLES]; extern char con2fb_map[MAX_NR_CONSOLES]; @@ -120,5 +134,7 @@ #define SCROLL_YNOPARTIAL __SCROLL_YNOPARTIAL extern int fb_console_init(void); +extern struct display_switch tile_switch; +extern struct display_switch accel_switch; #endif /* _VIDEO_FBCON_H */ diff -Naur linux-2.5.61-fbdev/drivers/video/console/fbcon_accelops.c linux-2.5.61/drivers/video/console/fbcon_accelops.c --- linux-2.5.61-fbdev/drivers/video/console/fbcon_accelops.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.5.61/drivers/video/console/fbcon_accelops.c 2003-02-23 07:08:50.000000000 +0000 @@ -0,0 +1,229 @@ +/* + * linux/drivers/video/fbcon_defops.c -- Console Ops using Classic Blitting + * + * Copyright (C) 2003 James Simmons + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include "fbcon.h" + +static __inline__ int real_y(struct display *p, int ypos) +{ + int rows = p->vrows; + + ypos += p->yscroll; + return ypos < rows ? ypos : ypos - rows; +} + +/* + * Accelerated handlers. + */ +static void accel_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + struct fb_info *info = p->fb_info; + struct vc_data *vc = p->conp; + struct fb_copyarea area; + + area.sx = sx * vc->vc_font.width; + area.sy = sy * vc->vc_font.height; + area.dx = dx * vc->vc_font.width; + area.dy = dy * vc->vc_font.height; + area.height = height * vc->vc_font.height; + area.width = width * vc->vc_font.width; + + info->fbops->fb_copyarea(info, &area); +} + +static void accel_clear(struct vc_data *vc, struct display *p, int sy, + int sx, int height, int width) +{ + struct fb_info *info = p->fb_info; + struct fb_fillrect region; + + region.color = attr_bgcol_ec(p, vc); + region.dx = sx * vc->vc_font.width; + region.dy = sy * vc->vc_font.height; + region.width = width * vc->vc_font.width; + region.height = height * vc->vc_font.height; + region.rop = ROP_COPY; + + info->fbops->fb_fillrect(info, ®ion); +} + +static void accel_putc(struct vc_data *vc, struct display *p, + int c, int ypos, int xpos) +{ + struct fb_info *info = p->fb_info; + unsigned short charmask = p->charmask; + unsigned int width = ((vc->vc_font.width + 7) >> 3); + struct fb_image image; + + image.dx = xpos * vc->vc_font.width; + image.dy = real_y(p, ypos) * vc->vc_font.height; + image.width = vc->vc_font.width; + image.height = vc->vc_font.height; + image.fg_color = attr_fgcol(p, c); + image.bg_color = attr_bgcol(p, c); + image.depth = 0; + image.data = p->fontdata + (c & charmask) * vc->vc_font.height * width; + + info->fbops->fb_imageblit(info, &image); +} + +#define FB_PIXMAPSIZE 8192 +static void putcs_unaligned(struct vc_data *vc, struct display *p, + struct fb_info *info, struct fb_image *image, + int count, const unsigned short *s) +{ + unsigned int width = (vc->vc_font.width + 7)/8; + unsigned int cellsize = vc->vc_font.height * width; + unsigned int maxcnt = FB_PIXMAPSIZE/cellsize; + unsigned int pitch, cnt, i, j, k; + unsigned int shift_low = 0, mod = vc->vc_font.width % 8; + unsigned int shift_high = 8; + unsigned int idx = vc->vc_font.width/8; + unsigned short charmask = p->charmask; + u8 mask, *src, *dst, *dst0; + + while (count) { + if (count > maxcnt) + cnt = k = maxcnt; + else + cnt = k = count; + + dst0 = (u8 *) image->data; + image->width = vc->vc_font.width * cnt; + pitch = (image->width + 7)/8; + while (k--) { + src = p->fontdata + (scr_readw(s++) & charmask) * cellsize; + dst = dst0; + mask = (u8) (0xfff << shift_high); + for (i = image->height; i--; ) { + for (j = 0; j < idx; j++) { + dst[j] &= mask; + dst[j] |= *src >> shift_low; + dst[j+1] = *src << shift_high; + src++; + } + dst[idx] &= mask; + dst[idx] |= *src++ >> shift_low; + dst += pitch; + } + shift_low += mod; + shift_low &= 7; + shift_high = 8 - shift_low; + dst0 += (shift_low) ? width - 1 : width; + } + + info->fbops->fb_imageblit(info, image); + image->dx += cnt * vc->vc_font.width; + count -= cnt; + } +} + +static void putcs_aligned(struct vc_data *vc, struct display *p, + struct fb_info *info, struct fb_image *image, + int count, const unsigned short *s) +{ + unsigned int width = (vc->vc_font.width + 7)/8; + unsigned int cellsize = vc->vc_font.height * width; + unsigned int maxcnt = FB_PIXMAPSIZE/cellsize; + unsigned int pitch, cnt, i, j, k; + unsigned short charmask = p->charmask; + u8 *src, *dst, *dst0; + + while (count) { + if (count > maxcnt) + cnt = k = maxcnt; + else + cnt = k = count; + dst0 = (u8 *) image->data; + pitch = width *cnt; + image->width = vc->vc_font.width * cnt; + while (k--) { + src = p->fontdata + (scr_readw(s++) & charmask) * cellsize; + dst = dst0; + for (i = image->height; i--; ) { + for (j = 0; j < width; j++) + dst[j] = *src++; + dst += pitch; + } + dst0 += width; + } + + info->fbops->fb_imageblit(info, image); + image->dx += cnt * vc->vc_font.width; + count -= cnt; + } +} + +static void accel_putcs(struct vc_data *vc, struct display *p, + const unsigned short *s, int count, int yy, int xx) +{ + static u8 pixmap[FB_PIXMAPSIZE]; + struct fb_info *info = p->fb_info; + struct fb_image image; + u16 c = scr_readw(s); + + image.fg_color = attr_fgcol(p, c); + image.bg_color = attr_bgcol(p, c); + image.dx = xx * vc->vc_font.width; + image.dy = yy * vc->vc_font.height; + image.height = vc->vc_font.height; + image.depth = 0; + image.data = pixmap; + + if (!(vc->vc_font.width & 7)) + putcs_aligned(vc, p, info, &image, count, s); + else + putcs_unaligned(vc, p, info, &image, count, s); +} + +static void accel_clear_margins(struct vc_data *vc, struct display *p, + int bottom_only) +{ + struct fb_info *info = p->fb_info; + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.xres % cw; + unsigned int bh = info->var.yres % ch; + unsigned int rs = info->var.xres - rw; + unsigned int bs = info->var.yres - bh; + struct fb_fillrect region; + + region.color = attr_bgcol_ec(p, vc); + region.rop = ROP_COPY; + + if (rw & !bottom_only) { + region.dx = info->var.xoffset + rs; + region.dy = 0; + region.width = rw; + region.height = info->var.yres_virtual; + info->fbops->fb_fillrect(info, ®ion); + } + + if (bh) { + region.dx = info->var.xoffset; + region.dy = info->var.yoffset + bs; + region.width = rs; + region.height = bh; + info->fbops->fb_fillrect(info, ®ion); + } +} + +struct display_switch accel_switch = { + .bmove = accel_bmove, + .clear = accel_clear, + .putc = accel_putc, + .putcs = accel_putcs, + .clear_margins = accel_clear_margins, +}; + +EXPORT_SYMBOL(accel_switch); diff -Naur linux-2.5.61-fbdev/drivers/video/console/fbcon_tileops.c linux-2.5.61/drivers/video/console/fbcon_tileops.c --- linux-2.5.61-fbdev/drivers/video/console/fbcon_tileops.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.5.61/drivers/video/console/fbcon_tileops.c 2003-02-23 06:42:26.000000000 +0000 @@ -0,0 +1,118 @@ +/* + * linux/drivers/video/fbcon_tileops.c -- Console Ops using Tile Blitting + * (ie. Text Mode support) + * + * Copyright (C) 2003 James Simmons + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include "fbcon.h" + +static void tile_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + struct fb_info *info = p->fb_info; + struct fb_tilecopy tilerect; + + tilerect.sx = sx; + tilerect.sy = sy; + tilerect.dx = dx; + tilerect.dy = dy; + tilerect.height = height; + tilerect.width = width; + + info->tileops->fb_tilecopy(info, &tilerect); +} + +static void tile_clear(struct vc_data *vc, struct display *p, int sy, + int sx, int height, int width) +{ + struct fb_info *info = p->fb_info; + struct fb_tilefill tilerect; + + tilerect.dx = sx; + tilerect.dy = sy; + tilerect.width = width; + tilerect.height = height; + tilerect.fg_color = attr_fgcol_ec(p, vc); + tilerect.bg_color = attr_bgcol_ec(p, vc); + tilerect.idx = vc->vc_video_erase_char & p->charmask; + tilerect.rop = ROP_COPY; + + info->tileops->fb_tilefill(info, &tilerect); +} + +static void tile_putc(struct vc_data *vc, struct display *p, + int c, int ypos, int xpos) +{ + struct fb_info *info = p->fb_info; + struct fb_tileblit tilerect; + u32 font = c & p->charmask; + + tilerect.dx = xpos; + tilerect.dy = ypos; + tilerect.width = 1; + tilerect.height = 1; + tilerect.fg_color = attr_fgcol(p, c); + tilerect.bg_color = attr_bgcol(p, c); + tilerect.data = &font; + + info->tileops->fb_tileblit(info, &tilerect); +} + +#define TILEMAP_SIZE 1024 +static void tile_putcs(struct vc_data *vc, struct display *p, + const unsigned short *s, int count, + int yy, int xx) +{ + static u32 tilemap[TILEMAP_SIZE]; + struct fb_info *info = p->fb_info; + struct fb_tileblit tilerect; + int maxcnt = TILEMAP_SIZE, i, cnt; + u16 c = scr_readw(s); + + tilerect.dx = xx; + tilerect.dy = yy; + tilerect.height = 1; + tilerect.fg_color = attr_fgcol(p, c); + tilerect.bg_color = attr_bgcol(p, c); + tilerect.data = tilemap; + + while (count) { + cnt = (count > maxcnt) ? maxcnt : count; + tilerect.width = cnt; + for (i = 0; i < cnt; i++) + tilemap[i] = (u32) (scr_readw(s++) & p->charmask); + + info->tileops->fb_tileblit(info, &tilerect); + tilerect.dx += cnt; + count -= cnt; + } +} + +static void tile_clear_margins(struct vc_data *vc, struct display *p, + int bottom_only) +{ + /* Not used */ + return; +} + +struct display_switch tile_switch = { + .bmove = tile_bmove, + .clear = tile_clear, + .putc = tile_putc, + .putcs = tile_putcs, + .clear_margins = tile_clear_margins, +}; + +EXPORT_SYMBOL(tile_switch); +MODULE_AUTHOR("James Simmons , " + "Antonino Daplas "); +MODULE_DESCRIPTION("Console Tile Blitting Ops"); +MODULE_LICENSE("GPL"); diff -Naur linux-2.5.61-fbdev/drivers/video/fbmem.c linux-2.5.61/drivers/video/fbmem.c --- linux-2.5.61-fbdev/drivers/video/fbmem.c 2003-02-22 02:34:26.000000000 +0000 +++ linux-2.5.61/drivers/video/fbmem.c 2003-02-23 06:42:26.000000000 +0000 @@ -363,14 +363,14 @@ static int ofonly __initdata = 0; #endif +#ifdef CONFIG_LOGO +#include + static inline unsigned safe_shift(unsigned d, int n) { return n < 0 ? d >> -n : d << n; } -#ifdef CONFIG_FB_LOGO -#include - static void __init fb_set_logocmap(struct fb_info *info, const struct linux_logo *logo) { diff -Naur linux-2.5.61-fbdev/include/linux/fb.h linux-2.5.61/include/linux/fb.h --- linux-2.5.61-fbdev/include/linux/fb.h 2003-02-22 02:34:26.000000000 +0000 +++ linux-2.5.61/include/linux/fb.h 2003-02-23 06:42:26.000000000 +0000 @@ -380,6 +380,77 @@ int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); }; +/* + * Tile Blitting Support + * + * In Tile Blitting, the basic unit is a Tile which is a bitmap with + * a predefined width and height, and optionally, other properties + * such as color depth, spacing, transparency, etc. For now, we'll + * just support width, height, and color depth. + * + * All operations are analogous to classic blitting operations which + * use pixels as the basic unit. Instead of pixels, it will use tiles, + * instead of info->pseudo_palette, it will use tiledata, etc. + */ + +struct fb_tile { + __u32 width; /* tile width in pixels */ + __u32 height; /* tile height in scanlines */ + __u32 depth; /* pixel depth */ +}; + +struct fb_tiledata { + struct fb_tile tile; /* tile properties */ + __u32 len; /* number of tiles in the map */ + __u8 *data; /* packed tile data */ +}; + +struct fb_tileblit { + __u32 dx; /* destination x origin, in tiles */ + __u32 dy; /* destination y origin, in tiles */ + __u32 width; /* destination window width, in tiles */ + __u32 height; /* destination window height, in tiles */ + __u32 fg_color; /* fg_color if monochrome */ + __u32 bg_color; /* bg_color if monochrome */ + __u32 *data; /* tile map - array of indices to tiledata */ +}; + +struct fb_tilecopy { + __u32 dx; /* destination window origin... */ + __u32 dy; /* in tiles */ + __u32 width; /* destination width, in tiles */ + __u32 height; /* destination height, in tiles */ + __u32 sx; /* source window origin ... */ + __u32 sy; /* in tiles */ +}; + +struct fb_tilefill { + __u32 dx; /* destination window origin ... */ + __u32 dy; /* in tiles */ + __u32 width; /* destination width in tiles */ + __u32 height; /* destination height in tiles */ + __u32 fg_color; /* fg_color if monochrome */ + __u32 bg_color; /* bg_color if monochrome */ + __u32 rop; /* rop operation */ + __u32 idx; /* index to current tiledata */ +}; + +struct fb_tileops { + /* upload tile data to driver and make it current... the driver + * must copy the contents of tiledata.data, not just the pointer to it */ + int (*fb_loadtiles)(struct fb_info *info, + const struct fb_tiledata *tileinfo); + /* blit tiles to destination from a tilemap */ + void (*fb_tileblit)(struct fb_info *info, + const struct fb_tileblit *tilemap); + /* copy tiles from one region of fb memory to another */ + void (*fb_tilecopy)(struct fb_info *info, const struct fb_tilecopy *area); + /* fill a region of fb memory with a tile */ + void (*fb_tilefill)(struct fb_info *info, + const struct fb_tilefill *region); + /* If driver is to support tile blitting, all hooks above are required */ +}; + struct fb_info { kdev_t node; int flags; @@ -391,6 +462,7 @@ struct fb_cursor cursor; /* Current cursor */ struct fb_cmap cmap; /* Current cmap */ struct fb_ops *fbops; + struct fb_tileops *tileops; /* Tile blitting */ char *screen_base; /* Virtual address */ struct vc_data *display_fg; /* Console visible on this display */ int currcon; /* Current VC. */