Index: ChangeLog
===================================================================
RCS file: /cvs/cairo/libpixman/ChangeLog,v
retrieving revision 1.93
diff -p -u -r1.93 ChangeLog
--- ChangeLog	1 Aug 2005 13:57:09 -0000	1.93
+++ ChangeLog	1 Aug 2005 20:17:42 -0000
@@ -1,3 +1,88 @@
+2005-08-01  Billy  <vektor@dumbterm.net>
+
+	* src/iccompose.c: (PictureTransformPoint3d), (fbFetch_a8r8g8b8),
+	(fbFetch_x8r8g8b8), (fbFetch_a8b8g8r8), (fbFetch_x8b8g8r8),
+	(fbFetch_r8g8b8), (fbFetch_b8g8r8), (fbFetch_r5g6b5),
+	(fbFetch_b5g6r5), (fbFetch_a1r5g5b5), (fbFetch_x1r5g5b5),
+	(fbFetch_a1b5g5r5), (fbFetch_x1b5g5r5), (fbFetch_a4r4g4b4),
+	(fbFetch_x4r4g4b4), (fbFetch_a4b4g4r4), (fbFetch_x4b4g4r4),
+	(fbFetch_a8), (fbFetch_r3g3b2), (fbFetch_b2g3r3),
+	(fbFetch_a2r2g2b2), (fbFetch_a2b2g2r2), (fbFetch_c8), (fbFetch_a4),
+	(fbFetch_r1g2b1), (fbFetch_b1g2r1), (fbFetch_a1r1g1b1),
+	(fbFetch_a1b1g1r1), (fbFetch_c4), (fbFetch_a1), (fbFetch_g1),
+	(fetchProcForPicture), (fbFetchPixel_a8r8g8b8),
+	(fbFetchPixel_x8r8g8b8), (fbFetchPixel_a8b8g8r8),
+	(fbFetchPixel_x8b8g8r8), (fbFetchPixel_r8g8b8),
+	(fbFetchPixel_b8g8r8), (fbFetchPixel_r5g6b5),
+	(fbFetchPixel_b5g6r5), (fbFetchPixel_a1r5g5b5),
+	(fbFetchPixel_x1r5g5b5), (fbFetchPixel_a1b5g5r5),
+	(fbFetchPixel_x1b5g5r5), (fbFetchPixel_a4r4g4b4),
+	(fbFetchPixel_x4r4g4b4), (fbFetchPixel_a4b4g4r4),
+	(fbFetchPixel_x4b4g4r4), (fbFetchPixel_a8), (fbFetchPixel_r3g3b2),
+	(fbFetchPixel_b2g3r3), (fbFetchPixel_a2r2g2b2),
+	(fbFetchPixel_a2b2g2r2), (fbFetchPixel_c8), (fbFetchPixel_a4),
+	(fbFetchPixel_r1g2b1), (fbFetchPixel_b1g2r1),
+	(fbFetchPixel_a1r1g1b1), (fbFetchPixel_a1b1g1r1),
+	(fbFetchPixel_c4), (fbFetchPixel_a1), (fbFetchPixel_g1),
+	(fetchPixelProcForPicture), (fbStore_a8r8g8b8), (fbStore_x8r8g8b8),
+	(fbStore_a8b8g8r8), (fbStore_x8b8g8r8), (fbStore_r8g8b8),
+	(fbStore_b8g8r8), (fbStore_r5g6b5), (fbStore_b5g6r5),
+	(fbStore_a1r5g5b5), (fbStore_x1r5g5b5), (fbStore_a1b5g5r5),
+	(fbStore_x1b5g5r5), (fbStore_a4r4g4b4), (fbStore_x4r4g4b4),
+	(fbStore_a4b4g4r4), (fbStore_x4b4g4r4), (fbStore_a8),
+	(fbStore_r3g3b2), (fbStore_b2g3r3), (fbStore_a2r2g2b2),
+	(fbStore_c8), (fbStore_a4), (fbStore_r1g2b1), (fbStore_b1g2r1),
+	(fbStore_a1r1g1b1), (fbStore_a1b1g1r1), (fbStore_c4), (fbStore_a1),
+	(fbStore_g1), (storeProcForPicture), (fbCombineMaskU),
+	(fbCombineClear), (fbCombineSrcU), (fbCombineOverU),
+	(fbCombineOverReverseU), (fbCombineInU), (fbCombineInReverseU),
+	(fbCombineOutU), (fbCombineOutReverseU), (fbCombineAtopU),
+	(fbCombineAtopReverseU), (fbCombineXorU), (fbCombineAddU),
+	(fbCombineSaturateU), (fbCombineDisjointOutPart),
+	(fbCombineDisjointInPart), (fbCombineDisjointGeneralU),
+	(fbCombineDisjointOverU), (fbCombineDisjointInU),
+	(fbCombineDisjointInReverseU), (fbCombineDisjointOutU),
+	(fbCombineDisjointOutReverseU), (fbCombineDisjointAtopU),
+	(fbCombineDisjointAtopReverseU), (fbCombineDisjointXorU),
+	(fbCombineConjointOutPart), (fbCombineConjointInPart),
+	(fbCombineConjointGeneralU), (fbCombineConjointOverU),
+	(fbCombineConjointOverReverseU), (fbCombineConjointInU),
+	(fbCombineConjointInReverseU), (fbCombineConjointOutU),
+	(fbCombineConjointOutReverseU), (fbCombineConjointAtopU),
+	(fbCombineConjointAtopReverseU), (fbCombineConjointXorU),
+	(fbCombineMaskC), (fbCombineMaskValueC), (fbCombineMaskAlphaC),
+	(fbCombineClearC), (fbCombineSrcC), (fbCombineOverC),
+	(fbCombineOverReverseC), (fbCombineInC), (fbCombineInReverseC),
+	(fbCombineOutC), (fbCombineOutReverseC), (fbCombineAtopC),
+	(fbCombineAtopReverseC), (fbCombineXorC), (fbCombineAddC),
+	(fbCombineSaturateC), (fbCombineDisjointGeneralC),
+	(fbCombineDisjointOverC), (fbCombineDisjointInC),
+	(fbCombineDisjointInReverseC), (fbCombineDisjointOutC),
+	(fbCombineDisjointOutReverseC), (fbCombineDisjointAtopC),
+	(fbCombineDisjointAtopReverseC), (fbCombineDisjointXorC),
+	(fbCombineConjointGeneralC), (fbCombineConjointOverC),
+	(fbCombineConjointOverReverseC), (fbCombineConjointInC),
+	(fbCombineConjointInReverseC), (fbCombineConjointOutC),
+	(fbCombineConjointOutReverseC), (fbCombineConjointAtopC),
+	(fbCombineConjointAtopReverseC), (fbCombineConjointXorC),
+	(fbFetchSolid), (fbFetch), (gradientPixel), (fbFetchSourcePict),
+	(fbFetchTransformed), (fbFetchExternalAlpha), (fbStore),
+	(fbStoreExternalAlpha), (fbCompositeRect),
+	(pixman_compositeGeneral):
+
+	Update iccompose.c to match the latest fbcompose.c from xserver.
+
+	* src/fbpict.h: Add a slightly modified version from the xserver
+	code to make the diff smaller.
+	* src/Makefile.am: Add fbpict.h
+
+	* src/ic.c: Use fbpict.h instead of including the macros.
+	* src/icimage.h: Remove duplicated macros from fbpict.h and
+	uncomment the indexed colour struct.
+	* src/pixman-xserver-compat.h: Fix fbGetDrawable and add the
+	new repeat attributes from RENDER 0.10 and a PictVector
+	structure.
+
 2005-08-01  Amaury Jacquot  <sxpert@esitcom.org>
 	
 	* NEWS: fix typo
Index: src/Makefile.am
===================================================================
RCS file: /cvs/cairo/libpixman/src/Makefile.am,v
retrieving revision 1.9
diff -p -u -r1.9 Makefile.am
--- src/Makefile.am	21 Jan 2005 18:59:33 -0000	1.9
+++ src/Makefile.am	1 Aug 2005 20:17:42 -0000
@@ -4,6 +4,7 @@ include_HEADERS = pixman.h
 libpixman_la_SOURCES = \
 	pixman.h \
 	pixman-xserver-compat.h \
+	fbpict.h \
 	pixregion.c \
 	pixregionint.h \
 	ic.c \
Index: src/fbpict.h
===================================================================
RCS file: src/fbpict.h
diff -N src/fbpict.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/fbpict.h	1 Aug 2005 20:17:42 -0000
@@ -0,0 +1,352 @@
+/*
+ * $Id: fbpict.h,v 1.24 2005/07/12 09:57:00 lars Exp $
+ *
+ * Copyright © 2000 Keith Packard
+ *             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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * 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.
+ */
+
+#ifndef _FBPICT_H_
+#define _FBPICT_H_
+
+#include "pixman-xserver-compat.h"
+#include "renderedge.h"
+
+#define FbIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) )
+#define FbIntDiv(a,b)	 (((CARD16) (a) * 255) / (b))
+
+#define FbGet8(v,i)   ((CARD16) (CARD8) ((v) >> i))
+
+/*
+ * There are two ways of handling alpha -- either as a single unified value or
+ * a separate value for each component, hence each macro must have two
+ * versions.  The unified alpha version has a 'U' at the end of the name,
+ * the component version has a 'C'.  Similarly, functions which deal with
+ * this difference will have two versions using the same convention.
+ */
+
+#define FbOverU(x,y,i,a,t) ((t) = FbIntMult(FbGet8(y,i),(a),(t)) + FbGet8(x,i),\
+			   (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
+
+#define FbOverC(x,y,i,a,t) ((t) = FbIntMult(FbGet8(y,i),FbGet8(a,i),(t)) + FbGet8(x,i),\
+			    (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
+
+#define FbInU(x,i,a,t) ((CARD32) FbIntMult(FbGet8(x,i),(a),(t)) << (i))
+
+#define FbInC(x,i,a,t) ((CARD32) FbIntMult(FbGet8(x,i),FbGet8(a,i),(t)) << (i))
+
+#define FbGen(x,y,i,ax,ay,t,u,v) ((t) = (FbIntMult(FbGet8(y,i),ay,(u)) + \
+					 FbIntMult(FbGet8(x,i),ax,(v))),\
+				  (CARD32) ((CARD8) ((t) | \
+						     (0 - ((t) >> 8)))) << (i))
+
+#define FbAdd(x,y,i,t)	((t) = FbGet8(x,i) + FbGet8(y,i), \
+			 (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
+
+
+#define Alpha(x) ((x) >> 24)
+#define Red(x) (((x) >> 16) & 0xff)
+#define Green(x) (((x) >> 8) & 0xff)
+#define Blue(x) ((x) & 0xff)
+
+#define fbComposeGetSolid(pict, bits) { \
+    FbBits	*__bits__; \
+    FbStride	__stride__; \
+    int		__bpp__; \
+    int		__xoff__,__yoff__; \
+\
+    fbGetDrawable((pict)->pDrawable,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \
+    switch (__bpp__) { \
+    case 32: \
+	(bits) = *(CARD32 *) __bits__; \
+	break; \
+    case 24: \
+	(bits) = Fetch24 ((CARD8 *) __bits__); \
+	break; \
+    case 16: \
+	(bits) = *(CARD16 *) __bits__; \
+	(bits) = cvt0565to0888(bits); \
+	break; \
+    case 8: \
+	(bits) = *(CARD8 *) __bits__; \
+	(bits) = (bits) << 24; \
+	break; \
+    case 1: \
+	(bits) = *(CARD32 *) __bits__; \
+	(bits) = FbLeftStipBits((bits),1) ? 0xff000000 : 0x00000000;\
+	break; \
+    default: \
+	return; \
+    } \
+    /* manage missing src alpha */ \
+    if ((pict)->image_format.alphaMask == 0) \
+	(bits) |= 0xff000000; \
+}
+
+#define fbComposeGetStart(pict,x,y,type,stride,line,mul) {\
+    FbBits	*__bits__; \
+    FbStride	__stride__; \
+    int		__bpp__; \
+    int		__xoff__,__yoff__; \
+\
+    fbGetDrawable((pict)->pDrawable,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \
+    (stride) = __stride__ * sizeof (FbBits) / sizeof (type); \
+    (line) = ((type *) __bits__) + (stride) * ((y) + __yoff__) + (mul) * ((x) + __xoff__); \
+}
+
+#define cvt8888to0565(s)    ((((s) >> 3) & 0x001f) | \
+			     (((s) >> 5) & 0x07e0) | \
+			     (((s) >> 8) & 0xf800))
+#define cvt0565to0888(s)    (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
+			     ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
+			     ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)))
+
+#if IMAGE_BYTE_ORDER == MSBFirst
+#define Fetch24(a)  ((unsigned long) (a) & 1 ? \
+		     ((*(a) << 16) | *((CARD16 *) ((a)+1))) : \
+		     ((*((CARD16 *) (a)) << 8) | *((a)+2)))
+#define Store24(a,v) ((unsigned long) (a) & 1 ? \
+		      ((*(a) = (CARD8) ((v) >> 16)), \
+		       (*((CARD16 *) ((a)+1)) = (CARD16) (v))) : \
+		      ((*((CARD16 *) (a)) = (CARD16) ((v) >> 8)), \
+		       (*((a)+2) = (CARD8) (v))))
+#else
+#define Fetch24(a)  ((unsigned long) (a) & 1 ? \
+		     ((*(a)) | (*((CARD16 *) ((a)+1)) << 8)) : \
+		     ((*((CARD16 *) (a))) | (*((a)+2) << 16)))
+#define Store24(a,v) ((unsigned long) (a) & 1 ? \
+		      ((*(a) = (CARD8) (v)), \
+		       (*((CARD16 *) ((a)+1)) = (CARD16) ((v) >> 8))) : \
+		      ((*((CARD16 *) (a)) = (CARD16) (v)),\
+		       (*((a)+2) = (CARD8) ((v) >> 16))))
+#endif
+		      
+/*
+  The methods below use some tricks to be able to do two color
+  components at the same time.
+*/
+
+/*
+  x_c = (x_c * a) / 255
+*/
+#define FbByteMul(x, a) do {                                      \
+        CARD32 t = (x & 0xff00ff) *a;                             \
+        t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;          \
+        t &= 0xff00ff;                                            \
+                                                                  \
+        x = ((x >> 8) & 0xff00ff) * a;                            \
+        x = (x + ((x >> 8) & 0xff00ff) + 0x800080);               \
+        x &= 0xff00ff00;                                          \
+        x += t;                                                   \
+    } while (0)
+
+/*
+  x_c = (x_c * a) / 255 + y
+*/
+#define FbByteMulAdd(x, a, y) do {                                \
+        CARD32 t = (x & 0xff00ff) * a;                            \
+        t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;          \
+        t &= 0xff00ff;                                            \
+        t += y & 0xff00ff;                                        \
+        t |= 0x1000100 - ((t >> 8) & 0xff00ff);                   \
+        t &= 0xff00ff;                                            \
+                                                                  \
+        x = ((x >> 8) & 0xff00ff) * a;                              \
+        x = (x + ((x >> 8) & 0xff00ff) + 0x800080) >> 8;            \
+        x &= 0xff00ff;                                              \
+        x += (y >> 8) & 0xff00ff;                                   \
+        x |= 0x1000100 - ((t >> 8) & 0xff00ff);                     \
+        x &= 0xff00ff;                                              \
+        x <<= 8;                                                    \
+        x += t;                                                     \
+    } while (0)
+
+/*
+  x_c = (x_c * a + y_c * b) / 255
+*/
+#define FbByteAddMul(x, a, y, b) do {                                   \
+        CARD32 t;                                                       \
+        CARD32 r = (x >> 24) * a + (y >> 24) * b;                       \
+        r += (r >> 8) + 0x80;                                           \
+        r >>= 8;                                                        \
+                                                                        \
+        t = (x & 0xff00) * a + (y & 0xff00) * b;                        \
+        t += (t >> 8) + 0x8000;                                         \
+        t >>= 16;                                                       \
+                                                                        \
+        t |= r << 16;                                                   \
+        t |= 0x1000100 - ((t >> 8) & 0xff00ff);                         \
+        t &= 0xff00ff;                                                  \
+        t <<= 8;                                                        \
+                                                                        \
+        r = ((x >> 16) & 0xff) * a + ((y >> 16) & 0xff) * b;            \
+        r += (r >> 8) + 0x80;                                           \
+        r >>= 8;                                                        \
+                                                                        \
+        x = (x & 0xff) * a + (y & 0xff) * b;                            \
+        x += (x >> 8) + 0x80;                                           \
+        x >>= 8;                                                        \
+        x |= r << 16;                                                   \
+        x |= 0x1000100 - ((x >> 8) & 0xff00ff);                         \
+        x &= 0xff00ff;                                                  \
+        x |= t;                                                         \
+} while (0)
+
+/*
+  x_c = (x_c * a + y_c *b) / 256
+*/
+#define FbByteAddMul_256(x, a, y, b) do {                               \
+        CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;             \
+        t >>= 8;                                                        \
+        t &= 0xff00ff;                                                  \
+                                                                        \
+        x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;      \
+        x &= 0xff00ff00;                                                \
+        x += t;                                                         \
+} while (0)
+/*
+  x_c = (x_c * a_c) / 255
+*/
+#define FbByteMulC(x, a) do {                                   \
+        CARD32 t;                                               \
+        CARD32 r = (x & 0xff) * (a & 0xff);                     \
+        r |= (x & 0xff0000) * ((a >> 16) & 0xff);               \
+        r = (r + ((r >> 8) & 0xff00ff) + 0x800080) >> 8;        \
+        r &= 0xff00ff;                                          \
+                                                                \
+        x >>= 8;                                                \
+        t = (x & 0xff) * ((a >> 8) & 0xff);                     \
+        t |= (x & 0xff0000) * (a >> 24);                        \
+        t = (t + ((t >> 8) & 0xff00ff) + 0x800080);             \
+        x = r | (t & 0xff00ff00);                               \
+                                                                \
+    } while (0)
+
+/*
+  x_c = (x_c * a) / 255 + y
+*/
+#define FbByteMulAddC(x, a, y) do {                                \
+        CARD32 t;                                                  \
+        CARD32 r = (x & 0xff) * (a & 0xff);                        \
+        r |= (x & 0xff0000) * ((a >> 16) & 0xff);                  \
+        r = (r + ((r >> 8) & 0xff00ff) + 0x800080) >> 8;           \
+        r &= 0xff00ff;                                             \
+        r += y & 0xff00ff;                                         \
+        r |= 0x1000100 - ((r >> 8) & 0xff00ff);                    \
+        r &= 0xff00ff;                                             \
+                                                                   \
+        x >>= 8;                                                   \
+        t = (x & 0xff) * ((a >> 8) & 0xff);                        \
+        t |= (x & 0xff0000) * (a >> 24);                              \
+        t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;              \
+        t &= 0xff00ff;                                                \
+        t += (y >> 8) & 0xff00ff;                                     \
+        t |= 0x1000100 - ((t >> 8) & 0xff00ff);                       \
+        t &= 0xff00ff;                                                \
+        x = r | (t << 8);                                             \
+    } while (0)
+
+/*
+  x_c = (x_c * a_c + y_c * b) / 255
+*/
+#define FbByteAddMulC(x, a, y, b) do {                                  \
+        CARD32 t;                                                       \
+        CARD32 r = (x >> 24) * (a >> 24) + (y >> 24) * b;               \
+        r += (r >> 8) + 0x80;                                           \
+        r >>= 8;                                                        \
+                                                                        \
+        t = (x & 0xff00) * ((a >> 8) & 0xff) + (y & 0xff00) * b;        \
+        t += (t >> 8) + 0x8000;                                         \
+        t >>= 16;                                                       \
+                                                                        \
+        t |= r << 16;                                                   \
+        t |= 0x1000100 - ((t >> 8) & 0xff00ff);                         \
+        t &= 0xff00ff;                                                  \
+        t <<= 8;                                                        \
+                                                                        \
+        r = ((x >> 16) & 0xff) * ((a >> 16) & 0xff) + ((y >> 16) & 0xff) * b; \
+        r += (r >> 8) + 0x80;                                           \
+        r >>= 8;                                                        \
+                                                                        \
+        x = (x & 0xff) * (a & 0xff) + (y & 0xff) * b;                   \
+        x += (x >> 8) + 0x80;                                           \
+        x >>= 8;                                                        \
+        x |= r << 16;                                                   \
+        x |= 0x1000100 - ((x >> 8) & 0xff00ff);                         \
+        x &= 0xff00ff;                                                  \
+        x |= t;                                                         \
+} while (0)
+
+/*
+  x_c = min(x_c + y_c, 255)
+*/
+#define FbByteAdd(x, y) do {                                            \
+        CARD32 t;                                                       \
+        CARD32 r = (x & 0xff00ff) + (y & 0xff00ff);                     \
+        r |= 0x1000100 - ((r >> 8) & 0xff00ff);                         \
+        r &= 0xff00ff;                                                  \
+                                                                        \
+        t = ((x >> 8) & 0xff00ff) + ((y >> 8) & 0xff00ff);              \
+        t |= 0x1000100 - ((t >> 8) & 0xff00ff);                         \
+        r |= (t & 0xff00ff) << 8;                                       \
+        x = r;                                                          \
+    } while (0)
+
+#define div_255(x) (((x) + ((x) >> 8) + 0x80) >> 8)
+
+#if defined(__i386__) && defined(__GNUC__)
+#define FASTCALL __attribute__((regparm(3)))
+#else
+#define FASTCALL
+#endif
+
+#if defined(__GNUC__)
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+
+typedef struct _FbComposeData {
+    CARD8	op;
+    PicturePtr	src;
+    PicturePtr	mask;
+    PicturePtr	dest;
+    INT16	xSrc;
+    INT16	ySrc;
+    INT16	xMask;
+    INT16	yMask;
+    INT16	xDest;
+    INT16	yDest;
+    CARD16	width;
+    CARD16	height;
+} FbComposeData;
+
+typedef FASTCALL void (*CombineMaskU) (CARD32 *src, const CARD32 *mask, int width);
+typedef FASTCALL void (*CombineFuncU) (CARD32 *dest, const CARD32 *src, int width);
+typedef FASTCALL void (*CombineFuncC) (CARD32 *dest, CARD32 *src, CARD32 *mask, int width);
+
+typedef struct _FbComposeFunctions {
+    CombineFuncU *combineU;
+    CombineFuncC *combineC;
+    CombineMaskU combineMaskU;
+} FbComposeFunctions;
+
+#endif /* _FBPICT_H_ */
Index: src/ic.c
===================================================================
RCS file: /cvs/cairo/libpixman/src/ic.c,v
retrieving revision 1.32
diff -p -u -r1.32 ic.c
--- src/ic.c	30 Jul 2005 17:23:21 -0000	1.32
+++ src/ic.c	1 Aug 2005 20:17:43 -0000
@@ -21,7 +21,7 @@
  * Author:  Keith Packard, SuSE, Inc.
  */
 
-#include "pixman-xserver-compat.h"
+#include "fbpict.h"
 
 #define cvt8888to0565(s)    ((((s) >> 3) & 0x001f) | \
 			     (((s) >> 5) & 0x07e0) | \
@@ -105,51 +105,6 @@ fbIn24 (CARD32 x, CARD8 y)
     return m|n|o|p;
 }
 
-#define fbComposeGetSolid(image, bits) { \
-    FbBits	*__bits__; \
-    FbStride	__stride__; \
-    int		__bpp__; \
-    int		__xoff__,__yoff__; \
-\
-    FbGetPixels((image)->pixels,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \
-    switch (__bpp__) { \
-    case 32: \
-	(bits) = *(CARD32 *) __bits__; \
-	break; \
-    case 24: \
-	(bits) = Fetch24 ((CARD8 *) __bits__); \
-	break; \
-    case 16: \
-	(bits) = *(CARD16 *) __bits__; \
-	(bits) = cvt0565to8888(bits); \
-	break; \
-    case 8: \
-	(bits) = *(CARD8 *) __bits__; \
-	(bits) = (bits) << 24; \
-	break; \
-    case 1: \
-	(bits) = *(CARD32 *) __bits__; \
-	(bits) = FbLeftStipBits((bits),1) ? 0xff000000 : 0x00000000;\
-	break; \
-    default: \
-	return; \
-    } \
-    /* manage missing src alpha */ \
-    if ((image)->image_format.alphaMask == 0) \
-	(bits) |= 0xff000000; \
-}
-
-#define fbComposeGetStart(image,x,y,type,stride,line,mul) {\
-    FbBits	*__bits__; \
-    FbStride	__stride__; \
-    int		__bpp__; \
-    int		__xoff__,__yoff__; \
-\
-    FbGetPixels((image)->pixels,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \
-    (stride) = __stride__ * sizeof (FbBits) / sizeof (type); \
-    (line) = ((type *) __bits__) + (stride) * ((y) + __yoff__) + (mul) * ((x) + __xoff__); \
-}
-
 #define genericCombine24(a,b,c,d) (((a)*(c)+(b)*(d)))
 
 #define fastcombine32(alpha, source, destval, destptr) { \
Index: src/iccompose.c
===================================================================
RCS file: /cvs/cairo/libpixman/src/iccompose.c,v
retrieving revision 1.26
diff -p -u -r1.26 iccompose.c
--- src/iccompose.c	30 Jul 2005 17:23:21 -0000	1.26
+++ src/iccompose.c	1 Aug 2005 20:17:44 -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,3474 @@
  * 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 <config.h>
+#endif
+#include <stdio.h>
 #include "pixman-xserver-compat.h"
+#include "fbpict.h"
 
-/*
- * General purpose compositing code optimized for minimal memory
- * references
- *
- * All work is done on canonical ARGB values, functions for fetching
- * and storing these exist for each format.
- */
+#ifdef RENDER
 
-/*
- * Combine src and mask using IN
- */
+#include "pixregionint.h"
 
-static CARD32
-fbCombineMaskU (FbCompositeOperand   *src,
-		FbCompositeOperand   *msk)
-{
-    CARD32  x;
-    CARD16  a;
-    CARD16  t;
-    CARD32  m,n,o,p;
+// #define PIXMAN_CONVOLUTION
+// #define PIXMAN_GRADIENTS
+// #define PIXMAN_INDEXED_FORMATS
+#define miIndexedPtr FbIndexedPtr
+#define miIndexToEnt24 FbIndexToEnt24
+#define miIndexToEntY24 FbIndexToEntY24
 
-    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 MAX_FIXED_48_16	    ((xFixed_48_16) 0x7fffffff)
+#define MIN_FIXED_48_16	    (-((xFixed_48_16) 1 << 31))
 
-    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;
+static Bool
+PictureTransformPoint3d (pixman_transform_t *transform,
+                         PictVector *vector)
+{
+    PictVector	    result;
+    int		    i, j;
+    xFixed_32_32    partial;
+    xFixed_48_16    v;
 
-    if (!msk)
+    for (j = 0; j < 3; j++)
     {
-	return (*src->fetch) (src);
+	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;
     }
-    
-    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;
+    if (!result.vector[2])
+	return FALSE;
+    *vector = result;
+    return TRUE;
 }
 
-/*
- * Combine src and mask using IN, generating only the alpha component
- */
-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);
-}
+// #define mod(a,b)	((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
 
-static CARD32
-fbCombineMaskAlphaC (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 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;
-}
+typedef FASTCALL void (*fetchProc)(const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed);
 
 /*
- * All of the composing functions
+ * All of the fetch functions
  */
-static void
-fbCombineClear (FbCompositeOperand   *src,
-		FbCompositeOperand   *msk,
-		FbCompositeOperand   *dst)
+
+static FASTCALL void
+fbFetch_a8r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 {
-    (*dst->store) (dst, 0);
+    memcpy(buffer, (const CARD32 *)bits + x, width*sizeof(CARD32));
 }
 
-static void
-fbCombineSrcU (FbCompositeOperand    *src,
-	       FbCompositeOperand    *msk,
-	       FbCompositeOperand    *dst)
+static FASTCALL void
+fbFetch_x8r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 {
-    (*dst->store) (dst, fbCombineMaskU (src, msk));
+    const CARD32 *pixel = (const CARD32 *)bits + x;
+    const CARD32 *end = pixel + width;
+    while (pixel < end) {
+        *buffer++ = *pixel++ | 0xff000000;
+    }
 }
 
-static void
-fbCombineSrcC (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, fbCombineMaskValueC (src, msk));
+    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
-fbCombineDst (FbCompositeOperand    *src,
-	      FbCompositeOperand    *msk,
-	      FbCompositeOperand    *dst)
+static FASTCALL void
+fbFetch_x8b8g8r8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 {
-    /* noop */
+    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
-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_r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
+{
+    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
-fbCombineOverC (FbCompositeOperand   *src,
-		FbCompositeOperand   *msk,
-		FbCompositeOperand   *dst)
+static FASTCALL void
+fbFetch_b8g8r8 (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;
-
-    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);
+    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
-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_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
-fbCombineOverReverseC (FbCompositeOperand    *src,
-		       FbCompositeOperand    *msk,
-		       FbCompositeOperand    *dst)
+static FASTCALL void
+fbFetch_b5g6r5 (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);
+        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
-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_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);
     }
-    (*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_x1r5g5b5 (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;
+
+        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);
     }
-    (*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_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);
     }
 }
 
-static void
-fbCombineInReverseC (FbCompositeOperand  *src,
-		     FbCompositeOperand  *msk,
-		     FbCompositeOperand  *dst)
+static FASTCALL void
+fbFetch_x1b5g5r5 (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);
+        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);
     }
 }
 
-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_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);
     }
-    (*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_x4r4g4b4 (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;
+
+        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);
     }
-    (*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_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);
     }
 }
 
-static void
-fbCombineOutReverseC (FbCompositeOperand *src,
-		      FbCompositeOperand *msk,
-		      FbCompositeOperand *dst)
+static FASTCALL void
+fbFetch_x4b4g4r4 (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);
+        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);
     }
 }
 
-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 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
-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_r3g3b2 (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);
+        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
-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_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
-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);
+        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
-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_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
-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;
+        r = ((p & 0x30) * 0x55) << 12;
+        g = ((p & 0x0c) * 0x55) << 6;
+        b = ((p & 0x03) * 0x55);
+        *buffer++ = a|r|g|b;
 	}
+}
+
+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;
+
+        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];
+
+    return ((pixel & 0xff000000) |
+	    ((pixel >> 16) & 0xff) |
+	    (pixel & 0x0000ff00) |
+	    ((pixel & 0xff) << 16));
 }
 
-static void
-fbCombineDisjointInReverseU (FbCompositeOperand  *src,
-			     FbCompositeOperand  *msk,
-			     FbCompositeOperand  *dst)
+static FASTCALL CARD32
+fbFetchPixel_x8b8g8r8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralU (src, msk, dst, CombineBIn);
+    CARD32  pixel = ((CARD32 *)bits)[offset];
+
+    return ((0xff000000) |
+	    ((pixel >> 16) & 0xff) |
+	    (pixel & 0x0000ff00) |
+	    ((pixel & 0xff) << 16));
 }
 
-static void
-fbCombineDisjointInReverseC (FbCompositeOperand  *src,
-			     FbCompositeOperand  *msk,
-			     FbCompositeOperand  *dst)
+static FASTCALL CARD32
+fbFetchPixel_r8g8b8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralC (src, msk, dst, CombineBIn);
+    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
-fbCombineDisjointOutU (FbCompositeOperand    *src,
-		       FbCompositeOperand    *msk,
-		       FbCompositeOperand    *dst)
+static FASTCALL CARD32
+fbFetchPixel_b8g8r8 (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[2] << 16) |
+	    (pixel[1] << 8) |
+	    (pixel[0]));
+#else
+    return (0xff000000 |
+	    (pixel[0] << 16) |
+	    (pixel[1] << 8) |
+	    (pixel[2]));
+#endif
 }
 
-static void
-fbCombineDisjointOutC (FbCompositeOperand    *src,
-		       FbCompositeOperand    *msk,
-		       FbCompositeOperand    *dst)
+static FASTCALL CARD32
+fbFetchPixel_r5g6b5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralC (src, msk, dst, CombineAOut);
+    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
-fbCombineDisjointOutReverseU (FbCompositeOperand *src,
-			      FbCompositeOperand *msk,
-			      FbCompositeOperand *dst)
+static FASTCALL CARD32
+fbFetchPixel_b5g6r5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralU (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
-fbCombineDisjointOutReverseC (FbCompositeOperand *src,
-			      FbCompositeOperand *msk,
-			      FbCompositeOperand *dst)
+static FASTCALL CARD32
+fbFetchPixel_a1r5g5b5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralC (src, msk, dst, CombineBOut);
+    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
-fbCombineDisjointAtopU (FbCompositeOperand   *src,
-			FbCompositeOperand   *msk,
-			FbCompositeOperand   *dst)
+static FASTCALL CARD32
+fbFetchPixel_x1r5g5b5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralU (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
-fbCombineDisjointAtopC (FbCompositeOperand   *src,
-			FbCompositeOperand   *msk,
-			FbCompositeOperand   *dst)
+static FASTCALL CARD32
+fbFetchPixel_a1b5g5r5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralC (src, msk, dst, CombineAAtop);
+    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
-fbCombineDisjointAtopReverseU (FbCompositeOperand    *src,
-			       FbCompositeOperand    *msk,
-			       FbCompositeOperand    *dst)
+static FASTCALL CARD32
+fbFetchPixel_x1b5g5r5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralU (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
-fbCombineDisjointAtopReverseC (FbCompositeOperand    *src,
-			       FbCompositeOperand    *msk,
-			       FbCompositeOperand    *dst)
+static FASTCALL CARD32
+fbFetchPixel_a4r4g4b4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralC (src, msk, dst, CombineBAtop);
+    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
-fbCombineDisjointXorU (FbCompositeOperand    *src,
-		       FbCompositeOperand    *msk,
-		       FbCompositeOperand    *dst)
+static FASTCALL CARD32
+fbFetchPixel_x4r4g4b4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralU (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);
 }
 
-static void
-fbCombineDisjointXorC (FbCompositeOperand    *src,
-		       FbCompositeOperand    *msk,
-		       FbCompositeOperand    *dst)
+static FASTCALL CARD32
+fbFetchPixel_a4b4g4r4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineDisjointGeneralC (src, msk, dst, CombineXor);
+    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 a but not b */
-static CARD8
-fbCombineConjointOutPart (CARD8 a, CARD8 b)
+static FASTCALL CARD32
+fbFetchPixel_x4b4g4r4 (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  r,g,b;
+
+    b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12;
+    g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
+    r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4));
+    return (0xff000000 | r | g | b);
 }
 
-/* portion covered by both a and b */
-static CARD8
-fbCombineConjointInPart (CARD8 a, CARD8 b)
+static FASTCALL CARD32
+fbFetchPixel_a8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    /* min (1,b/a) */
+    CARD32   pixel = ((CARD8 *) bits)[offset];
 
-    if (b >= a)		    /* b >= a -> b/a >= 1 */
-	return 0xff;	    /* 1 */
-    return FbIntDiv(b,a);   /* b/a */
+    return pixel << 24;
 }
 
-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_r3g3b2 (const FbBits *bits, int offset, miIndexedPtr indexed)
+{
+    CARD32   pixel = ((CARD8 *) bits)[offset];
+    CARD32  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 = 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);
+    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
-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_b2g3r3 (const FbBits *bits, int offset, miIndexedPtr indexed)
+{
+    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
-fbCombineConjointOverU (FbCompositeOperand   *src,
-			FbCompositeOperand   *msk,
-			FbCompositeOperand   *dst)
+static FASTCALL CARD32
+fbFetchPixel_a2r2g2b2 (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   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
-fbCombineConjointOverC (FbCompositeOperand   *src,
-			FbCompositeOperand   *msk,
-			FbCompositeOperand   *dst)
+static FASTCALL CARD32
+fbFetchPixel_a2b2g2r2 (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;
+    b = ((pixel & 0x30) * 0x55) >> 6;
+    g = ((pixel & 0x0c) * 0x55) << 6;
+    r = ((pixel & 0x03) * 0x55) << 16;
+    return a|r|g|b;
 }
 
-static void
-fbCombineConjointOverReverseU (FbCompositeOperand    *src,
-			       FbCompositeOperand    *msk,
-			       FbCompositeOperand    *dst)
+static FASTCALL CARD32
+fbFetchPixel_c8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineConjointGeneralU (src, msk, dst, CombineBOver);
+    CARD32   pixel = ((CARD8 *) bits)[offset];
+    return indexed->rgba[pixel];
 }
 
-static void
-fbCombineConjointOverReverseC (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)
 {
-    fbCombineConjointGeneralC (src, msk, dst, CombineBOver);
+    CARD32  pixel = Fetch4(bits, offset);
+
+    pixel |= pixel << 4;
+    return pixel << 24;
 }
 
-static void
-fbCombineConjointInU (FbCompositeOperand	    *src,
-		      FbCompositeOperand	    *msk,
-		      FbCompositeOperand	    *dst)
+static FASTCALL CARD32
+fbFetchPixel_r1g2b1 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineConjointGeneralU (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
-fbCombineConjointInC (FbCompositeOperand	    *src,
-		      FbCompositeOperand	    *msk,
-		      FbCompositeOperand	    *dst)
+static FASTCALL CARD32
+fbFetchPixel_b1g2r1 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineConjointGeneralC (src, msk, dst, CombineAIn);
+    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
-fbCombineConjointInReverseU (FbCompositeOperand  *src,
-			     FbCompositeOperand  *msk,
-			     FbCompositeOperand  *dst)
+static FASTCALL CARD32
+fbFetchPixel_a1r1g1b1 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineConjointGeneralU (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
-fbCombineConjointInReverseC (FbCompositeOperand  *src,
-			     FbCompositeOperand  *msk,
-			     FbCompositeOperand  *dst)
+static FASTCALL CARD32
+fbFetchPixel_a1b1g1r1 (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) >> 3;
+    g = ((pixel & 0x2) * 0xff) << 7;
+    b = ((pixel & 0x1) * 0xff) << 16;
+    return a|r|g|b;
 }
 
-static void
-fbCombineConjointOutU (FbCompositeOperand    *src,
-		       FbCompositeOperand    *msk,
-		       FbCompositeOperand    *dst)
+static FASTCALL CARD32
+fbFetchPixel_c4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineConjointGeneralU (src, msk, dst, CombineAOut);
+    CARD32  pixel = Fetch4(bits, offset);
+
+    return indexed->rgba[pixel];
 }
 
-static void
-fbCombineConjointOutC (FbCompositeOperand    *src,
-		       FbCompositeOperand    *msk,
-		       FbCompositeOperand    *dst)
+
+static FASTCALL CARD32
+fbFetchPixel_a1 (const FbBits *bits, int offset, miIndexedPtr indexed)
 {
-    fbCombineConjointGeneralC (src, msk, dst, CombineAOut);
+    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
-fbCombineConjointOutReverseU (FbCompositeOperand *src,
-			      FbCompositeOperand *msk,
-			      FbCompositeOperand *dst)
+static FASTCALL CARD32
+fbFetchPixel_g1 (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;
+    return indexed->rgba[a];
 }
 
-static void
-fbCombineConjointOutReverseC (FbCompositeOperand *src,
-			      FbCompositeOperand *msk,
-			      FbCompositeOperand *dst)
+static fetchPixelProc fetchPixelProcForPicture (PicturePtr pict)
 {
-    fbCombineConjointGeneralC (src, msk, dst, CombineBOut);
+    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
-fbCombineConjointAtopU (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)
 {
-    fbCombineConjointGeneralU (src, msk, dst, CombineAAtop);
+    memcpy(((CARD32 *)bits) + x, values, width*sizeof(CARD32));
 }
 
-static void
-fbCombineConjointAtopC (FbCompositeOperand   *src,
-			FbCompositeOperand   *msk,
-			FbCompositeOperand   *dst)
+static FASTCALL void
+fbStore_x8r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 {
-    fbCombineConjointGeneralC (src, msk, dst, CombineAAtop);
+    int i;
+    CARD32 *pixel = (CARD32 *)bits + x;
+    for (i = 0; i < width; ++i)
+        *pixel++ = values[i] & 0xffffff;
 }
 
-static void
-fbCombineConjointAtopReverseU (FbCompositeOperand    *src,
-			       FbCompositeOperand    *msk,
-			       FbCompositeOperand    *dst)
+static FASTCALL void
+fbStore_a8b8g8r8 (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] & 0xff00ff00) | ((values[i] >> 16) && 0xff) | ((values[i] & 0xff) << 16);
 }
 
-static void
-fbCombineConjointAtopReverseC (FbCompositeOperand    *src,
-			       FbCompositeOperand    *msk,
-			       FbCompositeOperand    *dst)
+static FASTCALL void
+fbStore_x8b8g8r8 (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] & 0x0000ff00) | ((values[i] >> 16) && 0xff) | ((values[i] & 0xff) << 16);
 }
 
-static void
-fbCombineConjointXorU (FbCompositeOperand    *src,
-		       FbCompositeOperand    *msk,
-		       FbCompositeOperand    *dst)
+static FASTCALL void
+fbStore_r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 {
-    fbCombineConjointGeneralU (src, msk, dst, CombineXor);
+    int i;
+    CARD8 *pixel = ((CARD8 *) bits) + x;
+    for (i = 0; i < width; ++i) {
+        Store24(pixel, values[i]);
+        pixel += 3;
+    }
 }
 
-static void
-fbCombineConjointXorC (FbCompositeOperand    *src,
-		       FbCompositeOperand    *msk,
-		       FbCompositeOperand    *dst)
+static FASTCALL void
+fbStore_b8g8r8 (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) {
+#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 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_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 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)
+
  */
 
-static CARD32
-fbFetch_a8r8g8b8 (FbCompositeOperand *op)
-{
-    FbBits  *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset;
-    return ((CARD32 *)line)[offset >> 5];
+#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;
+
+        x = src[i];
+        FbByteMulC(x, a);
+        src[i] = x;
+    }
+}
 
-#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 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 DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :\
+        ((a) - (b) + 1 - (((b) < 0) << 1)) / (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);
 
-    v.vector[0] = IntToxFixed(op->u.transform.x);
-    v.vector[1] = IntToxFixed(op->u.transform.y);
+    fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff);
+    x += xoff;
+    y += yoff;
+
+    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 || pict->filter == PIXMAN_FILTER_FAST)
+    {
+        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(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
+                        x = MOD(DIV(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(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
+                        x = MOD(DIV(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 = DIV(v.vector[1],v.vector[2]);
+                        x = DIV(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 = DIV(v.vector[1],v.vector[2]);
+                        x = DIV(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 || pict->filter == PIXMAN_FILTER_GOOD || pict->filter == PIXMAN_FILTER_BEST) {
+        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;
-    }
-    /* Build simple operand */
+    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;
+    else if (!data->src->pDrawable) {
+#ifdef PIXMAN_GRADIENTS
+        if (data->src->pSourcePict)
+            fetchSrc = fbFetchSourcePict;
+#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) {
+        if (!data->mask->pDrawable) {
+#ifdef PIXMAN_GRADIENTS
+            if (data->mask->pSourcePict)
+                fetchMask = fbFetchSourcePict;
+#endif
+        } else 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 +3499,110 @@ 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;
+    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;
+
+    region = pixman_region_create();
+    pixman_region_union_rect (region, region, xDst, yDst, width, height);
+
+    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 = pixman_region_num_rects (region);
+    pbox = pixman_region_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: src/icimage.h
===================================================================
RCS file: /cvs/cairo/libpixman/src/icimage.h,v
retrieving revision 1.26
diff -p -u -r1.26 icimage.h
--- src/icimage.h	25 Jun 2005 03:13:19 -0000	1.26
+++ src/icimage.h	1 Aug 2005 20:17:44 -0000
@@ -33,38 +33,6 @@
 #include "resource.h"
 */
 
-
-#define FbIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) )
-#define FbIntDiv(a,b)	 (((uint16_t) (a) * 255) / (b))
-
-#define FbGet8(v,i)   ((uint16_t) (uint8_t) ((v) >> i))
-
-/*
- * There are two ways of handling alpha -- either as a single unified value or
- * a separate value for each component, hence each macro must have two
- * versions.  The unified alpha version has a 'U' at the end of the name,
- * the component version has a 'C'.  Similarly, functions which deal with
- * this difference will have two versions using the same convention.
- */
-
-#define FbOverU(x,y,i,a,t) ((t) = FbIntMult(FbGet8(y,i),(a),(t)) + FbGet8(x,i),\
-			   (uint32_t) ((uint8_t) ((t) | (0 - ((t) >> 8)))) << (i))
-
-#define FbOverC(x,y,i,a,t) ((t) = FbIntMult(FbGet8(y,i),FbGet8(a,i),(t)) + FbGet8(x,i),\
-			    (uint32_t) ((uint8_t) ((t) | (0 - ((t) >> 8)))) << (i))
-
-#define FbInU(x,i,a,t) ((uint32_t) FbIntMult(FbGet8(x,i),(a),(t)) << (i))
-
-#define FbInC(x,i,a,t) ((uint32_t) FbIntMult(FbGet8(x,i),FbGet8(a,i),(t)) << (i))
-
-#define FbGen(x,y,i,ax,ay,t,u,v) ((t) = (FbIntMult(FbGet8(y,i),ay,(u)) + \
-					 FbIntMult(FbGet8(x,i),ax,(v))),\
-				  (uint32_t) ((uint8_t) ((t) | \
-						     (0 - ((t) >> 8)))) << (i))
-
-#define FbAdd(x,y,i,t)	((t) = FbGet8(x,i) + FbGet8(y,i), \
-			 (uint32_t) ((uint8_t) ((t) | (0 - ((t) >> 8)))) << (i))
-
 /*
 typedef struct _IndexFormat {
     VisualPtr	    pVisual; 
@@ -138,13 +106,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: src/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
--- src/pixman-xserver-compat.h	25 Jun 2005 22:03:17 -0000	1.6
+++ src/pixman-xserver-compat.h	1 Aug 2005 20:17:45 -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. */
 
