xserver-multidpi/fb/fbcompose.c
Søren Sandmann Pedersen 433c38f22f Thu Jan 13 15:40:29 2005 Søren Sandmann <sandmann@redhat.com>
Add MMX implementation of non-repeating source IN repeating mask, aka
    "translucent window".
Add MMX implementation of CopyArea.
Use MMX implementation of CopyArea.
Use the new implementations.
2005-01-13 20:49:21 +00:00

2871 lines
68 KiB
C

/*
* $XdotOrg: xc/programs/Xserver/fb/fbcompose.c,v 1.3 2004/05/12 01:49:46 anholt 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 0
ErrorF ("op: %d\n"
"src format: %lx\n"
"msk format %lx\n"
"dst format %lx\n"
"width: %d\n"
"height %d\n",
op,
pSrc? pSrc->format : 0,
pMask? pMask->format : 0,
pDst? pDst->format : 0,
width, height);
ErrorF ("PICT_x8r8g8b8: %lx\n", PICT_x8r8g8b8);
#endif
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);
}
}