Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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