Index: iccompose.c =================================================================== RCS file: /cvs/cairo/libpixman/src/iccompose.c,v retrieving revision 1.26 diff -p -u -r1.26 iccompose.c --- iccompose.c 30 Jul 2005 17:23:21 -0000 1.26 +++ iccompose.c 30 Jul 2005 19:10:58 -0000 @@ -1,5 +1,8 @@ /* - * Copyright © 2000 Keith Packard + * $XdotOrg: xc/programs/Xserver/fb/fbcompose.c,v 1.5 2005/01/13 20:49:21 sandmann Exp $ + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * 2005 Lars Knoll & Zack Rusin, Trolltech * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -11,2661 +14,3478 @@ * 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. + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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. */ - - +#ifdef HAVE_CONFIG_H +#include +#endif #include "pixman-xserver-compat.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. - */ +#ifdef RENDER -/* - * Combine src and mask using IN - */ +// #include "picturestr.h" +// #include "mipict.h" +#include "fbpict.h" +#include "pixregionint.h" + +// #define PIXMAN_CONVOLUTION +// #define PIXMAN_GRADIENTS +// #define PIXMAN_INDEXED_FORMATS +#define miIndexedPtr FbIndexedPtr +#define miIndexToEnt24 FbIndexToEnt24 +#define miIndexToEntY24 FbIndexToEntY24 + +#define MAX_FIXED_48_16 ((xFixed_48_16) 0x7fffffff) +#define MIN_FIXED_48_16 (-((xFixed_48_16) 1 << 31)) + +static Bool +PictureTransformPoint3d (pixman_transform_t *transform, + PictVector *vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + *vector = result; + return TRUE; +} -static 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; -} - -static FbCompSrc -fbCombineMaskC (FbCompositeOperand *src, - FbCompositeOperand *msk) -{ - FbCompSrc s; - CARD32 x; - CARD32 a; - CARD16 xa; - CARD16 t; - CARD32 m,n,o,p; +#define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b)) - 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; -} - -static CARD32 -fbCombineMaskValueC (FbCompositeOperand *src, - FbCompositeOperand *msk) -{ - CARD32 x; - CARD32 a; - CARD16 t; - CARD32 m,n,o,p; +#define SCANLINE_BUFFER_LENGTH 2048 - 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; -} +typedef FASTCALL void (*fetchProc)(const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed); /* - * Combine src and mask using IN, generating only the alpha component + * All of the fetch functions */ -static 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); +static FASTCALL void +fbFetch_a8r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + memcpy(buffer, (const CARD32 *)bits + x, width*sizeof(CARD32)); } -static CARD32 -fbCombineMaskAlphaC (FbCompositeOperand *src, - FbCompositeOperand *msk) +static FASTCALL void +fbFetch_x8r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - CARD32 x; - CARD32 a; - CARD16 t; - CARD32 m,n,o,p; - - if (!msk) - return (*src->fetch) (src); - - a = (*msk->fetcha) (msk); - if (!a) - return 0; - - x = (*src->fetcha) (src); - if (a == 0xffffffff) - return x; - - m = FbInC(x,0,a,t); - n = FbInC(x,8,a,t); - o = FbInC(x,16,a,t); - p = FbInC(x,24,a,t); - return m|n|o|p; + const CARD32 *pixel = (const CARD32 *)bits + x; + const CARD32 *end = pixel + width; + while (pixel < end) { + *buffer++ = *pixel++ | 0xff000000; + } } -/* - * All of the composing functions - */ -static void -fbCombineClear (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbFetch_a8b8g8r8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - (*dst->store) (dst, 0); + const CARD32 *pixel = (CARD32 *)bits + x; + const CARD32 *end = pixel + width; + while (pixel < end) { + *buffer++ = ((*pixel & 0xff00ff00) | + ((*pixel >> 16) & 0xff) | + ((*pixel & 0xff) << 16)); + ++pixel; + } } -static void -fbCombineSrcU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbFetch_x8b8g8r8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - (*dst->store) (dst, fbCombineMaskU (src, msk)); + const CARD32 *pixel = (CARD32 *)bits + x; + const CARD32 *end = pixel + width; + while (pixel < end) { + *buffer++ = 0xff000000 | + ((*pixel & 0x0000ff00) | + ((*pixel >> 16) & 0xff) | + ((*pixel & 0xff) << 16)); + ++pixel; + } } -static void -fbCombineSrcC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbFetch_r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - (*dst->store) (dst, fbCombineMaskValueC (src, msk)); + const CARD8 *pixel = (const CARD8 *)bits + 3*x; + const CARD8 *end = pixel + 3*width; + while (pixel < end) { + CARD32 b = Fetch24(pixel) | 0xff000000; + pixel += 3; + *buffer++ = b; + } } -static void -fbCombineDst (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbFetch_b8g8r8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - /* noop */ + const CARD8 *pixel = (const CARD8 *)bits + 3*x; + const CARD8 *end = pixel + 3*width; + while (pixel < end) { + CARD32 b = 0xff000000; +#if IMAGE_BYTE_ORDER == MSBFirst + b |= (*pixel++); + b |= (*pixel++ << 8); + b |= (*pixel++ << 16); +#else + b |= (*pixel++ << 16); + b |= (*pixel++ << 8); + b |= (*pixel++); +#endif + } } -static 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); +static FASTCALL void +fbFetch_r5g6b5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *)bits + x; + const CARD16 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r = (((p) << 3) & 0xf8) | + (((p) << 5) & 0xfc00) | + (((p) << 8) & 0xf80000); + r |= (r >> 5) & 0x70007; + r |= (r >> 6) & 0x300; + *buffer++ = 0xff000000 | r; } } -static void -fbCombineOverC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbFetch_b5g6r5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - FbCompSrc cs; - CARD32 s, d; - CARD32 a; - CARD16 t; - CARD32 m,n,o,p; + const CARD16 *pixel = (const CARD16 *)bits + x; + const CARD16 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b; - 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); + b = ((p & 0xf800) | ((p & 0xe000) >> 5)) >> 8; + g = ((p & 0x07e0) | ((p & 0x0600) >> 6)) << 5; + r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; + *buffer++ = (0xff000000 | r | g | b); } } -static 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); +static FASTCALL void +fbFetch_a1r5g5b5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *)bits + x; + const CARD16 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b, a; + + a = (CARD32) ((CARD8) (0 - ((p & 0x8000) >> 15))) << 24; + r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2; + *buffer++ = (a | r | g | b); } } -static void -fbCombineOverReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbFetch_x1r5g5b5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - CARD32 s, d; - CARD32 a; - CARD16 t; - CARD32 m,n,o,p; + const CARD16 *pixel = (const CARD16 *)bits + x; + const CARD16 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b; - 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); + r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2; + *buffer++ = (0xff000000 | r | g | b); } } -static 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; - } +static FASTCALL void +fbFetch_a1b5g5r5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *)bits + x; + const CARD16 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b, a; + + a = (CARD32) ((CARD8) (0 - ((p & 0x8000) >> 15))) << 24; + b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; + *buffer++ = (a | r | g | b); } - (*dst->store) (dst, s); } -static 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; - } +static FASTCALL void +fbFetch_x1b5g5r5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *)bits + x; + const CARD16 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b; + + b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; + *buffer++ = (0xff000000 | r | g | b); } - (*dst->store) (dst, s); } -static 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); +static FASTCALL void +fbFetch_a4r4g4b4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *)bits + x; + const CARD16 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b, a; + + a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16; + r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + b = ((p & 0x000f) | ((p & 0x000f) << 4)); + *buffer++ = (a | r | g | b); } } -static void -fbCombineInReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbFetch_x4r4g4b4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - CARD32 s, d; - CARD32 a; - CARD16 t; - CARD32 m,n,o,p; + const CARD16 *pixel = (const CARD16 *)bits + x; + const CARD16 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b; - 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); + r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + b = ((p & 0x000f) | ((p & 0x000f) << 4)); + *buffer++ = (0xff000000 | r | g | b); } } -static 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; - } +static FASTCALL void +fbFetch_a4b4g4r4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *)bits + x; + const CARD16 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b, a; + + a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16; + b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + r = ((p & 0x000f) | ((p & 0x000f) << 4)); + *buffer++ = (a | r | g | b); } - (*dst->store) (dst, s); } -static 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; - } +static FASTCALL void +fbFetch_x4b4g4r4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *)bits + x; + const CARD16 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b; + + b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + r = ((p & 0x000f) | ((p & 0x000f) << 4)); + *buffer++ = (0xff000000 | r | g | b); } - (*dst->store) (dst, s); } -static 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); +static FASTCALL void +fbFetch_a8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *)bits + x; + const CARD8 *end = pixel + width; + while (pixel < end) { + *buffer++ = (*pixel++) << 24; } } -static void -fbCombineOutReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbFetch_r3g3b2 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - CARD32 s, d; - CARD32 a; - CARD16 t; - CARD32 m,n,o,p; + const CARD8 *pixel = (const CARD8 *)bits + x; + const CARD8 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b; - 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); + r = ((p & 0xe0) | ((p & 0xe0) >> 3) | ((p & 0xc0) >> 6)) << 16; + g = ((p & 0x1c) | ((p & 0x18) >> 3) | ((p & 0x1c) << 3)) << 8; + b = (((p & 0x03) ) | + ((p & 0x03) << 2) | + ((p & 0x03) << 4) | + ((p & 0x03) << 6)); + *buffer++ = (0xff000000 | r | g | b); } } -static 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); -} - -static 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); -} +static FASTCALL void +fbFetch_b2g3r3 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *)bits + x; + const CARD8 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 r,g,b; -static 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); + b = (((p & 0xc0) ) | + ((p & 0xc0) >> 2) | + ((p & 0xc0) >> 4) | + ((p & 0xc0) >> 6)); + g = ((p & 0x38) | ((p & 0x38) >> 3) | ((p & 0x30) << 2)) << 8; + r = (((p & 0x07) ) | + ((p & 0x07) << 3) | + ((p & 0x06) << 6)) << 16; + *buffer++ = (0xff000000 | r | g | b); + } } -static 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); -} +static FASTCALL void +fbFetch_a2r2g2b2 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *)bits + x; + const CARD8 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 a,r,g,b; -static 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); + a = ((p & 0xc0) * 0x55) << 18; + r = ((p & 0x30) * 0x55) << 12; + g = ((p & 0x0c) * 0x55) << 6; + b = ((p & 0x03) * 0x55); + *buffer++ = a|r|g|b; + } } -static void -fbCombineXorC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) -{ - FbCompSrc cs; - CARD32 s, d, ad; - CARD16 as; - CARD16 t, u, v; - CARD32 m,n,o,p; - - cs = fbCombineMaskC (src, msk); - d = (*dst->fetch) (dst); - s = cs.value; - ad = ~cs.alpha; - as = ~d >> 24; - m = FbGen(s,d,0,as,ad,t,u,v); - n = FbGen(s,d,8,as,ad,t,u,v); - o = FbGen(s,d,16,as,ad,t,u,v); - p = FbGen(s,d,24,as,ad,t,u,v); - (*dst->store) (dst, m|n|o|p); -} +static FASTCALL void +fbFetch_a2b2g2r2 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *)bits + x; + const CARD8 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + CARD32 a,r,g,b; -static 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); - } + a = ((p & 0xc0) * 0x55) << 18; + b = ((p & 0x30) * 0x55) >> 6; + g = ((p & 0x0c) * 0x55) << 6; + r = ((p & 0x03) * 0x55) << 16; + *buffer++ = a|r|g|b; } } -static 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); - } +static FASTCALL void +fbFetch_c8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *)bits + x; + const CARD8 *end = pixel + width; + while (pixel < end) { + CARD32 p = *pixel++; + *buffer++ = indexed->rgba[p]; } } -/* - * All of the disjoint composing functions +#define Fetch8(l,o) (((CARD8 *) (l))[(o) >> 2]) +#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 - 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) +static FASTCALL void +fbFetch_a4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); - */ + p |= p << 4; + *buffer++ = p << 24; + } +} -#define CombineAOut 1 -#define CombineAIn 2 -#define CombineBOut 4 -#define CombineBIn 8 +static FASTCALL void +fbFetch_r1g2b1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + CARD32 r,g,b; -#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) + r = ((p & 0x8) * 0xff) << 13; + g = ((p & 0x6) * 0x55) << 7; + b = ((p & 0x1) * 0xff); + *buffer++ = 0xff000000|r|g|b; + } +} -/* portion covered by a but not b */ -static CARD8 -fbCombineDisjointOutPart (CARD8 a, CARD8 b) +static FASTCALL void +fbFetch_b1g2r1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - /* 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 */ + int i; + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + CARD32 r,g,b; + + b = ((p & 0x8) * 0xff) >> 3; + g = ((p & 0x6) * 0x55) << 7; + r = ((p & 0x1) * 0xff) << 16; + *buffer++ = 0xff000000|r|g|b; + } } -/* portion covered by both a and b */ -static CARD8 -fbCombineDisjointInPart (CARD8 a, CARD8 b) +static FASTCALL void +fbFetch_a1r1g1b1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - /* max (1-(1-b)/a,0) */ - /* = - min ((1-b)/a - 1, 0) */ - /* = 1 - min (1, (1-b)/a) */ + int i; + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + CARD32 a,r,g,b; - 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 */ + a = ((p & 0x8) * 0xff) << 21; + r = ((p & 0x4) * 0xff) << 14; + g = ((p & 0x2) * 0xff) << 7; + b = ((p & 0x1) * 0xff); + *buffer++ = a|r|g|b; + } } -static 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; +static FASTCALL void +fbFetch_a1b1g1r1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + CARD32 a,r,g,b; - 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; + a = ((p & 0x8) * 0xff) << 21; + r = ((p & 0x4) * 0xff) >> 3; + g = ((p & 0x2) * 0xff) << 7; + b = ((p & 0x1) * 0xff) << 16; + *buffer++ = a|r|g|b; } - - 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); } -static void -fbCombineDisjointGeneralC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst, - CARD8 combine) -{ - FbCompSrc cs; - CARD32 s, d; - CARD32 m,n,o,p; - CARD32 Fa; - CARD16 Fb, t, u, v; - CARD32 sa; - CARD8 da; - - cs = fbCombineMaskC (src, msk); - s = cs.value; - sa = cs.alpha; - - d = (*dst->fetch) (dst); - da = d >> 24; - - switch (combine & CombineA) { - default: - Fa = 0; - break; - case CombineAOut: - m = fbCombineDisjointOutPart ((CARD8) (sa >> 0), da); - n = fbCombineDisjointOutPart ((CARD8) (sa >> 8), da) << 8; - o = fbCombineDisjointOutPart ((CARD8) (sa >> 16), da) << 16; - p = fbCombineDisjointOutPart ((CARD8) (sa >> 24), da) << 24; - Fa = m|n|o|p; - break; - case CombineAIn: - m = fbCombineDisjointOutPart ((CARD8) (sa >> 0), da); - n = fbCombineDisjointOutPart ((CARD8) (sa >> 8), da) << 8; - o = fbCombineDisjointOutPart ((CARD8) (sa >> 16), da) << 16; - p = fbCombineDisjointOutPart ((CARD8) (sa >> 24), da) << 24; - Fa = m|n|o|p; - break; - case CombineA: - Fa = 0xffffffff; - break; +static FASTCALL void +fbFetch_c4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + + *buffer++ = indexed->rgba[p]; } - - switch (combine & CombineB) { - default: - Fb = 0; - break; - case CombineBOut: - Fb = fbCombineDisjointOutPart (da, sa); - break; - case CombineBIn: - Fb = fbCombineDisjointInPart (da, sa); - break; - case CombineB: - Fb = 0xff; - break; - } - m = FbGen (s,d,0,FbGet8(Fa,0),Fb,t,u,v); - n = FbGen (s,d,8,FbGet8(Fa,8),Fb,t,u,v); - o = FbGen (s,d,16,FbGet8(Fa,16),Fb,t,u,v); - p = FbGen (s,d,24,FbGet8(Fa,24),Fb,t,u,v); - s = m|n|o|p; - (*dst->store) (dst, s); } -static 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); + +static FASTCALL void +fbFetch_a1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 p = ((CARD32 *)bits)[(i + x) >> 5]; + CARD32 a; +#if BITMAP_BIT_ORDER == MSBFirst + a = p >> (0x1f - ((i+x) & 0x1f)); +#else + a = p >> ((i+x) & 0x1f); +#endif + a = a & 1; + a |= a << 1; + a |= a << 2; + a |= a << 4; + *buffer++ = a << 24; } } -static void -fbCombineDisjointOverC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbFetch_g1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed) { - fbCombineDisjointGeneralC (src, msk, dst, CombineAOver); + int i; + for (i = 0; i < width; ++i) { + CARD32 p = ((CARD32 *)bits)[(i+x) >> 5]; + CARD32 a; +#if BITMAP_BIT_ORDER == MSBFirst + a = p >> (0x1f - ((i+x) & 0x1f)); +#else + a = p >> ((i+x) & 0x1f); +#endif + a = a & 1; + *buffer++ = indexed->rgba[a]; + } } -static void -fbCombineDisjointOverReverseU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static fetchProc fetchProcForPicture (PicturePtr pict) { - fbCombineDisjointGeneralU (src, msk, dst, CombineBOver); + switch(pict->format_code) { + case PICT_a8r8g8b8: return fbFetch_a8r8g8b8; + case PICT_x8r8g8b8: return fbFetch_x8r8g8b8; + case PICT_a8b8g8r8: return fbFetch_a8b8g8r8; + case PICT_x8b8g8r8: return fbFetch_x8b8g8r8; + + /* 24bpp formats */ + case PICT_r8g8b8: return fbFetch_r8g8b8; + case PICT_b8g8r8: return fbFetch_b8g8r8; + + /* 16bpp formats */ + case PICT_r5g6b5: return fbFetch_r5g6b5; + case PICT_b5g6r5: return fbFetch_b5g6r5; + + case PICT_a1r5g5b5: return fbFetch_a1r5g5b5; + case PICT_x1r5g5b5: return fbFetch_x1r5g5b5; + case PICT_a1b5g5r5: return fbFetch_a1b5g5r5; + case PICT_x1b5g5r5: return fbFetch_x1b5g5r5; + case PICT_a4r4g4b4: return fbFetch_a4r4g4b4; +// case PICT_x4r4g4b4: return fbFetch_x4r4g4b4; +// case PICT_a4b4g4r4: return fbFetch_a4b4g4r4; +// case PICT_x4b4g4r4: return fbFetch_x4b4g4r4; + + /* 8bpp formats */ + case PICT_a8: return fbFetch_a8; + case PICT_r3g3b2: return fbFetch_r3g3b2; + case PICT_b2g3r3: return fbFetch_b2g3r3; + case PICT_a2r2g2b2: return fbFetch_a2r2g2b2; + case PICT_a2b2g2r2: return fbFetch_a2b2g2r2; + case PICT_c8: return fbFetch_c8; + case PICT_g8: return fbFetch_c8; + + /* 4bpp formats */ + case PICT_a4: return fbFetch_a4; + case PICT_r1g2b1: return fbFetch_r1g2b1; + case PICT_b1g2r1: return fbFetch_b1g2r1; + case PICT_a1r1g1b1: return fbFetch_a1r1g1b1; + case PICT_a1b1g1r1: return fbFetch_a1b1g1r1; + case PICT_c4: return fbFetch_c4; + case PICT_g4: return fbFetch_c4; + + /* 1bpp formats */ + case PICT_a1: return fbFetch_a1; + case PICT_g1: return fbFetch_g1; + default: + return 0; + } } -static void -fbCombineDisjointOverReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +/* + * Pixel wise fetching + */ + +typedef FASTCALL CARD32 (*fetchPixelProc)(const FbBits *bits, int offset, miIndexedPtr indexed); + +static FASTCALL CARD32 +fbFetchPixel_a8r8g8b8 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralC (src, msk, dst, CombineBOver); + return ((CARD32 *)bits)[offset]; } -static void -fbCombineDisjointInU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_x8r8g8b8 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralU (src, msk, dst, CombineAIn); + return ((CARD32 *)bits)[offset] | 0xff000000; } -static void -fbCombineDisjointInC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_a8b8g8r8 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralC (src, msk, dst, CombineAIn); -} + CARD32 pixel = ((CARD32 *)bits)[offset]; -static void -fbCombineDisjointInReverseU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) -{ - fbCombineDisjointGeneralU (src, msk, dst, CombineBIn); + return ((pixel & 0xff000000) | + ((pixel >> 16) & 0xff) | + (pixel & 0x0000ff00) | + ((pixel & 0xff) << 16)); } -static void -fbCombineDisjointInReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_x8b8g8r8 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralC (src, msk, dst, CombineBIn); + CARD32 pixel = ((CARD32 *)bits)[offset]; + + return ((0xff000000) | + ((pixel >> 16) & 0xff) | + (pixel & 0x0000ff00) | + ((pixel & 0xff) << 16)); } -static void -fbCombineDisjointOutU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_r8g8b8 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralU (src, msk, dst, CombineAOut); + CARD8 *pixel = ((CARD8 *) bits) + (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 } -static void -fbCombineDisjointOutC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_b8g8r8 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralC (src, msk, dst, CombineAOut); + CARD8 *pixel = ((CARD8 *) bits) + (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 } -static void -fbCombineDisjointOutReverseU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_r5g6b5 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralU (src, msk, dst, CombineBOut); + CARD32 pixel = ((CARD16 *) bits)[offset]; + 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); } -static void -fbCombineDisjointOutReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_b5g6r5 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralC (src, msk, dst, CombineBOut); + CARD32 pixel = ((CARD16 *) bits)[offset]; + 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); } -static void -fbCombineDisjointAtopU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_a1r5g5b5 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralU (src, msk, dst, CombineAAtop); + CARD32 pixel = ((CARD16 *) bits)[offset]; + 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); } -static void -fbCombineDisjointAtopC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_x1r5g5b5 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralC (src, msk, dst, CombineAAtop); + CARD32 pixel = ((CARD16 *) bits)[offset]; + 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); } -static void -fbCombineDisjointAtopReverseU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_a1b5g5r5 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralU (src, msk, dst, CombineBAtop); + CARD32 pixel = ((CARD16 *) bits)[offset]; + 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); } -static void -fbCombineDisjointAtopReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_x1b5g5r5 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralC (src, msk, dst, CombineBAtop); + CARD32 pixel = ((CARD16 *) bits)[offset]; + 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); } -static void -fbCombineDisjointXorU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_a4r4g4b4 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralU (src, msk, dst, CombineXor); + CARD32 pixel = ((CARD16 *) bits)[offset]; + 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); } -static void -fbCombineDisjointXorC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_x4r4g4b4 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineDisjointGeneralC (src, msk, dst, CombineXor); + CARD32 pixel = ((CARD16 *) bits)[offset]; + 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); } -/* portion covered by a but not b */ -static CARD8 -fbCombineConjointOutPart (CARD8 a, CARD8 b) +static FASTCALL CARD32 +fbFetchPixel_a4b4g4r4 (const FbBits *bits, int offset, miIndexedPtr indexed) { - /* 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 */ + CARD32 pixel = ((CARD16 *) bits)[offset]; + 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); } -/* portion covered by both a and b */ -static CARD8 -fbCombineConjointInPart (CARD8 a, CARD8 b) +static FASTCALL CARD32 +fbFetchPixel_x4b4g4r4 (const FbBits *bits, int offset, miIndexedPtr indexed) { - /* min (1,b/a) */ + CARD32 pixel = ((CARD16 *) bits)[offset]; + CARD32 r,g,b; - if (b >= a) /* b >= a -> b/a >= 1 */ - return 0xff; /* 1 */ - return FbIntDiv(b,a); /* b/a */ + 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); } -static 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; +static FASTCALL CARD32 +fbFetchPixel_a8 (const FbBits *bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD8 *) bits)[offset]; - 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); + return pixel << 24; } -static void -fbCombineConjointGeneralC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst, - CARD8 combine) -{ - FbCompSrc cs; - CARD32 s, d; - CARD32 m,n,o,p; - CARD32 Fa; - CARD16 Fb, t, u, v; - CARD32 sa; - CARD8 da; - - cs = fbCombineMaskC (src, msk); - s = cs.value; - sa = cs.alpha; - - d = (*dst->fetch) (dst); - da = d >> 24; - - switch (combine & CombineA) { - default: - Fa = 0; - break; - case CombineAOut: - m = fbCombineConjointOutPart ((CARD8) (sa >> 0), da); - n = fbCombineConjointOutPart ((CARD8) (sa >> 8), da) << 8; - o = fbCombineConjointOutPart ((CARD8) (sa >> 16), da) << 16; - p = fbCombineConjointOutPart ((CARD8) (sa >> 24), da) << 24; - Fa = m|n|o|p; - break; - case CombineAIn: - m = fbCombineConjointOutPart ((CARD8) (sa >> 0), da); - n = fbCombineConjointOutPart ((CARD8) (sa >> 8), da) << 8; - o = fbCombineConjointOutPart ((CARD8) (sa >> 16), da) << 16; - p = fbCombineConjointOutPart ((CARD8) (sa >> 24), da) << 24; - Fa = m|n|o|p; - break; - case CombineA: - Fa = 0xffffffff; - break; - } - - switch (combine & CombineB) { - default: - Fb = 0; - break; - case CombineBOut: - Fb = fbCombineConjointOutPart (da, sa); - break; - case CombineBIn: - Fb = fbCombineConjointInPart (da, sa); - break; - case CombineB: - Fb = 0xff; - break; - } - m = FbGen (s,d,0,FbGet8(Fa,0),Fb,t,u,v); - n = FbGen (s,d,8,FbGet8(Fa,8),Fb,t,u,v); - o = FbGen (s,d,16,FbGet8(Fa,16),Fb,t,u,v); - p = FbGen (s,d,24,FbGet8(Fa,24),Fb,t,u,v); - s = m|n|o|p; - (*dst->store) (dst, s); +static FASTCALL CARD32 +fbFetchPixel_r3g3b2 (const FbBits *bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD8 *) bits)[offset]; + 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); } -static void -fbCombineConjointOverU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_b2g3r3 (const FbBits *bits, int offset, miIndexedPtr indexed) { - 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); - } - */ + CARD32 pixel = ((CARD8 *) bits)[offset]; + 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); } -static void -fbCombineConjointOverC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_a2r2g2b2 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralC (src, msk, dst, CombineAOver); + CARD32 pixel = ((CARD8 *) bits)[offset]; + 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; } -static void -fbCombineConjointOverReverseU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_a2b2g2r2 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralU (src, msk, dst, CombineBOver); + CARD32 pixel = ((CARD8 *) bits)[offset]; + 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; } -static void -fbCombineConjointOverReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_c8 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralC (src, msk, dst, CombineBOver); + CARD32 pixel = ((CARD8 *) bits)[offset]; + return indexed->rgba[pixel]; } -static void -fbCombineConjointInU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +#define Fetch8(l,o) (((CARD8 *) (l))[(o) >> 2]) +#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 + +static FASTCALL CARD32 +fbFetchPixel_a4 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralU (src, msk, dst, CombineAIn); + CARD32 pixel = Fetch4(bits, offset); + + pixel |= pixel << 4; + return pixel << 24; } -static void -fbCombineConjointInC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_r1g2b1 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralC (src, msk, dst, CombineAIn); + CARD32 pixel = Fetch4(bits, offset); + CARD32 r,g,b; + + r = ((pixel & 0x8) * 0xff) << 13; + g = ((pixel & 0x6) * 0x55) << 7; + b = ((pixel & 0x1) * 0xff); + return 0xff000000|r|g|b; } -static void -fbCombineConjointInReverseU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_b1g2r1 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralU (src, msk, dst, CombineBIn); + CARD32 pixel = Fetch4(bits, 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; } -static void -fbCombineConjointInReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_a1r1g1b1 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralC (src, msk, dst, CombineBIn); + CARD32 pixel = Fetch4(bits, 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; } -static void -fbCombineConjointOutU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_a1b1g1r1 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralU (src, msk, dst, CombineAOut); + CARD32 pixel = Fetch4(bits, 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; } -static void -fbCombineConjointOutC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_c4 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralC (src, msk, dst, CombineAOut); + CARD32 pixel = Fetch4(bits, offset); + + return indexed->rgba[pixel]; } -static void -fbCombineConjointOutReverseU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) + +static FASTCALL CARD32 +fbFetchPixel_a1 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralU (src, msk, dst, CombineBOut); + CARD32 pixel = ((CARD32 *)bits)[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; } -static void -fbCombineConjointOutReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL CARD32 +fbFetchPixel_g1 (const FbBits *bits, int offset, miIndexedPtr indexed) { - fbCombineConjointGeneralC (src, msk, dst, CombineBOut); + CARD32 pixel = ((CARD32 *)bits)[offset >> 5]; + CARD32 a; +#if BITMAP_BIT_ORDER == MSBFirst + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + return indexed->rgba[a]; } -static void -fbCombineConjointAtopU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static fetchPixelProc fetchPixelProcForPicture (PicturePtr pict) { - fbCombineConjointGeneralU (src, msk, dst, CombineAAtop); + switch(pict->format_code) { + case PICT_a8r8g8b8: return fbFetchPixel_a8r8g8b8; + case PICT_x8r8g8b8: return fbFetchPixel_x8r8g8b8; + case PICT_a8b8g8r8: return fbFetchPixel_a8b8g8r8; + case PICT_x8b8g8r8: return fbFetchPixel_x8b8g8r8; + + /* 24bpp formats */ + case PICT_r8g8b8: return fbFetchPixel_r8g8b8; + case PICT_b8g8r8: return fbFetchPixel_b8g8r8; + + /* 16bpp formats */ + case PICT_r5g6b5: return fbFetchPixel_r5g6b5; + case PICT_b5g6r5: return fbFetchPixel_b5g6r5; + + case PICT_a1r5g5b5: return fbFetchPixel_a1r5g5b5; + case PICT_x1r5g5b5: return fbFetchPixel_x1r5g5b5; + case PICT_a1b5g5r5: return fbFetchPixel_a1b5g5r5; + case PICT_x1b5g5r5: return fbFetchPixel_x1b5g5r5; + case PICT_a4r4g4b4: return fbFetchPixel_a4r4g4b4; +// case PICT_x4r4g4b4: return fbFetchPixel_x4r4g4b4; +// case PICT_a4b4g4r4: return fbFetchPixel_a4b4g4r4; +// case PICT_x4b4g4r4: return fbFetchPixel_x4b4g4r4; + + /* 8bpp formats */ + case PICT_a8: return fbFetchPixel_a8; + case PICT_r3g3b2: return fbFetchPixel_r3g3b2; + case PICT_b2g3r3: return fbFetchPixel_b2g3r3; + case PICT_a2r2g2b2: return fbFetchPixel_a2r2g2b2; + case PICT_a2b2g2r2: return fbFetchPixel_a2b2g2r2; + case PICT_c8: return fbFetchPixel_c8; + case PICT_g8: return fbFetchPixel_c8; + + /* 4bpp formats */ + case PICT_a4: return fbFetchPixel_a4; + case PICT_r1g2b1: return fbFetchPixel_r1g2b1; + case PICT_b1g2r1: return fbFetchPixel_b1g2r1; + case PICT_a1r1g1b1: return fbFetchPixel_a1r1g1b1; + case PICT_a1b1g1r1: return fbFetchPixel_a1b1g1r1; + case PICT_c4: return fbFetchPixel_c4; + case PICT_g4: return fbFetchPixel_c4; + + /* 1bpp formats */ + case PICT_a1: return fbFetchPixel_a1; + case PICT_g1: return fbFetchPixel_g1; + default: + return 0; + } } -static void -fbCombineConjointAtopC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) + + +/* + * All the store functions + */ + +typedef FASTCALL void (*storeProc) (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed); + +#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 + +static FASTCALL void +fbStore_a8r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) { - fbCombineConjointGeneralC (src, msk, dst, CombineAAtop); + memcpy(((CARD32 *)bits) + x, values, width*sizeof(CARD32)); } -static void -fbCombineConjointAtopReverseU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbStore_x8r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) { - fbCombineConjointGeneralU (src, msk, dst, CombineBAtop); + int i; + CARD32 *pixel = (CARD32 *)bits + x; + for (i = 0; i < width; ++i) + *pixel++ = values[i] & 0xffffff; } -static void -fbCombineConjointAtopReverseC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbStore_a8b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) { - fbCombineConjointGeneralC (src, msk, dst, CombineBAtop); + int i; + CARD32 *pixel = (CARD32 *)bits + x; + for (i = 0; i < width; ++i) + *pixel++ = (values[i] & 0xff00ff00) | ((values[i] >> 16) && 0xff) | ((values[i] & 0xff) << 16); } -static void -fbCombineConjointXorU (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbStore_x8b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) { - fbCombineConjointGeneralU (src, msk, dst, CombineXor); + int i; + CARD32 *pixel = (CARD32 *)bits + x; + for (i = 0; i < width; ++i) + *pixel++ = (values[i] & 0x0000ff00) | ((values[i] >> 16) && 0xff) | ((values[i] & 0xff) << 16); } -static void -fbCombineConjointXorC (FbCompositeOperand *src, - FbCompositeOperand *msk, - FbCompositeOperand *dst) +static FASTCALL void +fbStore_r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) { - fbCombineConjointGeneralC (src, msk, dst, CombineXor); + int i; + CARD8 *pixel = ((CARD8 *) bits) + x; + for (i = 0; i < width; ++i) { + Store24(pixel, values[i]); + pixel += 3; + } } -static FbCombineFunc const fbCombineFuncU[] = { - fbCombineClear, - fbCombineSrcU, - fbCombineDst, - fbCombineOverU, - fbCombineOverReverseU, - fbCombineInU, - fbCombineInReverseU, - fbCombineOutU, - fbCombineOutReverseU, - fbCombineAtopU, - fbCombineAtopReverseU, - fbCombineXorU, - fbCombineAddU, - fbCombineDisjointOverU, /* Saturate */ - 0, - 0, - fbCombineClear, - fbCombineSrcU, - fbCombineDst, - fbCombineDisjointOverU, - fbCombineDisjointOverReverseU, - fbCombineDisjointInU, - fbCombineDisjointInReverseU, - fbCombineDisjointOutU, - fbCombineDisjointOutReverseU, - fbCombineDisjointAtopU, - fbCombineDisjointAtopReverseU, - fbCombineDisjointXorU, - 0, - 0, - 0, - 0, - fbCombineClear, - fbCombineSrcU, - fbCombineDst, - fbCombineConjointOverU, - fbCombineConjointOverReverseU, - fbCombineConjointInU, - fbCombineConjointInReverseU, - fbCombineConjointOutU, - fbCombineConjointOutReverseU, - fbCombineConjointAtopU, - fbCombineConjointAtopReverseU, - fbCombineConjointXorU, -}; +static FASTCALL void +fbStore_b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD8 *pixel = ((CARD8 *) bits) + x; + for (i = 0; i < width; ++i) { +#if IMAGE_BYTE_ORDER == MSBFirst + *pixel++ = Blue(values[i]); + *pixel++ = Green(values[i]); + *pixel++ = Red(values[i]); +#else + *pixel++ = Red(values[i]); + *pixel++ = Green(values[i]); + *pixel++ = Blue(values[i]); +#endif + } +} + +static FASTCALL void +fbStore_r5g6b5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD16 *pixel = ((CARD16 *) bits) + x; + for (i = 0; i < width; ++i) { + CARD32 s = values[i]; + *pixel++ = ((s >> 3) & 0x001f) | + ((s >> 5) & 0x07e0) | + ((s >> 8) & 0xf800); + } +} + +static FASTCALL void +fbStore_b5g6r5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD16 *pixel = ((CARD16 *) bits) + x; + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((b << 8) & 0xf800) | + ((g << 3) & 0x07e0) | + ((r >> 3) )); + } +} + +static FASTCALL void +fbStore_a1r5g5b5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD16 *pixel = ((CARD16 *) bits) + x; + for (i = 0; i < width; ++i) { + Splita(values[i]); + *pixel++ = (((a << 8) & 0x8000) | + ((r << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((b >> 3) )); + } +} + +static FASTCALL void +fbStore_x1r5g5b5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD16 *pixel = ((CARD16 *) bits) + x; + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((r << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((b >> 3) )); + } +} + +static FASTCALL void +fbStore_a1b5g5r5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD16 *pixel = ((CARD16 *) bits) + x; + for (i = 0; i < width; ++i) { + Splita(values[i]); + *pixel++ = (((a << 8) & 0x8000) | + ((b << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((r >> 3) )); + } +} + +static FASTCALL void +fbStore_x1b5g5r5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD16 *pixel = ((CARD16 *) bits) + x; + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((b << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((r >> 3) )); + } +} + +static FASTCALL void +fbStore_a4r4g4b4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD16 *pixel = ((CARD16 *) bits) + x; + for (i = 0; i < width; ++i) { + Splita(values[i]); + *pixel++ = (((a << 8) & 0xf000) | + ((r << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((b >> 4) )); + } +} + +static FASTCALL void +fbStore_x4r4g4b4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD16 *pixel = ((CARD16 *) bits) + x; + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((r << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((b >> 4) )); + } +} + +static FASTCALL void +fbStore_a4b4g4r4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD16 *pixel = ((CARD16 *) bits) + x; + for (i = 0; i < width; ++i) { + Splita(values[i]); + *pixel++ = (((a << 8) & 0xf000) | + ((b << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((r >> 4) )); + } +} + +static FASTCALL void +fbStore_x4b4g4r4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD16 *pixel = ((CARD16 *) bits) + x; + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((b << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((r >> 4) )); + } +} + +static FASTCALL void +fbStore_a8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD8 *pixel = ((CARD8 *) bits) + x; + for (i = 0; i < width; ++i) { + *pixel++ = values[i] >> 24; + } +} + +static FASTCALL void +fbStore_r3g3b2 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD8 *pixel = ((CARD8 *) bits) + x; + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((r ) & 0xe0) | + ((g >> 3) & 0x1c) | + ((b >> 6) )); + } +} + +static FASTCALL void +fbStore_b2g3r3 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD8 *pixel = ((CARD8 *) bits) + x; + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((b ) & 0xe0) | + ((g >> 3) & 0x1c) | + ((r >> 6) )); + } +} + +static FASTCALL void +fbStore_a2r2g2b2 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD8 *pixel = ((CARD8 *) bits) + x; + for (i = 0; i < width; ++i) { + Splita(values[i]); + *pixel++ = (((a ) & 0xc0) | + ((r >> 2) & 0x30) | + ((g >> 4) & 0x0c) | + ((b >> 6) )); + } +} + +static FASTCALL void +fbStore_c8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + CARD8 *pixel = ((CARD8 *) bits) + x; + for (i = 0; i < width; ++i) { + *pixel++ = miIndexToEnt24(indexed,values[i]); + } +} + +#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 + +static FASTCALL void +fbStore_a4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + Store4(bits, i + x, values[i]>>28); + } +} + +static FASTCALL void +fbStore_r1g2b1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 pixel; + + Split(values[i]); + pixel = (((r >> 4) & 0x8) | + ((g >> 5) & 0x6) | + ((b >> 7) )); + Store4(bits, i + x, pixel); + } +} + +static FASTCALL void +fbStore_b1g2r1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 pixel; + + Split(values[i]); + pixel = (((b >> 4) & 0x8) | + ((g >> 5) & 0x6) | + ((r >> 7) )); + Store4(bits, i + x, pixel); + } +} + +static FASTCALL void +fbStore_a1r1g1b1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 pixel; + Splita(values[i]); + pixel = (((a >> 4) & 0x8) | + ((r >> 5) & 0x4) | + ((g >> 6) & 0x2) | + ((b >> 7) )); + Store4(bits, i + x, pixel); + } +} + +static FASTCALL void +fbStore_a1b1g1r1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 pixel; + Splita(values[i]); + pixel = (((a >> 4) & 0x8) | + ((b >> 5) & 0x4) | + ((g >> 6) & 0x2) | + ((r >> 7) )); + Store4(bits, i + x, pixel); + } +} + +static FASTCALL void +fbStore_c4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 pixel; + + pixel = miIndexToEnt24(indexed, values[i]); + Store4(bits, i + x, pixel); + } +} + +static FASTCALL void +fbStore_a1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 *pixel = ((CARD32 *) bits) + ((i+x) >> 5); + CARD32 mask = FbStipMask((i+x) & 0x1f, 1); + + CARD32 v = values[i] & 0x80000000 ? mask : 0; + *pixel = (*pixel & ~mask) | v; + } +} + +static FASTCALL void +fbStore_g1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 *pixel = ((CARD32 *) bits) + ((i+x) >> 5); + CARD32 mask = FbStipMask((i+x) & 0x1f, 1); + + CARD32 v = miIndexToEntY24(indexed,values[i]) ? mask : 0; + *pixel = (*pixel & ~mask) | v; + } +} + + +static storeProc storeProcForPicture (PicturePtr pict) +{ + switch(pict->format_code) { + case PICT_a8r8g8b8: return fbStore_a8r8g8b8; + case PICT_x8r8g8b8: return fbStore_x8r8g8b8; + case PICT_a8b8g8r8: return fbStore_a8b8g8r8; + case PICT_x8b8g8r8: return fbStore_x8b8g8r8; + + /* 24bpp formats */ + case PICT_r8g8b8: return fbStore_r8g8b8; + case PICT_b8g8r8: return fbStore_b8g8r8; + + /* 16bpp formats */ + case PICT_r5g6b5: return fbStore_r5g6b5; + case PICT_b5g6r5: return fbStore_b5g6r5; + + case PICT_a1r5g5b5: return fbStore_a1r5g5b5; + case PICT_x1r5g5b5: return fbStore_x1r5g5b5; + case PICT_a1b5g5r5: return fbStore_a1b5g5r5; + case PICT_x1b5g5r5: return fbStore_x1b5g5r5; + case PICT_a4r4g4b4: return fbStore_a4r4g4b4; +// case PICT_x4r4g4b4: return fbStore_x4r4g4b4; +// case PICT_a4b4g4r4: return fbStore_a4b4g4r4; +// case PICT_x4b4g4r4: return fbStore_x4b4g4r4; + + /* 8bpp formats */ + case PICT_a8: return fbStore_a8; + case PICT_r3g3b2: return fbStore_r3g3b2; + case PICT_b2g3r3: return fbStore_b2g3r3; + case PICT_a2r2g2b2: return fbStore_a2r2g2b2; + case PICT_c8: return fbStore_c8; + case PICT_g8: return fbStore_c8; + + /* 4bpp formats */ + case PICT_a4: return fbStore_a4; + case PICT_r1g2b1: return fbStore_r1g2b1; + case PICT_b1g2r1: return fbStore_b1g2r1; + case PICT_a1r1g1b1: return fbStore_a1r1g1b1; + case PICT_a1b1g1r1: return fbStore_a1b1g1r1; + case PICT_c4: return fbStore_c4; + case PICT_g4: return fbStore_c4; + + /* 1bpp formats */ + case PICT_a1: return fbStore_a1; + case PICT_g1: return fbStore_g1; + default: + return 0; + } +} -static FbCombineFunc const fbCombineFuncC[] = { - fbCombineClear, - fbCombineSrcC, - fbCombineDst, - fbCombineOverC, - fbCombineOverReverseC, - fbCombineInC, - fbCombineInReverseC, - fbCombineOutC, - fbCombineOutReverseC, - fbCombineAtopC, - fbCombineAtopReverseC, - fbCombineXorC, - fbCombineAddC, - fbCombineDisjointOverC, /* Saturate */ - 0, - 0, - fbCombineClear, /* 0x10 */ - fbCombineSrcC, - fbCombineDst, - fbCombineDisjointOverC, - fbCombineDisjointOverReverseC, - fbCombineDisjointInC, - fbCombineDisjointInReverseC, - fbCombineDisjointOutC, - fbCombineDisjointOutReverseC, - fbCombineDisjointAtopC, - fbCombineDisjointAtopReverseC, - fbCombineDisjointXorC, /* 0x1b */ - 0, - 0, - 0, - 0, - fbCombineClear, - fbCombineSrcC, - fbCombineDst, - fbCombineConjointOverC, - fbCombineConjointOverReverseC, - fbCombineConjointInC, - fbCombineConjointInReverseC, - fbCombineConjointOutC, - fbCombineConjointOutReverseC, - fbCombineConjointAtopC, - fbCombineConjointAtopReverseC, - fbCombineConjointXorC, -}; /* - * All of the fetch functions + * Combine src and mask + */ +static FASTCALL void +fbCombineMaskU (CARD32 *src, const CARD32 *mask, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 a = mask[i] >> 24; + CARD32 s = src[i]; + FbByteMul(s, a); + src[i] = s; + } +} + +/* + * All of the composing functions */ -static CARD32 -fbFetch_a8r8g8b8 (FbCompositeOperand *op) -{ - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - return ((CARD32 *)line)[offset >> 5]; +static FASTCALL void +fbCombineClear (CARD32 *dest, const CARD32 *src, int width) +{ + memset(dest, 0, width*sizeof(CARD32)); +} + +static FASTCALL void +fbCombineSrcU (CARD32 *dest, const CARD32 *src, int width) +{ + memcpy(dest, src, width*sizeof(CARD32)); +} + + +static FASTCALL void +fbCombineOverU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 d = dest[i]; + CARD32 ia = Alpha(~s); + + FbByteMulAdd(d, ia, s); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineOverReverseU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 d = dest[i]; + CARD32 ia = Alpha(~dest[i]); + FbByteMulAdd(s, ia, d); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineInU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 a = Alpha(dest[i]); + FbByteMul(s, a); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineInReverseU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + CARD32 a = Alpha(src[i]); + FbByteMul(d, a); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineOutU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 a = Alpha(~dest[i]); + FbByteMul(s, a); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineOutReverseU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + CARD32 a = Alpha(~src[i]); + FbByteMul(d, a); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineAtopU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 d = dest[i]; + CARD32 dest_a = Alpha(d); + CARD32 src_ia = Alpha(~s); + + FbByteAddMul(s, dest_a, d, src_ia); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineAtopReverseU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 d = dest[i]; + CARD32 src_a = Alpha(s); + CARD32 dest_ia = Alpha(~d); + + FbByteAddMul(s, dest_ia, d, src_a); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineXorU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 d = dest[i]; + CARD32 src_ia = Alpha(~s); + CARD32 dest_ia = Alpha(~d); + + FbByteAddMul(s, dest_ia, d, src_ia); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineAddU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 d = dest[i]; + FbByteAdd(d, s); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineSaturateU (CARD32 *dest, const CARD32 *src, int width) +{ + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 d = dest[i]; + CARD16 sa, da; + + sa = s >> 24; + da = ~d >> 24; + if (sa > da) + { + sa = FbIntDiv(da, sa); + FbByteMul(s, sa); + } + FbByteAdd(d, s); + dest[i] = d; + } +} + +/* + * 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 */ +static INLINE 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 */ +static INLINE 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 */ } -static CARD32 -fbFetch_x8r8g8b8 (FbCompositeOperand *op) +static FASTCALL void +fbCombineDisjointGeneralU (CARD32 *dest, const CARD32 *src, int width, CARD8 combine) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - return ((CARD32 *)line)[offset >> 5] | 0xff000000; -} + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 d = dest[i]; + CARD32 m,n,o,p; + CARD16 Fa, Fb, t, u, v; + CARD8 sa = s >> 24; + CARD8 da = d >> 24; -static CARD32 -fbFetch_a8b8g8r8 (FbCompositeOperand *op) -{ - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + 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; + } - return ((pixel & 0xff000000) | - ((pixel >> 16) & 0xff) | - (pixel & 0x0000ff00) | - ((pixel & 0xff) << 16)); + 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; + dest[i] = s; + } } -static CARD32 -fbFetch_x8b8g8r8 (FbCompositeOperand *op) +static FASTCALL void +fbCombineDisjointOverU (CARD32 *dest, const CARD32 *src, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD16 a = s >> 24; - return ((0xff000000) | - ((pixel >> 16) & 0xff) | - (pixel & 0x0000ff00) | - ((pixel & 0xff) << 16)); + if (a != 0x00) + { + if (a != 0xff) + { + CARD32 d = dest[i]; + a = fbCombineDisjointOutPart (d >> 24, a); + FbByteMulAdd(d, a, s); + s = d; + } + dest[i] = s; + } + } } -static CARD32 -fbFetch_r8g8b8 (FbCompositeOperand *op) +static FASTCALL void +fbCombineDisjointInU (CARD32 *dest, const CARD32 *src, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); -#if IMAGE_BYTE_ORDER == MSBFirst - /* FIXME: implent WORKING_UNALIGNED_INT for this endian :) */ - return (0xff000000 | - (pixel[0] << 16) | - (pixel[1] << 8) | - (pixel[2])); -#else - #ifdef WORKING_UNALIGNED_INT - return *(CARD32 *)pixel|0xff000000; - #else - return (0xff000000 | - (pixel[2] << 16) | - (pixel[1] << 8) | - (pixel[0])); - #endif -#endif + fbCombineDisjointGeneralU (dest, src, width, CombineAIn); } -static CARD32 -fbFetch_b8g8r8 (FbCompositeOperand *op) +static FASTCALL void +fbCombineDisjointInReverseU (CARD32 *dest, const CARD32 *src, int width) { - 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 + fbCombineDisjointGeneralU (dest, src, width, CombineBIn); } -static CARD32 -fbFetch_r5g6b5 (FbCompositeOperand *op) +static FASTCALL void +fbCombineDisjointOutU (CARD32 *dest, const CARD32 *src, int width) { - 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); + fbCombineDisjointGeneralU (dest, src, width, CombineAOut); } -static CARD32 -fbFetch_b5g6r5 (FbCompositeOperand *op) +static FASTCALL void +fbCombineDisjointOutReverseU (CARD32 *dest, const CARD32 *src, int width) { - 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); + fbCombineDisjointGeneralU (dest, src, width, CombineBOut); } -static CARD32 -fbFetch_a1r5g5b5 (FbCompositeOperand *op) +static FASTCALL void +fbCombineDisjointAtopU (CARD32 *dest, const CARD32 *src, int width) { - 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); + fbCombineDisjointGeneralU (dest, src, width, CombineAAtop); } -static CARD32 -fbFetch_x1r5g5b5 (FbCompositeOperand *op) +static FASTCALL void +fbCombineDisjointAtopReverseU (CARD32 *dest, const CARD32 *src, int width) { - 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); + fbCombineDisjointGeneralU (dest, src, width, CombineBAtop); } -static CARD32 -fbFetch_a1b5g5r5 (FbCompositeOperand *op) +static FASTCALL void +fbCombineDisjointXorU (CARD32 *dest, const CARD32 *src, int width) { - 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); + fbCombineDisjointGeneralU (dest, src, width, CombineXor); } -static CARD32 -fbFetch_x1b5g5r5 (FbCompositeOperand *op) +/* portion covered by a but not b */ +static INLINE CARD8 +fbCombineConjointOutPart (CARD8 a, CARD8 b) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD32 pixel = ((CARD16 *) line)[offset >> 4]; - CARD32 r,g,b; + /* max (1-b/a,0) */ + /* = 1-min(b/a,1) */ - 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); + /* min (1, (1-b) / a) */ + + if (b >= a) /* b >= a -> b/a >= 1 */ + return 0x00; /* 0 */ + return ~FbIntDiv(b,a); /* 1 - b/a */ } -static CARD32 -fbFetch_a4r4g4b4 (FbCompositeOperand *op) +/* portion covered by both a and b */ +static INLINE CARD8 +fbCombineConjointInPart (CARD8 a, CARD8 b) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD32 pixel = ((CARD16 *) line)[offset >> 4]; - CARD32 a,r,g,b; + /* min (1,b/a) */ - 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); + if (b >= a) /* b >= a -> b/a >= 1 */ + return 0xff; /* 1 */ + return FbIntDiv(b,a); /* b/a */ } - -static 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); -} - -static CARD32 -fbFetch_a4b4g4r4 (FbCompositeOperand *op) +static FASTCALL void +fbCombineConjointGeneralU (CARD32 *dest, const CARD32 *src, int width, CARD8 combine) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD32 pixel = ((CARD16 *) line)[offset >> 4]; - CARD32 a,r,g,b; + int i; + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 d = dest[i]; + CARD32 m,n,o,p; + CARD16 Fa, Fb, t, u, v; + CARD8 sa = s >> 24; + CARD8 da = d >> 24; - 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); -} - -static 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; + 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; + } - 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); + 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; + dest[i] = s; + } } - -static CARD32 -fbFetch_a8 (FbCompositeOperand *op) + +static FASTCALL void +fbCombineConjointOverU (CARD32 *dest, const CARD32 *src, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD32 pixel = ((CARD8 *) line)[offset>>3]; - - return pixel << 24; + fbCombineConjointGeneralU (dest, src, width, CombineAOver); } -static CARD32 -fbFetcha_a8 (FbCompositeOperand *op) + +static FASTCALL void +fbCombineConjointOverReverseU (CARD32 *dest, const CARD32 *src, int width) { - 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; + fbCombineConjointGeneralU (dest, src, width, CombineBOver); } -static CARD32 -fbFetch_r3g3b2 (FbCompositeOperand *op) + +static FASTCALL void +fbCombineConjointInU (CARD32 *dest, const CARD32 *src, int width) { - 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); + fbCombineConjointGeneralU (dest, src, width, CombineAIn); } -static CARD32 -fbFetch_b2g3r3 (FbCompositeOperand *op) + +static FASTCALL void +fbCombineConjointInReverseU (CARD32 *dest, const CARD32 *src, int width) { - 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); + fbCombineConjointGeneralU (dest, src, width, CombineBIn); } -static CARD32 -fbFetch_a2r2g2b2 (FbCompositeOperand *op) +static FASTCALL void +fbCombineConjointOutU (CARD32 *dest, const CARD32 *src, int width) { - 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; + fbCombineConjointGeneralU (dest, src, width, CombineAOut); } -#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 - -static CARD32 -fbFetch_a4 (FbCompositeOperand *op) +static FASTCALL void +fbCombineConjointOutReverseU (CARD32 *dest, const CARD32 *src, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD32 pixel = Fetch4(line, offset); - - pixel |= pixel << 4; - return pixel << 24; + fbCombineConjointGeneralU (dest, src, width, CombineBOut); } -static CARD32 -fbFetcha_a4 (FbCompositeOperand *op) +static FASTCALL void +fbCombineConjointAtopU (CARD32 *dest, const CARD32 *src, int width) { - 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; + fbCombineConjointGeneralU (dest, src, width, CombineAAtop); } -static CARD32 -fbFetch_r1g2b1 (FbCompositeOperand *op) +static FASTCALL void +fbCombineConjointAtopReverseU (CARD32 *dest, const CARD32 *src, int width) { - 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; + fbCombineConjointGeneralU (dest, src, width, CombineBAtop); } -static CARD32 -fbFetch_b1g2r1 (FbCompositeOperand *op) +static FASTCALL void +fbCombineConjointXorU (CARD32 *dest, const CARD32 *src, int width) { - 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; + fbCombineConjointGeneralU (dest, src, width, CombineXor); } -static CARD32 -fbFetch_a1r1g1b1 (FbCompositeOperand *op) +static CombineFuncU fbCombineFuncU[] = { + fbCombineClear, + fbCombineSrcU, + 0, /* CombineDst */ + fbCombineOverU, + fbCombineOverReverseU, + fbCombineInU, + fbCombineInReverseU, + fbCombineOutU, + fbCombineOutReverseU, + fbCombineAtopU, + fbCombineAtopReverseU, + fbCombineXorU, + fbCombineAddU, + fbCombineSaturateU, + 0, + 0, + fbCombineClear, + fbCombineSrcU, + 0, /* CombineDst */ + fbCombineDisjointOverU, + fbCombineSaturateU, /* DisjointOverReverse */ + fbCombineDisjointInU, + fbCombineDisjointInReverseU, + fbCombineDisjointOutU, + fbCombineDisjointOutReverseU, + fbCombineDisjointAtopU, + fbCombineDisjointAtopReverseU, + fbCombineDisjointXorU, + 0, + 0, + 0, + 0, + fbCombineClear, + fbCombineSrcU, + 0, /* CombineDst */ + fbCombineConjointOverU, + fbCombineConjointOverReverseU, + fbCombineConjointInU, + fbCombineConjointInReverseU, + fbCombineConjointOutU, + fbCombineConjointOutReverseU, + fbCombineConjointAtopU, + fbCombineConjointAtopReverseU, + fbCombineConjointXorU, +}; + +static FASTCALL void +fbCombineMaskC (CARD32 *src, CARD32 *mask, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD32 pixel = Fetch4(line, offset); - CARD32 a,r,g,b; + int i; + for (i = 0; i < width; ++i) { + CARD32 a = mask[i]; - 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 x; + CARD16 xa; -static 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; + if (!a) + { + src[i] = 0; + continue; + } - 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; -} + x = src[i]; + if (a == 0xffffffff) + { + x = x >> 24; + x |= x << 8; + x |= x << 16; + mask[i] = x; + continue; + } -static 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; + xa = x >> 24; + FbByteMulC(x, a); + src[i] = x; + FbByteMul(a, xa); + mask[i] = a; + } } -static CARD32 -fbFetch_a1 (FbCompositeOperand *op) +static FASTCALL void +fbCombineMaskValueC (CARD32 *src, const CARD32 *mask, int width) { - 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; -} + int i; + for (i = 0; i < width; ++i) { + CARD32 a = mask[i]; + CARD32 x; -/* - * All the store functions - */ + if (!a) + { + src[i] = 0; + continue; + } + + if (a == 0xffffffff) + continue; -#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 + x = src[i]; + FbByteMulC(x, a); + src[i] = x; + } +} -static void -fbStore_a8r8g8b8 (FbCompositeOperand *op, CARD32 value) + +static FASTCALL void +fbCombineMaskAlphaC (const CARD32 *src, CARD32 *mask, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - ((CARD32 *)line)[offset >> 5] = value; + int i; + for (i = 0; i < width; ++i) { + CARD32 a = mask[i]; + CARD32 x; + + if (!a) + continue; + + x = src[i] >> 24; + if (x == 0xff) + continue; + if (a == 0xffffffff) + { + x = x >> 24; + x |= x << 8; + x |= x << 16; + mask[i] = x; + continue; + } + + FbByteMul(a, x); + mask[i] = a; + } } -static void -fbStore_x8r8g8b8 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineClearC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - ((CARD32 *)line)[offset >> 5] = value & 0xffffff; + memset(dest, 0, width*sizeof(CARD32)); } -static void -fbStore_a8b8g8r8 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineSrcC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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; + fbCombineMaskValueC(src, mask, width); + memcpy(dest, src, width*sizeof(CARD32)); } -static void -fbStore_x8b8g8r8 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - Split(value); - ((CARD32 *)line)[offset >> 5] = b << 16 | g << 8 | r; + int i; + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 a = ~mask[i]; + + if (a != 0xffffffff) + { + if (a) + { + CARD32 d = dest[i]; + FbByteMulAddC(d, a, s); + s = d; + } + dest[i] = s; + } + } } -static void -fbStore_r8g8b8 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineOverReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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 + int i; + fbCombineMaskValueC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + CARD32 a = ~d >> 24; + + if (a) + { + CARD32 s = src[i]; + if (a != 0xff) + { + FbByteMulAdd(s, a, d); + } + dest[i] = s; + } + } } -static void -fbStore_b8g8r8 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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 + int i; + fbCombineMaskValueC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + CARD16 a = d >> 24; + CARD32 s = 0; + if (a) + { + s = src[i]; + if (a != 0xff) + { + FbByteMul(s, a); + } + } + dest[i] = s; + } } -static void -fbStore_r5g6b5 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + int i; + fbCombineMaskAlphaC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 a = mask[i]; + + if (a != 0xffffffff) + { + CARD32 d = 0; + if (a) + { + d = dest[i]; + FbByteMulC(d, a); + } + dest[i] = d; + } + } } -static void -fbStore_b5g6r5 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + int i; + fbCombineMaskValueC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + CARD16 a = ~d >> 24; + CARD32 s = 0; + if (a) + { + s = src[i]; + if (a != 0xff) + { + FbByteMul(s, a); + } + } + dest[i] = s; + } } -static void -fbStore_a1r5g5b5 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + int i; + fbCombineMaskAlphaC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 a = ~mask[i]; + + if (a != 0xffffffff) + { + CARD32 d = 0; + if (a) + { + d = dest[i]; + FbByteMulC(d, a); + } + dest[i] = d; + } + } } -static void -fbStore_x1r5g5b5 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + int i; + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + CARD32 s = src[i]; + CARD32 ad = ~mask[i]; + CARD16 as = d >> 24; + FbByteAddMulC(d, ad, s, as); + dest[i] = d; + } } -static void -fbStore_a1b5g5r5 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + int i; + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + + CARD32 d = dest[i]; + CARD32 s = src[i]; + CARD32 ad = mask[i]; + CARD16 as = ~d >> 24; + FbByteAddMulC(d, ad, s, as); + dest[i] = d; + } } -static void -fbStore_x1b5g5r5 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + int i; + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + CARD32 s = src[i]; + CARD32 ad = ~mask[i]; + CARD16 as = ~d >> 24; + FbByteAddMulC(d, ad, s, as); + dest[i] = d; + } } -static void -fbStore_a4r4g4b4 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineAddC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + int i; + fbCombineMaskValueC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + CARD32 d = dest[i]; + FbByteAdd(d, s); + dest[i] = d; + } } -static void -fbStore_x4r4g4b4 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineSaturateC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + int i; + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 s, d; + CARD16 sa, sr, sg, sb, da; + CARD16 t, u, v; + CARD32 m,n,o,p; + + d = dest[i]; + s = src[i]; + sa = (mask[i] >> 24); + sr = (mask[i] >> 16) & 0xff; + sg = (mask[i] >> 8) & 0xff; + sb = (mask[i] ) & 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); + + dest[i] = m|n|o|p; + } } -static void -fbStore_a4b4g4r4 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineDisjointGeneralC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width, CARD8 combine) { - 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) )); + int i; + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 s, d; + CARD32 m,n,o,p; + CARD32 Fa, Fb; + CARD16 t, u, v; + CARD32 sa; + CARD8 da; + + s = src[i]; + sa = mask[i]; + d = dest[i]; + 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; + dest[i] = s; + } } -static void -fbStore_x4b4g4r4 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineDisjointOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + fbCombineDisjointGeneralC (dest, src, mask, width, CombineAOver); } -static void -fbStore_a8 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineDisjointInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); - *pixel = value >> 24; + fbCombineDisjointGeneralC (dest, src, mask, width, CombineAIn); } -static void -fbStore_r3g3b2 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineDisjointInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + fbCombineDisjointGeneralC (dest, src, mask, width, CombineBIn); } -static void -fbStore_b2g3r3 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineDisjointOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + fbCombineDisjointGeneralC (dest, src, mask, width, CombineAOut); } -static void -fbStore_a2r2g2b2 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineDisjointOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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) )); + fbCombineDisjointGeneralC (dest, src, mask, width, CombineBOut); } -#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 +static FASTCALL void +fbCombineDisjointAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineDisjointGeneralC (dest, src, mask, width, CombineAAtop); +} -static void -fbStore_a4 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineDisjointAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - Store4(line,offset,value>>28); + fbCombineDisjointGeneralC (dest, src, mask, width, CombineBAtop); } -static void -fbStore_r1g2b1 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineDisjointXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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); + fbCombineDisjointGeneralC (dest, src, mask, width, CombineXor); } -static void -fbStore_b1g2r1 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineConjointGeneralC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width, CARD8 combine) { - 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); + int i; + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 s, d; + CARD32 m,n,o,p; + CARD32 Fa, Fb; + CARD16 t, u, v; + CARD32 sa; + CARD8 da; + + s = src[i]; + sa = mask[i]; + d = dest[i]; + 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; + dest[i] = s; + } } -static void -fbStore_a1r1g1b1 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineConjointOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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); + fbCombineConjointGeneralC (dest, src, mask, width, CombineAOver); } -static void -fbStore_a1b1g1r1 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineConjointOverReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - 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); + fbCombineConjointGeneralC (dest, src, mask, width, CombineBOver); } -static void -fbStore_a1 (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineConjointInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; - CARD32 *pixel = ((CARD32 *) line) + (offset >> 5); - CARD32 mask = FbStipMask(offset & 0x1f, 1); + fbCombineConjointGeneralC (dest, src, mask, width, CombineAIn); +} - value = value & 0x80000000 ? mask : 0; - *pixel = (*pixel & ~mask) | value; +static FASTCALL void +fbCombineConjointInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineConjointGeneralC (dest, src, mask, width, CombineBIn); } -static CARD32 -fbFetch_external (FbCompositeOperand *op) +static FASTCALL void +fbCombineConjointOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - CARD32 rgb = (*op[1].fetch) (&op[1]); - CARD32 a = (*op[2].fetch) (&op[2]); + fbCombineConjointGeneralC (dest, src, mask, width, CombineAOut); +} - return (rgb & 0xffffff) | (a & 0xff000000); +static FASTCALL void +fbCombineConjointOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineConjointGeneralC (dest, src, mask, width, CombineBOut); } +static FASTCALL void +fbCombineConjointAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineConjointGeneralC (dest, src, mask, width, CombineAAtop); +} -static CARD32 -fbFetcha_external (FbCompositeOperand *op) +static FASTCALL void +fbCombineConjointAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - return (*op[2].fetch) (&op[2]); + fbCombineConjointGeneralC (dest, src, mask, width, CombineBAtop); } -static void -fbStore_external (FbCompositeOperand *op, CARD32 value) +static FASTCALL void +fbCombineConjointXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) { - (*op[1].store) (&op[1], value | 0xff000000); - (*op[2].store) (&op[2], value & 0xff000000); + fbCombineConjointGeneralC (dest, src, mask, width, CombineXor); } -static CARD32 -fbFetch_transform (FbCompositeOperand *op) +static CombineFuncC fbCombineFuncC[] = { + fbCombineClearC, + fbCombineSrcC, + 0, /* Dest */ + fbCombineOverC, + fbCombineOverReverseC, + fbCombineInC, + fbCombineInReverseC, + fbCombineOutC, + fbCombineOutReverseC, + fbCombineAtopC, + fbCombineAtopReverseC, + fbCombineXorC, + fbCombineAddC, + fbCombineSaturateC, + 0, + 0, + fbCombineClearC, /* 0x10 */ + fbCombineSrcC, + 0, /* Dest */ + fbCombineDisjointOverC, + fbCombineSaturateC, /* DisjointOverReverse */ + fbCombineDisjointInC, + fbCombineDisjointInReverseC, + fbCombineDisjointOutC, + fbCombineDisjointOutReverseC, + fbCombineDisjointAtopC, + fbCombineDisjointAtopReverseC, + fbCombineDisjointXorC, /* 0x1b */ + 0, + 0, + 0, + 0, + fbCombineClearC, + fbCombineSrcC, + 0, /* Dest */ + fbCombineConjointOverC, + fbCombineConjointOverReverseC, + fbCombineConjointInC, + fbCombineConjointInReverseC, + fbCombineConjointOutC, + fbCombineConjointOutReverseC, + fbCombineConjointAtopC, + fbCombineConjointAtopReverseC, + fbCombineConjointXorC, +}; + + +FbComposeFunctions composeFunctions = { + fbCombineFuncU, + fbCombineFuncC, + fbCombineMaskU +}; + + +static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer) { - pixman_vector_t v; - int x, y; - int minx, maxx, miny, maxy; - CARD32 rtot, gtot, btot, atot; - CARD32 xerr, yerr; - CARD32 bits; - pixman_box16_t box; + FbBits *bits; + FbStride stride; + int bpp; + int xoff, yoff; + CARD32 color; + CARD32 *end; + fetchPixelProc fetch = fetchPixelProcForPicture(pict); +#ifdef PIXMAN_INDEXED_FORMATS + miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; +#else + miIndexedPtr indexed = 0; +#endif - v.vector[0] = IntToxFixed(op->u.transform.x); - v.vector[1] = IntToxFixed(op->u.transform.y); - v.vector[2] = xFixed1; - if (!pixman_transform_point (op->u.transform.transform, &v)) - return 0; - switch (op->u.transform.filter) { - case PIXMAN_FILTER_FAST: - case PIXMAN_FILTER_NEAREST: - y = xFixedToInt (v.vector[1]) + op->u.transform.top_y; - x = xFixedToInt (v.vector[0]) + op->u.transform.left_x; - if (op->u.transform.repeat) - { - y = MOD (y, op->u.transform.height); - x = MOD (x, op->u.transform.width); - } - if (pixman_region_contains_point (op->src_clip, x, y, &box)) - { - (*op[1].set) (&op[1], x, y); - bits = (*op[1].fetch) (&op[1]); - } - else - bits = 0; - break; - case PIXMAN_FILTER_GOOD: - case PIXMAN_FILTER_BEST: - case PIXMAN_FILTER_BILINEAR: - 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; - int tx, ty; + fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff); + bits += yoff*stride + (xoff*bpp >> FB_SHIFT); - if (op->u.transform.repeat) - ty = MOD (y, op->u.transform.height); - else - ty = y; - - xerr = xFixed1 - xFixedFrac (v.vector[0]); - for (x = minx; x <= maxx; x++) - { - if (op->u.transform.repeat) - tx = MOD (x, op->u.transform.width); - else - tx = x; + color = fetch(bits, 0, indexed); - if (pixman_region_contains_point (op->src_clip, tx, ty, &box)) - { - (*op[1].set) (&op[1], tx, ty); - bits = (*op[1].fetch) (&op[1]); - { - Splita(bits); - lrtot += r * xerr; - lgtot += g * xerr; - lbtot += b * xerr; - latot += a * xerr; - } - } - 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; + end = buffer + width; + while (buffer < end) + *buffer++ = color; } -static CARD32 -fbFetcha_transform (FbCompositeOperand *op) +static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer) { - pixman_vector_t v; - int x, y; - int minx, maxx, miny, maxy; - CARD32 rtot, gtot, btot, atot; - CARD32 xerr, yerr; - CARD32 bits; - pixman_box16_t box; + FbBits *bits; + FbStride stride; + int bpp; + int xoff, yoff; + fetchProc fetch = fetchProcForPicture(pict); +#ifdef PIXMAN_INDEXED_FORMATS + miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; +#else + miIndexedPtr indexed = 0; +#endif + + fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff); + x += xoff; + y += yoff; + + bits += y*stride; + + fetch(bits, x, width, buffer, indexed); +} + +// #define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b)) + + +#ifdef PIXMAN_GRADIENTS +static CARD32 gradientPixel(const SourcePictPtr pGradient, xFixed_48_16 pos, unsigned int spread) +{ + int ipos = (pos * PICT_GRADIENT_STOPTABLE_SIZE - 1) >> 16; + + /* calculate the actual offset. */ + if (ipos < 0 || ipos >= PICT_GRADIENT_STOPTABLE_SIZE) { + if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal) { + ipos = ipos % PICT_GRADIENT_STOPTABLE_SIZE; + ipos = ipos < 0 ? PICT_GRADIENT_STOPTABLE_SIZE + ipos : ipos; + + } else if (spread == RepeatReflect) { + const int limit = PICT_GRADIENT_STOPTABLE_SIZE * 2 - 1; + ipos = ipos % limit; + ipos = ipos < 0 ? limit + ipos : ipos; + ipos = ipos >= PICT_GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos; + + } else if (spread == RepeatPad) { + if (ipos < 0) + ipos = 0; + else if (ipos >= PICT_GRADIENT_STOPTABLE_SIZE) + ipos = PICT_GRADIENT_STOPTABLE_SIZE-1; + } else { /* RepeatNone */ + return 0; + } + } + + assert(ipos >= 0); + assert(ipos < PICT_GRADIENT_STOPTABLE_SIZE); + + return pGradient->linear.colorTable[ipos]; +} + +static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer) +{ + SourcePictPtr pGradient = pict->pSourcePict; + CARD32 *end = buffer + width; + + if (pGradient->type == SourcePictTypeSolidFill) { + register CARD32 color = pGradient->solidFill.color; + while (buffer < end) { + *buffer++ = color; + } + } else if (pGradient->type == SourcePictTypeLinear) { + PictVector v, unit; + xFixed_32_32 l; + xFixed_48_16 dx, dy, a, b, off; + + v.vector[0] = IntToxFixed(x); + v.vector[1] = IntToxFixed(y); + v.vector[2] = xFixed1; + if (pict->transform) { + if (!PictureTransformPoint3d (pict->transform, &v)) + return; + unit.vector[0] = pict->transform->matrix[0][0]; + unit.vector[1] = pict->transform->matrix[1][0]; + unit.vector[2] = pict->transform->matrix[2][0]; + } else { + unit.vector[0] = xFixed1; + unit.vector[1] = 0; + unit.vector[2] = 0; + } + + dx = pGradient->linear.p2.x - pGradient->linear.p1.x; + dy = pGradient->linear.p2.y - pGradient->linear.p1.y; + l = dx*dx + dy*dy; + if (l != 0) { + a = (dx << 32) / l; + b = (dy << 32) / l; + off = (-a*pGradient->linear.p1.x - b*pGradient->linear.p1.y)>>16; + } + if (l == 0 || (unit.vector[2] == 0 && v.vector[2] == xFixed1)) { + xFixed_48_16 inc, t; + /* affine transformation only */ + if (l == 0) { + t = 0; + inc = 0; + } else { + t = ((a*v.vector[0] + b*v.vector[1]) >> 16) + off; + inc = (a * unit.vector[0] + b * unit.vector[1]) >> 16; + } + while (buffer < end) { + *buffer++ = gradientPixel(pGradient, t, pict->repeat); + t += inc; + } + } else { + /* projective transformation */ + while (buffer < end) { + xFixed_48_16 t; + if (v.vector[2] == 0) { + t = 0; + } else { + xFixed_48_16 x, y; + x = ((xFixed_48_16)v.vector[0] << 16) / v.vector[2]; + y = ((xFixed_48_16)v.vector[1] << 16) / v.vector[2]; + t = ((a*x + b*y) >> 16) + off; + } + *buffer++ = gradientPixel(pGradient, t, pict->repeat); + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } else { + /* radial or conical */ + Bool projective = FALSE; + double cx = 1.; + double cy = 0.; + double cz = 0.; + double rx = x; + double ry = y; + double rz = 1.; + + if (pict->transform) { + PictVector v; + v.vector[0] = IntToxFixed(x); + v.vector[1] = IntToxFixed(y); + v.vector[2] = xFixed1; + if (!PictureTransformPoint3d (pict->transform, &v)) + return; + + cx = pict->transform->matrix[0][0]/65536.; + cy = pict->transform->matrix[1][0]/65536.; + cz = pict->transform->matrix[2][0]/65536.; + rx = v.vector[0]/65536.; + ry = v.vector[1]/65536.; + rz = v.vector[2]/65536.; + projective = pict->transform->matrix[2][0] != 0 || v.vector[2] != xFixed1; + } + + if (pGradient->type == SourcePictTypeRadial) { + if (!projective) { + rx -= pGradient->radial.fx; + ry -= pGradient->radial.fy; + + while (buffer < end) { + double b = 2*(rx*pGradient->radial.dx + ry*pGradient->radial.dy); + double c = -(rx*rx + ry*ry); + double det = (b * b) - (4 * pGradient->radial.a * c); + double s = (-b + sqrt(det))/(2. * pGradient->radial.a); + *buffer = gradientPixel(pGradient, + (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536), + pict->repeat); + ++buffer; + rx += cx; + ry += cy; + } + } else { + while (buffer < end) { + double x, y; + double b, c, det, s; + if (rz != 0) { + x = rx/rz; + y = ry/rz; + } else { + x = y = 0.; + } + x -= pGradient->radial.fx; + y -= pGradient->radial.fy; + b = 2*(x*pGradient->radial.dx + y*pGradient->radial.dy); + c = -(x*x + y*y); + det = (b * b) - (4 * pGradient->radial.a * c); + s = (-b + sqrt(det))/(2. * pGradient->radial.a); + *buffer = gradientPixel(pGradient, + (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536), + pict->repeat); + ++buffer; + rx += cx; + ry += cy; + rz += cz; + } + } + } else /* SourcePictTypeConical */ { + double a = pGradient->conical.angle/(180.*65536); + if (!projective) { + rx -= pGradient->conical.center.x/65536.; + ry -= pGradient->conical.center.y/65536.; + + while (buffer < end) { + double angle = atan2(ry, rx) + a; + *buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))), + pict->repeat); + ++buffer; + rx += cx; + ry += cy; + } + } else { + + while (buffer < end) { + double x, y; + if (rz != 0) { + x = rx/rz; + y = ry/rz; + } else { + x = y = 0.; + } + x -= pGradient->conical.center.x/65536.; + y -= pGradient->conical.center.y/65536.; + double angle = atan2(y, x) + a; + *buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))), + pict->repeat); + ++buffer; + rx += cx; + ry += cy; + rz += cz; + } + } + } + } +} +#endif /* PIXMAN_GRADIENTS */ + + + +static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer) +{ + FbBits *bits; + FbStride stride; + int bpp; + int xoff, yoff; + fetchPixelProc fetch; + PictVector v; + PictVector unit; + int i; + BoxRec box; +#ifdef PIXMAN_INDEXED_FORMATS + miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; +#else + miIndexedPtr indexed = 0; +#endif + + fetch = fetchPixelProcForPicture(pict); + + fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff); + x += xoff; + y += yoff; - v.vector[0] = IntToxFixed(op->u.transform.x); - v.vector[1] = IntToxFixed(op->u.transform.y); + v.vector[0] = IntToxFixed(x); + v.vector[1] = IntToxFixed(y); v.vector[2] = xFixed1; - if (!pixman_transform_point (op->u.transform.transform, &v)) - return 0; - switch (op->u.transform.filter) { - case PIXMAN_FILTER_FAST: - case PIXMAN_FILTER_NEAREST: - y = xFixedToInt (v.vector[1]) + op->u.transform.left_x; - x = xFixedToInt (v.vector[0]) + op->u.transform.top_y; - if (op->u.transform.repeat) - { - y = MOD (y, op->u.transform.height); - x = MOD (x, op->u.transform.width); - } - if (pixman_region_contains_point (op->src_clip, x, y, &box)) - { - (*op[1].set) (&op[1], x, y); - bits = (*op[1].fetcha) (&op[1]); - } - else - bits = 0; - break; - case PIXMAN_FILTER_GOOD: - case PIXMAN_FILTER_BEST: - case PIXMAN_FILTER_BILINEAR: - 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; - int tx, ty; - if (op->u.transform.repeat) - ty = MOD (y, op->u.transform.height); - else - ty = y; - - xerr = xFixed1 - xFixedFrac (v.vector[0]); - for (x = minx; x <= maxx; x++) - { - if (op->u.transform.repeat) - tx = MOD (x, op->u.transform.width); - else - tx = x; - - if (pixman_region_contains_point (op->src_clip, tx, ty, &box)) - { - (*op[1].set) (&op[1], tx, ty); - bits = (*op[1].fetcha) (&op[1]); - { - Splita(bits); - lrtot += r * xerr; - lgtot += g * xerr; - lbtot += b * xerr; - latot += a * xerr; - } - } - 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; + /* when using convolution filters one might get here without a transform */ + if (pict->transform) { + if (!PictureTransformPoint3d (pict->transform, &v)) + return; + unit.vector[0] = pict->transform->matrix[0][0]; + unit.vector[1] = pict->transform->matrix[1][0]; + unit.vector[2] = pict->transform->matrix[2][0]; + } else { + unit.vector[0] = xFixed1; + unit.vector[1] = 0; + unit.vector[2] = 0; + } + + if (pict->filter == PIXMAN_FILTER_NEAREST) + { + if (pict->repeat == RepeatNormal) { + if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) { + box = pict->pCompositeClip->extents; + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } else { + y = MOD((v.vector[1]/v.vector[2]), pict->pDrawable->height); + x = MOD((v.vector[0]/v.vector[2]), pict->pDrawable->width); + buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed); + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } else { + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } else { + y = MOD((v.vector[1]/v.vector[2]), pict->pDrawable->height); + x = MOD((v.vector[0]/v.vector[2]), pict->pDrawable->width); + if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box)) + buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed); + else + buffer[i] = 0; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } else { + if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) { + box = pict->pCompositeClip->extents; + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } else { + y = (v.vector[1]/v.vector[2]); + x = (v.vector[0]/v.vector[2]); + buffer[i] = ((x < box.x1) | (x >= box.x2) | (y < box.y1) | (y >= box.y2)) ? + 0 : fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed); + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } else { + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } else { + y = (v.vector[1]/v.vector[2]); + x = (v.vector[0]/v.vector[2]); + if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box)) + buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed); + else + buffer[i] = 0; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } + } else if (pict->filter == PIXMAN_FILTER_BILINEAR) { + if (pict->repeat == RepeatNormal) { + if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) { + box = pict->pCompositeClip->extents; + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } else { + int x1, x2, y1, y2, distx, idistx, disty, idisty; + FbBits *b; + CARD32 tl, tr, bl, br; + xFixed_48_16 div; + + div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((xFixed)div >> 8) & 0xff; + x2 = x1 + 1; + div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + y2 = y1 + 1; + disty = ((xFixed)div >> 8) & 0xff; + + idistx = 256 - distx; + idisty = 256 - disty; + + x1 = MOD (x1, pict->pDrawable->width); + x2 = MOD (x2, pict->pDrawable->width); + y1 = MOD (y1, pict->pDrawable->height); + y2 = MOD (y2, pict->pDrawable->height); + + b = bits + (y1 + pict->pDrawable->y)*stride; + + tl = fetch(b, x1 + pict->pDrawable->x, indexed); + tr = fetch(b, x2 + pict->pDrawable->x, indexed); + b = bits + (y2 + pict->pDrawable->y)*stride; + bl = fetch(b, x1 + pict->pDrawable->x, indexed); + br = fetch(b, x2 + pict->pDrawable->x, indexed); + + FbByteAddMul_256(tl, idistx, tr, distx); + FbByteAddMul_256(bl, idistx, br, distx); + FbByteAddMul_256(tl, idisty, bl, disty); + buffer[i] = tl; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } else { + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } else { + int x1, x2, y1, y2, distx, idistx, disty, idisty; + FbBits *b; + CARD32 tl, tr, bl, br; + xFixed_48_16 div; + + div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((xFixed)div >> 8) & 0xff; + x2 = x1 + 1; + div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + y2 = y1 + 1; + disty = ((xFixed)div >> 8) & 0xff; + + idistx = 256 - distx; + idisty = 256 - disty; + + x1 = MOD (x1, pict->pDrawable->width); + x2 = MOD (x2, pict->pDrawable->width); + y1 = MOD (y1, pict->pDrawable->height); + y2 = MOD (y2, pict->pDrawable->height); + + b = bits + (y1 + pict->pDrawable->y)*stride; + + tl = pixman_region_contains_point(pict->pCompositeClip, x1, y1, &box) + ? fetch(b, x1 + pict->pDrawable->x, indexed) : 0; + tr = pixman_region_contains_point(pict->pCompositeClip, x2, y1, &box) + ? fetch(b, x2 + pict->pDrawable->x, indexed) : 0; + b = bits + (y2 + pict->pDrawable->y)*stride; + bl = pixman_region_contains_point(pict->pCompositeClip, x1, y2, &box) + ? fetch(b, x1 + pict->pDrawable->x, indexed) : 0; + br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box) + ? fetch(b, x2 + pict->pDrawable->x, indexed) : 0; + + FbByteAddMul_256(tl, idistx, tr, distx); + FbByteAddMul_256(bl, idistx, br, distx); + FbByteAddMul_256(tl, idisty, bl, disty); + buffer[i] = tl; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } else { + if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) { + box = pict->pCompositeClip->extents; + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } else { + int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off; + FbBits *b; + CARD32 tl, tr, bl, br; + Bool x1_out, x2_out, y1_out, y2_out; + xFixed_48_16 div; + + div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((xFixed)div >> 8) & 0xff; + x2 = x1 + 1; + div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + y2 = y1 + 1; + disty = ((xFixed)div >> 8) & 0xff; + + idistx = 256 - distx; + idisty = 256 - disty; + + b = bits + (y1 + pict->pDrawable->y)*stride; + x_off = x1 + pict->pDrawable->x; + + x1_out = (x1 < box.x1) | (x1 >= box.x2); + x2_out = (x2 < box.x1) | (x2 >= box.x2); + y1_out = (y1 < box.y1) | (y1 >= box.y2); + y2_out = (y2 < box.y1) | (y2 >= box.y2); + + tl = x1_out|y1_out ? 0 : fetch(b, x_off, indexed); + tr = x2_out|y1_out ? 0 : fetch(b, x_off + 1, indexed); + b += stride; + bl = x1_out|y2_out ? 0 : fetch(b, x_off, indexed); + br = x2_out|y2_out ? 0 : fetch(b, x_off + 1, indexed); + + FbByteAddMul_256(tl, idistx, tr, distx); + FbByteAddMul_256(bl, idistx, br, distx); + FbByteAddMul_256(tl, idisty, bl, disty); + buffer[i] = tl; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } else { + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } else { + int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off; + FbBits *b; + CARD32 tl, tr, bl, br; + xFixed_48_16 div; + + div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((xFixed)div >> 8) & 0xff; + x2 = x1 + 1; + div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + y2 = y1 + 1; + disty = ((xFixed)div >> 8) & 0xff; + + idistx = 256 - distx; + idisty = 256 - disty; + + b = bits + (y1 + pict->pDrawable->y)*stride; + x_off = x1 + pict->pDrawable->x; + + tl = pixman_region_contains_point(pict->pCompositeClip, x1, y1, &box) + ? fetch(b, x_off, indexed) : 0; + tr = pixman_region_contains_point(pict->pCompositeClip, x2, y1, &box) + ? fetch(b, x_off + 1, indexed) : 0; + b += stride; + bl = pixman_region_contains_point(pict->pCompositeClip, x1, y2, &box) + ? fetch(b, x_off, indexed) : 0; + br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box) + ? fetch(b, x_off + 1, indexed) : 0; + + FbByteAddMul_256(tl, idistx, tr, distx); + FbByteAddMul_256(bl, idistx, br, distx); + FbByteAddMul_256(tl, idisty, bl, disty); + buffer[i] = tl; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } +#ifdef PIXMAN_CONVOLUTION + } else if (pict->filter == PictFilterConvolution) { + xFixed *params = pict->filter_params; + INT32 cwidth = xFixedToInt(params[0]); + INT32 cheight = xFixedToInt(params[1]); + int xoff = params[0] >> 1; + int yoff = params[1] >> 1; + params += 2; + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } else { + int x1, x2, y1, y2, x, y; + INT32 srtot, sgtot, sbtot, satot; + xFixed *p = params; + xFixed_48_16 tmp; + tmp = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2] - xoff; + x1 = xFixedToInt(tmp); + x2 = x1 + cwidth; + tmp = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2] - yoff; + y1 = xFixedToInt(tmp); + y2 = y1 + cheight; + + srtot = sgtot = sbtot = satot = 0; + + for (y = y1; y < y2; y++) { + int ty = (pict->repeat == RepeatNormal) ? MOD (y, pict->pDrawable->height) : y; + for (x = x1; x < x2; x++) { + if (*p) { + int tx = (pict->repeat == RepeatNormal) ? MOD (x, pict->pDrawable->width) : x; + if (pixman_region_contains_point (pict->pCompositeClip, tx, ty, &box)) { + FbBits *b = bits + (ty + pict->pDrawable->y)*stride; + CARD32 c = fetch(b, tx + pict->pDrawable->x, indexed); + + srtot += Red(c) * *p; + sgtot += Green(c) * *p; + sbtot += Blue(c) * *p; + satot += Alpha(c) * *p; + } + } + p++; + } + } + + if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff; + if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff; + if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff; + if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff; + + buffer[i] = ((satot << 24) | + (srtot << 16) | + (sgtot << 8) | + (sbtot )); + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } +#endif } - return bits; } -static FbAccessMap const 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 }, - - /* 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 }, - /* 1bpp formats */ - { PICT_a1, fbFetch_a1, fbFetcha_a1, fbStore_a1 }, -}; -#define NumAccessMap (sizeof fbAccessMap / sizeof fbAccessMap[0]) - -static void -fbStepOver (FbCompositeOperand *op) +static void fbFetchExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer) { - op->u.drawable.offset += op->u.drawable.bpp; -} + int i; + CARD32 _alpha_buffer[SCANLINE_BUFFER_LENGTH]; + CARD32 *alpha_buffer = _alpha_buffer; -static void -fbStepDown (FbCompositeOperand *op) -{ - op->u.drawable.line += op->u.drawable.stride; - op->u.drawable.offset = op->u.drawable.start_offset; -} + if (!pict->alphaMap) { + fbFetchTransformed(pict, x, y, width, buffer); + return; + } + + if (width > SCANLINE_BUFFER_LENGTH) + alpha_buffer = (CARD32 *) malloc(width*sizeof(CARD32)); + + fbFetchTransformed(pict, x, y, width, buffer); + fbFetchTransformed(pict->alphaMap, x - pict->alphaOrigin.x, y - pict->alphaOrigin.y, width, alpha_buffer); + for (i = 0; i < width; ++i) { + int a = alpha_buffer[i]>>24; + buffer[i] = (a << 24) + | (div_255(Red(buffer[i]) * a) << 16) + | (div_255(Green(buffer[i]) * a) << 8) + | (div_255(Blue(buffer[i]) * a)); + } -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; + if (alpha_buffer != _alpha_buffer) + free(alpha_buffer); } -static void -fbStepOver_external (FbCompositeOperand *op) +static void fbStore(PicturePtr pict, int x, int y, int width, CARD32 *buffer) { - (*op[1].over) (&op[1]); - (*op[2].over) (&op[2]); -} + FbBits *bits; + FbStride stride; + int bpp; + int xoff, yoff; + storeProc store = storeProcForPicture(pict); +#ifdef PIXMAN_INDEXED_FORMATS + miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; +#else + miIndexedPtr indexed = 0; +#endif -static void -fbStepDown_external (FbCompositeOperand *op) -{ - (*op[1].down) (&op[1]); - (*op[2].down) (&op[2]); -} + fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff); + x += xoff; + y += yoff; + + bits += y*stride; + store(bits, buffer, x, width, indexed); +} + +static void fbStoreExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer) +{ + FbBits *bits, *alpha_bits; + FbStride stride, astride; + int bpp, abpp; + int xoff, yoff; + int ax, ay; + storeProc store; + storeProc astore; +#ifdef PIXMAN_INDEXED_FORMATS + miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; +#else + miIndexedPtr indexed = 0; +#endif + miIndexedPtr aindexed; -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); -} + if (!pict->alphaMap) { + fbStore(pict, x, y, width, buffer); + return; + } -static void -fbStepOver_transform (FbCompositeOperand *op) -{ - op->u.transform.x++; -} + store = storeProcForPicture(pict); + astore = storeProcForPicture(pict->alphaMap); +#ifdef PIXMAN_INDEXED_FORMATS + aindexed = (miIndexedPtr) pict->alphaMap->pFormat->index.devPrivate; +#else + aindexed = 0; +#endif -static void -fbStepDown_transform (FbCompositeOperand *op) -{ - op->u.transform.y++; - op->u.transform.x = op->u.transform.start_x; -} + ax = x; + ay = y; -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; + fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff); + x += xoff; + y += yoff; + fbGetDrawable (pict->alphaMap->pDrawable, alpha_bits, astride, abpp, xoff, yoff); + ax += xoff; + ay += yoff; + + bits += y*stride; + alpha_bits += (ay - pict->alphaOrigin.y)*astride; + + + store(bits, buffer, x, width, indexed); + astore(alpha_bits, buffer, ax - pict->alphaOrigin.x, width, aindexed); } +typedef void (*scanStoreProc)(PicturePtr , int , int , int , CARD32 *); +typedef void (*scanFetchProc)(PicturePtr , int , int , int , CARD32 *); -int -fbBuildCompositeOperand (pixman_image_t *image, - FbCompositeOperand op[4], - INT16 x, - INT16 y, - Bool transform, - Bool alpha) +static void +fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) { - /* Check for transform */ - if (transform && image->transform) - { - if (!fbBuildCompositeOperand (image, &op[1], 0, 0, 0, alpha)) - return 0; - - op->u.transform.top_y = image->pixels->y; - op->u.transform.left_x = image->pixels->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 = image->transform; - op->u.transform.filter = image->filter; - op->u.transform.repeat = image->repeat; - op->u.transform.width = image->pixels->width; - op->u.transform.height = image->pixels->height; - - op->fetch = fbFetch_transform; - op->fetcha = fbFetcha_transform; - op->store = 0; - op->over = fbStepOver_transform; - op->down = fbStepDown_transform; - op->set = fbSet_transform; - - op->src_clip = op[1].src_clip; - op->dst_clip = op[1].dst_clip; - - return 1; - } - /* Check for external alpha */ - else if (alpha && image->alphaMap) - { - if (!fbBuildCompositeOperand (image, &op[1], x, y, 0, 0)) - return 0; - if (!fbBuildCompositeOperand (image->alphaMap, &op[2], - x - image->alphaOrigin.x, - y - image->alphaOrigin.y, - 0, 0)) - return 0; - op->u.external.alpha_dx = image->alphaOrigin.x; - op->u.external.alpha_dy = image->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->src_clip = op[1].dst_clip; - op->dst_clip = op[1].dst_clip; - - return 1; + CARD32 *src_buffer = scanline_buffer; + CARD32 *dest_buffer = src_buffer + data->width; + int i; + scanStoreProc store; + scanFetchProc fetchSrc = 0, fetchMask = 0, fetchDest = 0; + + if (data->op == PIXMAN_OPERATOR_CLEAR) + fetchSrc = 0; +#ifdef PIXMAN_GRADIENTS + else if (!data->src->pDrawable) { + if (data->src->pSourcePict) + fetchSrc = fbFetchSourcePict; } - /* Build simple operand */ +#endif + else if (data->src->alphaMap) + fetchSrc = fbFetchExternalAlpha; + else if (data->src->repeat == RepeatNormal && + data->src->pDrawable->width == 1 && data->src->pDrawable->height == 1) + fetchSrc = fbFetchSolid; +#ifdef PIXMAN_CONVOLUTION + else if (!data->src->transform && data->src->filter != PictFilterConvolution) + fetchSrc = fbFetch; +#else + else if (!data->src->transform) + fetchSrc = fbFetch; +#endif else - { - int i; - int xoff, yoff; + fetchSrc = fbFetchTransformed; - for (i = 0; i < NumAccessMap; i++) - if (fbAccessMap[i].format_code == image->format_code) - { - 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->dst_clip = image->pCompositeClip; - if (image->compositeClipSource) - op->src_clip = image->pCompositeClip; - else - op->src_clip = image->pSourceClip; - - FbGetPixels (image->pixels, bits, stride, bpp, - xoff, yoff); - if (image->repeat && image->pixels->width == 1 && - image->pixels->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; + if (data->mask && data->op != PIXMAN_OPERATOR_CLEAR) { +#ifdef PIXMAN_GRADIENTS + if (!data->mask->pDrawable) { + if (data->mask->pSourcePict) + fetchMask = fbFetchSourcePict; + } else +#endif + if (data->mask->alphaMap) + fetchMask = fbFetchExternalAlpha; + else if (data->mask->repeat == RepeatNormal + && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1) + fetchMask = fbFetchSolid; +#ifdef PIXMAN_CONVOLUTION + else if (!data->mask->transform && data->mask->filter != PictFilterConvolution) + fetchMask = fbFetch; +#else + else if (!data->mask->transform) + fetchMask = fbFetch; +#endif + else + fetchMask = fbFetchTransformed; + } else { + fetchMask = 0; + } + + if (data->dest->alphaMap) { + fetchDest = fbFetchExternalAlpha; + store = fbStoreExternalAlpha; + } else { + fetchDest = fbFetch; + store = fbStore; + } + if (data->op == PIXMAN_OPERATOR_CLEAR || data->op == PIXMAN_OPERATOR_SRC) + fetchDest = 0; + + if (fetchSrc && fetchMask && data->mask && data->mask->componentAlpha && PICT_FORMAT_RGB(data->mask->format_code)) { + CARD32 *mask_buffer = dest_buffer + data->width; + CombineFuncC compose = composeFunctions.combineC[data->op]; + if (!compose) + return; + + for (i = 0; i < data->height; ++i) + { + /* fill first half of scanline with source */ + fetchSrc(data->src, data->xSrc, data->ySrc + i, data->width, src_buffer); + fetchMask(data->mask, data->xMask, data->yMask + i, data->width, mask_buffer); + + /* fill dest into second half of scanline */ + if (fetchDest) + fetchDest(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer); + + /* blend */ + compose(dest_buffer, src_buffer, mask_buffer, data->width); + + /* write back */ + store(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer); + } + } else { + + CombineFuncU compose = composeFunctions.combineU[data->op]; + if (!compose) + return; + + if (fetchSrc == fbFetchSolid && (!fetchMask || fetchMask == fbFetchSolid)) { + fetchSrc(data->src, data->xSrc, data->ySrc, data->width, src_buffer); + if (fetchMask) { + fetchMask(data->mask, data->xMask, data->yMask, data->width, dest_buffer); + composeFunctions.combineMaskU(src_buffer, dest_buffer, data->width); + } + fetchSrc = 0; + fetchMask = 0; + } + + for (i = 0; i < data->height; ++i) { + /* fill first half of scanline with source */ + if (fetchSrc) { + fetchSrc(data->src, data->xSrc, data->ySrc + i, data->width, src_buffer); + + /* add in mask */ + if (fetchMask) { + fetchMask(data->mask, data->xMask, data->yMask + i, data->width, dest_buffer); + composeFunctions.combineMaskU(src_buffer, dest_buffer, data->width); + } + } + + /* fill dest into second half of scanline */ + if (fetchDest) + fetchDest(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer); + + /* blend */ + compose(dest_buffer, src_buffer, data->width); + + /* write back */ + store(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer); + } } } @@ -2683,74 +3503,107 @@ pixman_compositeGeneral (pixman_operator CARD16 width, CARD16 height) { - FbCompositeOperand src[4],msk[4],dst[4],*pmsk; - FbCompositeOperand *srcPict, *srcAlpha; - FbCompositeOperand *dstPict, *dstAlpha; - FbCompositeOperand *mskPict = 0, *mskAlpha = 0; - FbCombineFunc f; - int w; - - if (!fbBuildCompositeOperand (pSrc, src, xSrc, ySrc, TRUE, TRUE)) - return; - if (!fbBuildCompositeOperand (pDst, dst, xDst, yDst, FALSE, TRUE)) - return; - if (pSrc->alphaMap) - { - srcPict = &src[1]; - srcAlpha = &src[2]; - } - else - { - srcPict = &src[0]; - srcAlpha = 0; - } - if (pDst->alphaMap) - { - dstPict = &dst[1]; - dstAlpha = &dst[2]; - } - else - { - dstPict = &dst[0]; - dstAlpha = 0; - } - f = fbCombineFuncU[op]; - if (pMask) - { - if (!fbBuildCompositeOperand (pMask, msk, xMask, yMask, TRUE, TRUE)) + pixman_region16_t *region = pixman_region_create(); + int n; + BoxPtr pbox; + Bool srcRepeat = FALSE; + Bool maskRepeat = FALSE; + int w, h; + CARD32 _scanline_buffer[SCANLINE_BUFFER_LENGTH*3]; + CARD32 *scanline_buffer = _scanline_buffer; + FbComposeData compose_data; + + if (pSrc->pDrawable) + srcRepeat = pSrc->repeat == RepeatNormal && !pSrc->transform + && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1); + + if (pMask && pMask->pDrawable) + maskRepeat = pMask->repeat == RepeatNormal && !pMask->transform + && (pMask->pDrawable->width != 1 || pMask->pDrawable->height != 1); + + if (op == PIXMAN_OPERATOR_OVER && !pMask && !pSrc->transform && !PICT_FORMAT_A(pSrc->format_code) && !pSrc->alphaMap) + op = PIXMAN_OPERATOR_SRC; + + if (!FbComputeCompositeRegion (region, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height)) return; - pmsk = msk; - if (pMask->componentAlpha) - f = fbCombineFuncC[op]; - if (pMask->alphaMap) - { - mskPict = &msk[1]; - mskAlpha = &msk[2]; - } - else - { - mskPict = &msk[0]; - mskAlpha = 0; - } - } - else - pmsk = 0; - while (height--) - { - w = width; - - while (w--) - { - (*f) (src, pmsk, dst); - (*src->over) (src); - (*dst->over) (dst); - if (pmsk) - (*pmsk->over) (pmsk); + + compose_data.op = op; + compose_data.src = pSrc; + compose_data.mask = pMask; + compose_data.dest = pDst; + if (width > SCANLINE_BUFFER_LENGTH) + scanline_buffer = (CARD32 *) malloc(width * 3 * sizeof(CARD32)); + + n = PIXREGION_NUM_RECTS (region); + pbox = PIXREGION_RECTS (region); + while (n--) + { + h = pbox->y2 - pbox->y1; + compose_data.ySrc = pbox->y1 - yDst + ySrc; + compose_data.yMask = pbox->y1 - yDst + yMask; + compose_data.yDest = pbox->y1; + while (h) + { + compose_data.height = h; + w = pbox->x2 - pbox->x1; + compose_data.xSrc = pbox->x1 - xDst + xSrc; + compose_data.xMask = pbox->x1 - xDst + xMask; + compose_data.xDest = pbox->x1; + if (maskRepeat) + { + compose_data.yMask = mod (compose_data.yMask, pMask->pDrawable->height); + if (compose_data.height > pMask->pDrawable->height - compose_data.yMask) + compose_data.height = pMask->pDrawable->height - compose_data.yMask; + } + if (srcRepeat) + { + compose_data.ySrc = mod (compose_data.ySrc, pSrc->pDrawable->height); + if (compose_data.height > pSrc->pDrawable->height - compose_data.ySrc) + compose_data.height = pSrc->pDrawable->height - compose_data.ySrc; + } + while (w) + { + compose_data.width = w; + if (maskRepeat) + { + compose_data.xMask = mod (compose_data.xMask, pMask->pDrawable->width); + if (compose_data.width > pMask->pDrawable->width - compose_data.xMask) + compose_data.width = pMask->pDrawable->width - compose_data.xMask; + } + if (srcRepeat) + { + compose_data.xSrc = mod (compose_data.xSrc, pSrc->pDrawable->width); + if (compose_data.width > pSrc->pDrawable->width - compose_data.xSrc) + compose_data.width = pSrc->pDrawable->width - compose_data.xSrc; + } + fbCompositeRect(&compose_data, scanline_buffer); + w -= compose_data.width; + compose_data.xSrc += compose_data.width; + compose_data.xMask += compose_data.width; + compose_data.xDest += compose_data.width; + } + h -= compose_data.height; + compose_data.ySrc += compose_data.height; + compose_data.yMask += compose_data.height; + compose_data.yDest += compose_data.height; } - (*src->down) (src); - (*dst->down) (dst); - if (pmsk) - (*pmsk->down) (pmsk); + pbox++; } + pixman_region_destroy (region); + + if (scanline_buffer != _scanline_buffer) + free(scanline_buffer); } +#endif Index: icimage.h =================================================================== RCS file: /cvs/cairo/libpixman/src/icimage.h,v retrieving revision 1.26 diff -p -u -r1.26 icimage.h --- icimage.h 25 Jun 2005 03:13:19 -0000 1.26 +++ icimage.h 30 Jul 2005 19:10:58 -0000 @@ -138,13 +138,12 @@ struct pixman_image { typedef uint8_t FbIndexType; #endif -/* XXX: We're not supporting indexed operations, right? +/* XXX: We're not supporting indexed operations, right? */ typedef struct _FbIndexed { int color; uint32_t rgba[IC_MAX_INDEXED]; FbIndexType ent[32768]; } FbIndexedRec, *FbIndexedPtr; -*/ #define FbCvtR8G8B8to15(s) ((((s) >> 3) & 0x001f) | \ (((s) >> 6) & 0x03e0) | \ Index: pixman-xserver-compat.h =================================================================== RCS file: /cvs/cairo/libpixman/src/pixman-xserver-compat.h,v retrieving revision 1.6 diff -p -u -r1.6 pixman-xserver-compat.h --- pixman-xserver-compat.h 25 Jun 2005 22:03:17 -0000 1.6 +++ pixman-xserver-compat.h 30 Jul 2005 19:10:58 -0000 @@ -78,14 +78,24 @@ typedef pixman_triangle_t xTriangle; /* XXX: We changed some function and field names which makes for some * ugly hacks... */ #define pDrawable pixels -#define fbGetDrawable(pDrawable, pointer, stride, bpp, xoff, yoff) { \ +#define fbGetDrawable(pDrawable, buf, outstride, outbpp, xoff, yoff) { \ (buf) = (pDrawable)->data; \ - (stride) = ((int) pDrawable->stride) / sizeof (pixman_bits_t); \ - (bpp) = (pDrawable)->bpp; \ + (outstride) = ((int) pDrawable->stride) / sizeof (pixman_bits_t); \ + (outbpp) = (pDrawable)->bpp; \ (xoff) = 0; \ (yoff) = 0; \ } +/* Extended repeat attributes included in 0.10 */ +#define RepeatNone 0 +#define RepeatNormal 1 +#define RepeatPad 2 +#define RepeatReflect 3 + +typedef struct _PictVector { + xFixed vector[3]; +} PictVector, *PictVectorPtr; + /* Then, include any header files that have been copied directly * from xserver. */