root/drivers/video/fbdev/core/sysimgblt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. color_imageblit
  2. slow_imageblit
  3. fast_imageblit
  4. sys_imageblit

   1 /*
   2  *  Generic 1-bit or 8-bit source to 1-32 bit destination expansion
   3  *  for frame buffer located in system RAM with packed pixels of any depth.
   4  *
   5  *  Based almost entirely on cfbimgblt.c
   6  *
   7  *      Copyright (C)  April 2007 Antonino Daplas <adaplas@pol.net>
   8  *
   9  *  This file is subject to the terms and conditions of the GNU General Public
  10  *  License.  See the file COPYING in the main directory of this archive for
  11  *  more details.
  12  */
  13 #include <linux/module.h>
  14 #include <linux/string.h>
  15 #include <linux/fb.h>
  16 #include <asm/types.h>
  17 
  18 #define DEBUG
  19 
  20 #ifdef DEBUG
  21 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args)
  22 #else
  23 #define DPRINTK(fmt, args...)
  24 #endif
  25 
  26 static const u32 cfb_tab8_be[] = {
  27     0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
  28     0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
  29     0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
  30     0xffff0000,0xffff00ff,0xffffff00,0xffffffff
  31 };
  32 
  33 static const u32 cfb_tab8_le[] = {
  34     0x00000000,0xff000000,0x00ff0000,0xffff0000,
  35     0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
  36     0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
  37     0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
  38 };
  39 
  40 static const u32 cfb_tab16_be[] = {
  41     0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
  42 };
  43 
  44 static const u32 cfb_tab16_le[] = {
  45     0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
  46 };
  47 
  48 static const u32 cfb_tab32[] = {
  49         0x00000000, 0xffffffff
  50 };
  51 
  52 static void color_imageblit(const struct fb_image *image, struct fb_info *p,
  53                             void *dst1, u32 start_index, u32 pitch_index)
  54 {
  55         /* Draw the penguin */
  56         u32 *dst, *dst2;
  57         u32 color = 0, val, shift;
  58         int i, n, bpp = p->var.bits_per_pixel;
  59         u32 null_bits = 32 - bpp;
  60         u32 *palette = (u32 *) p->pseudo_palette;
  61         const u8 *src = image->data;
  62 
  63         dst2 = dst1;
  64         for (i = image->height; i--; ) {
  65                 n = image->width;
  66                 dst = dst1;
  67                 shift = 0;
  68                 val = 0;
  69 
  70                 if (start_index) {
  71                         u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
  72                                                          start_index));
  73                         val = *dst & start_mask;
  74                         shift = start_index;
  75                 }
  76                 while (n--) {
  77                         if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
  78                             p->fix.visual == FB_VISUAL_DIRECTCOLOR )
  79                                 color = palette[*src];
  80                         else
  81                                 color = *src;
  82                         color <<= FB_LEFT_POS(p, bpp);
  83                         val |= FB_SHIFT_HIGH(p, color, shift);
  84                         if (shift >= null_bits) {
  85                                 *dst++ = val;
  86 
  87                                 val = (shift == null_bits) ? 0 :
  88                                         FB_SHIFT_LOW(p, color, 32 - shift);
  89                         }
  90                         shift += bpp;
  91                         shift &= (32 - 1);
  92                         src++;
  93                 }
  94                 if (shift) {
  95                         u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
  96 
  97                         *dst &= end_mask;
  98                         *dst |= val;
  99                 }
 100                 dst1 += p->fix.line_length;
 101                 if (pitch_index) {
 102                         dst2 += p->fix.line_length;
 103                         dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
 104 
 105                         start_index += pitch_index;
 106                         start_index &= 32 - 1;
 107                 }
 108         }
 109 }
 110 
 111 static void slow_imageblit(const struct fb_image *image, struct fb_info *p,
 112                                   void *dst1, u32 fgcolor, u32 bgcolor,
 113                                   u32 start_index, u32 pitch_index)
 114 {
 115         u32 shift, color = 0, bpp = p->var.bits_per_pixel;
 116         u32 *dst, *dst2;
 117         u32 val, pitch = p->fix.line_length;
 118         u32 null_bits = 32 - bpp;
 119         u32 spitch = (image->width+7)/8;
 120         const u8 *src = image->data, *s;
 121         u32 i, j, l;
 122 
 123         dst2 = dst1;
 124         fgcolor <<= FB_LEFT_POS(p, bpp);
 125         bgcolor <<= FB_LEFT_POS(p, bpp);
 126 
 127         for (i = image->height; i--; ) {
 128                 shift = val = 0;
 129                 l = 8;
 130                 j = image->width;
 131                 dst = dst1;
 132                 s = src;
 133 
 134                 /* write leading bits */
 135                 if (start_index) {
 136                         u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
 137                                                          start_index));
 138                         val = *dst & start_mask;
 139                         shift = start_index;
 140                 }
 141 
 142                 while (j--) {
 143                         l--;
 144                         color = (*s & (1 << l)) ? fgcolor : bgcolor;
 145                         val |= FB_SHIFT_HIGH(p, color, shift);
 146 
 147                         /* Did the bitshift spill bits to the next long? */
 148                         if (shift >= null_bits) {
 149                                 *dst++ = val;
 150                                 val = (shift == null_bits) ? 0 :
 151                                         FB_SHIFT_LOW(p, color, 32 - shift);
 152                         }
 153                         shift += bpp;
 154                         shift &= (32 - 1);
 155                         if (!l) { l = 8; s++; }
 156                 }
 157 
 158                 /* write trailing bits */
 159                 if (shift) {
 160                         u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
 161 
 162                         *dst &= end_mask;
 163                         *dst |= val;
 164                 }
 165 
 166                 dst1 += pitch;
 167                 src += spitch;
 168                 if (pitch_index) {
 169                         dst2 += pitch;
 170                         dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
 171                         start_index += pitch_index;
 172                         start_index &= 32 - 1;
 173                 }
 174 
 175         }
 176 }
 177 
 178 /*
 179  * fast_imageblit - optimized monochrome color expansion
 180  *
 181  * Only if:  bits_per_pixel == 8, 16, or 32
 182  *           image->width is divisible by pixel/dword (ppw);
 183  *           fix->line_legth is divisible by 4;
 184  *           beginning and end of a scanline is dword aligned
 185  */
 186 static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
 187                                   void *dst1, u32 fgcolor, u32 bgcolor)
 188 {
 189         u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
 190         u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
 191         u32 bit_mask, end_mask, eorx, shift;
 192         const char *s = image->data, *src;
 193         u32 *dst;
 194         const u32 *tab = NULL;
 195         int i, j, k;
 196 
 197         switch (bpp) {
 198         case 8:
 199                 tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
 200                 break;
 201         case 16:
 202                 tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
 203                 break;
 204         case 32:
 205         default:
 206                 tab = cfb_tab32;
 207                 break;
 208         }
 209 
 210         for (i = ppw-1; i--; ) {
 211                 fgx <<= bpp;
 212                 bgx <<= bpp;
 213                 fgx |= fgcolor;
 214                 bgx |= bgcolor;
 215         }
 216 
 217         bit_mask = (1 << ppw) - 1;
 218         eorx = fgx ^ bgx;
 219         k = image->width/ppw;
 220 
 221         for (i = image->height; i--; ) {
 222                 dst = dst1;
 223                 shift = 8;
 224                 src = s;
 225 
 226                 for (j = k; j--; ) {
 227                         shift -= ppw;
 228                         end_mask = tab[(*src >> shift) & bit_mask];
 229                         *dst++ = (end_mask & eorx) ^ bgx;
 230                         if (!shift) {
 231                                 shift = 8;
 232                                 src++;
 233                         }
 234                 }
 235                 dst1 += p->fix.line_length;
 236                 s += spitch;
 237         }
 238 }
 239 
 240 void sys_imageblit(struct fb_info *p, const struct fb_image *image)
 241 {
 242         u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
 243         u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
 244         u32 width = image->width;
 245         u32 dx = image->dx, dy = image->dy;
 246         void *dst1;
 247 
 248         if (p->state != FBINFO_STATE_RUNNING)
 249                 return;
 250 
 251         bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
 252         start_index = bitstart & (32 - 1);
 253         pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
 254 
 255         bitstart /= 8;
 256         bitstart &= ~(bpl - 1);
 257         dst1 = (void __force *)p->screen_base + bitstart;
 258 
 259         if (p->fbops->fb_sync)
 260                 p->fbops->fb_sync(p);
 261 
 262         if (image->depth == 1) {
 263                 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
 264                     p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
 265                         fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
 266                         bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
 267                 } else {
 268                         fgcolor = image->fg_color;
 269                         bgcolor = image->bg_color;
 270                 }
 271 
 272                 if (32 % bpp == 0 && !start_index && !pitch_index &&
 273                     ((width & (32/bpp-1)) == 0) &&
 274                     bpp >= 8 && bpp <= 32)
 275                         fast_imageblit(image, p, dst1, fgcolor, bgcolor);
 276                 else
 277                         slow_imageblit(image, p, dst1, fgcolor, bgcolor,
 278                                         start_index, pitch_index);
 279         } else
 280                 color_imageblit(image, p, dst1, start_index, pitch_index);
 281 }
 282 
 283 EXPORT_SYMBOL(sys_imageblit);
 284 
 285 MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
 286 MODULE_DESCRIPTION("1-bit/8-bit to 1-32 bit color expansion (sys-to-sys)");
 287 MODULE_LICENSE("GPL");
 288 

/* [<][>][^][v][top][bottom][index][help] */