xserver: Branch 'master'

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Fri Apr 20 01:42:44 EEST 2007


 fb/fbcompose.c      | 1485 ++++++++++++++++++++++++++++++++--------------------
 render/picture.c    |  108 +--
 render/picturestr.h |   26 
 3 files changed, 973 insertions(+), 646 deletions(-)

New commits:
diff-tree 0a9239ec258828ec1da6c208634a55fc4053d7da (from d0e55774e0da641ba85c5173f27f68de27372747)
Author: Soren Sandmann Pedersen <ssp at dhcp83-218.boston.redhat.com>
Date:   Thu Apr 19 18:19:34 2007 -0400

    Merge David Reveman's gradient optimization patch from pixman

diff --git a/fb/fbcompose.c b/fb/fbcompose.c
index 6ea9483..3043637 100644
--- a/fb/fbcompose.c
+++ b/fb/fbcompose.c
@@ -40,6 +40,65 @@
 #include "mipict.h"
 #include "fbpict.h"
 
+static unsigned int
+SourcePictureClassify (PicturePtr pict,
+		       int	  x,
+		       int	  y,
+		       int	  width,
+		       int	  height)
+{
+    if (pict->pSourcePict->type == SourcePictTypeSolidFill)
+    {
+	pict->pSourcePict->solidFill.class = SourcePictClassHorizontal;
+    }
+    else if (pict->pSourcePict->type == SourcePictTypeLinear)
+    {
+	PictVector   v;
+	xFixed_32_32 l;
+	xFixed_48_16 dx, dy, a, b, off;
+	xFixed_48_16 factors[4];
+	int	     i;
+
+	dx = pict->pSourcePict->linear.p2.x - pict->pSourcePict->linear.p1.x;
+	dy = pict->pSourcePict->linear.p2.y - pict->pSourcePict->linear.p1.y;
+	l = dx * dx + dy * dy;
+	if (l)
+	{
+	    a = (dx << 32) / l;
+	    b = (dy << 32) / l;
+	}
+	else
+	{
+	    a = b = 0;
+	}
+
+	off = (-a * pict->pSourcePict->linear.p1.x
+	       -b * pict->pSourcePict->linear.p1.y) >> 16;
+
+	for (i = 0; i < 3; i++)
+	{
+	    v.vector[0] = IntToxFixed ((i % 2) * (width  - 1) + x);
+	    v.vector[1] = IntToxFixed ((i / 2) * (height - 1) + y);
+	    v.vector[2] = xFixed1;
+
+	    if (pict->transform)
+	    {
+		if (!PictureTransformPoint3d (pict->transform, &v))
+		    return SourcePictClassUnknown;
+	    }
+
+	    factors[i] = ((a * v.vector[0] + b * v.vector[1]) >> 16) + off;
+	}
+
+	if (factors[2] == factors[0])
+	    pict->pSourcePict->linear.class = SourcePictClassHorizontal;
+	else if (factors[1] == factors[0])
+	    pict->pSourcePict->linear.class = SourcePictClassVertical;
+    }
+
+    return pict->pSourcePict->solidFill.class;
+}
+
 #define mod(a,b)	((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
 
 #define SCANLINE_BUFFER_LENGTH 2048
@@ -86,9 +145,9 @@ fbFetch_x8b8g8r8 (const FbBits *bits, in
     const CARD32 *end = pixel + width;
     while (pixel < end) {
         WRITE(buffer++, 0xff000000 |
-                        ((READ(pixel) & 0x0000ff00) |
-                         ((READ(pixel) >> 16) & 0xff) |
-                         ((READ(pixel) & 0xff) << 16)));
+	      ((READ(pixel) & 0x0000ff00) |
+	       ((READ(pixel) >> 16) & 0xff) |
+	       ((READ(pixel) & 0xff) << 16)));
         ++pixel;
     }
 }
@@ -132,8 +191,8 @@ fbFetch_r5g6b5 (const FbBits *bits, int 
     while (pixel < end) {
         CARD32  p = READ(pixel++);
         CARD32 r = (((p) << 3) & 0xf8) | 
-                   (((p) << 5) & 0xfc00) |
-                   (((p) << 8) & 0xf80000);
+	    (((p) << 5) & 0xfc00) |
+	    (((p) << 8) & 0xf80000);
         r |= (r >> 5) & 0x70007;
         r |= (r >> 6) & 0x300;
         WRITE(buffer++, 0xff000000 | r);
@@ -335,7 +394,7 @@ fbFetch_b2g3r3 (const FbBits *bits, int 
              ((p & 0x07) << 3) |
              ((p & 0x06) << 6)) << 16;
         WRITE(buffer++, (0xff000000 | r | g | b));
-	}
+    }
 }
 
 static FASTCALL void
@@ -558,7 +617,7 @@ static fetchProc fetchProcForPicture (Pi
     case PICT_c8: return  fbFetch_c8;
     case PICT_g8: return  fbFetch_c8;
     case PICT_x4a4: return fbFetch_x4a4;
-    
+
         /* 4bpp formats */
     case PICT_a4: return  fbFetch_a4;
     case PICT_r1g2b1: return fbFetch_r1g2b1;
@@ -1095,8 +1154,8 @@ fbStore_r5g6b5 (FbBits *bits, const CARD
     for (i = 0; i < width; ++i) {
         CARD32 s = READ(values + i);
         WRITE(pixel++, ((s >> 3) & 0x001f) |
-                       ((s >> 5) & 0x07e0) |
-                       ((s >> 8) & 0xf800));
+	      ((s >> 5) & 0x07e0) |
+	      ((s >> 8) & 0xf800));
     }
 }
 
@@ -1108,8 +1167,8 @@ fbStore_b5g6r5 (FbBits *bits, const CARD
     for (i = 0; i < width; ++i) {
         Split(READ(values + i));
         WRITE(pixel++, ((b << 8) & 0xf800) |
-                       ((g << 3) & 0x07e0) |
-                       ((r >> 3)         ));
+	      ((g << 3) & 0x07e0) |
+	      ((r >> 3)         ));
     }
 }
 
@@ -1121,9 +1180,9 @@ fbStore_a1r5g5b5 (FbBits *bits, const CA
     for (i = 0; i < width; ++i) {
         Splita(READ(values + i));
         WRITE(pixel++, ((a << 8) & 0x8000) |
-                       ((r << 7) & 0x7c00) |
-                       ((g << 2) & 0x03e0) |
-                       ((b >> 3)         ));
+	      ((r << 7) & 0x7c00) |
+	      ((g << 2) & 0x03e0) |
+	      ((b >> 3)         ));
     }
 }
 
@@ -1135,8 +1194,8 @@ fbStore_x1r5g5b5 (FbBits *bits, const CA
     for (i = 0; i < width; ++i) {
         Split(READ(values + i));
         WRITE(pixel++, ((r << 7) & 0x7c00) |
-                       ((g << 2) & 0x03e0) |
-                       ((b >> 3)         ));
+	      ((g << 2) & 0x03e0) |
+	      ((b >> 3)         ));
     }
 }
 
@@ -1148,10 +1207,10 @@ fbStore_a1b5g5r5 (FbBits *bits, const CA
     for (i = 0; i < width; ++i) {
         Splita(READ(values + i));
         WRITE(pixel++, ((a << 8) & 0x8000) |
-                       ((b << 7) & 0x7c00) |
-                       ((g << 2) & 0x03e0) |
-                       ((r >> 3)         ));
-	}
+	      ((b << 7) & 0x7c00) |
+	      ((g << 2) & 0x03e0) |
+	      ((r >> 3)         ));
+    }
 }
 
 static FASTCALL void
@@ -1162,8 +1221,8 @@ fbStore_x1b5g5r5 (FbBits *bits, const CA
     for (i = 0; i < width; ++i) {
         Split(READ(values + i));
         WRITE(pixel++, ((b << 7) & 0x7c00) |
-                       ((g << 2) & 0x03e0) |
-                       ((r >> 3)         ));
+	      ((g << 2) & 0x03e0) |
+	      ((r >> 3)         ));
     }
 }
 
@@ -1175,9 +1234,9 @@ fbStore_a4r4g4b4 (FbBits *bits, const CA
     for (i = 0; i < width; ++i) {
         Splita(READ(values + i));
         WRITE(pixel++, ((a << 8) & 0xf000) |
-                       ((r << 4) & 0x0f00) |
-                       ((g     ) & 0x00f0) |
-                       ((b >> 4)         ));
+	      ((r << 4) & 0x0f00) |
+	      ((g     ) & 0x00f0) |
+	      ((b >> 4)         ));
     }
 }
 
@@ -1189,8 +1248,8 @@ fbStore_x4r4g4b4 (FbBits *bits, const CA
     for (i = 0; i < width; ++i) {
         Split(READ(values + i));
         WRITE(pixel++, ((r << 4) & 0x0f00) |
-                       ((g     ) & 0x00f0) |
-                       ((b >> 4)         ));
+	      ((g     ) & 0x00f0) |
+	      ((b >> 4)         ));
     }
 }
 
@@ -1202,9 +1261,9 @@ fbStore_a4b4g4r4 (FbBits *bits, const CA
     for (i = 0; i < width; ++i) {
         Splita(READ(values + i));
         WRITE(pixel++, ((a << 8) & 0xf000) |
-                       ((b << 4) & 0x0f00) |
-                       ((g     ) & 0x00f0) |
-                       ((r >> 4)         ));
+	      ((b << 4) & 0x0f00) |
+	      ((g     ) & 0x00f0) |
+	      ((r >> 4)         ));
     }
 }
 
@@ -1216,8 +1275,8 @@ fbStore_x4b4g4r4 (FbBits *bits, const CA
     for (i = 0; i < width; ++i) {
         Split(READ(values + i));
         WRITE(pixel++, ((b << 4) & 0x0f00) |
-                       ((g     ) & 0x00f0) |
-                       ((r >> 4)         ));
+	      ((g     ) & 0x00f0) |
+	      ((r >> 4)         ));
     }
 }
 
@@ -1239,8 +1298,8 @@ fbStore_r3g3b2 (FbBits *bits, const CARD
     for (i = 0; i < width; ++i) {
         Split(READ(values + i));
         WRITE(pixel++, ((r     ) & 0xe0) |
-                       ((g >> 3) & 0x1c) |
-                       ((b >> 6)       ));
+	      ((g >> 3) & 0x1c) |
+	      ((b >> 6)       ));
     }
 }
 
@@ -1252,8 +1311,8 @@ fbStore_b2g3r3 (FbBits *bits, const CARD
     for (i = 0; i < width; ++i) {
         Split(READ(values + i));
         WRITE(pixel++, ((b     ) & 0xe0) |
-                       ((g >> 3) & 0x1c) |
-                       ((r >> 6)       ));
+	      ((g >> 3) & 0x1c) |
+	      ((r >> 6)       ));
     }
 }
 
@@ -1265,9 +1324,9 @@ fbStore_a2r2g2b2 (FbBits *bits, const CA
     for (i = 0; i < width; ++i) {
         Splita(READ(values + i));
         WRITE(pixel++, ((a     ) & 0xc0) |
-                       ((r >> 2) & 0x30) |
-                       ((g >> 4) & 0x0c) |
-                       ((b >> 6)       ));
+	      ((r >> 2) & 0x30) |
+	      ((g >> 4) & 0x0c) |
+	      ((b >> 6)       ));
     }
 }
 
@@ -1293,11 +1352,11 @@ fbStore_x4a4 (FbBits *bits, const CARD32
 
 #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) : \
+#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 ? \
+#define Store4(l,o,v)  Store8(l,o,((o) & 4 ?			       \
 				   (Fetch8(l,o) & 0x0f) | ((v) << 4) : \
 				   (Fetch8(l,o) & 0xf0) | (v)))
 #endif
@@ -1655,22 +1714,22 @@ fbCombineSaturateU (CARD32 *dest, const 
  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)
+ Disjoint			Conjoint
+ Fa		Fb		Fa		Fb
+ (0,0,0,0)	0		0		0		0
+ (0,A,0,A)	1		0		1		0
+ (0,0,B,B)	0		1		0		1
+ (0,A,B,A)	1		min((1-a)/b,1)	1		max(1-a/b,0)
+ (0,A,B,B)	min((1-b)/a,1)	1		max(1-b/a,0)	1
+ (0,0,0,A)	max(1-(1-b)/a,0) 0		min(1,b/a)	0
+ (0,0,0,B)	0		max(1-(1-a)/b,0) 0		min(a/b,1)
+ (0,A,0,0)	min(1,(1-b)/a)	0		max(1-b/a,0)	0
+ (0,0,B,0)	0		min(1,(1-a)/b)	0		max(1-a/b,0)
+ (0,0,B,A)	max(1-(1-b)/a,0) min(1,(1-a)/b)	 min(1,b/a)	max(1-a/b,0)
+ (0,A,0,B)	min(1,(1-b)/a)	max(1-(1-a)/b,0) max(1-b/a,0)	min(1,a/b)
+ (0,A,B,0)	min(1,(1-b)/a)	min(1,(1-a)/b)	max(1-b/a,0)	max(1-a/b,0)
 
- */
+*/
 
 #define CombineAOut 1
 #define CombineAIn  2
@@ -2634,7 +2693,7 @@ FbComposeFunctions composeFunctions = {
 };
 
 
-static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
+static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
 {
     FbBits *bits;
     FbStride stride;
@@ -2656,7 +2715,7 @@ static void fbFetchSolid(PicturePtr pict
     fbFinishAccess (pict->pDrawable);
 }
 
-static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
+static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
 {
     FbBits *bits;
     FbStride stride;
@@ -2676,43 +2735,78 @@ static void fbFetch(PicturePtr pict, int
 }
 
 #define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
-#define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :\
-        ((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
+#define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :		\
+		  ((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
 
+static CARD32
+xRenderColorMultToCard32 (xRenderColor *c)
+{
+    return
+	((((CARD32) c->red   * c->alpha) >> 24) << 16) |
+	((((CARD32) c->green * c->alpha) >> 24) <<  8) |
+	((((CARD32) c->blue  * c->alpha) >> 24) <<  0) |
+	((((CARD32) c->alpha		 ) >> 8)  << 24);
+}
 
 static CARD32 gradientPixel(const SourcePictPtr pGradient, xFixed_48_16 pos, unsigned int spread)
 {
-    int ipos = (pos * PICT_GRADIENT_STOPTABLE_SIZE - 1) >> 16;
+    int ipos = (pos * pGradient->gradient.stopRange - 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;
+    if (ipos < 0 || ipos >= pGradient->gradient.stopRange)
+    {
+	if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal)
+	{
+	    ipos = ipos % pGradient->gradient.stopRange;
+	    ipos = ipos < 0 ? pGradient->gradient.stopRange + ipos : ipos;
+
+	}
+	else if (spread == RepeatReflect)
+	{
+	    const int limit = pGradient->gradient.stopRange * 2 - 1;
 
-        } 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;
+	    ipos = ipos % limit;
+	    ipos = ipos < 0 ? limit + ipos : ipos;
+	    ipos = ipos >= pGradient->gradient.stopRange ? 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;
-        }
+	}
+	else if (spread == RepeatPad)
+	{
+	    if (ipos < 0)
+		ipos = 0;
+	    else
+		ipos = pGradient->gradient.stopRange - 1;
+	}
+	else  /* RepeatNone */
+	{
+	    return 0;
+	}
+    }
+
+    if (pGradient->gradient.colorTableSize)
+    {
+	return pGradient->gradient.colorTable[ipos];
     }
+    else
+    {
+	int i;
 
-    assert(ipos >= 0);
-    assert(ipos < PICT_GRADIENT_STOPTABLE_SIZE);
+	if (ipos <= pGradient->gradient.stops->x)
+	    return xRenderColorMultToCard32 (&pGradient->gradient.stops->color);
 
-    return pGradient->linear.colorTable[ipos];
+	for (i = 1; i < pGradient->gradient.nstops; i++)
+	{
+	    if (pGradient->gradient.stops[i].x >= ipos)
+		return PictureGradientColor (&pGradient->gradient.stops[i - 1],
+					     &pGradient->gradient.stops[i],
+					     ipos);
+	}
+
+	return xRenderColorMultToCard32 (&pGradient->gradient.stops[--i].color);
+    }
 }
 
-static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
+static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
 {
     SourcePictPtr pGradient = pict->pSourcePict;
     CARD32 *end = buffer + width;
@@ -2761,26 +2855,73 @@ static void fbFetchSourcePict(PicturePtr
                 t = ((a*v.vector[0] + b*v.vector[1]) >> 16) + off;
                 inc = (a * unit.vector[0] + b * unit.vector[1]) >> 16;
             }
-            while (buffer < end) {
-                WRITE(buffer++, gradientPixel(pGradient, t, pict->repeatType));
-                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;
-                }
-                WRITE(buffer++, gradientPixel(pGradient, t, pict->repeatType));
-                v.vector[0] += unit.vector[0];
-                v.vector[1] += unit.vector[1];
-                v.vector[2] += unit.vector[2];
+
+	    if (pGradient->linear.class == SourcePictClassVertical)
+	    {
+		register CARD32 color;
+
+		color = gradientPixel (pGradient, t, pict->repeat);
+		while (buffer < end)
+		    *buffer++ = color;
+	    }
+	    else
+	    {
+		while (buffer < end) {
+		    if (!mask || *mask++ & maskBits)
+		    {
+			*buffer = gradientPixel (pGradient, t, pict->repeat);
+		    }
+		    ++buffer;
+		    t += inc;
+		}
+	    }
+	}
+	else /* projective transformation */
+	{
+	    xFixed_48_16 t;
+
+	    if (pGradient->linear.class == SourcePictClassVertical)
+	    {
+		register CARD32 color;
+
+		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;
+		}
+
+		color = gradientPixel (pGradient, t, pict->repeat);
+		while (buffer < end)
+		    *buffer++ = color;
+	    }
+	    else
+	    {
+		while (buffer < end)
+		{
+		    if (!mask || *mask++ & maskBits)
+		    {
+			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);
+		    }
+		    ++buffer;
+		    v.vector[0] += unit.vector[0];
+		    v.vector[1] += unit.vector[1];
+		    v.vector[2] += unit.vector[2];
+		}
             }
         }
     } else {
@@ -2817,14 +2958,20 @@ static void fbFetchSourcePict(PicturePtr
                 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);
-                    WRITE(buffer, gradientPixel(pGradient,
-                                                (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
-                                                pict->repeatType));
-                    ++buffer;
+		    double b, c, det, s;
+
+		    if (!mask || *mask++ & maskBits)
+		    {
+			b = 2*(rx*pGradient->radial.dx + ry*pGradient->radial.dy);
+			c = -(rx*rx + ry*ry);
+			det = (b * b) - (4 * pGradient->radial.a * c);
+			s = (-b + sqrt(det))/(2. * pGradient->radial.a);
+			WRITE(buffer, gradientPixel(pGradient,
+						    (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
+						    pict->repeatType));
+		    }
+		    ++buffer;
+
                     rx += cx;
                     ry += cy;
                 }
@@ -2832,22 +2979,27 @@ static void fbFetchSourcePict(PicturePtr
                 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);
-                    WRITE(buffer, gradientPixel(pGradient,
-                                                (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
-                                                pict->repeatType));
-                    ++buffer;
+
+		    if (!mask || *mask++ & maskBits)
+		    {
+			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;
@@ -2860,28 +3012,37 @@ static void fbFetchSourcePict(PicturePtr
                 ry -= pGradient->conical.center.y/65536.;
 
                 while (buffer < end) {
-                    double angle = atan2(ry, rx) + a;
-                    WRITE(buffer, gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
-                                                pict->repeatType));
+		    double angle;
+
+		    if (!mask || *mask++ & maskBits)
+		    {
+			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, angle;
-                    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.;
-                    angle = atan2(y, x) + a;
-                    WRITE(buffer, gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
-                                                pict->repeatType));
+		    if (!mask || *mask++ & maskBits)
+		    {
+			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.;
+			angle = atan2(y, x) + a;
+			*buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
+						pict->repeat);
+		    }
                     ++buffer;
                     rx += cx;
                     ry += cy;
@@ -2892,9 +3053,7 @@ static void fbFetchSourcePict(PicturePtr
     }
 }
 
-
-
-static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
+static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
 {
     FbBits     *bits;
     FbStride    stride;
@@ -2943,39 +3102,47 @@ static void fbFetchTransformed(PicturePt
         if (pict->repeatType == RepeatNormal) {
             if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
                 for (i = 0; i < width; ++i) {
-                    if (!v.vector[2]) {
-                        WRITE(buffer + i, 0);
-                    } else {
-                        if (!affine) {
-                            y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
-                            x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width);
-                        } else {
-                            y = MOD(v.vector[1]>>16, pict->pDrawable->height);
-                            x = MOD(v.vector[0]>>16, pict->pDrawable->width);
-                        }
-                        WRITE(buffer + i, fetch(bits + (y + dy)*stride, x + dx, indexed));
-                    }
+		    if (!mask || mask[i] & maskBits)
+		    {
+			if (!v.vector[2]) {
+			    buffer[i] = 0;
+			} else {
+			    if (!affine) {
+				y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
+				x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width);
+			    } else {
+				y = MOD(v.vector[1]>>16, pict->pDrawable->height);
+				x = MOD(v.vector[0]>>16, 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]) {
-                        WRITE(buffer + i, 0);
-                    } else {
-                        if (!affine) {
-                            y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
-                            x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width);
-                        } else {
-                            y = MOD(v.vector[1]>>16, pict->pDrawable->height);
-                            x = MOD(v.vector[0]>>16, pict->pDrawable->width);
-                        }
-                        if (POINT_IN_REGION (0, pict->pCompositeClip, x + dx, y + dy, &box))
-                            WRITE(buffer + i, fetch(bits + (y + dy)*stride, x + dx, indexed));
-                        else
-                            WRITE(buffer + i, 0);
-                    }
+		    if (!mask || mask[i] & maskBits)
+		    {
+			if (!v.vector[2]) {
+			    buffer[i] = 0;
+			} else {
+			    if (!affine) {
+				y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
+				x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width);
+			    } else {
+				y = MOD(v.vector[1]>>16, pict->pDrawable->height);
+				x = MOD(v.vector[0]>>16, pict->pDrawable->width);
+			    }
+			    if (POINT_IN_REGION (0, 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];
@@ -2985,40 +3152,46 @@ static void fbFetchTransformed(PicturePt
             if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
                 box = pict->pCompositeClip->extents;
                 for (i = 0; i < width; ++i) {
-                    if (!v.vector[2]) {
-                        WRITE(buffer + i, 0);
-                    } else {
-                        if (!affine) {
-                            y = DIV(v.vector[1],v.vector[2]);
-                            x = DIV(v.vector[0],v.vector[2]);
-                        } else {
-                            y = v.vector[1]>>16;
-                            x = v.vector[0]>>16;
-                        }
-                        WRITE(buffer + i, ((x < box.x1-dx) | (x >= box.x2-dx) | (y < box.y1-dy) | (y >= box.y2-dy)) ?
-                                          0 : fetch(bits + (y + dy)*stride, x + dx, indexed));
-                    }
+		    if (!mask || mask[i] & maskBits)
+		    {
+			if (!v.vector[2]) {
+			    WRITE(buffer + i, 0);
+			} else {
+			    if (!affine) {
+				y = DIV(v.vector[1],v.vector[2]);
+				x = DIV(v.vector[0],v.vector[2]);
+			    } else {
+				y = v.vector[1]>>16;
+				x = v.vector[0]>>16;
+			    }
+			    WRITE(buffer + i, ((x < box.x1-dx) | (x >= box.x2-dx) | (y < box.y1-dy) | (y >= box.y2-dy)) ?
+				  0 : fetch(bits + (y + dy)*stride, x + dx, 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]) {
-                        WRITE(buffer + i, 0);
-                    } else {
-                        if (!affine) {
-                            y = DIV(v.vector[1],v.vector[2]);
-                            x = DIV(v.vector[0],v.vector[2]);
-                        } else {
-                            y = v.vector[1]>>16;
-                            x = v.vector[0]>>16;
-                        }
-                        if (POINT_IN_REGION (0, pict->pCompositeClip, x + dx, y + dy, &box))
-                            WRITE(buffer + i, fetch(bits + (y + dy)*stride, x + dx, indexed));
-                        else
-                            WRITE(buffer + i, 0);
-                    }
+                    if (!mask || mask[i] & maskBits)
+		    {
+			if (!v.vector[2]) {
+			    WRITE(buffer + i, 0);
+			} else {
+			    if (!affine) {
+				y = DIV(v.vector[1],v.vector[2]);
+				x = DIV(v.vector[0],v.vector[2]);
+			    } else {
+				y = v.vector[1]>>16;
+				x = v.vector[0]>>16;
+			    }
+			    if (POINT_IN_REGION (0, pict->pCompositeClip, x + dx, y + dy, &box))
+				WRITE(buffer + i, fetch(bits + (y + dy)*stride, x + dx, indexed));
+			    else
+				WRITE(buffer + i, 0);
+			}
+		    }
                     v.vector[0] += unit.vector[0];
                     v.vector[1] += unit.vector[1];
                     v.vector[2] += unit.vector[2];
@@ -3035,126 +3208,133 @@ static void fbFetchTransformed(PicturePt
         if (pict->repeatType == RepeatNormal) {
             if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
                 for (i = 0; i < width; ++i) {
-                    if (!v.vector[2]) {
-                        WRITE(buffer + i, 0);
-                    } else {
-                        int x1, x2, y1, y2, distx, idistx, disty, idisty;
-                        FbBits *b;
-                        CARD32 tl, tr, bl, br, r;
-                        CARD32 ft, fb;
-
-                        if (!affine) {
-                            xFixed_48_16 div;
-                            div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
-                            x1 = div >> 16;
-                            distx = ((xFixed)div >> 8) & 0xff;
-                            div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
-                            y1 = div >> 16;
-                            disty = ((xFixed)div >> 8) & 0xff;
-                        } else {
-                            x1 = v.vector[0] >> 16;
-                            distx = (v.vector[0] >> 8) & 0xff;
-                            y1 = v.vector[1] >> 16;
-                            disty = (v.vector[1] >> 8) & 0xff;
-                        }
-                        x2 = x1 + 1;
-                        y2 = y1 + 1;
-
-                        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 + dy)*stride;
-
-                        tl = fetch(b, x1 + dx, indexed);
-                        tr = fetch(b, x2 + dx, indexed);
-                        b = bits + (y2 + dy)*stride;
-                        bl = fetch(b, x1 + dx, indexed);
-                        br = fetch(b, x2 + dx, indexed);
-
-                        ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
-                        fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
-                        r = (((ft * idisty + fb * disty) >> 16) & 0xff);
-                        ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
-                        fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
-                        r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
-                        ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
-                        fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
-                        r |= (((ft * idisty + fb * disty)) & 0xff0000);
-                        ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
-                        fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
-                        r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
-                        WRITE(buffer + i, r);
-                    }
+                    if (!mask || mask[i] & maskBits)
+		    {
+			if (!v.vector[2]) {
+			    WRITE(buffer + i, 0);
+			} else {
+			    int x1, x2, y1, y2, distx, idistx, disty, idisty;
+			    FbBits *b;
+			    CARD32 tl, tr, bl, br, r;
+			    CARD32 ft, fb;
+
+			    if (!affine) {
+				xFixed_48_16 div;
+				div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
+				x1 = div >> 16;
+				distx = ((xFixed)div >> 8) & 0xff;
+				div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
+				y1 = div >> 16;
+				disty = ((xFixed)div >> 8) & 0xff;
+			    } else {
+				x1 = v.vector[0] >> 16;
+				distx = (v.vector[0] >> 8) & 0xff;
+				y1 = v.vector[1] >> 16;
+				disty = (v.vector[1] >> 8) & 0xff;
+			    }
+			    x2 = x1 + 1;
+			    y2 = y1 + 1;
+
+			    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 + dy)*stride;
+
+			    tl = fetch(b, x1 + dx, indexed);
+			    tr = fetch(b, x2 + dx, indexed);
+			    b = bits + (y2 + dy)*stride;
+			    bl = fetch(b, x1 + dx, indexed);
+			    br = fetch(b, x2 + dx, indexed);
+
+			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
+			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+			    WRITE(buffer + i, r);
+			}
+		    }
                     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]) {
-                        WRITE(buffer + i, 0);
-                    } else {
-                        int x1, x2, y1, y2, distx, idistx, disty, idisty;
-                        FbBits *b;
-                        CARD32 tl, tr, bl, br, r;
-                        CARD32 ft, fb;
-
-                        if (!affine) {
-                            xFixed_48_16 div;
-                            div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
-                            x1 = div >> 16;
-                            distx = ((xFixed)div >> 8) & 0xff;
-                            div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
-                            y1 = div >> 16;
-                            disty = ((xFixed)div >> 8) & 0xff;
-                        } else {
-                            x1 = v.vector[0] >> 16;
-                            distx = (v.vector[0] >> 8) & 0xff;
-                            y1 = v.vector[1] >> 16;
-                            disty = (v.vector[1] >> 8) & 0xff;
-                        }
-                        x2 = x1 + 1;
-                        y2 = y1 + 1;
-
-                        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 + dy)*stride;
-
-                        tl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y1 + dy, &box)
-                             ? fetch(b, x1 + dx, indexed) : 0;
-                        tr = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y1 + dy, &box)
-                             ? fetch(b, x2 + dx, indexed) : 0;
-                        b = bits + (y2 + dy)*stride;
-                        bl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y2 + dy, &box)
-                             ? fetch(b, x1 + dx, indexed) : 0;
-                        br = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y2 + dy, &box)
-                             ? fetch(b, x2 + dx, indexed) : 0;
-
-                        ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
-                        fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
-                        r = (((ft * idisty + fb * disty) >> 16) & 0xff);
-                        ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
-                        fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
-                        r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
-                        ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
-                        fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
-                        r |= (((ft * idisty + fb * disty)) & 0xff0000);
-                        ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
-                        fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
-                        r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
-                        WRITE(buffer + i, r);
-                    }
+		    if (!mask || mask[i] & maskBits)
+		    {
+			if (!v.vector[2]) {
+			    WRITE(buffer + i, 0);
+			} else {
+			    int x1, x2, y1, y2, distx, idistx, disty, idisty;
+			    FbBits *b;
+			    CARD32 tl, tr, bl, br, r;
+			    CARD32 ft, fb;
+
+			    if (!affine) {
+				xFixed_48_16 div;
+				div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
+				x1 = div >> 16;
+				distx = ((xFixed)div >> 8) & 0xff;
+				div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
+				y1 = div >> 16;
+				disty = ((xFixed)div >> 8) & 0xff;
+			    } else {
+				x1 = v.vector[0] >> 16;
+				distx = (v.vector[0] >> 8) & 0xff;
+				y1 = v.vector[1] >> 16;
+				disty = (v.vector[1] >> 8) & 0xff;
+			    }
+			    x2 = x1 + 1;
+			    y2 = y1 + 1;
+
+			    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 + dy)*stride;
+
+			    tl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y1 + dy, &box)
+				? fetch(b, x1 + dx, indexed) : 0;
+			    tr = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y1 + dy, &box)
+				? fetch(b, x2 + dx, indexed) : 0;
+			    b = bits + (y2 + dy)*stride;
+			    bl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y2 + dy, &box)
+				? fetch(b, x1 + dx, indexed) : 0;
+			    br = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y2 + dy, &box)
+				? fetch(b, x2 + dx, indexed) : 0;
+
+			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
+			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+			    WRITE(buffer + i, r);
+			}
+		    }
+
                     v.vector[0] += unit.vector[0];
                     v.vector[1] += unit.vector[1];
                     v.vector[2] += unit.vector[2];
@@ -3164,124 +3344,132 @@ static void fbFetchTransformed(PicturePt
             if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
                 box = pict->pCompositeClip->extents;
                 for (i = 0; i < width; ++i) {
-                    if (!v.vector[2]) {
-                        WRITE(buffer + i, 0);
-                    } else {
-                        int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
-                        FbBits *b;
-                        CARD32 tl, tr, bl, br, r;
-                        Bool x1_out, x2_out, y1_out, y2_out;
-                        CARD32 ft, fb;
-
-                        if (!affine) {
-                            xFixed_48_16 div;
-                            div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
-                            x1 = div >> 16;
-                            distx = ((xFixed)div >> 8) & 0xff;
-                            div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
-                            y1 = div >> 16;
-                            disty = ((xFixed)div >> 8) & 0xff;
-                        } else {
-                            x1 = v.vector[0] >> 16;
-                            distx = (v.vector[0] >> 8) & 0xff;
-                            y1 = v.vector[1] >> 16;
-                            disty = (v.vector[1] >> 8) & 0xff;
-                        }
-                        x2 = x1 + 1;
-                        y2 = y1 + 1;
-
-                        idistx = 256 - distx;
-                        idisty = 256 - disty;
-
-                        b = bits + (y1 + dy)*stride;
-                        x_off = x1 + dx;
-
-                        x1_out = (x1 < box.x1-dx) | (x1 >= box.x2-dx);
-                        x2_out = (x2 < box.x1-dx) | (x2 >= box.x2-dx);
-                        y1_out = (y1 < box.y1-dy) | (y1 >= box.y2-dy);
-                        y2_out = (y2 < box.y1-dy) | (y2 >= box.y2-dy);
-
-                        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);
-
-                        ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
-                        fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
-                        r = (((ft * idisty + fb * disty) >> 16) & 0xff);
-                        ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
-                        fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
-                        r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
-                        ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
-                        fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
-                        r |= (((ft * idisty + fb * disty)) & 0xff0000);
-                        ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
-                        fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
-                        r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
-                        WRITE(buffer + i, r);
-                    }
+		    if (!mask || mask[i] & maskBits)
+		    {
+			if (!v.vector[2]) {
+			    WRITE(buffer + i, 0);
+			} else {
+			    int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
+			    FbBits *b;
+			    CARD32 tl, tr, bl, br, r;
+			    Bool x1_out, x2_out, y1_out, y2_out;
+			    CARD32 ft, fb;
+
+			    if (!affine) {
+				xFixed_48_16 div;
+				div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
+				x1 = div >> 16;
+				distx = ((xFixed)div >> 8) & 0xff;
+				div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
+				y1 = div >> 16;
+				disty = ((xFixed)div >> 8) & 0xff;
+			    } else {
+				x1 = v.vector[0] >> 16;
+				distx = (v.vector[0] >> 8) & 0xff;
+				y1 = v.vector[1] >> 16;
+				disty = (v.vector[1] >> 8) & 0xff;
+			    }
+			    x2 = x1 + 1;
+			    y2 = y1 + 1;
+
+			    idistx = 256 - distx;
+			    idisty = 256 - disty;
+
+			    b = bits + (y1 + dy)*stride;
+			    x_off = x1 + dx;
+
+			    x1_out = (x1 < box.x1-dx) | (x1 >= box.x2-dx);
+			    x2_out = (x2 < box.x1-dx) | (x2 >= box.x2-dx);
+			    y1_out = (y1 < box.y1-dy) | (y1 >= box.y2-dy);
+			    y2_out = (y2 < box.y1-dy) | (y2 >= box.y2-dy);
+
+			    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);
+
+			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
+			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+			    WRITE(buffer + i, r);
+			}
+		    }
+
                     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]) {
-                        WRITE(buffer + i, 0);
-                    } else {
-                        int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
-                        FbBits *b;
-                        CARD32 tl, tr, bl, br, r;
-                        CARD32 ft, fb;
-
-                        if (!affine) {
-                            xFixed_48_16 div;
-                            div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
-                            x1 = div >> 16;
-                            distx = ((xFixed)div >> 8) & 0xff;
-                            div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
-                            y1 = div >> 16;
-                            disty = ((xFixed)div >> 8) & 0xff;
-                        } else {
-                            x1 = v.vector[0] >> 16;
-                            distx = (v.vector[0] >> 8) & 0xff;
-                            y1 = v.vector[1] >> 16;
-                            disty = (v.vector[1] >> 8) & 0xff;
-                        }
-                        x2 = x1 + 1;
-                        y2 = y1 + 1;
-
-                        idistx = 256 - distx;
-                        idisty = 256 - disty;
-
-                        b = bits + (y1 + dy)*stride;
-                        x_off = x1 + dx;
-
-                        tl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y1 + dy, &box)
-                             ? fetch(b, x_off, indexed) : 0;
-                        tr = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y1 + dy, &box)
-                             ? fetch(b, x_off + 1, indexed) : 0;
-                        b += stride;
-                        bl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y2 + dy, &box)
-                             ? fetch(b, x_off, indexed) : 0;
-                        br = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y2 + dy, &box)
-                             ? fetch(b, x_off + 1, indexed) : 0;
-
-                        ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
-                        fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
-                        r = (((ft * idisty + fb * disty) >> 16) & 0xff);
-                        ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
-                        fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
-                        r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
-                        ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
-                        fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
-                        r |= (((ft * idisty + fb * disty)) & 0xff0000);
-                        ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
-                        fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
-                        r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
-                        WRITE(buffer + i, r);
-                    }
+                    if (!mask || mask[i] & maskBits)
+		    {
+			if (!v.vector[2]) {
+			    WRITE(buffer + i, 0);
+			} else {
+			    int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
+			    FbBits *b;
+			    CARD32 tl, tr, bl, br, r;
+			    CARD32 ft, fb;
+
+			    if (!affine) {
+				xFixed_48_16 div;
+				div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
+				x1 = div >> 16;
+				distx = ((xFixed)div >> 8) & 0xff;
+				div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
+				y1 = div >> 16;
+				disty = ((xFixed)div >> 8) & 0xff;
+			    } else {
+				x1 = v.vector[0] >> 16;
+				distx = (v.vector[0] >> 8) & 0xff;
+				y1 = v.vector[1] >> 16;
+				disty = (v.vector[1] >> 8) & 0xff;
+			    }
+			    x2 = x1 + 1;
+			    y2 = y1 + 1;
+
+			    idistx = 256 - distx;
+			    idisty = 256 - disty;
+
+			    b = bits + (y1 + dy)*stride;
+			    x_off = x1 + dx;
+
+			    tl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y1 + dy, &box)
+				? fetch(b, x_off, indexed) : 0;
+			    tr = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y1 + dy, &box)
+				? fetch(b, x_off + 1, indexed) : 0;
+			    b += stride;
+			    bl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y2 + dy, &box)
+				? fetch(b, x_off, indexed) : 0;
+			    br = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y2 + dy, &box)
+				? fetch(b, x_off + 1, indexed) : 0;
+
+			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
+			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+			    WRITE(buffer + i, r);
+			}
+		    }
+
                     v.vector[0] += unit.vector[0];
                     v.vector[1] += unit.vector[1];
                     v.vector[2] += unit.vector[2];
@@ -3296,62 +3484,65 @@ static void fbFetchTransformed(PicturePt
 	int yoff = (params[1] - xFixed1) >> 1;
         params += 2;
         for (i = 0; i < width; ++i) {
-            if (!v.vector[2]) {
-                WRITE(buffer + i, 0);
-            } else {
-                int x1, x2, y1, y2, x, y;
-                INT32 srtot, sgtot, sbtot, satot;
-                xFixed *p = params;
-
-                if (!affine) {
-                    xFixed_48_16 tmp;
-                    tmp = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2] - xoff;
-                    x1 = xFixedToInt(tmp);
-                    tmp = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2] - yoff;
-                    y1 = xFixedToInt(tmp);
-                } else {
-                    x1 = xFixedToInt(v.vector[0] - xoff);
-                    y1 = xFixedToInt(v.vector[1] - yoff);
-                }
-                x2 = x1 + cwidth;
-                y2 = y1 + cheight;
-
-                srtot = sgtot = sbtot = satot = 0;
-
-                for (y = y1; y < y2; y++) {
-                    int ty = (pict->repeatType == RepeatNormal) ? MOD (y, pict->pDrawable->height) : y;
-                    for (x = x1; x < x2; x++) {
-                        if (*p) {
-                            int tx = (pict->repeatType == RepeatNormal) ? MOD (x, pict->pDrawable->width) : x;
-                            if (POINT_IN_REGION (0, pict->pCompositeClip, tx + dx, ty + dy, &box)) {
-                                FbBits *b = bits + (ty + dy)*stride;
-                                CARD32 c = fetch(b, tx + dx, indexed);
-
-                                srtot += Red(c) * *p;
-                                sgtot += Green(c) * *p;
-                                sbtot += Blue(c) * *p;
-                                satot += Alpha(c) * *p;
-                            }
-                        }
-                        p++;
-                    }
-                }
-
-		satot >>= 16;
-		srtot >>= 16;
-		sgtot >>= 16;
-		sbtot >>= 16;
-
-                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;
-
-                WRITE(buffer + i, ((satot << 24) |
-                                  (srtot << 16) |
-                                  (sgtot <<  8) |
-                                  (sbtot       )));
-            }
+	    if (!mask || mask[i] & maskBits)
+	    {
+		if (!v.vector[2]) {
+		    WRITE(buffer + i, 0);
+		} else {
+		    int x1, x2, y1, y2, x, y;
+		    INT32 srtot, sgtot, sbtot, satot;
+		    xFixed *p = params;
+
+		    if (!affine) {
+			xFixed_48_16 tmp;
+			tmp = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2] - xoff;
+			x1 = xFixedToInt(tmp);
+			tmp = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2] - yoff;
+			y1 = xFixedToInt(tmp);
+		    } else {
+			x1 = xFixedToInt(v.vector[0] - xoff);
+			y1 = xFixedToInt(v.vector[1] - yoff);
+		    }
+		    x2 = x1 + cwidth;
+		    y2 = y1 + cheight;
+
+		    srtot = sgtot = sbtot = satot = 0;
+
+		    for (y = y1; y < y2; y++) {
+			int ty = (pict->repeatType == RepeatNormal) ? MOD (y, pict->pDrawable->height) : y;
+			for (x = x1; x < x2; x++) {
+			    if (*p) {
+				int tx = (pict->repeatType == RepeatNormal) ? MOD (x, pict->pDrawable->width) : x;
+				if (POINT_IN_REGION (0, pict->pCompositeClip, tx + dx, ty + dy, &box)) {
+				    FbBits *b = bits + (ty + dy)*stride;
+				    CARD32 c = fetch(b, tx + dx, indexed);
+
+				    srtot += Red(c) * *p;
+				    sgtot += Green(c) * *p;
+				    sbtot += Blue(c) * *p;
+				    satot += Alpha(c) * *p;
+				}
+			    }
+			    p++;
+			}
+		    }
+
+		    satot >>= 16;
+		    srtot >>= 16;
+		    sgtot >>= 16;
+		    sbtot >>= 16;
+
+		    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;
+
+		    WRITE(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];
@@ -3362,27 +3553,32 @@ static void fbFetchTransformed(PicturePt
 }
 
 
-static void fbFetchExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
+static void fbFetchExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
 {
     int i;
     CARD32 _alpha_buffer[SCANLINE_BUFFER_LENGTH];
     CARD32 *alpha_buffer = _alpha_buffer;
 
     if (!pict->alphaMap) {
-        fbFetchTransformed(pict, x, y, width, buffer);
+        fbFetchTransformed(pict, x, y, width, buffer, mask, maskBits);
 	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);
+    fbFetchTransformed(pict, x, y, width, buffer, mask, maskBits);
+    fbFetchTransformed(pict->alphaMap, x - pict->alphaOrigin.x,
+		       y - pict->alphaOrigin.y, width, alpha_buffer,
+		       mask, maskBits);
     for (i = 0; i < width; ++i) {
-        int a = alpha_buffer[i]>>24;
-        WRITE(buffer + i, (a << 24)
-                          | (div_255(Red(READ(buffer + i)) * a) << 16)
-                          | (div_255(Green(READ(buffer + i)) * a) << 8)
-                          | (div_255(Blue(READ(buffer + i)) * a)));
+        if (!mask || mask[i] & maskBits)
+	{
+	    int a = alpha_buffer[i]>>24;
+	    WRITE(buffer + i, (a << 24)
+		  | (div_255(Red(READ(buffer + i)) * a) << 16)
+		  | (div_255(Green(READ(buffer + i)) * a) << 8)
+		  | (div_255(Blue(READ(buffer + i)) * a)));
+	}
     }
 
     if (alpha_buffer != _alpha_buffer)
@@ -3450,7 +3646,7 @@ static void fbStoreExternalAlpha(Picture
 }
 
 typedef void (*scanStoreProc)(PicturePtr , int , int , int , CARD32 *);
-typedef void (*scanFetchProc)(PicturePtr , int , int , int , CARD32 *);
+typedef void (*scanFetchProc)(PicturePtr , int , int , int , CARD32 * , CARD32 *, CARD32);
 
 static void
 fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
@@ -3460,31 +3656,52 @@ fbCompositeRect (const FbComposeData *da
     int i;
     scanStoreProc store;
     scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
-
+    unsigned int srcClass = SourcePictClassUnknown;
+    unsigned int maskClass = SourcePictClassUnknown;
+    FbBits *bits;
+    FbStride stride;
+    int xoff, yoff;
+    
     if (data->op == PictOpClear)
         fetchSrc = NULL;
     else if (!data->src->pDrawable) {
         if (data->src->pSourcePict)
+	{
             fetchSrc = fbFetchSourcePict;
+	    srcClass = SourcePictureClassify (data->src,
+					      data->xSrc, data->ySrc,
+					      data->width, data->height);
+	}
     } else if (data->src->alphaMap)
         fetchSrc = fbFetchExternalAlpha;
     else if (data->src->repeatType == RepeatNormal &&
              data->src->pDrawable->width == 1 && data->src->pDrawable->height == 1)
+    {
         fetchSrc = fbFetchSolid;
+	srcClass = SourcePictClassHorizontal;
+    }
     else if (!data->src->transform && data->src->filter != PictFilterConvolution)
         fetchSrc = fbFetch;
     else
         fetchSrc = fbFetchTransformed;
-
+    
     if (data->mask && data->op != PictOpClear) {
         if (!data->mask->pDrawable) {
             if (data->mask->pSourcePict)
                 fetchMask = fbFetchSourcePict;
         } else if (data->mask->alphaMap)
+	{
             fetchMask = fbFetchExternalAlpha;
+	    maskClass = SourcePictureClassify (data->mask,
+					       data->xMask, data->yMask,
+					       data->width, data->height);
+	}
         else if (data->mask->repeatType == RepeatNormal
                  && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1)
-            fetchMask = fbFetchSolid;
+	{
+	    fetchMask = fbFetchSolid;
+	    maskClass = SourcePictClassHorizontal;
+	}
         else if (!data->mask->transform && data->mask->filter != PictFilterConvolution)
             fetchMask = fbFetch;
         else
@@ -3492,78 +3709,206 @@ fbCompositeRect (const FbComposeData *da
     } else {
         fetchMask = NULL;
     }
-
-    if (data->dest->alphaMap) {
-        fetchDest = fbFetchExternalAlpha;
-        store = fbStoreExternalAlpha;
-    } else {
-        fetchDest = fbFetch;
-        store = fbStore;
+    
+    if (data->dest->alphaMap)
+    {
+	fetchDest = fbFetchExternalAlpha;
+	store = fbStoreExternalAlpha;
+	
+	if (data->op == PictOpClear || data->op == PictOpSrc)
+	    fetchDest = NULL;
     }
-    if (data->op == PictOpClear || data->op == PictOpSrc)
-        fetchDest = NULL;
-
-    if (fetchSrc && fetchMask && data->mask && data->mask->componentAlpha && PICT_FORMAT_RGB(data->mask->format)) {
-        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 = NULL;
-            fetchMask = NULL;
-        }
-
-        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);
-        }
+    else
+    {
+	fetchDest = fbFetch;
+	store = fbStore;
+	
+	switch (data->op) {
+	case PictOpClear:
+	case PictOpSrc:
+	    fetchDest = NULL;
+	    /* fall-through */
+	case PictOpAdd:
+	case PictOpOver:
+	    switch (data->dest->format) {
+	    case PICT_a8r8g8b8:
+	    case PICT_x8r8g8b8:
+		store = NULL;
+		break;
+	    default:
+		break;
+	    }
+	    break;
+	}
+    }
+    
+    if (!store)
+    {
+	int bpp;
+	
+	fbGetDrawable (data->dest->pDrawable, bits, stride, bpp, xoff, yoff);
+    }
+    else
+    {
+	bits = NULL;
+	stride = 0;
+	xoff = yoff = 0;
+    }
+    
+    if (fetchSrc		   &&
+	fetchMask		   &&
+	data->mask		   &&
+	data->mask->componentAlpha &&
+	PICT_FORMAT_RGB (data->mask->format))
+    {
+	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 */
+	    if (fetchSrc)
+	    {
+		if (fetchMask)
+		{
+		    /* fetch mask before source so that fetching of
+		       source can be optimized */
+		    fetchMask (data->mask, data->xMask, data->yMask + i,
+			       data->width, mask_buffer, 0, 0);
+		    
+		    if (maskClass == SourcePictClassHorizontal)
+			fetchMask = NULL;
+		}
+		
+		if (srcClass == SourcePictClassHorizontal)
+		{
+		    fetchSrc (data->src, data->xSrc, data->ySrc + i,
+			      data->width, src_buffer, 0, 0);
+		    fetchSrc = NULL;
+		}
+		else
+		{
+		    fetchSrc (data->src, data->xSrc, data->ySrc + i,
+			      data->width, src_buffer, mask_buffer,
+			      0xffffffff);
+		}
+	    }
+	    else if (fetchMask)
+	    {
+		fetchMask (data->mask, data->xMask, data->yMask + i,
+			   data->width, mask_buffer, 0, 0);
+	    }
+	    
+	    if (store)
+	    {
+		/* fill dest into second half of scanline */
+		if (fetchDest)
+		    fetchDest (data->dest, data->xDest, data->yDest + i,
+			       data->width, dest_buffer, 0, 0);
+		
+		/* 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
+	    {
+		/* blend */
+		compose (bits + (data->yDest + i+ yoff) * stride +
+			 data->xDest + xoff,
+			 src_buffer, mask_buffer, data->width);
+	    }
+	}
+    }
+    else
+    {
+	CARD32 *src_mask_buffer = 0, *mask_buffer = 0;
+	CombineFuncU compose = composeFunctions.combineU[data->op];
+	if (!compose)
+	    return;
+	
+	if (fetchMask)
+	    mask_buffer = dest_buffer + data->width;
+	
+	for (i = 0; i < data->height; ++i) {
+	    /* fill first half of scanline with source */
+	    if (fetchSrc)
+	    {
+		if (fetchMask)
+		{
+		    /* fetch mask before source so that fetching of
+		       source can be optimized */
+		    fetchMask (data->mask, data->xMask, data->yMask + i,
+			       data->width, mask_buffer, 0, 0);
+		    
+		    if (maskClass == SourcePictClassHorizontal)
+			fetchMask = NULL;
+		}
+		
+		if (srcClass == SourcePictClassHorizontal)
+		{
+		    fetchSrc (data->src, data->xSrc, data->ySrc + i,
+			      data->width, src_buffer, 0, 0);
+		    
+		    if (mask_buffer)
+		    {
+			fbCombineInU (mask_buffer, src_buffer, data->width);
+			src_mask_buffer = mask_buffer;
+		    }
+		    else
+			src_mask_buffer = src_buffer;
+		    
+		    fetchSrc = NULL;
+		}
+		else
+		{
+		    fetchSrc (data->src, data->xSrc, data->ySrc + i,
+			      data->width, src_buffer, mask_buffer,
+			      0xff000000);
+		    
+		    if (mask_buffer)
+			composeFunctions.combineMaskU (src_buffer,
+						       mask_buffer,
+						       data->width);
+		    
+		    src_mask_buffer = src_buffer;
+		}
+	    }
+	    else if (fetchMask)
+	    {
+		fetchMask (data->mask, data->xMask, data->yMask + i,
+			   data->width, mask_buffer, 0, 0);
+		
+		fbCombineInU (mask_buffer, src_buffer, data->width);
+		
+		src_mask_buffer = mask_buffer;
+	    }
+	    
+	    if (store)
+	    {
+		/* fill dest into second half of scanline */
+		if (fetchDest)
+		    fetchDest (data->dest, data->xDest, data->yDest + i,
+			       data->width, dest_buffer, 0, 0);
+		
+		/* blend */
+		compose (dest_buffer, src_mask_buffer, data->width);
+		
+		/* write back */
+		store (data->dest, data->xDest, data->yDest + i, data->width,
+		       dest_buffer);
+	    }
+	    else
+	    {
+		/* blend */
+		compose (bits + (data->yDest + i+ yoff) * stride +
+			 data->xDest + xoff,
+			 src_mask_buffer, data->width);
+	    }
+	}
     }
 }
 
@@ -3593,11 +3938,11 @@ fbCompositeGeneral (CARD8	op,
     
     if (pSrc->pDrawable)
         srcRepeat = pSrc->repeatType == RepeatNormal && !pSrc->transform
-                    && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1);
+	    && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1);
 
     if (pMask && pMask->pDrawable)
 	maskRepeat = pMask->repeatType == RepeatNormal && !pMask->transform
-                     && (pMask->pDrawable->width != 1 || pMask->pDrawable->height != 1);
+	    && (pMask->pDrawable->width != 1 || pMask->pDrawable->height != 1);
 
     if (op == PictOpOver && !pMask && !pSrc->transform && !PICT_FORMAT_A(pSrc->format) && !pSrc->alphaMap)
         op = PictOpSrc;
@@ -3614,7 +3959,7 @@ fbCompositeGeneral (CARD8	op,
 				   yDst,
 				   width,
 				   height))
-	    return;
+	return;
 
     compose_data.op = op;
     compose_data.src = pSrc;
@@ -3675,7 +4020,7 @@ fbCompositeGeneral (CARD8	op,
 	    compose_data.ySrc += compose_data.height;
 	    compose_data.yMask += compose_data.height;
 	    compose_data.yDest += compose_data.height;
-    }
+	}
 	pbox++;
     }
     REGION_UNINIT (pDst->pDrawable->pScreen, &region);
diff --git a/render/picture.c b/render/picture.c
index c30649c..3f64182 100644
--- a/render/picture.c
+++ b/render/picture.c
@@ -890,54 +890,22 @@ static unsigned int INTERPOLATE_PIXEL_25
     return x;
 }
 
-static void initGradientColorTable(SourcePictPtr pGradient, int *error)
-{
-    int begin_pos, end_pos;
-    xFixed incr, dpos;
-    int pos, current_stop;
-    PictGradientStopPtr stops = pGradient->linear.stops;
-    int nstops = pGradient->linear.nstops;
-
-    /* The position where the gradient begins and ends */
-    begin_pos = (stops[0].x * PICT_GRADIENT_STOPTABLE_SIZE) >> 16;
-    end_pos = (stops[nstops - 1].x * PICT_GRADIENT_STOPTABLE_SIZE) >> 16;
-
-    pos = 0; /* The position in the color table. */
-
-    /* Up to first point */
-    while (pos <= begin_pos) {
-        pGradient->linear.colorTable[pos] = xRenderColorToCard32(stops[0].color);
-        ++pos;
-    }
-
-    incr =  (1<<16)/ PICT_GRADIENT_STOPTABLE_SIZE; /* the double increment. */
-    dpos = incr * pos; /* The position in terms of 0-1. */
-
-    current_stop = 0; /* We always interpolate between current and current + 1. */
-
-    /* Gradient area */
-    while (pos < end_pos) {
-        unsigned int current_color = xRenderColorToCard32(stops[current_stop].color);
-        unsigned int next_color = xRenderColorToCard32(stops[current_stop + 1].color);
+CARD32
+PictureGradientColor (PictGradientStopPtr stop1,
+		      PictGradientStopPtr stop2,
+		      CARD32	          x)
+{
+     CARD32 current_color, next_color;
+     int	   dist, idist;
 
-        int dist = (int)(256*(dpos - stops[current_stop].x)
-                         / (stops[current_stop+1].x - stops[current_stop].x));
-        int idist = 256 - dist;
+     current_color = xRenderColorToCard32 (stop1->color);
+     next_color    = xRenderColorToCard32 (stop2->color);
 
-        pGradient->linear.colorTable[pos] = premultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
+     dist  = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x));
+     idist = 256 - dist;
 
-        ++pos;
-        dpos += incr;
-
-        if (dpos > stops[current_stop + 1].x)
-            ++current_stop;
-    }
-
-    /* After last point */
-    while (pos < PICT_GRADIENT_STOPTABLE_SIZE) {
-        pGradient->linear.colorTable[pos] = xRenderColorToCard32(stops[nstops - 1].color);
-        ++pos;
-    }
+     return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist,
+					       next_color, dist));
 }
 
 static void initGradient(SourcePictPtr pGradient, int stopCount,
@@ -953,26 +921,30 @@ static void initGradient(SourcePictPtr p
 
     dpos = -1;
     for (i = 0; i < stopCount; ++i) {
-        if (stopPoints[i] <= dpos || stopPoints[i] > (1<<16)) {
+        if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) {
             *error = BadValue;
             return;
         }
         dpos = stopPoints[i];
     }
 
-    pGradient->linear.stops = xalloc(stopCount*sizeof(PictGradientStop));
-    if (!pGradient->linear.stops) {
+    pGradient->gradient.stops = xalloc(stopCount*sizeof(PictGradientStop));
+    if (!pGradient->gradient.stops) {
         *error = BadAlloc;
         return;
     }
 
-    pGradient->linear.nstops = stopCount;
+    pGradient->gradient.nstops = stopCount;
 
     for (i = 0; i < stopCount; ++i) {
-        pGradient->linear.stops[i].x = stopPoints[i];
-        pGradient->linear.stops[i].color = stopColors[i];
+        pGradient->gradient.stops[i].x = stopPoints[i];
+        pGradient->gradient.stops[i].color = stopColors[i];
     }
-    initGradientColorTable(pGradient, error);
+
+    pGradient->gradient.class	       = SourcePictClassUnknown;
+    pGradient->gradient.stopRange      = 0xffff;
+    pGradient->gradient.colorTable     = NULL;
+    pGradient->gradient.colorTableSize = 0;
 }
 
 static PicturePtr createSourcePicture(void)
@@ -980,9 +952,9 @@ static PicturePtr createSourcePicture(vo
     PicturePtr pPicture;
     pPicture = (PicturePtr) xalloc(sizeof(PictureRec));
     pPicture->pDrawable = 0;
-    pPicture->format = PICT_a8r8g8b8;
     pPicture->pFormat = 0;
     pPicture->pNext = 0;
+    pPicture->format = PICT_a8r8g8b8;
     pPicture->devPrivates = 0;
 
     SetPictureToDefaults(pPicture);
@@ -1027,10 +999,6 @@ CreateLinearGradientPicture (Picture pid
         *error = BadAlloc;
         return 0;
     }
-    if (p1->x == p2->x && p1->y == p2->y) {
-        *error = BadValue;
-        return 0;
-    }
 
     pPicture->id = pid;
     pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictLinearGradient));
@@ -1072,14 +1040,6 @@ CreateRadialGradientPicture (Picture pid
         *error = BadAlloc;
         return 0;
     }
-    {
-        double dx = (double)(inner->x - outer->x);
-        double dy = (double)(inner->y - outer->y);
-        if (sqrt(dx*dx + dy*dy) + (double)(innerRadius) > (double)(outerRadius)) {
-            *error = BadValue;
-            return 0;
-        }
-    }
 
     pPicture->id = pid;
     pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictRadialGradient));
@@ -1627,13 +1587,17 @@ FreePicture (pointer	value,
     {
 	if (pPicture->transform)
 	    xfree (pPicture->transform);
-        if (!pPicture->pDrawable) {
-            if (pPicture->pSourcePict) {
-                if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
-                    xfree(pPicture->pSourcePict->linear.stops);
-                xfree(pPicture->pSourcePict);
-            }
-        } else {
+
+	if (pPicture->pSourcePict)
+	{
+	    if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
+		xfree(pPicture->pSourcePict->linear.stops);
+
+	    xfree(pPicture->pSourcePict);
+	}
+
+	if (pPicture->pDrawable)
+	{
             ScreenPtr	    pScreen = pPicture->pDrawable->pScreen;
             PictureScreenPtr    ps = GetPictureScreen(pScreen);
 	
diff --git a/render/picturestr.h b/render/picturestr.h
index f1617f6..3f3c600 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -68,8 +68,13 @@ typedef struct _PictTransform {
 #define SourcePictTypeRadial 2
 #define SourcePictTypeConical 3
 
+#define SourcePictClassUnknown    0
+#define SourcePictClassHorizontal 1
+#define SourcePictClassVertical   2
+
 typedef struct _PictSolidFill {
     unsigned int type;
+    unsigned int class;
     CARD32 color;
 } PictSolidFill, *PictSolidFillPtr;
 
@@ -80,16 +85,22 @@ typedef struct _PictGradientStop {
 
 typedef struct _PictGradient {
     unsigned int type;
+    unsigned int class;
     int nstops;
     PictGradientStopPtr stops;
-    CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
+    int stopRange;
+    CARD32 *colorTable;
+    int colorTableSize;
 } PictGradient, *PictGradientPtr;
 
 typedef struct _PictLinearGradient {
     unsigned int type;
+    unsigned int class;
     int nstops;
     PictGradientStopPtr stops;
-    CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
+    int stopRange;
+    CARD32 *colorTable;
+    int colorTableSize;
     xPointFixed p1;
     xPointFixed p2;
 } PictLinearGradient, *PictLinearGradientPtr;
@@ -98,7 +109,6 @@ typedef struct _PictRadialGradient {
     unsigned int type;
     int nstops;
     PictGradientStopPtr stops;
-    CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
     double fx;
     double fy;
     double dx;
@@ -110,9 +120,12 @@ typedef struct _PictRadialGradient {
 
 typedef struct _PictConicalGradient {
     unsigned int type;
+    unsigned int class;
     int nstops;
     PictGradientStopPtr stops;
-    CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
+    int stopRange;
+    CARD32 *colorTable;
+    int colorTableSize;
     xPointFixed center;
     xFixed angle;
 } PictConicalGradient, *PictConicalGradientPtr;
@@ -624,6 +637,11 @@ Bool
 PictureTransformPoint3d (PictTransformPtr transform,
                          PictVectorPtr	vector);
 
+CARD32
+PictureGradientColor (PictGradientStopPtr stop1,
+		      PictGradientStopPtr stop2,
+		      CARD32	          x);
+
 void RenderExtensionInit (void);
 
 Bool



More information about the xorg-commit mailing list