brintos

brintos / linux-shallow public Read only

0
0
Text · 7.4 KiB · e49221a Raw
329 lines · c
1/*2 *  Generic fillrect for frame buffers in system RAM with packed pixels of3 *  any depth.4 *5 *  Based almost entirely from cfbfillrect.c (which is based almost entirely6 *  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 Public11 *  License.  See the file COPYING in the main directory of this archive for12 *  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 accesses22     */23 24static void25bitfill_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		memset_l(dst, pat, n);54		dst += n;55 56		/* Trailing bits */57		if (last)58			*dst = comp(pat, *dst, last);59	}60}61 62 63    /*64     *  Unaligned generic pattern fill using 32/64-bit memory accesses65     *  The pattern must have been expanded to a full 32/64-bit value66     *  Left/right are the appropriate shifts to convert to the pattern to be67     *  used for the next 32/64-bit word68     */69 70static void71bitfill_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	if (!n)77		return;78 79	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);80	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));81 82	if (dst_idx+n <= bits) {83		/* Single word */84		if (last)85			first &= last;86		*dst = comp(pat, *dst, first);87	} else {88		/* Multiple destination words */89		/* Leading bits */90		if (first) {91			*dst = comp(pat, *dst, first);92			dst++;93			pat = pat << left | pat >> right;94			n -= bits - dst_idx;95		}96 97		/* Main chunk */98		n /= bits;99		while (n >= 4) {100			*dst++ = pat;101			pat = pat << left | pat >> right;102			*dst++ = pat;103			pat = pat << left | pat >> right;104			*dst++ = pat;105			pat = pat << left | pat >> right;106			*dst++ = pat;107			pat = pat << left | pat >> right;108			n -= 4;109		}110		while (n--) {111			*dst++ = pat;112			pat = pat << left | pat >> right;113		}114 115		/* Trailing bits */116		if (last)117			*dst = comp(pat, *dst, last);118	}119}120 121    /*122     *  Aligned pattern invert using 32/64-bit memory accesses123     */124static void125bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx,126		    unsigned long pat, unsigned n, int bits)127{128	unsigned long val = pat;129	unsigned long first, last;130 131	if (!n)132		return;133 134	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);135	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));136 137	if (dst_idx+n <= bits) {138		/* Single word */139		if (last)140			first &= last;141		*dst = comp(*dst ^ val, *dst, first);142	} else {143		/* Multiple destination words */144		/* Leading bits */145		if (first!=0UL) {146			*dst = comp(*dst ^ val, *dst, first);147			dst++;148			n -= bits - dst_idx;149		}150 151		/* Main chunk */152		n /= bits;153		while (n >= 8) {154			*dst++ ^= val;155			*dst++ ^= val;156			*dst++ ^= val;157			*dst++ ^= val;158			*dst++ ^= val;159			*dst++ ^= val;160			*dst++ ^= val;161			*dst++ ^= val;162			n -= 8;163		}164		while (n--)165			*dst++ ^= val;166		/* Trailing bits */167		if (last)168			*dst = comp(*dst ^ val, *dst, last);169	}170}171 172 173    /*174     *  Unaligned generic pattern invert using 32/64-bit memory accesses175     *  The pattern must have been expanded to a full 32/64-bit value176     *  Left/right are the appropriate shifts to convert to the pattern to be177     *  used for the next 32/64-bit word178     */179 180static void181bitfill_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	if (!n)188		return;189 190	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);191	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));192 193	if (dst_idx+n <= bits) {194		/* Single word */195		if (last)196			first &= last;197		*dst = comp(*dst ^ pat, *dst, first);198	} else {199		/* Multiple destination words */200 201		/* Leading bits */202		if (first != 0UL) {203			*dst = comp(*dst ^ pat, *dst, first);204			dst++;205			pat = pat << left | pat >> right;206			n -= bits - dst_idx;207		}208 209		/* Main chunk */210		n /= bits;211		while (n >= 4) {212			*dst++ ^= pat;213			pat = pat << left | pat >> right;214			*dst++ ^= pat;215			pat = pat << left | pat >> right;216			*dst++ ^= pat;217			pat = pat << left | pat >> right;218			*dst++ ^= pat;219			pat = pat << left | pat >> right;220			n -= 4;221		}222		while (n--) {223			*dst ^= pat;224			pat = pat << left | pat >> right;225		}226 227		/* Trailing bits */228		if (last)229			*dst = comp(*dst ^ pat, *dst, last);230	}231}232 233void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)234{235	unsigned long pat, pat2, fg;236	unsigned long width = rect->width, height = rect->height;237	int bits = BITS_PER_LONG, bytes = bits >> 3;238	u32 bpp = p->var.bits_per_pixel;239	unsigned long *dst;240	int dst_idx, left;241 242	if (p->state != FBINFO_STATE_RUNNING)243		return;244 245	if (!(p->flags & FBINFO_VIRTFB))246		fb_warn_once(p, "Framebuffer is not in virtual address space.");247 248	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||249	    p->fix.visual == FB_VISUAL_DIRECTCOLOR )250		fg = ((u32 *) (p->pseudo_palette))[rect->color];251	else252		fg = rect->color;253 254	pat = pixel_to_pat( bpp, fg);255 256	dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));257	dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;258	dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;259	/* FIXME For now we support 1-32 bpp only */260	left = bits % bpp;261	if (p->fbops->fb_sync)262		p->fbops->fb_sync(p);263	if (!left) {264		void (*fill_op32)(struct fb_info *p, unsigned long *dst,265				  int dst_idx, unsigned long pat, unsigned n,266				  int bits) = NULL;267 268		switch (rect->rop) {269		case ROP_XOR:270			fill_op32 = bitfill_aligned_rev;271			break;272		case ROP_COPY:273			fill_op32 = bitfill_aligned;274			break;275		default:276			printk( KERN_ERR "cfb_fillrect(): unknown rop, "277				"defaulting to ROP_COPY\n");278			fill_op32 = bitfill_aligned;279			break;280		}281		while (height--) {282			dst += dst_idx >> (ffs(bits) - 1);283			dst_idx &= (bits - 1);284			fill_op32(p, dst, dst_idx, pat, width*bpp, bits);285			dst_idx += p->fix.line_length*8;286		}287	} else {288		int right, r;289		void (*fill_op)(struct fb_info *p, unsigned long *dst,290				int dst_idx, unsigned long pat, int left,291				int right, unsigned n, int bits) = NULL;292#ifdef __LITTLE_ENDIAN293		right = left;294		left = bpp - right;295#else296		right = bpp - left;297#endif298		switch (rect->rop) {299		case ROP_XOR:300			fill_op = bitfill_unaligned_rev;301			break;302		case ROP_COPY:303			fill_op = bitfill_unaligned;304			break;305		default:306			printk(KERN_ERR "sys_fillrect(): unknown rop, "307				"defaulting to ROP_COPY\n");308			fill_op = bitfill_unaligned;309			break;310		}311		while (height--) {312			dst += dst_idx / bits;313			dst_idx &= (bits - 1);314			r = dst_idx % bpp;315			/* rotate pattern to the correct start position */316			pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));317			fill_op(p, dst, dst_idx, pat2, left, right,318				width*bpp, bits);319			dst_idx += p->fix.line_length*8;320		}321	}322}323 324EXPORT_SYMBOL(sys_fillrect);325 326MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");327MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");328MODULE_LICENSE("GPL");329