/* * $XdotOrg: xc/programs/Xserver/fb/fbcompose.c,v 1.2 2004/04/23 19:05:14 eich Exp $ * $XFree86: xc/programs/Xserver/fb/fbcompose.c,v 1.17tsi 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->fetch) (src) >> 24; if (x == 0xff) return a; m = FbInU(a,0,x,t); n = FbInU(a,8,x,t); o = FbInU(a,16,x,t); p = FbInU(a,24,x,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,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 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; CARD16 sa, da; CARD16 ad, as; CARD16 t, u, v; 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); } 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, Fb; CARD16 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 = fbCombineDisjointInPart ((CARD8) (sa >> 0), da); n = fbCombineDisjointInPart ((CARD8) (sa >> 8), da) << 8; o = fbCombineDisjointInPart ((CARD8) (sa >> 16), da) << 16; p = fbCombineDisjointInPart ((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: m = fbCombineDisjointOutPart (da, (CARD8) (sa >> 0)); n = fbCombineDisjointOutPart (da, (CARD8) (sa >> 8)) << 8; o = fbCombineDisjointOutPart (da, (CARD8) (sa >> 16)) << 16; p = fbCombineDisjointOutPart (da, (CARD8) (sa >> 24)) << 24; Fb = m|n|o|p; break; case CombineBIn: m = fbCombineDisjointInPart (da, (CARD8) (sa >> 0)); n = fbCombineDisjointInPart (da, (CARD8) (sa >> 8)) << 8; o = fbCombineDisjointInPart (da, (CARD8) (sa >> 16)) << 16; p = fbCombineDisjointInPart (da, (CARD8) (sa >> 24)) << 24; Fb = m|n|o|p; break; case CombineB: Fb = 0xffffffff; break; } m = FbGen (s,d,0,FbGet8(Fa,0),FbGet8(Fb,0),t,u,v); n = FbGen (s,d,8,FbGet8(Fa,8),FbGet8(Fb,8),t,u,v); o = FbGen (s,d,16,FbGet8(Fa,16),FbGet8(Fb,16),t,u,v); p = FbGen (s,d,24,FbGet8(Fa,24),FbGet8(Fb,24),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 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, Fb; CARD16 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 = fbCombineConjointInPart ((CARD8) (sa >> 0), da); n = fbCombineConjointInPart ((CARD8) (sa >> 8), da) << 8; o = fbCombineConjointInPart ((CARD8) (sa >> 16), da) << 16; p = fbCombineConjointInPart ((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: m = fbCombineConjointOutPart (da, (CARD8) (sa >> 0)); n = fbCombineConjointOutPart (da, (CARD8) (sa >> 8)) << 8; o = fbCombineConjointOutPart (da, (CARD8) (sa >> 16)) << 16; p = fbCombineConjointOutPart (da, (CARD8) (sa >> 24)) << 24; Fb = m|n|o|p; break; case CombineBIn: m = fbCombineConjointInPart (da, (CARD8) (sa >> 0)); n = fbCombineConjointInPart (da, (CARD8) (sa >> 8)) << 8; o = fbCombineConjointInPart (da, (CARD8) (sa >> 16)) << 16; p = fbCombineConjointInPart (da, (CARD8) (sa >> 24)) << 24; Fb = m|n|o|p; break; case CombineB: Fb = 0xffffffff; break; } m = FbGen (s,d,0,FbGet8(Fa,0),FbGet8(Fb,0),t,u,v); n = FbGen (s,d,8,FbGet8(Fa,8),FbGet8(Fb,8),t,u,v); o = FbGen (s,d,16,FbGet8(Fa,16),FbGet8(Fb,16),t,u,v); p = FbGen (s,d,24,FbGet8(Fa,24),FbGet8(Fb,24),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, fbCombineSaturateU, 0, 0, fbCombineClear, fbCombineSrcU, fbCombineDst, fbCombineDisjointOverU, fbCombineSaturateU, /* DisjointOverReverse */ 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, fbCombineSaturateC, 0, 0, fbCombineClear, /* 0x10 */ fbCombineSrcC, fbCombineDst, fbCombineDisjointOverC, fbCombineSaturateC, /* DisjointOverReverse */ 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); } #define dummyScreen screenInfo.screens[0] 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 (dummyScreen, 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 (dummyScreen, 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 (dummyScreen, 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 (dummyScreen, 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; FbCombineFunc f; int w; if (!fbBuildCompositeOperand (pSrc, src, xSrc, ySrc, TRUE, TRUE)) return; if (!fbBuildCompositeOperand (pDst, dst, xDst, yDst, FALSE, TRUE)) return; f = fbCombineFuncU[op]; if (pMask) { if (!fbBuildCompositeOperand (pMask, msk, xMask, yMask, TRUE, TRUE)) return; pmsk = msk; if (pMask->componentAlpha) f = fbCombineFuncC[op]; } 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); } }