LCOV - code coverage report
Current view: top level - drivers/video/fbdev/core - cfbfillrect.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 190 0.0 %
Date: 2022-04-01 14:17:54 Functions: 0 5 0.0 %
Branches: 0 82 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  Generic fillrect for frame buffers with packed pixels of any depth.
       3                 :            :  *
       4                 :            :  *      Copyright (C)  2000 James Simmons (jsimmons@linux-fbdev.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                 :            :  *  Also need to add code to deal with cards endians that are different than
      13                 :            :  *  the native cpu endians. I also need to deal with MSB position in the word.
      14                 :            :  *
      15                 :            :  */
      16                 :            : #include <linux/module.h>
      17                 :            : #include <linux/string.h>
      18                 :            : #include <linux/fb.h>
      19                 :            : #include <asm/types.h>
      20                 :            : #include "fb_draw.h"
      21                 :            : 
      22                 :            : #if BITS_PER_LONG == 32
      23                 :            : #  define FB_WRITEL fb_writel
      24                 :            : #  define FB_READL  fb_readl
      25                 :            : #else
      26                 :            : #  define FB_WRITEL fb_writeq
      27                 :            : #  define FB_READL  fb_readq
      28                 :            : #endif
      29                 :            : 
      30                 :            :     /*
      31                 :            :      *  Aligned pattern fill using 32/64-bit memory accesses
      32                 :            :      */
      33                 :            : 
      34                 :            : static void
      35                 :          0 : bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
      36                 :            :                 unsigned long pat, unsigned n, int bits, u32 bswapmask)
      37                 :            : {
      38                 :          0 :         unsigned long first, last;
      39                 :            : 
      40         [ #  # ]:          0 :         if (!n)
      41                 :            :                 return;
      42                 :            : 
      43         [ #  # ]:          0 :         first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
      44                 :          0 :         last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
      45                 :            : 
      46         [ #  # ]:          0 :         if (dst_idx+n <= bits) {
      47                 :            :                 // Single word
      48         [ #  # ]:          0 :                 if (last)
      49                 :          0 :                         first &= last;
      50                 :          0 :                 FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
      51                 :            :         } else {
      52                 :            :                 // Multiple destination words
      53                 :            : 
      54                 :            :                 // Leading bits
      55         [ #  # ]:          0 :                 if (first!= ~0UL) {
      56                 :          0 :                         FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
      57                 :          0 :                         dst++;
      58                 :          0 :                         n -= bits - dst_idx;
      59                 :            :                 }
      60                 :            : 
      61                 :            :                 // Main chunk
      62                 :          0 :                 n /= bits;
      63         [ #  # ]:          0 :                 while (n >= 8) {
      64                 :          0 :                         FB_WRITEL(pat, dst++);
      65                 :          0 :                         FB_WRITEL(pat, dst++);
      66                 :          0 :                         FB_WRITEL(pat, dst++);
      67                 :          0 :                         FB_WRITEL(pat, dst++);
      68                 :          0 :                         FB_WRITEL(pat, dst++);
      69                 :          0 :                         FB_WRITEL(pat, dst++);
      70                 :          0 :                         FB_WRITEL(pat, dst++);
      71                 :          0 :                         FB_WRITEL(pat, dst++);
      72                 :          0 :                         n -= 8;
      73                 :            :                 }
      74         [ #  # ]:          0 :                 while (n--)
      75                 :          0 :                         FB_WRITEL(pat, dst++);
      76                 :            : 
      77                 :            :                 // Trailing bits
      78         [ #  # ]:          0 :                 if (last)
      79                 :          0 :                         FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
      80                 :            :         }
      81                 :            : }
      82                 :            : 
      83                 :            : 
      84                 :            :     /*
      85                 :            :      *  Unaligned generic pattern fill using 32/64-bit memory accesses
      86                 :            :      *  The pattern must have been expanded to a full 32/64-bit value
      87                 :            :      *  Left/right are the appropriate shifts to convert to the pattern to be
      88                 :            :      *  used for the next 32/64-bit word
      89                 :            :      */
      90                 :            : 
      91                 :            : static void
      92                 :          0 : bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
      93                 :            :                   unsigned long pat, int left, int right, unsigned n, int bits)
      94                 :            : {
      95                 :          0 :         unsigned long first, last;
      96                 :            : 
      97         [ #  # ]:          0 :         if (!n)
      98                 :            :                 return;
      99                 :            : 
     100         [ #  # ]:          0 :         first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
     101                 :          0 :         last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
     102                 :            : 
     103         [ #  # ]:          0 :         if (dst_idx+n <= bits) {
     104                 :            :                 // Single word
     105         [ #  # ]:          0 :                 if (last)
     106                 :          0 :                         first &= last;
     107                 :          0 :                 FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
     108                 :            :         } else {
     109                 :            :                 // Multiple destination words
     110                 :            :                 // Leading bits
     111         [ #  # ]:          0 :                 if (first) {
     112                 :          0 :                         FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
     113                 :          0 :                         dst++;
     114                 :          0 :                         pat = pat << left | pat >> right;
     115                 :          0 :                         n -= bits - dst_idx;
     116                 :            :                 }
     117                 :            : 
     118                 :            :                 // Main chunk
     119                 :          0 :                 n /= bits;
     120         [ #  # ]:          0 :                 while (n >= 4) {
     121                 :          0 :                         FB_WRITEL(pat, dst++);
     122                 :          0 :                         pat = pat << left | pat >> right;
     123                 :          0 :                         FB_WRITEL(pat, dst++);
     124                 :          0 :                         pat = pat << left | pat >> right;
     125                 :          0 :                         FB_WRITEL(pat, dst++);
     126                 :          0 :                         pat = pat << left | pat >> right;
     127                 :          0 :                         FB_WRITEL(pat, dst++);
     128                 :          0 :                         pat = pat << left | pat >> right;
     129                 :          0 :                         n -= 4;
     130                 :            :                 }
     131         [ #  # ]:          0 :                 while (n--) {
     132                 :          0 :                         FB_WRITEL(pat, dst++);
     133                 :          0 :                         pat = pat << left | pat >> right;
     134                 :            :                 }
     135                 :            : 
     136                 :            :                 // Trailing bits
     137         [ #  # ]:          0 :                 if (last)
     138                 :          0 :                         FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
     139                 :            :         }
     140                 :            : }
     141                 :            : 
     142                 :            :     /*
     143                 :            :      *  Aligned pattern invert using 32/64-bit memory accesses
     144                 :            :      */
     145                 :            : static void
     146                 :          0 : bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst,
     147                 :            :                     int dst_idx, unsigned long pat, unsigned n, int bits,
     148                 :            :                     u32 bswapmask)
     149                 :            : {
     150                 :          0 :         unsigned long val = pat, dat;
     151                 :          0 :         unsigned long first, last;
     152                 :            : 
     153         [ #  # ]:          0 :         if (!n)
     154                 :            :                 return;
     155                 :            : 
     156         [ #  # ]:          0 :         first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
     157                 :          0 :         last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
     158                 :            : 
     159         [ #  # ]:          0 :         if (dst_idx+n <= bits) {
     160                 :            :                 // Single word
     161         [ #  # ]:          0 :                 if (last)
     162                 :          0 :                         first &= last;
     163                 :          0 :                 dat = FB_READL(dst);
     164                 :          0 :                 FB_WRITEL(comp(dat ^ val, dat, first), dst);
     165                 :            :         } else {
     166                 :            :                 // Multiple destination words
     167                 :            :                 // Leading bits
     168         [ #  # ]:          0 :                 if (first!=0UL) {
     169                 :          0 :                         dat = FB_READL(dst);
     170                 :          0 :                         FB_WRITEL(comp(dat ^ val, dat, first), dst);
     171                 :          0 :                         dst++;
     172                 :          0 :                         n -= bits - dst_idx;
     173                 :            :                 }
     174                 :            : 
     175                 :            :                 // Main chunk
     176                 :          0 :                 n /= bits;
     177         [ #  # ]:          0 :                 while (n >= 8) {
     178                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ val, dst);
     179                 :          0 :                         dst++;
     180                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ val, dst);
     181                 :          0 :                         dst++;
     182                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ val, dst);
     183                 :          0 :                         dst++;
     184                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ val, dst);
     185                 :          0 :                         dst++;
     186                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ val, dst);
     187                 :          0 :                         dst++;
     188                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ val, dst);
     189                 :          0 :                         dst++;
     190                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ val, dst);
     191                 :          0 :                         dst++;
     192                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ val, dst);
     193                 :          0 :                         dst++;
     194                 :          0 :                         n -= 8;
     195                 :            :                 }
     196         [ #  # ]:          0 :                 while (n--) {
     197                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ val, dst);
     198                 :          0 :                         dst++;
     199                 :            :                 }
     200                 :            :                 // Trailing bits
     201         [ #  # ]:          0 :                 if (last) {
     202                 :          0 :                         dat = FB_READL(dst);
     203                 :          0 :                         FB_WRITEL(comp(dat ^ val, dat, last), dst);
     204                 :            :                 }
     205                 :            :         }
     206                 :            : }
     207                 :            : 
     208                 :            : 
     209                 :            :     /*
     210                 :            :      *  Unaligned generic pattern invert using 32/64-bit memory accesses
     211                 :            :      *  The pattern must have been expanded to a full 32/64-bit value
     212                 :            :      *  Left/right are the appropriate shifts to convert to the pattern to be
     213                 :            :      *  used for the next 32/64-bit word
     214                 :            :      */
     215                 :            : 
     216                 :            : static void
     217                 :          0 : bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst,
     218                 :            :                       int dst_idx, unsigned long pat, int left, int right,
     219                 :            :                       unsigned n, int bits)
     220                 :            : {
     221                 :          0 :         unsigned long first, last, dat;
     222                 :            : 
     223         [ #  # ]:          0 :         if (!n)
     224                 :            :                 return;
     225                 :            : 
     226         [ #  # ]:          0 :         first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
     227                 :          0 :         last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
     228                 :            : 
     229         [ #  # ]:          0 :         if (dst_idx+n <= bits) {
     230                 :            :                 // Single word
     231         [ #  # ]:          0 :                 if (last)
     232                 :          0 :                         first &= last;
     233                 :          0 :                 dat = FB_READL(dst);
     234                 :          0 :                 FB_WRITEL(comp(dat ^ pat, dat, first), dst);
     235                 :            :         } else {
     236                 :            :                 // Multiple destination words
     237                 :            : 
     238                 :            :                 // Leading bits
     239         [ #  # ]:          0 :                 if (first != 0UL) {
     240                 :          0 :                         dat = FB_READL(dst);
     241                 :          0 :                         FB_WRITEL(comp(dat ^ pat, dat, first), dst);
     242                 :          0 :                         dst++;
     243                 :          0 :                         pat = pat << left | pat >> right;
     244                 :          0 :                         n -= bits - dst_idx;
     245                 :            :                 }
     246                 :            : 
     247                 :            :                 // Main chunk
     248                 :          0 :                 n /= bits;
     249         [ #  # ]:          0 :                 while (n >= 4) {
     250                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ pat, dst);
     251                 :          0 :                         dst++;
     252                 :          0 :                         pat = pat << left | pat >> right;
     253                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ pat, dst);
     254                 :          0 :                         dst++;
     255                 :          0 :                         pat = pat << left | pat >> right;
     256                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ pat, dst);
     257                 :          0 :                         dst++;
     258                 :          0 :                         pat = pat << left | pat >> right;
     259                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ pat, dst);
     260                 :          0 :                         dst++;
     261                 :          0 :                         pat = pat << left | pat >> right;
     262                 :          0 :                         n -= 4;
     263                 :            :                 }
     264         [ #  # ]:          0 :                 while (n--) {
     265                 :          0 :                         FB_WRITEL(FB_READL(dst) ^ pat, dst);
     266                 :          0 :                         dst++;
     267                 :          0 :                         pat = pat << left | pat >> right;
     268                 :            :                 }
     269                 :            : 
     270                 :            :                 // Trailing bits
     271         [ #  # ]:          0 :                 if (last) {
     272                 :          0 :                         dat = FB_READL(dst);
     273                 :          0 :                         FB_WRITEL(comp(dat ^ pat, dat, last), dst);
     274                 :            :                 }
     275                 :            :         }
     276                 :            : }
     277                 :            : 
     278                 :          0 : void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
     279                 :            : {
     280                 :          0 :         unsigned long pat, pat2, fg;
     281                 :          0 :         unsigned long width = rect->width, height = rect->height;
     282                 :          0 :         int bits = BITS_PER_LONG, bytes = bits >> 3;
     283                 :          0 :         u32 bpp = p->var.bits_per_pixel;
     284                 :          0 :         unsigned long __iomem *dst;
     285                 :          0 :         int dst_idx, left;
     286                 :            : 
     287         [ #  # ]:          0 :         if (p->state != FBINFO_STATE_RUNNING)
     288                 :            :                 return;
     289                 :            : 
     290         [ #  # ]:          0 :         if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
     291                 :            :             p->fix.visual == FB_VISUAL_DIRECTCOLOR )
     292                 :          0 :                 fg = ((u32 *) (p->pseudo_palette))[rect->color];
     293                 :            :         else
     294                 :          0 :                 fg = rect->color;
     295                 :            : 
     296                 :          0 :         pat = pixel_to_pat(bpp, fg);
     297                 :            : 
     298                 :          0 :         dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
     299                 :          0 :         dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
     300                 :          0 :         dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
     301                 :            :         /* FIXME For now we support 1-32 bpp only */
     302                 :          0 :         left = bits % bpp;
     303         [ #  # ]:          0 :         if (p->fbops->fb_sync)
     304                 :          0 :                 p->fbops->fb_sync(p);
     305         [ #  # ]:          0 :         if (!left) {
     306                 :          0 :                 u32 bswapmask = fb_compute_bswapmask(p);
     307                 :          0 :                 void (*fill_op32)(struct fb_info *p,
     308                 :            :                                   unsigned long __iomem *dst, int dst_idx,
     309                 :            :                                   unsigned long pat, unsigned n, int bits,
     310                 :            :                                   u32 bswapmask) = NULL;
     311                 :            : 
     312      [ #  #  # ]:          0 :                 switch (rect->rop) {
     313                 :            :                 case ROP_XOR:
     314                 :            :                         fill_op32 = bitfill_aligned_rev;
     315                 :            :                         break;
     316                 :          0 :                 case ROP_COPY:
     317                 :          0 :                         fill_op32 = bitfill_aligned;
     318                 :          0 :                         break;
     319                 :          0 :                 default:
     320                 :          0 :                         printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
     321                 :          0 :                         fill_op32 = bitfill_aligned;
     322                 :          0 :                         break;
     323                 :            :                 }
     324         [ #  # ]:          0 :                 while (height--) {
     325                 :          0 :                         dst += dst_idx >> (ffs(bits) - 1);
     326                 :          0 :                         dst_idx &= (bits - 1);
     327                 :          0 :                         fill_op32(p, dst, dst_idx, pat, width*bpp, bits,
     328                 :            :                                   bswapmask);
     329                 :          0 :                         dst_idx += p->fix.line_length*8;
     330                 :            :                 }
     331                 :            :         } else {
     332                 :          0 :                 int right, r;
     333                 :          0 :                 void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
     334                 :            :                                 int dst_idx, unsigned long pat, int left,
     335                 :            :                                 int right, unsigned n, int bits) = NULL;
     336                 :            : #ifdef __LITTLE_ENDIAN
     337                 :          0 :                 right = left;
     338                 :          0 :                 left = bpp - right;
     339                 :            : #else
     340                 :            :                 right = bpp - left;
     341                 :            : #endif
     342      [ #  #  # ]:          0 :                 switch (rect->rop) {
     343                 :            :                 case ROP_XOR:
     344                 :            :                         fill_op = bitfill_unaligned_rev;
     345                 :            :                         break;
     346                 :          0 :                 case ROP_COPY:
     347                 :          0 :                         fill_op = bitfill_unaligned;
     348                 :          0 :                         break;
     349                 :          0 :                 default:
     350                 :          0 :                         printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
     351                 :          0 :                         fill_op = bitfill_unaligned;
     352                 :          0 :                         break;
     353                 :            :                 }
     354         [ #  # ]:          0 :                 while (height--) {
     355                 :          0 :                         dst += dst_idx / bits;
     356                 :          0 :                         dst_idx &= (bits - 1);
     357                 :          0 :                         r = dst_idx % bpp;
     358                 :            :                         /* rotate pattern to the correct start position */
     359                 :          0 :                         pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
     360                 :          0 :                         fill_op(p, dst, dst_idx, pat2, left, right,
     361                 :            :                                 width*bpp, bits);
     362                 :          0 :                         dst_idx += p->fix.line_length*8;
     363                 :            :                 }
     364                 :            :         }
     365                 :            : }
     366                 :            : 
     367                 :            : EXPORT_SYMBOL(cfb_fillrect);
     368                 :            : 
     369                 :            : MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
     370                 :            : MODULE_DESCRIPTION("Generic software accelerated fill rectangle");
     371                 :            : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14