CTC++ Coverage Report - Execution Profile    #814/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/video/cfbcopyarea.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 0/ 89)

Start/ End/    
True False - Line Source

  1 /*
  2  *  Generic function for frame buffer with packed pixels of any depth.
  3  *
  4  *      Copyright (C)  1999-2005 James Simmons <jsimmons@www.infradead.org>
  5  *
  6  *  This file is subject to the terms and conditions of the GNU General Public
  7  *  License.  See the file COPYING in the main directory of this archive for
  8  *  more details.
  9  *
  10  * NOTES:
  11  *
  12  *  This is for cfb packed pixels. Iplan and such are incorporated in the
  13  *  drivers that need them.
  14  *
  15  *  FIXME
  16  *
  17  *  Also need to add code to deal with cards endians that are different than
  18  *  the native cpu endians. I also need to deal with MSB position in the word.
  19  *
  20  *  The two functions or copying forward and backward could be split up like
  21  *  the ones for filling, i.e. in aligned and unaligned versions. This would
  22  *  help moving some redundant computations and branches out of the loop, too.
  23  */
  24 
  25 
  26 
  27 #include <linux/config.h>
  28 #include <linux/module.h>
  29 #include <linux/kernel.h>
  30 #include <linux/string.h>
  31 #include <linux/fb.h>
  32 #include <linux/slab.h>
  33 #include <asm/types.h>
  34 #include <asm/io.h>
  35 
  36 #if BITS_PER_LONG == 32
  37 #  define FB_WRITEL fb_writel
  38 #  define FB_READL  fb_readl
  39 #else
  40 #  define FB_WRITEL fb_writeq
  41 #  define FB_READL  fb_readq
  42 #endif
  43 
  44     /*
  45      *  Compose two values, using a bitmask as decision value
  46      *  This is equivalent to (a & mask) | (b & ~mask)
  47      */
  48 
  49 static inline unsigned long
 
- 50 comp(unsigned long a, unsigned long b, unsigned long mask)
  51 {
 - 52     return ((a ^ b) & mask) ^ b;
  53 }
  54 
  55     /*
  56      *  Generic bitwise copy algorithm
  57      */
  58 
  59 static void
 
- 60 bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
  61    int src_idx, int bits, unsigned n)
  62 {
  63    unsigned long first, last;
  64    int const shift = dst_idx-src_idx;
  65    int left, right;
  66 
  67    first = FB_SHIFT_HIGH(~0UL, dst_idx);
  68    last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
  69 
- 70    if (!shift) {
  71       // Same alignment for source and dest
  72 
- 73       if (dst_idx+n <= bits) {
  74          // Single word
- 75          if (last)
  76             first &= last;
  77          FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
    78       } else {
  79          // Multiple destination words
  80 
  81          // Leading bits
- 82          if (first != ~0UL) {
  83             FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
  84             dst++;
  85             src++;
  86             n -= bits - dst_idx;
  87          }
  88 
  89          // Main chunk
  90          n /= bits;
- 91          while (n >= 8) {
  92             FB_WRITEL(FB_READL(src++), dst++);
  93             FB_WRITEL(FB_READL(src++), dst++);
  94             FB_WRITEL(FB_READL(src++), dst++);
  95             FB_WRITEL(FB_READL(src++), dst++);
  96             FB_WRITEL(FB_READL(src++), dst++);
  97             FB_WRITEL(FB_READL(src++), dst++);
  98             FB_WRITEL(FB_READL(src++), dst++);
  99             FB_WRITEL(FB_READL(src++), dst++);
  100             n -= 8;
  101          }
- 102          while (n--)
  103             FB_WRITEL(FB_READL(src++), dst++);
  104 
  105          // Trailing bits
- 106          if (last)
  107             FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
  108       }
    109    } else {
  110       unsigned long d0, d1;
  111       int m;
  112       // Different alignment for source and dest
  113 
  114       right = shift & (bits - 1);
  115       left = -shift & (bits - 1);
  116 
- 117       if (dst_idx+n <= bits) {
  118          // Single destination word
- 119          if (last)
  120             first &= last;
- 121          if (shift > 0) {
  122             // Single source word
  123             FB_WRITEL( comp( FB_READL(src) >> right, FB_READL(dst), first), dst);
- 124          } else if (src_idx+n <= bits) {
  125             // Single source word
  126             FB_WRITEL( comp(FB_READL(src) << left, FB_READL(dst), first), dst);
    127          } else {
  128             // 2 source words
  129             d0 = FB_READL(src++);
  130             d1 = FB_READL(src);
  131             FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
  132          }
    133       } else {
  134          // Multiple destination words
  135          /** We must always remember the last value read, because in case
  136          SRC and DST overlap bitwise (e.g. when moving just one pixel in
  137          1bpp), we always collect one full long for DST and that might
  138          overlap with the current long from SRC. We store this value in
  139          'd0'. */
  140          d0 = FB_READL(src++);
  141          // Leading bits
- 142          if (shift > 0) {
  143             // Single source word
  144             FB_WRITEL( comp(d0 >> right, FB_READL(dst), first), dst);
  145             dst++;
  146             n -= bits - dst_idx;
    147          } else {
  148             // 2 source words
  149             d1 = FB_READL(src++);
  150             FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
  151             d0 = d1;
  152             dst++;
  153             n -= bits - dst_idx;
  154          }
  155 
  156          // Main chunk
  157          m = n % bits;
  158          n /= bits;
- 159          while (n >= 4) {
  160             d1 = FB_READL(src++);
  161             FB_WRITEL(d0 << left | d1 >> right, dst++);
  162             d0 = d1;
  163             d1 = FB_READL(src++);
  164             FB_WRITEL(d0 << left | d1 >> right, dst++);
  165             d0 = d1;
  166             d1 = FB_READL(src++);
  167             FB_WRITEL(d0 << left | d1 >> right, dst++);
  168             d0 = d1;
  169             d1 = FB_READL(src++);
  170             FB_WRITEL(d0 << left | d1 >> right, dst++);
  171             d0 = d1;
  172             n -= 4;
  173          }
- 174          while (n--) {
  175             d1 = FB_READL(src++);
  176             FB_WRITEL(d0 << left | d1 >> right, dst++);
  177             d0 = d1;
  178          }
  179 
  180          // Trailing bits
- 181          if (last) {
- 182             if (m <= right) {
  183                // Single source word
  184                FB_WRITEL( comp(d0 << left, FB_READL(dst), last), dst);
    185             } else {
  186                // 2 source words
  187                d1 = FB_READL(src);
  188                FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), last), dst);
  189             }
  190          }
  191       }
  192    }
  193 }
  194 
  195     /*
  196      *  Generic bitwise copy algorithm, operating backward
  197      */
  198 
  199 static void
 
- 200 bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
  201       int src_idx, int bits, unsigned n)
  202 {
  203    unsigned long first, last;
  204    int shift;
  205 
  206    dst += (n-1)/bits;
  207    src += (n-1)/bits;
- 208    if ((n-1) % bits) {
  209       dst_idx += (n-1) % bits;
  210       dst += dst_idx >> (ffs(bits) - 1);
  211       dst_idx &= bits - 1;
  212       src_idx += (n-1) % bits;
  213       src += src_idx >> (ffs(bits) - 1);
  214       src_idx &= bits - 1;
  215    }
  216 
  217    shift = dst_idx-src_idx;
  218 
  219    first = FB_SHIFT_LOW(~0UL, bits - 1 - dst_idx);
  220    last = ~(FB_SHIFT_LOW(~0UL, bits - 1 - ((dst_idx-n) % bits)));
  221 
- 222    if (!shift) {
  223       // Same alignment for source and dest
  224 
- 225       if ((unsigned long)dst_idx+1 >= n) {
  226          // Single word
- 227          if (last)
  228             first &= last;
  229          FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
    230       } else {
  231          // Multiple destination words
  232 
  233          // Leading bits
- 234          if (first != ~0UL) {
  235             FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
  236             dst--;
  237             src--;
  238             n -= dst_idx+1;
  239          }
  240 
  241          // Main chunk
  242          n /= bits;
- 243          while (n >= 8) {
  244             FB_WRITEL(FB_READL(src--), dst--);
  245             FB_WRITEL(FB_READL(src--), dst--);
  246             FB_WRITEL(FB_READL(src--), dst--);
  247             FB_WRITEL(FB_READL(src--), dst--);
  248             FB_WRITEL(FB_READL(src--), dst--);
  249             FB_WRITEL(FB_READL(src--), dst--);
  250             FB_WRITEL(FB_READL(src--), dst--);
  251             FB_WRITEL(FB_READL(src--), dst--);
  252             n -= 8;
  253          }
- 254          while (n--)
  255             FB_WRITEL(FB_READL(src--), dst--);
  256 
  257          // Trailing bits
- 258          if (last)
  259             FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
  260       }
    261    } else {
  262       // Different alignment for source and dest
  263 
  264       int const left = -shift & (bits-1);
  265       int const right = shift & (bits-1);
  266 
- 267       if ((unsigned long)dst_idx+1 >= n) {
  268          // Single destination word
- 269          if (last)
  270             first &= last;
- 271          if (shift < 0) {
  272             // Single source word
  273             FB_WRITEL( comp( FB_READL(src)<<left, FB_READL(dst), first), dst);
- 274          } else if (1+(unsigned long)src_idx >= n) {
  275             // Single source word
  276             FB_WRITEL( comp( FB_READL(src)>>right, FB_READL(dst), first), dst);
    277          } else {
  278             // 2 source words
  279             FB_WRITEL( comp( (FB_READL(src)>>right | FB_READL(src-1)<<left), FB_READL(dst), first), dst);
  280          }
    281       } else {
  282          // Multiple destination words
  283          /** We must always remember the last value read, because in case
  284          SRC and DST overlap bitwise (e.g. when moving just one pixel in
  285          1bpp), we always collect one full long for DST and that might
  286          overlap with the current long from SRC. We store this value in
  287          'd0'. */
  288          unsigned long d0, d1;
  289          int m;
  290 
  291          d0 = FB_READL(src--);
  292          // Leading bits
- 293          if (shift < 0) {
  294             // Single source word
  295             FB_WRITEL( comp( (d0 << left), FB_READL(dst), first), dst);
    296          } else {
  297             // 2 source words
  298             d1 = FB_READL(src--);
  299             FB_WRITEL( comp( (d0>>right | d1<<left), FB_READL(dst), first), dst);
  300             d0 = d1;
  301          }
  302          dst--;
  303          n -= dst_idx+1;
  304 
  305          // Main chunk
  306          m = n % bits;
  307          n /= bits;
- 308          while (n >= 4) {
  309             d1 = FB_READL(src--);
  310             FB_WRITEL(d0 >> right | d1 << left, dst--);
  311             d0 = d1;
  312             d1 = FB_READL(src--);
  313             FB_WRITEL(d0 >> right | d1 << left, dst--);
  314             d0 = d1;
  315             d1 = FB_READL(src--);
  316             FB_WRITEL(d0 >> right | d1 << left, dst--);
  317             d0 = d1;
  318             d1 = FB_READL(src--);
  319             FB_WRITEL(d0 >> right | d1 << left, dst--);
  320             d0 = d1;
  321             n -= 4;
  322          }
- 323          while (n--) {
  324             d1 = FB_READL(src--);
  325             FB_WRITEL(d0 >> right | d1 << left, dst--);
  326             d0 = d1;
  327          }
  328 
  329          // Trailing bits
- 330          if (last) {
- 331             if (m <= left) {
  332                // Single source word
  333                FB_WRITEL( comp(d0 >> right, FB_READL(dst), last), dst);
    334             } else {
  335                // 2 source words
  336                d1 = FB_READL(src);
  337                FB_WRITEL( comp(d0>>right | d1<<left, FB_READL(dst), last), dst);
  338             }
  339          }
  340       }
  341    }
  342 }
  343 
 
- 344 void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
  345 {
  346    u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
  347    u32 height = area->height, width = area->width;
  348    unsigned long const bits_per_line = p->fix.line_length*8u;
  349    unsigned long __iomem *dst = NULL, *src = NULL;
  350    int bits = BITS_PER_LONG, bytes = bits >> 3;
  351    int dst_idx = 0, src_idx = 0, rev_copy = 0;
  352 
- 353    if (p->state != FBINFO_STATE_RUNNING)
 - 354       return;
  355 
  356    /* if the beginning of the target area might overlap with the end of
  357    the source area, be have to copy the area reverse. */
- 358    if ((dy == sy && dx > sx) || (dy > sy)) {
 - 358   (T && T) || (_)
 - 358   (T && F) || (T)
 - 358   (F && _) || (T)
 - 358   (T && F) || (F)
 - 358   (F && _) || (F)
  359       dy += height;
  360       sy += height;
  361       rev_copy = 1;
  362    }
  363 
  364    // split the base of the framebuffer into a long-aligned address and the
  365    // index of the first bit
  366    dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
  367    dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
  368    // add offset of source and target area
  369    dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
  370    src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
  371 
- 372    if (p->fbops->fb_sync)
  373       p->fbops->fb_sync(p);
  374 
- 375    if (rev_copy) {
- 376       while (height--) {
  377          dst_idx -= bits_per_line;
  378          src_idx -= bits_per_line;
  379          dst += dst_idx >> (ffs(bits) - 1);
  380          dst_idx &= (bytes - 1);
  381          src += src_idx >> (ffs(bits) - 1);
  382          src_idx &= (bytes - 1);
  383          bitcpy_rev(dst, dst_idx, src, src_idx, bits,
  384             width*p->var.bits_per_pixel);
  385       }
    386    } else {
- 387       while (height--) {
  388          dst += dst_idx >> (ffs(bits) - 1);
  389          dst_idx &= (bytes - 1);
  390          src += src_idx >> (ffs(bits) - 1);
  391          src_idx &= (bytes - 1);
  392          bitcpy(dst, dst_idx, src, src_idx, bits,
  393             width*p->var.bits_per_pixel);
  394          dst_idx += bits_per_line;
  395          src_idx += bits_per_line;
  396       }
  397    }
  398 }
  399 
  400 EXPORT_SYMBOL(cfb_copyarea);
  401 
  402 MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
  403 MODULE_DESCRIPTION("Generic software accelerated copyarea");
  404 MODULE_LICENSE("GPL");
  405 
***TER 0% (0/89) of SOURCE FILE cfbcopyarea.c

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last | Top