linux-old/drivers/video/fbcon-ilbm.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/video/ilbm.c -- Low level frame buffer operations for
   3 *                                interleaved bitplanes à la Amiga
   4 *
   5 *      Created 5 Apr 1997 by Geert Uytterhoeven
   6 *
   7 *  This file is subject to the terms and conditions of the GNU General Public
   8 *  License.  See the file COPYING in the main directory of this archive for
   9 *  more details.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/tty.h>
  14#include <linux/console.h>
  15#include <linux/string.h>
  16#include <linux/fb.h>
  17
  18#include <video/fbcon.h>
  19#include <video/fbcon-ilbm.h>
  20
  21
  22    /*
  23     *  Interleaved bitplanes à la Amiga
  24     *
  25     *  This code heavily relies on the fact that
  26     *
  27     *      next_line == interleave == next_plane*bits_per_pixel
  28     *
  29     *  But maybe it can be merged with the code for normal bitplanes without
  30     *  much performance loss?
  31     */
  32
  33void fbcon_ilbm_setup(struct display *p)
  34{
  35    if (p->line_length) {
  36        p->next_line = p->line_length*p->var.bits_per_pixel;
  37        p->next_plane = p->line_length;
  38    } else {
  39        p->next_line = p->type_aux;
  40        p->next_plane = p->type_aux/p->var.bits_per_pixel;
  41    }
  42}
  43
  44void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx,
  45                      int height, int width)
  46{
  47    if (sx == 0 && dx == 0 && width == p->next_plane)
  48        fb_memmove(p->screen_base+dy*fontheight(p)*p->next_line,
  49                  p->screen_base+sy*fontheight(p)*p->next_line,
  50                  height*fontheight(p)*p->next_line);
  51    else {
  52        u8 *src, *dest;
  53        u_int i;
  54
  55        if (dy <= sy) {
  56            src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
  57            dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
  58            for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) {
  59                fb_memmove(dest, src, width);
  60                src += p->next_plane;
  61                dest += p->next_plane;
  62            }
  63        } else {
  64            src = p->screen_base+(sy+height)*fontheight(p)*p->next_line+sx;
  65            dest = p->screen_base+(dy+height)*fontheight(p)*p->next_line+dx;
  66            for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) {
  67                src -= p->next_plane;
  68                dest -= p->next_plane;
  69                fb_memmove(dest, src, width);
  70            }
  71        }
  72    }
  73}
  74
  75void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy, int sx,
  76                      int height, int width)
  77{
  78    u8 *dest;
  79    u_int i, rows;
  80    int bg, bg0;
  81
  82    dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
  83
  84    bg0 = attr_bgcol_ec(p,conp);
  85    for (rows = height*fontheight(p); rows--;) {
  86        bg = bg0;
  87        for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
  88            if (bg & 1)
  89                fb_memset255(dest, width);
  90            else
  91                fb_memclear(dest, width);
  92            bg >>= 1;
  93        }
  94    }
  95}
  96
  97void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, int yy,
  98                     int xx)
  99{
 100    u8 *dest, *cdat;
 101    u_int rows, i;
 102    u8 d;
 103    int fg0, bg0, fg, bg;
 104
 105    dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
 106    cdat = p->fontdata+(c&p->charmask)*fontheight(p);
 107    fg0 = attr_fgcol(p,c);
 108    bg0 = attr_bgcol(p,c);
 109
 110    for (rows = fontheight(p); rows--;) {
 111        d = *cdat++;
 112        fg = fg0;
 113        bg = bg0;
 114        for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
 115            if (bg & 1){
 116                if (fg & 1)
 117                    *dest = 0xff;
 118                else
 119                    *dest = ~d;
 120            }else{
 121                if (fg & 1)
 122                    *dest = d;
 123                else
 124                    *dest = 0x00;
 125            }
 126            bg >>= 1;
 127            fg >>= 1;
 128        }
 129    }
 130}
 131
 132    /*
 133     *  I've split the console character loop in two parts:
 134     *
 135     *      - slow version: this blits one character at a time
 136     *
 137     *      - fast version: this blits 4 characters at a time at a longword
 138     *                      aligned address, to reduce the number of expensive
 139     *                      Chip RAM accesses.
 140     *
 141     *  Experiments on my A4000/040 revealed that this makes a console switch
 142     *  on a 640x400 screen with 256 colors about 3 times faster.
 143     *
 144     *  -- Geert
 145     */
 146
 147void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, 
 148                      const unsigned short *s, int count, int yy, int xx)
 149{
 150    u8 *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4;
 151    u_int rows, i;
 152    u16 c1, c2, c3, c4;
 153    u32 d;
 154    int fg0, bg0, fg, bg;
 155
 156    dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
 157    c1 = scr_readw(s);
 158    fg0 = attr_fgcol(p, c1);
 159    bg0 = attr_bgcol(p, c1);
 160
 161    while (count--)
 162        if (xx&3 || count < 3) {        /* Slow version */
 163            c1 = scr_readw(s++) & p->charmask;
 164            dest = dest0++;
 165            xx++;
 166
 167            cdat1 = p->fontdata+c1*fontheight(p);
 168            for (rows = fontheight(p); rows--;) {
 169                d = *cdat1++;
 170                fg = fg0;
 171                bg = bg0;
 172                for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
 173                    if (bg & 1){
 174                        if (fg & 1)
 175                            *dest = 0xff;
 176                        else
 177                            *dest = ~d;
 178                    }else{
 179                        if (fg & 1)
 180                            *dest = d;
 181                        else
 182                            *dest = 0x00;
 183                    }
 184                    bg >>= 1;
 185                    fg >>= 1;
 186                }
 187            }
 188        } else {                /* Fast version */
 189            c1 = scr_readw(&s[0]) & p->charmask;
 190            c2 = scr_readw(&s[1]) & p->charmask;
 191            c3 = scr_readw(&s[2]) & p->charmask;
 192            c4 = scr_readw(&s[3]) & p->charmask;
 193
 194            dest = dest0;
 195            cdat1 = p->fontdata+c1*fontheight(p);
 196            cdat2 = p->fontdata+c2*fontheight(p);
 197            cdat3 = p->fontdata+c3*fontheight(p);
 198            cdat4 = p->fontdata+c4*fontheight(p);
 199            for (rows = fontheight(p); rows--;) {
 200#if defined(__BIG_ENDIAN)
 201                d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
 202#elif defined(__LITTLE_ENDIAN)
 203                d = *cdat1++ | *cdat2++<<8 | *cdat3++<<16 | *cdat4++<<24;
 204#else
 205#error FIXME: No endianness??
 206#endif
 207                fg = fg0;
 208                bg = bg0;
 209                for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
 210                    if (bg & 1){
 211                        if (fg & 1)
 212                            *(u32 *)dest = 0xffffffff;
 213                        else
 214                            *(u32 *)dest = ~d;
 215                    }else{
 216                        if (fg & 1)
 217                            *(u32 *)dest = d;
 218                        else
 219                            *(u32 *)dest = 0x00000000;
 220                    }
 221                    bg >>= 1;
 222                    fg >>= 1;
 223                }
 224            }
 225            s += 4;
 226            dest0 += 4;
 227            xx += 4;
 228            count -= 3;
 229        }
 230}
 231
 232void fbcon_ilbm_revc(struct display *p, int xx, int yy)
 233{
 234    u8 *dest, *dest0;
 235    u_int rows, i;
 236    int mask;
 237
 238    dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
 239    mask = p->fgcol ^ p->bgcol;
 240
 241    /*
 242     *  This should really obey the individual character's
 243     *  background and foreground colors instead of simply
 244     *  inverting.
 245     */
 246
 247    for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
 248        if (mask & 1) {
 249            dest = dest0;
 250            for (rows = fontheight(p); rows--; dest += p->next_line)
 251                *dest = ~*dest;
 252        }
 253        mask >>= 1;
 254    }
 255}
 256
 257
 258    /*
 259     *  `switch' for the low level operations
 260     */
 261
 262struct display_switch fbcon_ilbm = {
 263    setup:              fbcon_ilbm_setup,
 264    bmove:              fbcon_ilbm_bmove,
 265    clear:              fbcon_ilbm_clear,
 266    putc:               fbcon_ilbm_putc,
 267    putcs:              fbcon_ilbm_putcs,
 268    revc:               fbcon_ilbm_revc,
 269    fontwidthmask:      FONTWIDTH(8)
 270};
 271
 272
 273#ifdef MODULE
 274MODULE_LICENSE("GPL");
 275
 276int init_module(void)
 277{
 278    return 0;
 279}
 280
 281void cleanup_module(void)
 282{}
 283#endif /* MODULE */
 284
 285
 286    /*
 287     *  Visible symbols for modules
 288     */
 289
 290EXPORT_SYMBOL(fbcon_ilbm);
 291EXPORT_SYMBOL(fbcon_ilbm_setup);
 292EXPORT_SYMBOL(fbcon_ilbm_bmove);
 293EXPORT_SYMBOL(fbcon_ilbm_clear);
 294EXPORT_SYMBOL(fbcon_ilbm_putc);
 295EXPORT_SYMBOL(fbcon_ilbm_putcs);
 296EXPORT_SYMBOL(fbcon_ilbm_revc);
 297
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.