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

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

DEFINITIONS

This source file includes following definitions.
  1. bitfill_aligned
  2. bitfill_unaligned
  3. bitfill_aligned_rev
  4. bitfill_unaligned_rev
  5. sys_fillrect

   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 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         if (!n)
  31                 return;
  32 
  33         first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
  34         last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
  35 
  36         if (dst_idx+n <= bits) {
  37                 /* Single word */
  38                 if (last)
  39                         first &= last;
  40                 *dst = comp(pat, *dst, first);
  41         } else {
  42                 /* Multiple destination words */
  43 
  44                 /* Leading bits */
  45                 if (first!= ~0UL) {
  46                         *dst = comp(pat, *dst, first);
  47                         dst++;
  48                         n -= bits - dst_idx;
  49                 }
  50 
  51                 /* Main chunk */
  52                 n /= bits;
  53                 while (n >= 8) {
  54                         *dst++ = pat;
  55                         *dst++ = pat;
  56                         *dst++ = pat;
  57                         *dst++ = pat;
  58                         *dst++ = pat;
  59                         *dst++ = pat;
  60                         *dst++ = pat;
  61                         *dst++ = pat;
  62                         n -= 8;
  63                 }
  64                 while (n--)
  65                         *dst++ = pat;
  66                 /* Trailing bits */
  67                 if (last)
  68                         *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 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         unsigned long first, last;
  85 
  86         if (!n)
  87                 return;
  88 
  89         first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
  90         last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
  91 
  92         if (dst_idx+n <= bits) {
  93                 /* Single word */
  94                 if (last)
  95                         first &= last;
  96                 *dst = comp(pat, *dst, first);
  97         } else {
  98                 /* Multiple destination words */
  99                 /* Leading bits */
 100                 if (first) {
 101                         *dst = comp(pat, *dst, first);
 102                         dst++;
 103                         pat = pat << left | pat >> right;
 104                         n -= bits - dst_idx;
 105                 }
 106 
 107                 /* Main chunk */
 108                 n /= bits;
 109                 while (n >= 4) {
 110                         *dst++ = pat;
 111                         pat = pat << left | pat >> right;
 112                         *dst++ = pat;
 113                         pat = pat << left | pat >> right;
 114                         *dst++ = pat;
 115                         pat = pat << left | pat >> right;
 116                         *dst++ = pat;
 117                         pat = pat << left | pat >> right;
 118                         n -= 4;
 119                 }
 120                 while (n--) {
 121                         *dst++ = pat;
 122                         pat = pat << left | pat >> right;
 123                 }
 124 
 125                 /* Trailing bits */
 126                 if (last)
 127                         *dst = comp(pat, *dst, last);
 128         }
 129 }
 130 
 131     /*
 132      *  Aligned pattern invert using 32/64-bit memory accesses
 133      */
 134 static void
 135 bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
 136                     unsigned long pat, unsigned n, int bits)
 137 {
 138         unsigned long val = pat;
 139         unsigned long first, last;
 140 
 141         if (!n)
 142                 return;
 143 
 144         first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
 145         last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
 146 
 147         if (dst_idx+n <= bits) {
 148                 /* Single word */
 149                 if (last)
 150                         first &= last;
 151                 *dst = comp(*dst ^ val, *dst, first);
 152         } else {
 153                 /* Multiple destination words */
 154                 /* Leading bits */
 155                 if (first!=0UL) {
 156                         *dst = comp(*dst ^ val, *dst, first);
 157                         dst++;
 158                         n -= bits - dst_idx;
 159                 }
 160 
 161                 /* Main chunk */
 162                 n /= bits;
 163                 while (n >= 8) {
 164                         *dst++ ^= val;
 165                         *dst++ ^= val;
 166                         *dst++ ^= val;
 167                         *dst++ ^= val;
 168                         *dst++ ^= val;
 169                         *dst++ ^= val;
 170                         *dst++ ^= val;
 171                         *dst++ ^= val;
 172                         n -= 8;
 173                 }
 174                 while (n--)
 175                         *dst++ ^= val;
 176                 /* Trailing bits */
 177                 if (last)
 178                         *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 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         unsigned long first, last;
 196 
 197         if (!n)
 198                 return;
 199 
 200         first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
 201         last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
 202 
 203         if (dst_idx+n <= bits) {
 204                 /* Single word */
 205                 if (last)
 206                         first &= last;
 207                 *dst = comp(*dst ^ pat, *dst, first);
 208         } else {
 209                 /* Multiple destination words */
 210 
 211                 /* Leading bits */
 212                 if (first != 0UL) {
 213                         *dst = comp(*dst ^ pat, *dst, first);
 214                         dst++;
 215                         pat = pat << left | pat >> right;
 216                         n -= bits - dst_idx;
 217                 }
 218 
 219                 /* Main chunk */
 220                 n /= bits;
 221                 while (n >= 4) {
 222                         *dst++ ^= pat;
 223                         pat = pat << left | pat >> right;
 224                         *dst++ ^= pat;
 225                         pat = pat << left | pat >> right;
 226                         *dst++ ^= pat;
 227                         pat = pat << left | pat >> right;
 228                         *dst++ ^= pat;
 229                         pat = pat << left | pat >> right;
 230                         n -= 4;
 231                 }
 232                 while (n--) {
 233                         *dst ^= pat;
 234                         pat = pat << left | pat >> right;
 235                 }
 236 
 237                 /* Trailing bits */
 238                 if (last)
 239                         *dst = comp(*dst ^ pat, *dst, last);
 240         }
 241 }
 242 
 243 void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
 244 {
 245         unsigned long pat, pat2, fg;
 246         unsigned long width = rect->width, height = rect->height;
 247         int bits = BITS_PER_LONG, bytes = bits >> 3;
 248         u32 bpp = p->var.bits_per_pixel;
 249         unsigned long *dst;
 250         int dst_idx, left;
 251 
 252         if (p->state != FBINFO_STATE_RUNNING)
 253                 return;
 254 
 255         if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
 256             p->fix.visual == FB_VISUAL_DIRECTCOLOR )
 257                 fg = ((u32 *) (p->pseudo_palette))[rect->color];
 258         else
 259                 fg = rect->color;
 260 
 261         pat = pixel_to_pat( bpp, fg);
 262 
 263         dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));
 264         dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
 265         dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
 266         /* FIXME For now we support 1-32 bpp only */
 267         left = bits % bpp;
 268         if (p->fbops->fb_sync)
 269                 p->fbops->fb_sync(p);
 270         if (!left) {
 271                 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                 switch (rect->rop) {
 276                 case ROP_XOR:
 277                         fill_op32 = bitfill_aligned_rev;
 278                         break;
 279                 case ROP_COPY:
 280                         fill_op32 = bitfill_aligned;
 281                         break;
 282                 default:
 283                         printk( KERN_ERR "cfb_fillrect(): unknown rop, "
 284                                 "defaulting to ROP_COPY\n");
 285                         fill_op32 = bitfill_aligned;
 286                         break;
 287                 }
 288                 while (height--) {
 289                         dst += dst_idx >> (ffs(bits) - 1);
 290                         dst_idx &= (bits - 1);
 291                         fill_op32(p, dst, dst_idx, pat, width*bpp, bits);
 292                         dst_idx += p->fix.line_length*8;
 293                 }
 294         } else {
 295                 int right, r;
 296                 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                 right = left;
 301                 left = bpp - right;
 302 #else
 303                 right = bpp - left;
 304 #endif
 305                 switch (rect->rop) {
 306                 case ROP_XOR:
 307                         fill_op = bitfill_unaligned_rev;
 308                         break;
 309                 case ROP_COPY:
 310                         fill_op = bitfill_unaligned;
 311                         break;
 312                 default:
 313                         printk(KERN_ERR "sys_fillrect(): unknown rop, "
 314                                 "defaulting to ROP_COPY\n");
 315                         fill_op = bitfill_unaligned;
 316                         break;
 317                 }
 318                 while (height--) {
 319                         dst += dst_idx / bits;
 320                         dst_idx &= (bits - 1);
 321                         r = dst_idx % bpp;
 322                         /* rotate pattern to the correct start position */
 323                         pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
 324                         fill_op(p, dst, dst_idx, pat2, left, right,
 325                                 width*bpp, bits);
 326                         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");

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