LCOV - code coverage report
Current view: top level - drivers/video/fbdev/core - sysfillrect.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 169 0.0 %
Date: 2022-03-28 15:32:58 Functions: 0 5 0.0 %
Branches: 0 82 0.0 %

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

Generated by: LCOV version 1.14