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.27 375 lines 9.1 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(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, 40 unsigned long pat, 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(p, dst_idx, bswapmask); 48 last = ~fb_shifted_pixels_mask_long(p, (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(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, 97 unsigned long pat, 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(p, ~0UL, dst_idx); 105 last = ~(FB_SHIFT_HIGH(p, ~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(struct fb_info *p, unsigned long __iomem *dst, 151 int dst_idx, unsigned long pat, unsigned n, int bits, 152 u32 bswapmask) 153{ 154 unsigned long val = pat, dat; 155 unsigned long first, last; 156 157 if (!n) 158 return; 159 160 first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); 161 last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); 162 163 if (dst_idx+n <= bits) { 164 // Single word 165 if (last) 166 first &= last; 167 dat = FB_READL(dst); 168 FB_WRITEL(comp(dat ^ val, dat, first), dst); 169 } else { 170 // Multiple destination words 171 // Leading bits 172 if (first!=0UL) { 173 dat = FB_READL(dst); 174 FB_WRITEL(comp(dat ^ val, dat, first), dst); 175 dst++; 176 n -= bits - dst_idx; 177 } 178 179 // Main chunk 180 n /= bits; 181 while (n >= 8) { 182 FB_WRITEL(FB_READL(dst) ^ val, dst); 183 dst++; 184 FB_WRITEL(FB_READL(dst) ^ val, dst); 185 dst++; 186 FB_WRITEL(FB_READL(dst) ^ val, dst); 187 dst++; 188 FB_WRITEL(FB_READL(dst) ^ val, dst); 189 dst++; 190 FB_WRITEL(FB_READL(dst) ^ val, dst); 191 dst++; 192 FB_WRITEL(FB_READL(dst) ^ val, dst); 193 dst++; 194 FB_WRITEL(FB_READL(dst) ^ val, dst); 195 dst++; 196 FB_WRITEL(FB_READL(dst) ^ val, dst); 197 dst++; 198 n -= 8; 199 } 200 while (n--) { 201 FB_WRITEL(FB_READL(dst) ^ val, dst); 202 dst++; 203 } 204 // Trailing bits 205 if (last) { 206 dat = FB_READL(dst); 207 FB_WRITEL(comp(dat ^ val, dat, last), dst); 208 } 209 } 210} 211 212 213 /* 214 * Unaligned generic pattern invert using 32/64-bit memory accesses 215 * The pattern must have been expanded to a full 32/64-bit value 216 * Left/right are the appropriate shifts to convert to the pattern to be 217 * used for the next 32/64-bit word 218 */ 219 220static void 221bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, 222 int dst_idx, unsigned long pat, int left, int right, 223 unsigned n, int bits) 224{ 225 unsigned long first, last, dat; 226 227 if (!n) 228 return; 229 230 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); 231 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); 232 233 if (dst_idx+n <= bits) { 234 // Single word 235 if (last) 236 first &= last; 237 dat = FB_READL(dst); 238 FB_WRITEL(comp(dat ^ pat, dat, first), dst); 239 } else { 240 // Multiple destination words 241 242 // Leading bits 243 if (first != 0UL) { 244 dat = FB_READL(dst); 245 FB_WRITEL(comp(dat ^ pat, dat, first), dst); 246 dst++; 247 pat = pat << left | pat >> right; 248 n -= bits - dst_idx; 249 } 250 251 // Main chunk 252 n /= bits; 253 while (n >= 4) { 254 FB_WRITEL(FB_READL(dst) ^ pat, dst); 255 dst++; 256 pat = pat << left | pat >> right; 257 FB_WRITEL(FB_READL(dst) ^ pat, dst); 258 dst++; 259 pat = pat << left | pat >> right; 260 FB_WRITEL(FB_READL(dst) ^ pat, dst); 261 dst++; 262 pat = pat << left | pat >> right; 263 FB_WRITEL(FB_READL(dst) ^ pat, dst); 264 dst++; 265 pat = pat << left | pat >> right; 266 n -= 4; 267 } 268 while (n--) { 269 FB_WRITEL(FB_READL(dst) ^ pat, dst); 270 dst++; 271 pat = pat << left | pat >> right; 272 } 273 274 // Trailing bits 275 if (last) { 276 dat = FB_READL(dst); 277 FB_WRITEL(comp(dat ^ pat, dat, last), dst); 278 } 279 } 280} 281 282void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) 283{ 284 unsigned long pat, fg; 285 unsigned long width = rect->width, height = rect->height; 286 int bits = BITS_PER_LONG, bytes = bits >> 3; 287 u32 bpp = p->var.bits_per_pixel; 288 unsigned long __iomem *dst; 289 int dst_idx, left; 290 291 if (p->state != FBINFO_STATE_RUNNING) 292 return; 293 294 if (p->fix.visual == FB_VISUAL_TRUECOLOR || 295 p->fix.visual == FB_VISUAL_DIRECTCOLOR ) 296 fg = ((u32 *) (p->pseudo_palette))[rect->color]; 297 else 298 fg = rect->color; 299 300 pat = pixel_to_pat( bpp, fg); 301 302 dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); 303 dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; 304 dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; 305 /* FIXME For now we support 1-32 bpp only */ 306 left = bits % bpp; 307 if (p->fbops->fb_sync) 308 p->fbops->fb_sync(p); 309 if (!left) { 310 u32 bswapmask = fb_compute_bswapmask(p); 311 void (*fill_op32)(struct fb_info *p, 312 unsigned long __iomem *dst, int dst_idx, 313 unsigned long pat, unsigned n, int bits, 314 u32 bswapmask) = NULL; 315 316 switch (rect->rop) { 317 case ROP_XOR: 318 fill_op32 = bitfill_aligned_rev; 319 break; 320 case ROP_COPY: 321 fill_op32 = bitfill_aligned; 322 break; 323 default: 324 printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); 325 fill_op32 = bitfill_aligned; 326 break; 327 } 328 while (height--) { 329 dst += dst_idx >> (ffs(bits) - 1); 330 dst_idx &= (bits - 1); 331 fill_op32(p, dst, dst_idx, pat, width*bpp, bits, 332 bswapmask); 333 dst_idx += p->fix.line_length*8; 334 } 335 } else { 336 int right; 337 int r; 338 int rot = (left-dst_idx) % bpp; 339 void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst, 340 int dst_idx, unsigned long pat, int left, 341 int right, unsigned n, int bits) = NULL; 342 343 /* rotate pattern to correct start position */ 344 pat = pat << rot | pat >> (bpp-rot); 345 346 right = bpp-left; 347 switch (rect->rop) { 348 case ROP_XOR: 349 fill_op = bitfill_unaligned_rev; 350 break; 351 case ROP_COPY: 352 fill_op = bitfill_unaligned; 353 break; 354 default: 355 printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); 356 fill_op = bitfill_unaligned; 357 break; 358 } 359 while (height--) { 360 dst += dst_idx >> (ffs(bits) - 1); 361 dst_idx &= (bits - 1); 362 fill_op(p, dst, dst_idx, pat, left, right, 363 width*bpp, bits); 364 r = (p->fix.line_length*8) % bpp; 365 pat = pat << (bpp-r) | pat >> r; 366 dst_idx += p->fix.line_length*8; 367 } 368 } 369} 370 371EXPORT_SYMBOL(cfb_fillrect); 372 373MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); 374MODULE_DESCRIPTION("Generic software accelerated fill rectangle"); 375MODULE_LICENSE("GPL");