URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [video/] [fbcon-ilbm.c] - Rev 1765
Compare with Previous | Blame | View Log
/* * linux/drivers/video/ilbm.c -- Low level frame buffer operations for * interleaved bitplanes à la Amiga * * Created 5 Apr 1997 by Geert Uytterhoeven * * 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 <linux/module.h> #include <linux/tty.h> #include <linux/console.h> #include <linux/string.h> #include <linux/fb.h> #include <video/fbcon.h> #include <video/fbcon-ilbm.h> /* * Interleaved bitplanes à la Amiga * * This code heavily relies on the fact that * * next_line == interleave == next_plane*bits_per_pixel * * But maybe it can be merged with the code for normal bitplanes without * much performance loss? */ void fbcon_ilbm_setup(struct display *p) { if (p->line_length) { p->next_line = p->line_length*p->var.bits_per_pixel; p->next_plane = p->line_length; } else { p->next_line = p->type_aux; p->next_plane = p->type_aux/p->var.bits_per_pixel; } } void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx, int height, int width) { if (sx == 0 && dx == 0 && width == p->next_plane) fb_memmove(p->screen_base+dy*fontheight(p)*p->next_line, p->screen_base+sy*fontheight(p)*p->next_line, height*fontheight(p)*p->next_line); else { u8 *src, *dest; u_int i; if (dy <= sy) { src = p->screen_base+sy*fontheight(p)*p->next_line+sx; dest = p->screen_base+dy*fontheight(p)*p->next_line+dx; for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) { fb_memmove(dest, src, width); src += p->next_plane; dest += p->next_plane; } } else { src = p->screen_base+(sy+height)*fontheight(p)*p->next_line+sx; dest = p->screen_base+(dy+height)*fontheight(p)*p->next_line+dx; for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) { src -= p->next_plane; dest -= p->next_plane; fb_memmove(dest, src, width); } } } } void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy, int sx, int height, int width) { u8 *dest; u_int i, rows; int bg, bg0; dest = p->screen_base+sy*fontheight(p)*p->next_line+sx; bg0 = attr_bgcol_ec(p,conp); for (rows = height*fontheight(p); rows--;) { bg = bg0; for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { if (bg & 1) fb_memset255(dest, width); else fb_memclear(dest, width); bg >>= 1; } } } void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { u8 *dest, *cdat; u_int rows, i; u8 d; int fg0, bg0, fg, bg; dest = p->screen_base+yy*fontheight(p)*p->next_line+xx; cdat = p->fontdata+(c&p->charmask)*fontheight(p); fg0 = attr_fgcol(p,c); bg0 = attr_bgcol(p,c); for (rows = fontheight(p); rows--;) { d = *cdat++; fg = fg0; bg = bg0; for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { if (bg & 1){ if (fg & 1) *dest = 0xff; else *dest = ~d; }else{ if (fg & 1) *dest = d; else *dest = 0x00; } bg >>= 1; fg >>= 1; } } } /* * I've split the console character loop in two parts: * * - slow version: this blits one character at a time * * - fast version: this blits 4 characters at a time at a longword * aligned address, to reduce the number of expensive * Chip RAM accesses. * * Experiments on my A4000/040 revealed that this makes a console switch * on a 640x400 screen with 256 colors about 3 times faster. * * -- Geert */ void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, int count, int yy, int xx) { u8 *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4; u_int rows, i; u16 c1, c2, c3, c4; u32 d; int fg0, bg0, fg, bg; dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx; c1 = scr_readw(s); fg0 = attr_fgcol(p, c1); bg0 = attr_bgcol(p, c1); while (count--) if (xx&3 || count < 3) { /* Slow version */ c1 = scr_readw(s++) & p->charmask; dest = dest0++; xx++; cdat1 = p->fontdata+c1*fontheight(p); for (rows = fontheight(p); rows--;) { d = *cdat1++; fg = fg0; bg = bg0; for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { if (bg & 1){ if (fg & 1) *dest = 0xff; else *dest = ~d; }else{ if (fg & 1) *dest = d; else *dest = 0x00; } bg >>= 1; fg >>= 1; } } } else { /* Fast version */ c1 = scr_readw(&s[0]) & p->charmask; c2 = scr_readw(&s[1]) & p->charmask; c3 = scr_readw(&s[2]) & p->charmask; c4 = scr_readw(&s[3]) & p->charmask; dest = dest0; cdat1 = p->fontdata+c1*fontheight(p); cdat2 = p->fontdata+c2*fontheight(p); cdat3 = p->fontdata+c3*fontheight(p); cdat4 = p->fontdata+c4*fontheight(p); for (rows = fontheight(p); rows--;) { #if defined(__BIG_ENDIAN) d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++; #elif defined(__LITTLE_ENDIAN) d = *cdat1++ | *cdat2++<<8 | *cdat3++<<16 | *cdat4++<<24; #else #error FIXME: No endianness?? #endif fg = fg0; bg = bg0; for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { if (bg & 1){ if (fg & 1) *(u32 *)dest = 0xffffffff; else *(u32 *)dest = ~d; }else{ if (fg & 1) *(u32 *)dest = d; else *(u32 *)dest = 0x00000000; } bg >>= 1; fg >>= 1; } } s += 4; dest0 += 4; xx += 4; count -= 3; } } void fbcon_ilbm_revc(struct display *p, int xx, int yy) { u8 *dest, *dest0; u_int rows, i; int mask; dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx; mask = p->fgcol ^ p->bgcol; /* * This should really obey the individual character's * background and foreground colors instead of simply * inverting. */ for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) { if (mask & 1) { dest = dest0; for (rows = fontheight(p); rows--; dest += p->next_line) *dest = ~*dest; } mask >>= 1; } } /* * `switch' for the low level operations */ struct display_switch fbcon_ilbm = { setup: fbcon_ilbm_setup, bmove: fbcon_ilbm_bmove, clear: fbcon_ilbm_clear, putc: fbcon_ilbm_putc, putcs: fbcon_ilbm_putcs, revc: fbcon_ilbm_revc, fontwidthmask: FONTWIDTH(8) }; #ifdef MODULE MODULE_LICENSE("GPL"); int init_module(void) { return 0; } void cleanup_module(void) {} #endif /* MODULE */ /* * Visible symbols for modules */ EXPORT_SYMBOL(fbcon_ilbm); EXPORT_SYMBOL(fbcon_ilbm_setup); EXPORT_SYMBOL(fbcon_ilbm_bmove); EXPORT_SYMBOL(fbcon_ilbm_clear); EXPORT_SYMBOL(fbcon_ilbm_putc); EXPORT_SYMBOL(fbcon_ilbm_putcs); EXPORT_SYMBOL(fbcon_ilbm_revc);