0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/module.h>
0015 #include <linux/string.h>
0016 #include <linux/fb.h>
0017 #include <asm/types.h>
0018 #include "fb_draw.h"
0019
0020
0021
0022
0023
0024 static void
0025 bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx,
0026 unsigned long pat, unsigned n, int bits)
0027 {
0028 unsigned long first, last;
0029
0030 if (!n)
0031 return;
0032
0033 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
0034 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
0035
0036 if (dst_idx+n <= bits) {
0037
0038 if (last)
0039 first &= last;
0040 *dst = comp(pat, *dst, first);
0041 } else {
0042
0043
0044
0045 if (first!= ~0UL) {
0046 *dst = comp(pat, *dst, first);
0047 dst++;
0048 n -= bits - dst_idx;
0049 }
0050
0051
0052 n /= bits;
0053 memset_l(dst, pat, n);
0054 dst += n;
0055
0056
0057 if (last)
0058 *dst = comp(pat, *dst, last);
0059 }
0060 }
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 static void
0071 bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx,
0072 unsigned long pat, int left, int right, unsigned n, int bits)
0073 {
0074 unsigned long first, last;
0075
0076 if (!n)
0077 return;
0078
0079 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
0080 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
0081
0082 if (dst_idx+n <= bits) {
0083
0084 if (last)
0085 first &= last;
0086 *dst = comp(pat, *dst, first);
0087 } else {
0088
0089
0090 if (first) {
0091 *dst = comp(pat, *dst, first);
0092 dst++;
0093 pat = pat << left | pat >> right;
0094 n -= bits - dst_idx;
0095 }
0096
0097
0098 n /= bits;
0099 while (n >= 4) {
0100 *dst++ = pat;
0101 pat = pat << left | pat >> right;
0102 *dst++ = pat;
0103 pat = pat << left | pat >> right;
0104 *dst++ = pat;
0105 pat = pat << left | pat >> right;
0106 *dst++ = pat;
0107 pat = pat << left | pat >> right;
0108 n -= 4;
0109 }
0110 while (n--) {
0111 *dst++ = pat;
0112 pat = pat << left | pat >> right;
0113 }
0114
0115
0116 if (last)
0117 *dst = comp(pat, *dst, last);
0118 }
0119 }
0120
0121
0122
0123
0124 static void
0125 bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
0126 unsigned long pat, unsigned n, int bits)
0127 {
0128 unsigned long val = pat;
0129 unsigned long first, last;
0130
0131 if (!n)
0132 return;
0133
0134 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
0135 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
0136
0137 if (dst_idx+n <= bits) {
0138
0139 if (last)
0140 first &= last;
0141 *dst = comp(*dst ^ val, *dst, first);
0142 } else {
0143
0144
0145 if (first!=0UL) {
0146 *dst = comp(*dst ^ val, *dst, first);
0147 dst++;
0148 n -= bits - dst_idx;
0149 }
0150
0151
0152 n /= bits;
0153 while (n >= 8) {
0154 *dst++ ^= val;
0155 *dst++ ^= val;
0156 *dst++ ^= val;
0157 *dst++ ^= val;
0158 *dst++ ^= val;
0159 *dst++ ^= val;
0160 *dst++ ^= val;
0161 *dst++ ^= val;
0162 n -= 8;
0163 }
0164 while (n--)
0165 *dst++ ^= val;
0166
0167 if (last)
0168 *dst = comp(*dst ^ val, *dst, last);
0169 }
0170 }
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180 static void
0181 bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,
0182 unsigned long pat, int left, int right, unsigned n,
0183 int bits)
0184 {
0185 unsigned long first, last;
0186
0187 if (!n)
0188 return;
0189
0190 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
0191 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
0192
0193 if (dst_idx+n <= bits) {
0194
0195 if (last)
0196 first &= last;
0197 *dst = comp(*dst ^ pat, *dst, first);
0198 } else {
0199
0200
0201
0202 if (first != 0UL) {
0203 *dst = comp(*dst ^ pat, *dst, first);
0204 dst++;
0205 pat = pat << left | pat >> right;
0206 n -= bits - dst_idx;
0207 }
0208
0209
0210 n /= bits;
0211 while (n >= 4) {
0212 *dst++ ^= pat;
0213 pat = pat << left | pat >> right;
0214 *dst++ ^= pat;
0215 pat = pat << left | pat >> right;
0216 *dst++ ^= pat;
0217 pat = pat << left | pat >> right;
0218 *dst++ ^= pat;
0219 pat = pat << left | pat >> right;
0220 n -= 4;
0221 }
0222 while (n--) {
0223 *dst ^= pat;
0224 pat = pat << left | pat >> right;
0225 }
0226
0227
0228 if (last)
0229 *dst = comp(*dst ^ pat, *dst, last);
0230 }
0231 }
0232
0233 void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
0234 {
0235 unsigned long pat, pat2, fg;
0236 unsigned long width = rect->width, height = rect->height;
0237 int bits = BITS_PER_LONG, bytes = bits >> 3;
0238 u32 bpp = p->var.bits_per_pixel;
0239 unsigned long *dst;
0240 int dst_idx, left;
0241
0242 if (p->state != FBINFO_STATE_RUNNING)
0243 return;
0244
0245 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
0246 p->fix.visual == FB_VISUAL_DIRECTCOLOR )
0247 fg = ((u32 *) (p->pseudo_palette))[rect->color];
0248 else
0249 fg = rect->color;
0250
0251 pat = pixel_to_pat( bpp, fg);
0252
0253 dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));
0254 dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
0255 dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
0256
0257 left = bits % bpp;
0258 if (p->fbops->fb_sync)
0259 p->fbops->fb_sync(p);
0260 if (!left) {
0261 void (*fill_op32)(struct fb_info *p, unsigned long *dst,
0262 int dst_idx, unsigned long pat, unsigned n,
0263 int bits) = NULL;
0264
0265 switch (rect->rop) {
0266 case ROP_XOR:
0267 fill_op32 = bitfill_aligned_rev;
0268 break;
0269 case ROP_COPY:
0270 fill_op32 = bitfill_aligned;
0271 break;
0272 default:
0273 printk( KERN_ERR "cfb_fillrect(): unknown rop, "
0274 "defaulting to ROP_COPY\n");
0275 fill_op32 = bitfill_aligned;
0276 break;
0277 }
0278 while (height--) {
0279 dst += dst_idx >> (ffs(bits) - 1);
0280 dst_idx &= (bits - 1);
0281 fill_op32(p, dst, dst_idx, pat, width*bpp, bits);
0282 dst_idx += p->fix.line_length*8;
0283 }
0284 } else {
0285 int right, r;
0286 void (*fill_op)(struct fb_info *p, unsigned long *dst,
0287 int dst_idx, unsigned long pat, int left,
0288 int right, unsigned n, int bits) = NULL;
0289 #ifdef __LITTLE_ENDIAN
0290 right = left;
0291 left = bpp - right;
0292 #else
0293 right = bpp - left;
0294 #endif
0295 switch (rect->rop) {
0296 case ROP_XOR:
0297 fill_op = bitfill_unaligned_rev;
0298 break;
0299 case ROP_COPY:
0300 fill_op = bitfill_unaligned;
0301 break;
0302 default:
0303 printk(KERN_ERR "sys_fillrect(): unknown rop, "
0304 "defaulting to ROP_COPY\n");
0305 fill_op = bitfill_unaligned;
0306 break;
0307 }
0308 while (height--) {
0309 dst += dst_idx / bits;
0310 dst_idx &= (bits - 1);
0311 r = dst_idx % bpp;
0312
0313 pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
0314 fill_op(p, dst, dst_idx, pat2, left, right,
0315 width*bpp, bits);
0316 dst_idx += p->fix.line_length*8;
0317 }
0318 }
0319 }
0320
0321 EXPORT_SYMBOL(sys_fillrect);
0322
0323 MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
0324 MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
0325 MODULE_LICENSE("GPL");