xserver: Branch 'master'

Alan Hourihane alanh at fairlite.demon.co.uk
Thu Apr 19 16:14:25 PDT 2007


Hi Søren,

There are places in this patch where you've broken the fb wrapper
module.

For example,

*buffer++ = color;

should be

WRITE(buffer++, color);

and there's plenty of other places where the equivalent should be
happening.

Can you fix this up ??

Thanks,

Alan.

On Thu, 2007-04-19 at 15:42 -0700, Søren Sandmann Pedersen wrote:
>  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
> _______________________________________________
> xorg-commit mailing list
> xorg-commit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/xorg-commit




More information about the xorg mailing list