diff options
Diffstat (limited to 'fb/fbcompose.c')
-rw-r--r-- | fb/fbcompose.c | 2897 |
1 files changed, 2897 insertions, 0 deletions
diff --git a/fb/fbcompose.c b/fb/fbcompose.c new file mode 100644 index 000000000..b7733dbb5 --- /dev/null +++ b/fb/fbcompose.c @@ -0,0 +1,2897 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fbcompose.c,v 1.16 2002/11/06 22:45:35 keithp Exp $ + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "fb.h" +#include "picturestr.h" +#include "mipict.h" +#include "fbpict.h" + +/* + * General purpose compositing code optimized for minimal memory + * references + * + * All work is done on canonical ARGB values, functions for fetching + * and storing these exist for each format. + */ + +/* + * Combine src and mask using IN + */ + +CARD32 +fbCombineMaskU (FbCompositeOperand *src, + FbCompositeOperand *msk) +{ + CARD32 x; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + if (!msk) + return (*src->fetch) (src); + + a = (*msk->fetch) (msk) >> 24; + if (!a) + return 0; + + x = (*src->fetch) (src); + if (a == 0xff) + return x; + + m = FbInU(x,0,a,t); + n = FbInU(x,8,a,t); + o = FbInU(x,16,a,t); + p = FbInU(x,24,a,t); + return m|n|o|p; +} + +FbCompSrc +fbCombineMaskC (FbCompositeOperand *src, + FbCompositeOperand *msk) +{ + FbCompSrc s; + CARD32 x; + CARD32 a; + CARD16 xa; + CARD16 t; + CARD32 m,n,o,p; + + if (!msk) + { + x = (*src->fetch) (src); + s.value = x; + x = x >> 24; + x |= x << 8; + x |= x << 16; + s.alpha = x; + return s; + } + + a = (*msk->fetcha) (msk); + if (!a) + { + s.value = 0; + s.alpha = 0; + return s; + } + + x = (*src->fetch) (src); + if (a == 0xffffffff) + { + s.value = x; + x = x >> 24; + x |= x << 8; + x |= x << 16; + s.alpha = x; + return s; + } + + m = FbInC(x,0,a,t); + n = FbInC(x,8,a,t); + o = FbInC(x,16,a,t); + p = FbInC(x,24,a,t); + s.value = m|n|o|p; + xa = x >> 24; + m = FbInU(a,0,xa,t); + n = FbInU(a,8,xa,t); + o = FbInU(a,16,xa,t); + p = FbInU(a,24,xa,t); + s.alpha = m|n|o|p; + return s; +} + +CARD32 +fbCombineMaskValueC (FbCompositeOperand *src, + FbCompositeOperand *msk) +{ + CARD32 x; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + if (!msk) + { + return (*src->fetch) (src); + } + + a = (*msk->fetcha) (msk); + if (!a) + return a; + + x = (*src->fetch) (src); + if (a == 0xffffffff) + return x; + + m = FbInC(x,0,a,t); + n = FbInC(x,8,a,t); + o = FbInC(x,16,a,t); + p = FbInC(x,24,a,t); + return m|n|o|p; +} + +/* + * Combine src and mask using IN, generating only the alpha component + */ +CARD32 +fbCombineMaskAlphaU (FbCompositeOperand *src, + FbCompositeOperand *msk) +{ + CARD32 x; + CARD16 a; + CARD16 t; + + if (!msk) + return (*src->fetch) (src); + + a = (*msk->fetch) (msk) >> 24; + if (!a) + return 0; + + x = (*src->fetch) (src); + if (a == 0xff) + return x; + + return FbInU(x,24,a,t); +} + +CARD32 +fbCombineMaskAlphaC (FbCompositeOperand *src, + FbCompositeOperand *msk) +{ + CARD32 x; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + if (!msk) + return (*src->fetch) (src); + + a = (*msk->fetcha) (msk); + if (!a) + return 0; + + x = (*src->fetcha) (src); + if (a == 0xffffffff) + return x; + + m = FbInC(x,0,a,t); + n = FbInC(x,8,a,t); + o = FbInC(x,16,a,t); + p = FbInC(x,24,a,t); + return m|n|o|p; +} + +/* + * All of the composing functions + */ +void +fbCombineClear (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + (*dst->store) (dst, 0); +} + +void +fbCombineSrcU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + (*dst->store) (dst, fbCombineMaskU (src, msk)); +} + +void +fbCombineSrcC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + (*dst->store) (dst, fbCombineMaskValueC (src, msk)); +} + +void +fbCombineDst (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + /* noop */ +} + +void +fbCombineOverU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + a = ~s >> 24; + if (a != 0xff) + { + if (a) + { + d = (*dst->fetch) (dst); + m = FbOverU(s,d,0,a,t); + n = FbOverU(s,d,8,a,t); + o = FbOverU(s,d,16,a,t); + p = FbOverU(s,d,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } +} + +void +fbCombineOverC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + FbCompSrc cs; + CARD32 s, d; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + cs = fbCombineMaskC (src, msk); + s = cs.value; + a = ~cs.alpha; + if (a != 0xffffffff) + { + if (a) + { + d = (*dst->fetch) (dst); + m = FbOverC(s,d,0,a,t); + n = FbOverC(s,d,8,a,t); + o = FbOverC(s,d,16,a,t); + p = FbOverC(s,d,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } +} + +void +fbCombineOverReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = ~d >> 24; + if (a) + { + s = fbCombineMaskU (src, msk); + if (a != 0xff) + { + m = FbOverU(d,s,0,a,t); + n = FbOverU(d,s,8,a,t); + o = FbOverU(d,s,16,a,t); + p = FbOverU(d,s,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } +} + +void +fbCombineOverReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = ~d >> 24; + if (a) + { + s = fbCombineMaskValueC (src, msk); + if (a != 0xff) + { + m = FbOverU(d,s,0,a,t); + n = FbOverU(d,s,8,a,t); + o = FbOverU(d,s,16,a,t); + p = FbOverU(d,s,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } +} + +void +fbCombineInU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = d >> 24; + s = 0; + if (a) + { + s = fbCombineMaskU (src, msk); + if (a != 0xff) + { + m = FbInU(s,0,a,t); + n = FbInU(s,8,a,t); + o = FbInU(s,16,a,t); + p = FbInU(s,24,a,t); + s = m|n|o|p; + } + } + (*dst->store) (dst, s); +} + +void +fbCombineInC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = d >> 24; + s = 0; + if (a) + { + s = fbCombineMaskValueC (src, msk); + if (a != 0xff) + { + m = FbInU(s,0,a,t); + n = FbInU(s,8,a,t); + o = FbInU(s,16,a,t); + p = FbInU(s,24,a,t); + s = m|n|o|p; + } + } + (*dst->store) (dst, s); +} + +void +fbCombineInReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskAlphaU (src, msk); + a = s >> 24; + if (a != 0xff) + { + d = 0; + if (a) + { + d = (*dst->fetch) (dst); + m = FbInU(d,0,a,t); + n = FbInU(d,8,a,t); + o = FbInU(d,16,a,t); + p = FbInU(d,24,a,t); + d = m|n|o|p; + } + (*dst->store) (dst, d); + } +} + +void +fbCombineInReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskAlphaC (src, msk); + a = s; + if (a != 0xffffffff) + { + d = 0; + if (a) + { + d = (*dst->fetch) (dst); + m = FbInC(d,0,a,t); + n = FbInC(d,8,a,t); + o = FbInC(d,16,a,t); + p = FbInC(d,24,a,t); + d = m|n|o|p; + } + (*dst->store) (dst, d); + } +} + +void +fbCombineOutU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = ~d >> 24; + s = 0; + if (a) + { + s = fbCombineMaskU (src, msk); + if (a != 0xff) + { + m = FbInU(s,0,a,t); + n = FbInU(s,8,a,t); + o = FbInU(s,16,a,t); + p = FbInU(s,24,a,t); + s = m|n|o|p; + } + } + (*dst->store) (dst, s); +} + +void +fbCombineOutC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = ~d >> 24; + s = 0; + if (a) + { + s = fbCombineMaskValueC (src, msk); + if (a != 0xff) + { + m = FbInU(s,0,a,t); + n = FbInU(s,8,a,t); + o = FbInU(s,16,a,t); + p = FbInU(s,24,a,t); + s = m|n|o|p; + } + } + (*dst->store) (dst, s); +} + +void +fbCombineOutReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskAlphaU (src, msk); + a = ~s >> 24; + if (a != 0xff) + { + d = 0; + if (a) + { + d = (*dst->fetch) (dst); + m = FbInU(d,0,a,t); + n = FbInU(d,8,a,t); + o = FbInU(d,16,a,t); + p = FbInU(d,24,a,t); + d = m|n|o|p; + } + (*dst->store) (dst, d); + } +} + +void +fbCombineOutReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskAlphaC (src, msk); + a = ~s; + if (a != 0xffffffff) + { + d = 0; + if (a) + { + d = (*dst->fetch) (dst); + m = FbInC(d,0,a,t); + n = FbInC(d,8,a,t); + o = FbInC(d,16,a,t); + p = FbInC(d,24,a,t); + d = m|n|o|p; + } + (*dst->store) (dst, d); + } +} + +void +fbCombineAtopU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 ad, as; + CARD16 t,u,v; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + d = (*dst->fetch) (dst); + ad = ~s >> 24; + as = d >> 24; + m = FbGen(s,d,0,as,ad,t,u,v); + n = FbGen(s,d,8,as,ad,t,u,v); + o = FbGen(s,d,16,as,ad,t,u,v); + p = FbGen(s,d,24,as,ad,t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineAtopC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + FbCompSrc cs; + CARD32 s, d; + CARD32 ad; + CARD16 as; + CARD16 t, u, v; + CARD32 m,n,o,p; + + cs = fbCombineMaskC (src, msk); + d = (*dst->fetch) (dst); + s = cs.value; + ad = cs.alpha; + as = d >> 24; + m = FbGen(s,d,0,as,FbGet8(ad,0),t,u,v); + n = FbGen(s,d,8,as,FbGet8(ad,8),t,u,v); + o = FbGen(s,d,16,as,FbGet8(ad,16),t,u,v); + p = FbGen(s,d,24,as,FbGet8(ad,24),t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineAtopReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 ad, as; + CARD16 t, u, v; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + d = (*dst->fetch) (dst); + ad = s >> 24; + as = ~d >> 24; + m = FbGen(s,d,0,as,ad,t,u,v); + n = FbGen(s,d,8,as,ad,t,u,v); + o = FbGen(s,d,16,as,ad,t,u,v); + p = FbGen(s,d,24,as,ad,t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineAtopReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + FbCompSrc cs; + CARD32 s, d, ad; + CARD16 as; + CARD16 t, u, v; + CARD32 m,n,o,p; + + cs = fbCombineMaskC (src, msk); + d = (*dst->fetch) (dst); + s = cs.value; + ad = cs.alpha; + as = ~d >> 24; + m = FbGen(s,d,0,as,FbGet8(ad,0),t,u,v); + n = FbGen(s,d,8,as,FbGet8(ad,8),t,u,v); + o = FbGen(s,d,16,as,FbGet8(ad,16),t,u,v); + p = FbGen(s,d,24,as,FbGet8(ad,24),t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineXorU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 ad, as; + CARD16 t, u, v; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + d = (*dst->fetch) (dst); + ad = ~s >> 24; + as = ~d >> 24; + m = FbGen(s,d,0,as,ad,t,u,v); + n = FbGen(s,d,8,as,ad,t,u,v); + o = FbGen(s,d,16,as,ad,t,u,v); + p = FbGen(s,d,24,as,ad,t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineXorC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + FbCompSrc cs; + CARD32 s, d, ad; + CARD16 as; + CARD16 t, u, v; + CARD32 m,n,o,p; + + cs = fbCombineMaskC (src, msk); + d = (*dst->fetch) (dst); + s = cs.value; + ad = ~cs.alpha; + as = ~d >> 24; + m = FbGen(s,d,0,as,ad,t,u,v); + n = FbGen(s,d,8,as,ad,t,u,v); + o = FbGen(s,d,16,as,ad,t,u,v); + p = FbGen(s,d,24,as,ad,t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineAddU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + if (s == ~0) + (*dst->store) (dst, s); + else + { + d = (*dst->fetch) (dst); + if (s && d != ~0) + { + m = FbAdd(s,d,0,t); + n = FbAdd(s,d,8,t); + o = FbAdd(s,d,16,t); + p = FbAdd(s,d,24,t); + (*dst->store) (dst, m|n|o|p); + } + } +} + +void +fbCombineAddC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskValueC (src, msk); + if (s == ~0) + (*dst->store) (dst, s); + else + { + d = (*dst->fetch) (dst); + if (s && d != ~0) + { + m = FbAdd(s,d,0,t); + n = FbAdd(s,d,8,t); + o = FbAdd(s,d,16,t); + p = FbAdd(s,d,24,t); + (*dst->store) (dst, m|n|o|p); + } + } +} + +void +fbCombineSaturateU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s = fbCombineMaskU (src, msk), d; +#if 0 + CARD16 sa, da; + CARD16 ad, as; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + sa = s >> 24; + da = ~d >> 24; + if (sa <= da) + { + m = FbAdd(s,d,0,t); + n = FbAdd(s,d,8,t); + o = FbAdd(s,d,16,t); + p = FbAdd(s,d,24,t); + } + else + { + as = (da << 8) / sa; + ad = 0xff; + m = FbGen(s,d,0,as,ad,t,u,v); + n = FbGen(s,d,8,as,ad,t,u,v); + o = FbGen(s,d,16,as,ad,t,u,v); + p = FbGen(s,d,24,as,ad,t,u,v); + } + (*dst->store) (dst, m|n|o|p); +#else + if ((s >> 24) == 0xff) + (*dst->store) (dst, s); + else + { + d = (*dst->fetch) (dst); + if ((s >> 24) > (d >> 24)) + (*dst->store) (dst, s); + } +#endif +} + +void +fbCombineSaturateC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + FbCompSrc cs; + CARD32 s, d; + CARD16 sa, sr, sg, sb, da; + CARD16 t, u, v; + CARD32 m,n,o,p; + + cs = fbCombineMaskC (src, msk); + d = (*dst->fetch) (dst); + s = cs.value; + sa = (cs.alpha >> 24) & 0xff; + sr = (cs.alpha >> 16) & 0xff; + sg = (cs.alpha >> 8) & 0xff; + sb = (cs.alpha ) & 0xff; + da = ~d >> 24; + + if (sb <= da) + m = FbAdd(s,d,0,t); + else + m = FbGen (s, d, 0, (da << 8) / sb, 0xff, t, u, v); + + if (sg <= da) + n = FbAdd(s,d,8,t); + else + n = FbGen (s, d, 8, (da << 8) / sg, 0xff, t, u, v); + + if (sr < da) + o = FbAdd(s,d,16,t); + else + o = FbGen (s, d, 16, (da << 8) / sr, 0xff, t, u, v); + + if (sa <= da) + p = FbAdd(s,d,24,t); + else + p = FbGen (s, d, 24, (da << 8) / sa, 0xff, t, u, v); + + (*dst->store) (dst, m|n|o|p); +} + +/* + * All of the disjoint composing functions + + The four entries in the first column indicate what source contributions + come from each of the four areas of the picture -- areas covered by neither + A nor B, areas covered only by A, areas covered only by B and finally + areas covered by both A and B. + + Disjoint Conjoint + Fa Fb Fa Fb +(0,0,0,0) 0 0 0 0 +(0,A,0,A) 1 0 1 0 +(0,0,B,B) 0 1 0 1 +(0,A,B,A) 1 min((1-a)/b,1) 1 max(1-a/b,0) +(0,A,B,B) min((1-b)/a,1) 1 max(1-b/a,0) 1 +(0,0,0,A) max(1-(1-b)/a,0) 0 min(1,b/a) 0 +(0,0,0,B) 0 max(1-(1-a)/b,0) 0 min(a/b,1) +(0,A,0,0) min(1,(1-b)/a) 0 max(1-b/a,0) 0 +(0,0,B,0) 0 min(1,(1-a)/b) 0 max(1-a/b,0) +(0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0) +(0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b) +(0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0) + + */ + +#define CombineAOut 1 +#define CombineAIn 2 +#define CombineBOut 4 +#define CombineBIn 8 + +#define CombineClear 0 +#define CombineA (CombineAOut|CombineAIn) +#define CombineB (CombineBOut|CombineBIn) +#define CombineAOver (CombineAOut|CombineBOut|CombineAIn) +#define CombineBOver (CombineAOut|CombineBOut|CombineBIn) +#define CombineAAtop (CombineBOut|CombineAIn) +#define CombineBAtop (CombineAOut|CombineBIn) +#define CombineXor (CombineAOut|CombineBOut) + +/* portion covered by a but not b */ +CARD8 +fbCombineDisjointOutPart (CARD8 a, CARD8 b) +{ + /* min (1, (1-b) / a) */ + + b = ~b; /* 1 - b */ + if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ + return 0xff; /* 1 */ + return FbIntDiv(b,a); /* (1-b) / a */ +} + +/* portion covered by both a and b */ +CARD8 +fbCombineDisjointInPart (CARD8 a, CARD8 b) +{ + /* max (1-(1-b)/a,0) */ + /* = - min ((1-b)/a - 1, 0) */ + /* = 1 - min (1, (1-b)/a) */ + + b = ~b; /* 1 - b */ + if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ + return 0; /* 1 - 1 */ + return ~FbIntDiv(b,a); /* 1 - (1-b) / a */ +} + +void +fbCombineDisjointGeneralU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine) +{ + CARD32 s, d; + CARD32 m,n,o,p; + CARD16 Fa, Fb, t, u, v; + CARD8 sa, da; + + s = fbCombineMaskU (src, msk); + sa = s >> 24; + + d = (*dst->fetch) (dst); + da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + Fa = fbCombineDisjointOutPart (sa, da); + break; + case CombineAIn: + Fa = fbCombineDisjointInPart (sa, da); + break; + case CombineA: + Fa = 0xff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + Fb = fbCombineDisjointOutPart (da, sa); + break; + case CombineBIn: + Fb = fbCombineDisjointInPart (da, sa); + break; + case CombineB: + Fb = 0xff; + break; + } + m = FbGen (s,d,0,Fa,Fb,t,u,v); + n = FbGen (s,d,8,Fa,Fb,t,u,v); + o = FbGen (s,d,16,Fa,Fb,t,u,v); + p = FbGen (s,d,24,Fa,Fb,t,u,v); + s = m|n|o|p; + (*dst->store) (dst, s); +} + +void +fbCombineDisjointGeneralC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine) +{ + FbCompSrc cs; + CARD32 s, d; + CARD32 m,n,o,p; + CARD32 Fa; + CARD16 Fb, t, u, v; + CARD32 sa; + CARD8 da; + + cs = fbCombineMaskC (src, msk); + s = cs.value; + sa = cs.alpha; + + d = (*dst->fetch) (dst); + da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + m = fbCombineDisjointOutPart ((CARD8) (sa >> 0), da); + n = fbCombineDisjointOutPart ((CARD8) (sa >> 8), da) << 8; + o = fbCombineDisjointOutPart ((CARD8) (sa >> 16), da) << 16; + p = fbCombineDisjointOutPart ((CARD8) (sa >> 24), da) << 24; + Fa = m|n|o|p; + break; + case CombineAIn: + m = fbCombineDisjointOutPart ((CARD8) (sa >> 0), da); + n = fbCombineDisjointOutPart ((CARD8) (sa >> 8), da) << 8; + o = fbCombineDisjointOutPart ((CARD8) (sa >> 16), da) << 16; + p = fbCombineDisjointOutPart ((CARD8) (sa >> 24), da) << 24; + Fa = m|n|o|p; + break; + case CombineA: + Fa = 0xffffffff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + Fb = fbCombineDisjointOutPart (da, sa); + break; + case CombineBIn: + Fb = fbCombineDisjointInPart (da, sa); + break; + case CombineB: + Fb = 0xff; + break; + } + m = FbGen (s,d,0,FbGet8(Fa,0),Fb,t,u,v); + n = FbGen (s,d,8,FbGet8(Fa,8),Fb,t,u,v); + o = FbGen (s,d,16,FbGet8(Fa,16),Fb,t,u,v); + p = FbGen (s,d,24,FbGet8(Fa,24),Fb,t,u,v); + s = m|n|o|p; + (*dst->store) (dst, s); +} + +void +fbCombineDisjointOverU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + a = s >> 24; + if (a != 0x00) + { + if (a != 0xff) + { + d = (*dst->fetch) (dst); + a = fbCombineDisjointOutPart (d >> 24, a); + m = FbOverU(s,d,0,a,t); + n = FbOverU(s,d,8,a,t); + o = FbOverU(s,d,16,a,t); + p = FbOverU(s,d,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } +} + +void +fbCombineDisjointOverC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineAOver); +} + +void +fbCombineDisjointOverReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineBOver); +} + +void +fbCombineDisjointOverReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineBOver); +} + +void +fbCombineDisjointInU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineAIn); +} + +void +fbCombineDisjointInC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineAIn); +} + +void +fbCombineDisjointInReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineBIn); +} + +void +fbCombineDisjointInReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineBIn); +} + +void +fbCombineDisjointOutU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineAOut); +} + +void +fbCombineDisjointOutC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineAOut); +} + +void +fbCombineDisjointOutReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineBOut); +} + +void +fbCombineDisjointOutReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineBOut); +} + +void +fbCombineDisjointAtopU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineAAtop); +} + +void +fbCombineDisjointAtopC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineAAtop); +} + +void +fbCombineDisjointAtopReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineBAtop); +} + +void +fbCombineDisjointAtopReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineBAtop); +} + +void +fbCombineDisjointXorU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineXor); +} + +void +fbCombineDisjointXorC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineXor); +} + +/* portion covered by a but not b */ +CARD8 +fbCombineConjointOutPart (CARD8 a, CARD8 b) +{ + /* max (1-b/a,0) */ + /* = 1-min(b/a,1) */ + + /* min (1, (1-b) / a) */ + + if (b >= a) /* b >= a -> b/a >= 1 */ + return 0x00; /* 0 */ + return ~FbIntDiv(b,a); /* 1 - b/a */ +} + +/* portion covered by both a and b */ +CARD8 +fbCombineConjointInPart (CARD8 a, CARD8 b) +{ + /* min (1,b/a) */ + + if (b >= a) /* b >= a -> b/a >= 1 */ + return 0xff; /* 1 */ + return FbIntDiv(b,a); /* b/a */ +} + +void +fbCombineConjointGeneralU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine) +{ + CARD32 s, d; + CARD32 m,n,o,p; + CARD16 Fa, Fb, t, u, v; + CARD8 sa, da; + + s = fbCombineMaskU (src, msk); + sa = s >> 24; + + d = (*dst->fetch) (dst); + da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + Fa = fbCombineConjointOutPart (sa, da); + break; + case CombineAIn: + Fa = fbCombineConjointInPart (sa, da); + break; + case CombineA: + Fa = 0xff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + Fb = fbCombineConjointOutPart (da, sa); + break; + case CombineBIn: + Fb = fbCombineConjointInPart (da, sa); + break; + case CombineB: + Fb = 0xff; + break; + } + m = FbGen (s,d,0,Fa,Fb,t,u,v); + n = FbGen (s,d,8,Fa,Fb,t,u,v); + o = FbGen (s,d,16,Fa,Fb,t,u,v); + p = FbGen (s,d,24,Fa,Fb,t,u,v); + s = m|n|o|p; + (*dst->store) (dst, s); +} + +void +fbCombineConjointGeneralC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine) +{ + FbCompSrc cs; + CARD32 s, d; + CARD32 m,n,o,p; + CARD32 Fa; + CARD16 Fb, t, u, v; + CARD32 sa; + CARD8 da; + + cs = fbCombineMaskC (src, msk); + s = cs.value; + sa = cs.alpha; + + d = (*dst->fetch) (dst); + da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + m = fbCombineConjointOutPart ((CARD8) (sa >> 0), da); + n = fbCombineConjointOutPart ((CARD8) (sa >> 8), da) << 8; + o = fbCombineConjointOutPart ((CARD8) (sa >> 16), da) << 16; + p = fbCombineConjointOutPart ((CARD8) (sa >> 24), da) << 24; + Fa = m|n|o|p; + break; + case CombineAIn: + m = fbCombineConjointOutPart ((CARD8) (sa >> 0), da); + n = fbCombineConjointOutPart ((CARD8) (sa >> 8), da) << 8; + o = fbCombineConjointOutPart ((CARD8) (sa >> 16), da) << 16; + p = fbCombineConjointOutPart ((CARD8) (sa >> 24), da) << 24; + Fa = m|n|o|p; + break; + case CombineA: + Fa = 0xffffffff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + Fb = fbCombineConjointOutPart (da, sa); + break; + case CombineBIn: + Fb = fbCombineConjointInPart (da, sa); + break; + case CombineB: + Fb = 0xff; + break; + } + m = FbGen (s,d,0,FbGet8(Fa,0),Fb,t,u,v); + n = FbGen (s,d,8,FbGet8(Fa,8),Fb,t,u,v); + o = FbGen (s,d,16,FbGet8(Fa,16),Fb,t,u,v); + p = FbGen (s,d,24,FbGet8(Fa,24),Fb,t,u,v); + s = m|n|o|p; + (*dst->store) (dst, s); +} + +void +fbCombineConjointOverU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineAOver); +/* + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + a = s >> 24; + if (a != 0x00) + { + if (a != 0xff) + { + d = (*dst->fetch) (dst); + a = fbCombineConjointOutPart (d >> 24, a); + m = FbOverU(s,d,0,a,t); + n = FbOverU(s,d,8,a,t); + o = FbOverU(s,d,16,a,t); + p = FbOverU(s,d,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } + */ +} + +void +fbCombineConjointOverC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineAOver); +} + +void +fbCombineConjointOverReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineBOver); +} + +void +fbCombineConjointOverReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineBOver); +} + +void +fbCombineConjointInU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineAIn); +} + +void +fbCombineConjointInC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineAIn); +} + +void +fbCombineConjointInReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineBIn); +} + +void +fbCombineConjointInReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineBIn); +} + +void +fbCombineConjointOutU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineAOut); +} + +void +fbCombineConjointOutC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineAOut); +} + +void +fbCombineConjointOutReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineBOut); +} + +void +fbCombineConjointOutReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineBOut); +} + +void +fbCombineConjointAtopU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineAAtop); +} + +void +fbCombineConjointAtopC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineAAtop); +} + +void +fbCombineConjointAtopReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineBAtop); +} + +void +fbCombineConjointAtopReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineBAtop); +} + +void +fbCombineConjointXorU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineXor); +} + +void +fbCombineConjointXorC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineXor); +} + +FbCombineFunc fbCombineFuncU[] = { + fbCombineClear, + fbCombineSrcU, + fbCombineDst, + fbCombineOverU, + fbCombineOverReverseU, + fbCombineInU, + fbCombineInReverseU, + fbCombineOutU, + fbCombineOutReverseU, + fbCombineAtopU, + fbCombineAtopReverseU, + fbCombineXorU, + fbCombineAddU, + fbCombineDisjointOverU, /* Saturate */ + 0, + 0, + fbCombineClear, + fbCombineSrcU, + fbCombineDst, + fbCombineDisjointOverU, + fbCombineDisjointOverReverseU, + fbCombineDisjointInU, + fbCombineDisjointInReverseU, + fbCombineDisjointOutU, + fbCombineDisjointOutReverseU, + fbCombineDisjointAtopU, + fbCombineDisjointAtopReverseU, + fbCombineDisjointXorU, + 0, + 0, + 0, + 0, + fbCombineClear, + fbCombineSrcU, + fbCombineDst, + fbCombineConjointOverU, + fbCombineConjointOverReverseU, + fbCombineConjointInU, + fbCombineConjointInReverseU, + fbCombineConjointOutU, + fbCombineConjointOutReverseU, + fbCombineConjointAtopU, + fbCombineConjointAtopReverseU, + fbCombineConjointXorU, +}; + +FbCombineFunc fbCombineFuncC[] = { + fbCombineClear, + fbCombineSrcC, + fbCombineDst, + fbCombineOverC, + fbCombineOverReverseC, + fbCombineInC, + fbCombineInReverseC, + fbCombineOutC, + fbCombineOutReverseC, + fbCombineAtopC, + fbCombineAtopReverseC, + fbCombineXorC, + fbCombineAddC, + fbCombineDisjointOverC, /* Saturate */ + 0, + 0, + fbCombineClear, /* 0x10 */ + fbCombineSrcC, + fbCombineDst, + fbCombineDisjointOverC, + fbCombineDisjointOverReverseC, + fbCombineDisjointInC, + fbCombineDisjointInReverseC, + fbCombineDisjointOutC, + fbCombineDisjointOutReverseC, + fbCombineDisjointAtopC, + fbCombineDisjointAtopReverseC, + fbCombineDisjointXorC, /* 0x1b */ + 0, + 0, + 0, + 0, + fbCombineClear, + fbCombineSrcC, + fbCombineDst, + fbCombineConjointOverC, + fbCombineConjointOverReverseC, + fbCombineConjointInC, + fbCombineConjointInReverseC, + fbCombineConjointOutC, + fbCombineConjointOutReverseC, + fbCombineConjointAtopC, + fbCombineConjointAtopReverseC, + fbCombineConjointXorC, +}; + +/* + * All of the fetch functions + */ + +CARD32 +fbFetch_a8r8g8b8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + return ((CARD32 *)line)[offset >> 5]; +} + +CARD32 +fbFetch_x8r8g8b8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + return ((CARD32 *)line)[offset >> 5] | 0xff000000; +} + +CARD32 +fbFetch_a8b8g8r8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + + return ((pixel & 0xff000000) | + ((pixel >> 16) & 0xff) | + (pixel & 0x0000ff00) | + ((pixel & 0xff) << 16)); +} + +CARD32 +fbFetch_x8b8g8r8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + + return ((0xff000000) | + ((pixel >> 16) & 0xff) | + (pixel & 0x0000ff00) | + ((pixel & 0xff) << 16)); +} + +CARD32 +fbFetch_r8g8b8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); +#if IMAGE_BYTE_ORDER == MSBFirst + return (0xff000000 | + (pixel[0] << 16) | + (pixel[1] << 8) | + (pixel[2])); +#else + return (0xff000000 | + (pixel[2] << 16) | + (pixel[1] << 8) | + (pixel[0])); +#endif +} + +CARD32 +fbFetch_b8g8r8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); +#if IMAGE_BYTE_ORDER == MSBFirst + return (0xff000000 | + (pixel[2] << 16) | + (pixel[1] << 8) | + (pixel[0])); +#else + return (0xff000000 | + (pixel[0] << 16) | + (pixel[1] << 8) | + (pixel[2])); +#endif +} + +CARD32 +fbFetch_r5g6b5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + r = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) << 8; + g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_b5g6r5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + b = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) >> 8; + g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a1r5g5b5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 a,r,g,b; + + a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24; + r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + return (a | r | g | b); +} + +CARD32 +fbFetch_x1r5g5b5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a1b5g5r5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 a,r,g,b; + + a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24; + b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + return (a | r | g | b); +} + +CARD32 +fbFetch_x1b5g5r5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a4r4g4b4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 a,r,g,b; + + a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16; + r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + return (a | r | g | b); +} + +CARD32 +fbFetch_x4r4g4b4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a4b4g4r4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 a,r,g,b; + + a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16; + b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + return (a | r | g | b); +} + +CARD32 +fbFetch_x4b4g4r4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + + return pixel << 24; +} + +CARD32 +fbFetcha_a8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + + pixel |= pixel << 8; + pixel |= pixel << 16; + return pixel; +} + +CARD32 +fbFetch_r3g3b2 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + CARD32 r,g,b; + + r = ((pixel & 0xe0) | ((pixel & 0xe0) >> 3) | ((pixel & 0xc0) >> 6)) << 16; + g = ((pixel & 0x1c) | ((pixel & 0x18) >> 3) | ((pixel & 0x1c) << 3)) << 8; + b = (((pixel & 0x03) ) | + ((pixel & 0x03) << 2) | + ((pixel & 0x03) << 4) | + ((pixel & 0x03) << 6)); + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_b2g3r3 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + CARD32 r,g,b; + + b = (((pixel & 0xc0) ) | + ((pixel & 0xc0) >> 2) | + ((pixel & 0xc0) >> 4) | + ((pixel & 0xc0) >> 6)); + g = ((pixel & 0x38) | ((pixel & 0x38) >> 3) | ((pixel & 0x30) << 2)) << 8; + r = (((pixel & 0x07) ) | + ((pixel & 0x07) << 3) | + ((pixel & 0x06) << 6)) << 16; + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a2r2g2b2 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + CARD32 a,r,g,b; + + a = ((pixel & 0xc0) * 0x55) << 18; + r = ((pixel & 0x30) * 0x55) << 12; + g = ((pixel & 0x0c) * 0x55) << 6; + b = ((pixel & 0x03) * 0x55); + return a|r|g|b; +} + +CARD32 +fbFetch_a2b2g2r2 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + CARD32 a,r,g,b; + + a = ((pixel & 0xc0) * 0x55) << 18; + b = ((pixel & 0x30) * 0x55) >> 6; + g = ((pixel & 0x0c) * 0x55) << 6; + r = ((pixel & 0x03) * 0x55) << 16; + return a|r|g|b; +} + +CARD32 +fbFetch_c8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + + return op->indexed->rgba[pixel]; +} + +#define Fetch8(l,o) (((CARD8 *) (l))[(o) >> 3]) +#if IMAGE_BYTE_ORDER == MSBFirst +#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) & 0xf : Fetch8(l,o) >> 4) +#else +#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) >> 4 : Fetch8(l,o) & 0xf) +#endif + +CARD32 +fbFetch_a4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + + pixel |= pixel << 4; + return pixel << 24; +} + +CARD32 +fbFetcha_a4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + + pixel |= pixel << 4; + pixel |= pixel << 8; + pixel |= pixel << 16; + return pixel; +} + +CARD32 +fbFetch_r1g2b1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + CARD32 r,g,b; + + r = ((pixel & 0x8) * 0xff) << 13; + g = ((pixel & 0x6) * 0x55) << 7; + b = ((pixel & 0x1) * 0xff); + return 0xff000000|r|g|b; +} + +CARD32 +fbFetch_b1g2r1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + CARD32 r,g,b; + + b = ((pixel & 0x8) * 0xff) >> 3; + g = ((pixel & 0x6) * 0x55) << 7; + r = ((pixel & 0x1) * 0xff) << 16; + return 0xff000000|r|g|b; +} + +CARD32 +fbFetch_a1r1g1b1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + CARD32 a,r,g,b; + + a = ((pixel & 0x8) * 0xff) << 21; + r = ((pixel & 0x4) * 0xff) << 14; + g = ((pixel & 0x2) * 0xff) << 7; + b = ((pixel & 0x1) * 0xff); + return a|r|g|b; +} + +CARD32 +fbFetch_a1b1g1r1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + CARD32 a,r,g,b; + + a = ((pixel & 0x8) * 0xff) << 21; + r = ((pixel & 0x4) * 0xff) >> 3; + g = ((pixel & 0x2) * 0xff) << 7; + b = ((pixel & 0x1) * 0xff) << 16; + return a|r|g|b; +} + +CARD32 +fbFetch_c4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + + return op->indexed->rgba[pixel]; +} + +CARD32 +fbFetcha_a1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + CARD32 a; +#if BITMAP_BIT_ORDER == MSBFirst + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + a |= a << 1; + a |= a << 2; + a |= a << 4; + a |= a << 8; + a |= a << 16; + return a; +} + +CARD32 +fbFetch_a1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + CARD32 a; +#if BITMAP_BIT_ORDER == MSBFirst + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + a |= a << 1; + a |= a << 2; + a |= a << 4; + return a << 24; +} + +CARD32 +fbFetch_g1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + CARD32 a; +#if BITMAP_BIT_ORDER == MSBFirst + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + return op->indexed->rgba[a]; +} + +/* + * All the store functions + */ + +#define Splita(v) CARD32 a = ((v) >> 24), r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff +#define Split(v) CARD32 r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff + +void +fbStore_a8r8g8b8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + ((CARD32 *)line)[offset >> 5] = value; +} + +void +fbStore_x8r8g8b8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + ((CARD32 *)line)[offset >> 5] = value & 0xffffff; +} + +void +fbStore_a8b8g8r8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + Splita(value); + ((CARD32 *)line)[offset >> 5] = a << 24 | b << 16 | g << 8 | r; +} + +void +fbStore_x8b8g8r8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + Split(value); + ((CARD32 *)line)[offset >> 5] = b << 16 | g << 8 | r; +} + +void +fbStore_r8g8b8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + Split(value); +#if IMAGE_BYTE_ORDER == MSBFirst + pixel[0] = r; + pixel[1] = g; + pixel[2] = b; +#else + pixel[0] = b; + pixel[1] = g; + pixel[2] = r; +#endif +} + +void +fbStore_b8g8r8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + Split(value); +#if IMAGE_BYTE_ORDER == MSBFirst + pixel[0] = b; + pixel[1] = g; + pixel[2] = r; +#else + pixel[0] = r; + pixel[1] = g; + pixel[2] = b; +#endif +} + +void +fbStore_r5g6b5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((r << 8) & 0xf800) | + ((g << 3) & 0x07e0) | + ((b >> 3) )); +} + +void +fbStore_b5g6r5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((b << 8) & 0xf800) | + ((g << 3) & 0x07e0) | + ((r >> 3) )); +} + +void +fbStore_a1r5g5b5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Splita(value); + *pixel = (((a << 8) & 0x8000) | + ((r << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((b >> 3) )); +} + +void +fbStore_x1r5g5b5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((r << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((b >> 3) )); +} + +void +fbStore_a1b5g5r5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Splita(value); + *pixel = (((a << 8) & 0x8000) | + ((b << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((r >> 3) )); +} + +void +fbStore_x1b5g5r5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((b << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((r >> 3) )); +} + +void +fbStore_a4r4g4b4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Splita(value); + *pixel = (((a << 8) & 0xf000) | + ((r << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((b >> 4) )); +} + +void +fbStore_x4r4g4b4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((r << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((b >> 4) )); +} + +void +fbStore_a4b4g4r4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Splita(value); + *pixel = (((a << 8) & 0xf000) | + ((b << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((r >> 4) )); +} + +void +fbStore_x4b4g4r4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((b << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((r >> 4) )); +} + +void +fbStore_a8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + *pixel = value >> 24; +} + +void +fbStore_r3g3b2 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + Split(value); + *pixel = (((r ) & 0xe0) | + ((g >> 3) & 0x1c) | + ((b >> 6) )); +} + +void +fbStore_b2g3r3 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + Split(value); + *pixel = (((b ) & 0xe0) | + ((g >> 3) & 0x1c) | + ((r >> 6) )); +} + +void +fbStore_a2r2g2b2 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + Splita(value); + *pixel = (((a ) & 0xc0) | + ((r >> 2) & 0x30) | + ((g >> 4) & 0x0c) | + ((b >> 6) )); +} + +void +fbStore_c8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + *pixel = miIndexToEnt24(op->indexed,value); +} + +void +fbStore_g8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + *pixel = miIndexToEntY24(op->indexed,value); +} + +#define Store8(l,o,v) (((CARD8 *) l)[(o) >> 3] = (v)) +#if IMAGE_BYTE_ORDER == MSBFirst +#define Store4(l,o,v) Store8(l,o,((o) & 4 ? \ + (Fetch8(l,o) & 0xf0) | (v) : \ + (Fetch8(l,o) & 0x0f) | ((v) << 4))) +#else +#define Store4(l,o,v) Store8(l,o,((o) & 4 ? \ + (Fetch8(l,o) & 0x0f) | ((v) << 4) : \ + (Fetch8(l,o) & 0xf0) | (v))) +#endif + +void +fbStore_a4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + Store4(line,offset,value>>28); +} + +void +fbStore_r1g2b1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + + Split(value); + pixel = (((r >> 4) & 0x8) | + ((g >> 5) & 0x6) | + ((b >> 7) )); + Store4(line,offset,pixel); +} + +void +fbStore_b1g2r1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + + Split(value); + pixel = (((b >> 4) & 0x8) | + ((g >> 5) & 0x6) | + ((r >> 7) )); + Store4(line,offset,pixel); +} + +void +fbStore_a1r1g1b1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + Splita(value); + pixel = (((a >> 4) & 0x8) | + ((r >> 5) & 0x4) | + ((g >> 6) & 0x2) | + ((b >> 7) )); + Store4(line,offset,pixel); +} + +void +fbStore_a1b1g1r1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + Splita(value); + pixel = (((a >> 4) & 0x8) | + ((b >> 5) & 0x4) | + ((g >> 6) & 0x2) | + ((r >> 7) )); + Store4(line,offset,pixel); +} + +void +fbStore_c4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + + pixel = miIndexToEnt24(op->indexed,value); + Store4(line,offset,pixel); +} + +void +fbStore_g4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + + pixel = miIndexToEntY24(op->indexed,value); + Store4(line,offset,pixel); +} + +void +fbStore_a1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 *pixel = ((CARD32 *) line) + (offset >> 5); + CARD32 mask = FbStipMask(offset & 0x1f, 1); + + value = value & 0x80000000 ? mask : 0; + *pixel = (*pixel & ~mask) | value; +} + +void +fbStore_g1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 *pixel = ((CARD32 *) line) + (offset >> 5); + CARD32 mask = FbStipMask(offset & 0x1f, 1); + + value = miIndexToEntY24(op->indexed,value) ? mask : 0; + *pixel = (*pixel & ~mask) | value; +} + +CARD32 +fbFetch_external (FbCompositeOperand *op) +{ + CARD32 rgb = (*op[1].fetch) (&op[1]); + CARD32 a = (*op[2].fetch) (&op[2]); + + return (rgb & 0xffffff) | (a & 0xff000000); +} + + +CARD32 +fbFetcha_external (FbCompositeOperand *op) +{ + return (*op[2].fetch) (&op[2]); +} + +void +fbStore_external (FbCompositeOperand *op, CARD32 value) +{ + (*op[1].store) (&op[1], value | 0xff000000); + (*op[2].store) (&op[2], value & 0xff000000); +} + +CARD32 +fbFetch_transform (FbCompositeOperand *op) +{ + PictVector v; + int x, y; + int minx, maxx, miny, maxy; + int n; + BoxRec box; + CARD32 rtot, gtot, btot, atot; + CARD32 xerr, yerr; + CARD32 bits; + + v.vector[0] = IntToxFixed(op->u.transform.x); + v.vector[1] = IntToxFixed(op->u.transform.y); + v.vector[2] = xFixed1; + if (!PictureTransformPoint (op->u.transform.transform, &v)) + return 0; + switch (op->u.transform.filter) { + case PictFilterNearest: + y = xFixedToInt (v.vector[1]) + op->u.transform.top_y; + x = xFixedToInt (v.vector[0]) + op->u.transform.left_x; + if (POINT_IN_REGION (0, op->clip, x, y, &box)) + { + (*op[1].set) (&op[1], x, y); + bits = (*op[1].fetch) (&op[1]); + } + else + bits = 0; + break; + case PictFilterBilinear: + rtot = gtot = btot = atot = 0; + miny = xFixedToInt (v.vector[1]) + op->u.transform.top_y; + maxy = xFixedToInt (xFixedCeil (v.vector[1])) + op->u.transform.top_y; + + minx = xFixedToInt (v.vector[0]) + op->u.transform.left_x; + maxx = xFixedToInt (xFixedCeil (v.vector[0])) + op->u.transform.left_x; + + yerr = xFixed1 - xFixedFrac (v.vector[1]); + for (y = miny; y <= maxy; y++) + { + CARD32 lrtot = 0, lgtot = 0, lbtot = 0, latot = 0; + + xerr = xFixed1 - xFixedFrac (v.vector[0]); + for (x = minx; x <= maxx; x++) + { + if (POINT_IN_REGION (0, op->clip, x, y, &box)) + { + (*op[1].set) (&op[1], x, y); + bits = (*op[1].fetch) (&op[1]); + { + Splita(bits); + lrtot += r * xerr; + lgtot += g * xerr; + lbtot += b * xerr; + latot += a * xerr; + n++; + } + } + xerr = xFixed1 - xerr; + } + rtot += (lrtot >> 10) * yerr; + gtot += (lgtot >> 10) * yerr; + btot += (lbtot >> 10) * yerr; + atot += (latot >> 10) * yerr; + yerr = xFixed1 - yerr; + } + if ((atot >>= 22) > 0xff) atot = 0xff; + if ((rtot >>= 22) > 0xff) rtot = 0xff; + if ((gtot >>= 22) > 0xff) gtot = 0xff; + if ((btot >>= 22) > 0xff) btot = 0xff; + bits = ((atot << 24) | + (rtot << 16) | + (gtot << 8) | + (btot )); + break; + default: + bits = 0; + break; + } + return bits; +} + +CARD32 +fbFetcha_transform (FbCompositeOperand *op) +{ + PictVector v; + int x, y; + int minx, maxx, miny, maxy; + int n; + BoxRec box; + CARD32 rtot, gtot, btot, atot; + CARD32 xerr, yerr; + CARD32 bits; + + v.vector[0] = IntToxFixed(op->u.transform.x); + v.vector[1] = IntToxFixed(op->u.transform.y); + v.vector[2] = xFixed1; + if (!PictureTransformPoint (op->u.transform.transform, &v)) + return 0; + switch (op->u.transform.filter) { + case PictFilterNearest: + y = xFixedToInt (v.vector[1]) + op->u.transform.left_x; + x = xFixedToInt (v.vector[0]) + op->u.transform.top_y; + if (POINT_IN_REGION (0, op->clip, x, y, &box)) + { + (*op[1].set) (&op[1], x, y); + bits = (*op[1].fetcha) (&op[1]); + } + else + bits = 0; + break; + case PictFilterBilinear: + rtot = gtot = btot = atot = 0; + + miny = xFixedToInt (v.vector[1]) + op->u.transform.top_y; + maxy = xFixedToInt (xFixedCeil (v.vector[1])) + op->u.transform.top_y; + + minx = xFixedToInt (v.vector[0]) + op->u.transform.left_x; + maxx = xFixedToInt (xFixedCeil (v.vector[0])) + op->u.transform.left_x; + + yerr = xFixed1 - xFixedFrac (v.vector[1]); + for (y = miny; y <= maxy; y++) + { + CARD32 lrtot = 0, lgtot = 0, lbtot = 0, latot = 0; + xerr = xFixed1 - xFixedFrac (v.vector[0]); + for (x = minx; x <= maxx; x++) + { + if (POINT_IN_REGION (0, op->clip, x, y, &box)) + { + (*op[1].set) (&op[1], x, y); + bits = (*op[1].fetcha) (&op[1]); + { + Splita(bits); + lrtot += r * xerr; + lgtot += g * xerr; + lbtot += b * xerr; + latot += a * xerr; + n++; + } + } + x++; + xerr = xFixed1 - xerr; + } + rtot += (lrtot >> 10) * yerr; + gtot += (lgtot >> 10) * yerr; + btot += (lbtot >> 10) * yerr; + atot += (latot >> 10) * yerr; + y++; + yerr = xFixed1 - yerr; + } + if ((atot >>= 22) > 0xff) atot = 0xff; + if ((rtot >>= 22) > 0xff) rtot = 0xff; + if ((gtot >>= 22) > 0xff) gtot = 0xff; + if ((btot >>= 22) > 0xff) btot = 0xff; + bits = ((atot << 24) | + (rtot << 16) | + (gtot << 8) | + (btot )); + break; + default: + bits = 0; + break; + } + return bits; +} + +FbAccessMap fbAccessMap[] = { + /* 32bpp formats */ + { PICT_a8r8g8b8, fbFetch_a8r8g8b8, fbFetch_a8r8g8b8, fbStore_a8r8g8b8 }, + { PICT_x8r8g8b8, fbFetch_x8r8g8b8, fbFetch_x8r8g8b8, fbStore_x8r8g8b8 }, + { PICT_a8b8g8r8, fbFetch_a8b8g8r8, fbFetch_a8b8g8r8, fbStore_a8b8g8r8 }, + { PICT_x8b8g8r8, fbFetch_x8b8g8r8, fbFetch_x8b8g8r8, fbStore_x8b8g8r8 }, + + /* 24bpp formats */ + { PICT_r8g8b8, fbFetch_r8g8b8, fbFetch_r8g8b8, fbStore_r8g8b8 }, + { PICT_b8g8r8, fbFetch_b8g8r8, fbFetch_b8g8r8, fbStore_b8g8r8 }, + + /* 16bpp formats */ + { PICT_r5g6b5, fbFetch_r5g6b5, fbFetch_r5g6b5, fbStore_r5g6b5 }, + { PICT_b5g6r5, fbFetch_b5g6r5, fbFetch_b5g6r5, fbStore_b5g6r5 }, + + { PICT_a1r5g5b5, fbFetch_a1r5g5b5, fbFetch_a1r5g5b5, fbStore_a1r5g5b5 }, + { PICT_x1r5g5b5, fbFetch_x1r5g5b5, fbFetch_x1r5g5b5, fbStore_x1r5g5b5 }, + { PICT_a1b5g5r5, fbFetch_a1b5g5r5, fbFetch_a1b5g5r5, fbStore_a1b5g5r5 }, + { PICT_x1b5g5r5, fbFetch_x1b5g5r5, fbFetch_x1b5g5r5, fbStore_x1b5g5r5 }, + { PICT_a4r4g4b4, fbFetch_a4r4g4b4, fbFetch_a4r4g4b4, fbStore_a4r4g4b4 }, + { PICT_x4r4g4b4, fbFetch_x4r4g4b4, fbFetch_x4r4g4b4, fbStore_x4r4g4b4 }, + { PICT_a4b4g4r4, fbFetch_a4b4g4r4, fbFetch_a4b4g4r4, fbStore_a4b4g4r4 }, + { PICT_x4b4g4r4, fbFetch_x4b4g4r4, fbFetch_x4b4g4r4, fbStore_x4b4g4r4 }, + + /* 8bpp formats */ + { PICT_a8, fbFetch_a8, fbFetcha_a8, fbStore_a8 }, + { PICT_r3g3b2, fbFetch_r3g3b2, fbFetch_r3g3b2, fbStore_r3g3b2 }, + { PICT_b2g3r3, fbFetch_b2g3r3, fbFetch_b2g3r3, fbStore_b2g3r3 }, + { PICT_a2r2g2b2, fbFetch_a2r2g2b2, fbFetch_a2r2g2b2, fbStore_a2r2g2b2 }, + { PICT_c8, fbFetch_c8, fbFetch_c8, fbStore_c8 }, + { PICT_g8, fbFetch_c8, fbFetch_c8, fbStore_g8 }, + + /* 4bpp formats */ + { PICT_a4, fbFetch_a4, fbFetcha_a4, fbStore_a4 }, + { PICT_r1g2b1, fbFetch_r1g2b1, fbFetch_r1g2b1, fbStore_r1g2b1 }, + { PICT_b1g2r1, fbFetch_b1g2r1, fbFetch_b1g2r1, fbStore_b1g2r1 }, + { PICT_a1r1g1b1, fbFetch_a1r1g1b1, fbFetch_a1r1g1b1, fbStore_a1r1g1b1 }, + { PICT_a1b1g1r1, fbFetch_a1b1g1r1, fbFetch_a1b1g1r1, fbStore_a1b1g1r1 }, + { PICT_c4, fbFetch_c4, fbFetch_c4, fbStore_c4 }, + { PICT_g4, fbFetch_c4, fbFetch_c4, fbStore_g4 }, + + /* 1bpp formats */ + { PICT_a1, fbFetch_a1, fbFetcha_a1, fbStore_a1 }, + { PICT_g1, fbFetch_g1, fbFetch_g1, fbStore_g1 }, +}; +#define NumAccessMap (sizeof fbAccessMap / sizeof fbAccessMap[0]) + +static void +fbStepOver (FbCompositeOperand *op) +{ + op->u.drawable.offset += op->u.drawable.bpp; +} + +static void +fbStepDown (FbCompositeOperand *op) +{ + op->u.drawable.line += op->u.drawable.stride; + op->u.drawable.offset = op->u.drawable.start_offset; +} + +static void +fbSet (FbCompositeOperand *op, int x, int y) +{ + op->u.drawable.line = op->u.drawable.top_line + y * op->u.drawable.stride; + op->u.drawable.offset = op->u.drawable.left_offset + x * op->u.drawable.bpp; +} + +static void +fbStepOver_external (FbCompositeOperand *op) +{ + (*op[1].over) (&op[1]); + (*op[2].over) (&op[2]); +} + +static void +fbStepDown_external (FbCompositeOperand *op) +{ + (*op[1].down) (&op[1]); + (*op[2].down) (&op[2]); +} + +static void +fbSet_external (FbCompositeOperand *op, int x, int y) +{ + (*op[1].set) (&op[1], x, y); + (*op[2].set) (&op[2], + x - op->u.external.alpha_dx, + y - op->u.external.alpha_dy); +} + +static void +fbStepOver_transform (FbCompositeOperand *op) +{ + op->u.transform.x++; +} + +static void +fbStepDown_transform (FbCompositeOperand *op) +{ + op->u.transform.y++; + op->u.transform.x = op->u.transform.start_x; +} + +static void +fbSet_transform (FbCompositeOperand *op, int x, int y) +{ + op->u.transform.x = x - op->u.transform.left_x; + op->u.transform.y = y - op->u.transform.top_y; +} + + +Bool +fbBuildCompositeOperand (PicturePtr pPict, + FbCompositeOperand op[4], + INT16 x, + INT16 y, + Bool transform, + Bool alpha) +{ + /* Check for transform */ + if (transform && pPict->transform) + { + if (!fbBuildCompositeOperand (pPict, &op[1], 0, 0, FALSE, alpha)) + return FALSE; + + op->u.transform.top_y = pPict->pDrawable->y; + op->u.transform.left_x = pPict->pDrawable->x; + + op->u.transform.start_x = x - op->u.transform.left_x; + op->u.transform.x = op->u.transform.start_x; + op->u.transform.y = y - op->u.transform.top_y; + op->u.transform.transform = pPict->transform; + op->u.transform.filter = pPict->filter; + + op->fetch = fbFetch_transform; + op->fetcha = fbFetcha_transform; + op->store = 0; + op->over = fbStepOver_transform; + op->down = fbStepDown_transform; + op->set = fbSet_transform; + op->indexed = (miIndexedPtr) pPict->pFormat->index.devPrivate; + op->clip = op[1].clip; + + return TRUE; + } + /* Check for external alpha */ + else if (alpha && pPict->alphaMap) + { + if (!fbBuildCompositeOperand (pPict, &op[1], x, y, FALSE, FALSE)) + return FALSE; + if (!fbBuildCompositeOperand (pPict->alphaMap, &op[2], + x - pPict->alphaOrigin.x, + y - pPict->alphaOrigin.y, + FALSE, FALSE)) + return FALSE; + op->u.external.alpha_dx = pPict->alphaOrigin.x; + op->u.external.alpha_dy = pPict->alphaOrigin.y; + + op->fetch = fbFetch_external; + op->fetcha = fbFetcha_external; + op->store = fbStore_external; + op->over = fbStepOver_external; + op->down = fbStepDown_external; + op->set = fbSet_external; + op->indexed = (miIndexedPtr) pPict->pFormat->index.devPrivate; + /* XXX doesn't handle external alpha clips yet */ + op->clip = op[1].clip; + + return TRUE; + } + /* Build simple operand */ + else + { + int i; + int xoff, yoff; + + for (i = 0; i < NumAccessMap; i++) + if (fbAccessMap[i].format == pPict->format) + { + FbBits *bits; + FbStride stride; + int bpp; + + op->fetch = fbAccessMap[i].fetch; + op->fetcha = fbAccessMap[i].fetcha; + op->store = fbAccessMap[i].store; + op->over = fbStepOver; + op->down = fbStepDown; + op->set = fbSet; + op->indexed = (miIndexedPtr) pPict->pFormat->index.devPrivate; + op->clip = pPict->pCompositeClip; + + fbGetDrawable (pPict->pDrawable, bits, stride, bpp, + xoff, yoff); + if (pPict->repeat && pPict->pDrawable->width == 1 && + pPict->pDrawable->height == 1) + { + bpp = 0; + stride = 0; + } + /* + * Coordinates of upper left corner of drawable + */ + op->u.drawable.top_line = bits + yoff * stride; + op->u.drawable.left_offset = xoff * bpp; + + /* + * Starting position within drawable + */ + op->u.drawable.start_offset = op->u.drawable.left_offset + x * bpp; + op->u.drawable.line = op->u.drawable.top_line + y * stride; + op->u.drawable.offset = op->u.drawable.start_offset; + + op->u.drawable.stride = stride; + op->u.drawable.bpp = bpp; + return TRUE; + } + return FALSE; + } +} + +void +fbCompositeGeneral (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + FbCompositeOperand src[4],msk[4],dst[4],*pmsk; + FbCompositeOperand *srcPict, *srcAlpha; + FbCompositeOperand *dstPict, *dstAlpha; + FbCompositeOperand *mskPict = 0, *mskAlpha = 0; + FbCombineFunc f; + int w; + + if (!fbBuildCompositeOperand (pSrc, src, xSrc, ySrc, TRUE, TRUE)) + return; + if (!fbBuildCompositeOperand (pDst, dst, xDst, yDst, FALSE, TRUE)) + return; + if (pSrc->alphaMap) + { + srcPict = &src[1]; + srcAlpha = &src[2]; + } + else + { + srcPict = &src[0]; + srcAlpha = 0; + } + if (pDst->alphaMap) + { + dstPict = &dst[1]; + dstAlpha = &dst[2]; + } + else + { + dstPict = &dst[0]; + dstAlpha = 0; + } + f = fbCombineFuncU[op]; + if (pMask) + { + if (!fbBuildCompositeOperand (pMask, msk, xMask, yMask, TRUE, TRUE)) + return; + pmsk = msk; + if (pMask->componentAlpha) + f = fbCombineFuncC[op]; + if (pMask->alphaMap) + { + mskPict = &msk[1]; + mskAlpha = &msk[2]; + } + else + { + mskPict = &msk[0]; + mskAlpha = 0; + } + } + else + pmsk = 0; + while (height--) + { + w = width; + + while (w--) + { + (*f) (src, pmsk, dst); + (*src->over) (src); + (*dst->over) (dst); + if (pmsk) + (*pmsk->over) (pmsk); + } + (*src->down) (src); + (*dst->down) (dst); + if (pmsk) + (*pmsk->down) (pmsk); + } +} |