LCOV - code coverage report
Current view: top level - drivers/video/fbdev/core - sysfillrect.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 147 0.0 %
Date: 2023-08-24 13:40:31 Functions: 0 5 0.0 %

          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             :         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 :                 memset_l(dst, pat, n);
      54           0 :                 dst += n;
      55             : 
      56             :                 /* Trailing bits */
      57           0 :                 if (last)
      58           0 :                         *dst = comp(pat, *dst, last);
      59             :         }
      60             : }
      61             : 
      62             : 
      63             :     /*
      64             :      *  Unaligned generic pattern fill using 32/64-bit memory accesses
      65             :      *  The pattern must have been expanded to a full 32/64-bit value
      66             :      *  Left/right are the appropriate shifts to convert to the pattern to be
      67             :      *  used for the next 32/64-bit word
      68             :      */
      69             : 
      70             : static void
      71           0 : bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx,
      72             :                   unsigned long pat, int left, int right, unsigned n, int bits)
      73             : {
      74             :         unsigned long first, last;
      75             : 
      76           0 :         if (!n)
      77             :                 return;
      78             : 
      79           0 :         first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
      80           0 :         last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
      81             : 
      82           0 :         if (dst_idx+n <= bits) {
      83             :                 /* Single word */
      84           0 :                 if (last)
      85           0 :                         first &= last;
      86           0 :                 *dst = comp(pat, *dst, first);
      87             :         } else {
      88             :                 /* Multiple destination words */
      89             :                 /* Leading bits */
      90           0 :                 if (first) {
      91           0 :                         *dst = comp(pat, *dst, first);
      92           0 :                         dst++;
      93           0 :                         pat = pat << left | pat >> right;
      94           0 :                         n -= bits - dst_idx;
      95             :                 }
      96             : 
      97             :                 /* Main chunk */
      98           0 :                 n /= bits;
      99           0 :                 while (n >= 4) {
     100           0 :                         *dst++ = pat;
     101           0 :                         pat = pat << left | pat >> right;
     102           0 :                         *dst++ = pat;
     103           0 :                         pat = pat << left | pat >> right;
     104           0 :                         *dst++ = pat;
     105           0 :                         pat = pat << left | pat >> right;
     106           0 :                         *dst++ = pat;
     107           0 :                         pat = pat << left | pat >> right;
     108           0 :                         n -= 4;
     109             :                 }
     110           0 :                 while (n--) {
     111           0 :                         *dst++ = pat;
     112           0 :                         pat = pat << left | pat >> right;
     113             :                 }
     114             : 
     115             :                 /* Trailing bits */
     116           0 :                 if (last)
     117           0 :                         *dst = comp(pat, *dst, last);
     118             :         }
     119             : }
     120             : 
     121             :     /*
     122             :      *  Aligned pattern invert using 32/64-bit memory accesses
     123             :      */
     124             : static void
     125           0 : bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
     126             :                     unsigned long pat, unsigned n, int bits)
     127             : {
     128           0 :         unsigned long val = pat;
     129             :         unsigned long first, last;
     130             : 
     131           0 :         if (!n)
     132             :                 return;
     133             : 
     134           0 :         first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
     135           0 :         last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
     136             : 
     137           0 :         if (dst_idx+n <= bits) {
     138             :                 /* Single word */
     139           0 :                 if (last)
     140           0 :                         first &= last;
     141           0 :                 *dst = comp(*dst ^ val, *dst, first);
     142             :         } else {
     143             :                 /* Multiple destination words */
     144             :                 /* Leading bits */
     145           0 :                 if (first!=0UL) {
     146           0 :                         *dst = comp(*dst ^ val, *dst, first);
     147           0 :                         dst++;
     148           0 :                         n -= bits - dst_idx;
     149             :                 }
     150             : 
     151             :                 /* Main chunk */
     152           0 :                 n /= bits;
     153           0 :                 while (n >= 8) {
     154           0 :                         *dst++ ^= val;
     155           0 :                         *dst++ ^= val;
     156           0 :                         *dst++ ^= val;
     157           0 :                         *dst++ ^= val;
     158           0 :                         *dst++ ^= val;
     159           0 :                         *dst++ ^= val;
     160           0 :                         *dst++ ^= val;
     161           0 :                         *dst++ ^= val;
     162           0 :                         n -= 8;
     163             :                 }
     164           0 :                 while (n--)
     165           0 :                         *dst++ ^= val;
     166             :                 /* Trailing bits */
     167           0 :                 if (last)
     168           0 :                         *dst = comp(*dst ^ val, *dst, last);
     169             :         }
     170             : }
     171             : 
     172             : 
     173             :     /*
     174             :      *  Unaligned generic pattern invert using 32/64-bit memory accesses
     175             :      *  The pattern must have been expanded to a full 32/64-bit value
     176             :      *  Left/right are the appropriate shifts to convert to the pattern to be
     177             :      *  used for the next 32/64-bit word
     178             :      */
     179             : 
     180             : static void
     181           0 : bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
     182             :                       unsigned long pat, int left, int right, unsigned n,
     183             :                       int bits)
     184             : {
     185             :         unsigned long first, last;
     186             : 
     187           0 :         if (!n)
     188             :                 return;
     189             : 
     190           0 :         first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
     191           0 :         last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
     192             : 
     193           0 :         if (dst_idx+n <= bits) {
     194             :                 /* Single word */
     195           0 :                 if (last)
     196           0 :                         first &= last;
     197           0 :                 *dst = comp(*dst ^ pat, *dst, first);
     198             :         } else {
     199             :                 /* Multiple destination words */
     200             : 
     201             :                 /* Leading bits */
     202           0 :                 if (first != 0UL) {
     203           0 :                         *dst = comp(*dst ^ pat, *dst, first);
     204           0 :                         dst++;
     205           0 :                         pat = pat << left | pat >> right;
     206           0 :                         n -= bits - dst_idx;
     207             :                 }
     208             : 
     209             :                 /* Main chunk */
     210           0 :                 n /= bits;
     211           0 :                 while (n >= 4) {
     212           0 :                         *dst++ ^= pat;
     213           0 :                         pat = pat << left | pat >> right;
     214           0 :                         *dst++ ^= pat;
     215           0 :                         pat = pat << left | pat >> right;
     216           0 :                         *dst++ ^= pat;
     217           0 :                         pat = pat << left | pat >> right;
     218           0 :                         *dst++ ^= pat;
     219           0 :                         pat = pat << left | pat >> right;
     220           0 :                         n -= 4;
     221             :                 }
     222           0 :                 while (n--) {
     223           0 :                         *dst ^= pat;
     224           0 :                         pat = pat << left | pat >> right;
     225             :                 }
     226             : 
     227             :                 /* Trailing bits */
     228           0 :                 if (last)
     229           0 :                         *dst = comp(*dst ^ pat, *dst, last);
     230             :         }
     231             : }
     232             : 
     233           0 : void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
     234             : {
     235             :         unsigned long pat, pat2, fg;
     236           0 :         unsigned long width = rect->width, height = rect->height;
     237           0 :         int bits = BITS_PER_LONG, bytes = bits >> 3;
     238           0 :         u32 bpp = p->var.bits_per_pixel;
     239             :         unsigned long *dst;
     240             :         int dst_idx, left;
     241             : 
     242           0 :         if (p->state != FBINFO_STATE_RUNNING)
     243             :                 return;
     244             : 
     245           0 :         if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
     246             :             p->fix.visual == FB_VISUAL_DIRECTCOLOR )
     247           0 :                 fg = ((u32 *) (p->pseudo_palette))[rect->color];
     248             :         else
     249           0 :                 fg = rect->color;
     250             : 
     251           0 :         pat = pixel_to_pat( bpp, fg);
     252             : 
     253           0 :         dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));
     254           0 :         dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
     255           0 :         dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
     256             :         /* FIXME For now we support 1-32 bpp only */
     257           0 :         left = bits % bpp;
     258           0 :         if (p->fbops->fb_sync)
     259           0 :                 p->fbops->fb_sync(p);
     260           0 :         if (!left) {
     261           0 :                 void (*fill_op32)(struct fb_info *p, unsigned long *dst,
     262             :                                   int dst_idx, unsigned long pat, unsigned n,
     263             :                                   int bits) = NULL;
     264             : 
     265           0 :                 switch (rect->rop) {
     266             :                 case ROP_XOR:
     267             :                         fill_op32 = bitfill_aligned_rev;
     268             :                         break;
     269             :                 case ROP_COPY:
     270           0 :                         fill_op32 = bitfill_aligned;
     271           0 :                         break;
     272             :                 default:
     273           0 :                         printk( KERN_ERR "cfb_fillrect(): unknown rop, "
     274             :                                 "defaulting to ROP_COPY\n");
     275           0 :                         fill_op32 = bitfill_aligned;
     276           0 :                         break;
     277             :                 }
     278           0 :                 while (height--) {
     279           0 :                         dst += dst_idx >> (ffs(bits) - 1);
     280           0 :                         dst_idx &= (bits - 1);
     281           0 :                         fill_op32(p, dst, dst_idx, pat, width*bpp, bits);
     282           0 :                         dst_idx += p->fix.line_length*8;
     283             :                 }
     284             :         } else {
     285             :                 int right, r;
     286           0 :                 void (*fill_op)(struct fb_info *p, unsigned long *dst,
     287             :                                 int dst_idx, unsigned long pat, int left,
     288             :                                 int right, unsigned n, int bits) = NULL;
     289             : #ifdef __LITTLE_ENDIAN
     290           0 :                 right = left;
     291           0 :                 left = bpp - right;
     292             : #else
     293             :                 right = bpp - left;
     294             : #endif
     295           0 :                 switch (rect->rop) {
     296             :                 case ROP_XOR:
     297             :                         fill_op = bitfill_unaligned_rev;
     298             :                         break;
     299             :                 case ROP_COPY:
     300           0 :                         fill_op = bitfill_unaligned;
     301           0 :                         break;
     302             :                 default:
     303           0 :                         printk(KERN_ERR "sys_fillrect(): unknown rop, "
     304             :                                 "defaulting to ROP_COPY\n");
     305           0 :                         fill_op = bitfill_unaligned;
     306           0 :                         break;
     307             :                 }
     308           0 :                 while (height--) {
     309           0 :                         dst += dst_idx / bits;
     310           0 :                         dst_idx &= (bits - 1);
     311           0 :                         r = dst_idx % bpp;
     312             :                         /* rotate pattern to the correct start position */
     313           0 :                         pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
     314           0 :                         fill_op(p, dst, dst_idx, pat2, left, right,
     315             :                                 width*bpp, bits);
     316           0 :                         dst_idx += p->fix.line_length*8;
     317             :                 }
     318             :         }
     319             : }
     320             : 
     321             : EXPORT_SYMBOL(sys_fillrect);
     322             : 
     323             : MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
     324             : MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
     325             : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14