xserver/render mipict.c, 1.25, 1.26 picture.c, 1.41, 1.42 render.c, 1.34, 1.35

Lars Knoll <xserver-commit-u7BhqnqprCWvj1b/[email protected]> Wed, 29 Jun 2005 04:57:21 -0700 (PDT)
Newsgroups gmane.comp.freedesktop.xserver.cvs
Message-ID <[email protected]>
Committed by: lars

Update of /cvs/xserver/xserver/render
In directory gabe:/tmp/cvs-serv16798/render

Modified Files:
	mipict.c picture.c render.c 
Log Message:
Add support for gradients and solid fills to Render. 

Changed the semantics of the Convolution filter a
bit. It now doesn't try to normalize the filter
values but leaves this to the client. This gives
more reasonable behaviour in the limit where the filter
parameters sum up to 0.



Index: mipict.c
===================================================================
RCS file: /cvs/xserver/xserver/render/mipict.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- mipict.c	13 Jun 2005 08:00:59 -0000	1.25
+++ mipict.c	29 Jun 2005 11:57:18 -0000	1.26
@@ -344,7 +344,7 @@
 		  int		dy)
 {
     /* XXX what to do with clipping from transformed pictures? */
-    if (pPicture->transform)
+    if (pPicture->transform || !pPicture->pDrawable)
 	return TRUE;
 
     /* XXX what to do with clipping from pictures with filter that touch
@@ -385,7 +385,12 @@
 			   CARD16	height)
 {
     DrawablePtr	pDrawable = pPicture->pDrawable;
-    ScreenPtr	pScreen = pDrawable->pScreen;
+    ScreenPtr	pScreen;
+
+    if (!pDrawable)
+        return;
+
+    pScreen = pDrawable->pScreen;
 
     if (pScreen->SourceValidate)
     {
@@ -590,9 +595,14 @@
 Bool
 miIsSolidAlpha (PicturePtr pSrc)
 {
-    ScreenPtr	pScreen = pSrc->pDrawable->pScreen;
+    ScreenPtr	pScreen;
     char	line[1];
 
+    if (!pSrc->pDrawable)
+        return FALSE;
+
+    pScreen = pSrc->pDrawable->pScreen;
+
     /* Alpha-only */
     if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A)
 	return FALSE;

Index: picture.c
===================================================================
RCS file: /cvs/xserver/xserver/render/picture.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- picture.c	15 Jun 2005 12:13:57 -0000	1.41
+++ picture.c	29 Jun 2005 11:57:18 -0000	1.42
@@ -712,6 +712,7 @@
 
     pPicture->serialNumber = GC_CHANGE_SERIAL_BIT;
     pPicture->stateChanges = (1 << (CPLastBit+1)) - 1;
+    pPicture->pSourcePict = 0;
 }
 
 PicturePtr
@@ -795,6 +796,301 @@
     return pPicture;
 }
 
+static CARD32 xRenderColorToCard32(xRenderColor c)
+{
+    return
+        (c.alpha >> 8 << 24) |
+        (c.red >> 8 << 16) |
+        (c.green & 0xff00) |
+        (c.blue >> 8);
+}
+
+static uint premultiply(uint x)
+{
+    uint a = x >> 24;
+    uint t = (x & 0xff00ff) * a;
+    t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
+    t &= 0xff00ff;
+
+    x = ((x >> 8) & 0xff) * a;
+    x = (x + ((x >> 8) & 0xff) + 0x80);
+    x &= 0xff00;
+    x |= t | (a << 24);
+    return x;
+}
+
+static uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b)
+{
+    CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
+    t >>= 8;
+    t &= 0xff00ff;
+
+    x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
+    x &= 0xff00ff00;
+    x |= t;
+    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) {
+        uint current_color = xRenderColorToCard32(stops[current_stop].color);
+        uint next_color = xRenderColorToCard32(stops[current_stop + 1].color);
+
+        int dist = (int)(256*(dpos - stops[current_stop].x)
+                         / (stops[current_stop+1].x - stops[current_stop].x));
+        int idist = 256 - dist;
+
+        pGradient->linear.colorTable[pos] = premultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, 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;
+    }
+}
+
+static void initGradient(SourcePictPtr pGradient, int stopCount,
+                         xFixed *stopPoints, xRenderColor *stopColors, int *error)
+{
+    int i;
+    xFixed dpos;
+
+    if (stopCount <= 0) {
+        *error = BadValue;
+        return;
+    }
+
+    dpos = -1;
+    for (i = 0; i < stopCount; ++i) {
+        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) {
+        *error = BadAlloc;
+        return;
+    }
+
+    pGradient->linear.nstops = stopCount;
+
+    for (i = 0; i < stopCount; ++i) {
+        pGradient->linear.stops[i].x = stopPoints[i];
+        pGradient->linear.stops[i].color = stopColors[i];
+    }
+    initGradientColorTable(pGradient, error);
+}
+
+static PicturePtr createSourcePicture(void)
+{
+    PicturePtr pPicture;
+    pPicture = (PicturePtr) xalloc(sizeof(PictureRec));
+    pPicture->pDrawable = 0;
+    pPicture->pFormat = 0;
+    pPicture->pNext = 0;
+
+    SetPictureToDefaults(pPicture);
+    return pPicture;
+}
+
+PicturePtr
+CreateSolidPicture (Picture pid, xRenderColor *color, int *error)
+{
+    PicturePtr pPicture;
+    pPicture = createSourcePicture();
+    if (!pPicture) {
+        *error = BadAlloc;
+        return 0;
+    }
+
+    pPicture->id = pid;
+    pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictSolidFill));
+    if (!pPicture->pSourcePict) {
+        *error = BadAlloc;
+        xfree(pPicture);
+        return 0;
+    }
+    pPicture->pSourcePict->type = SourcePictTypeSolidFill;
+    pPicture->pSourcePict->solidFill.color = premultiply(xRenderColorToCard32(*color));
+    return pPicture;
+}
+
+PicturePtr
+CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2,
+                             int nStops, xFixed *stops, xRenderColor *colors, int *error)
+{
+    PicturePtr pPicture;
+
+    if (nStops < 2) {
+        *error = BadValue;
+        return 0;
+    }
+
+    pPicture = createSourcePicture();
+    if (!pPicture) {
+        *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));
+    if (!pPicture->pSourcePict) {
+        *error = BadAlloc;
+        xfree(pPicture);
+        return 0;
+    }
+
+    pPicture->pSourcePict->linear.type = SourcePictTypeLinear;
+    pPicture->pSourcePict->linear.p1 = *p1;
+    pPicture->pSourcePict->linear.p2 = *p2;
+
+    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
+    if (*error) {
+        xfree(pPicture);
+        return 0;
+    }
+    return pPicture;
+}
+
+#define FixedToDouble(x) ((x)/65536.)
+
+PicturePtr
+CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer,
+                             xFixed innerRadius, xFixed outerRadius,
+                             int nStops, xFixed *stops, xRenderColor *colors, int *error)
+{
+    PicturePtr pPicture;
+    PictRadialGradient *radial;
+
+    if (nStops < 2) {
+        *error = BadValue;
+        return 0;
+    }
+
+    pPicture = createSourcePicture();
+    if (!pPicture) {
+        *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));
+    if (!pPicture->pSourcePict) {
+        *error = BadAlloc;
+        xfree(pPicture);
+        return 0;
+    }
+    radial = &pPicture->pSourcePict->radial;
+
+    radial->type = SourcePictTypeRadial;
+    {
+        double x = (double)innerRadius / (double)outerRadius;
+        radial->dx = (outer->x - inner->x);
+        radial->dy = (outer->y - inner->y);
+        radial->fx = (inner->x) - x*radial->dx;
+        radial->fy = (inner->y) - x*radial->dy;
+        radial->m = 1./(1+x);
+        radial->b = -x*radial->m;
+        radial->dx /= 65536.;
+        radial->dy /= 65536.;
+        radial->fx /= 65536.;
+        radial->fy /= 65536.;
+        x = outerRadius/65536.;
+        radial->a = x*x - radial->dx*radial->dx - radial->dy*radial->dy;
+    }
+
+    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
+    if (*error) {
+        xfree(pPicture);
+        return 0;
+    }
+    return pPicture;
+}
+
+PicturePtr
+CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle,
+                              int nStops, xFixed *stops, xRenderColor *colors, int *error)
+{
+    PicturePtr pPicture;
+
+    if (nStops < 2) {
+        *error = BadValue;
+        return 0;
+    }
+
+    pPicture = createSourcePicture();
+    if (!pPicture) {
+        *error = BadAlloc;
+        return 0;
+    }
+
+    pPicture->id = pid;
+    pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictConicalGradient));
+    if (!pPicture->pSourcePict) {
+        *error = BadAlloc;
+        xfree(pPicture);
+        return 0;
+    }
+
+    pPicture->pSourcePict->conical.type = SourcePictTypeConical;
+    pPicture->pSourcePict->conical.center = *center;
+    pPicture->pSourcePict->conical.angle = angle;
+
+    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
+    if (*error) {
+        xfree(pPicture);
+        return 0;
+    }
+    return pPicture;
+}
+
 #define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
 
 #define NEXT_PTR(_type) ((_type) ulist++->ptr)
@@ -806,8 +1102,8 @@
 	       DevUnion		*ulist,
 	       ClientPtr	client)
 {
-    ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
-    PictureScreenPtr	ps = GetPictureScreen(pScreen);
+    ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0;
+    PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0;
     BITS32		index2;
     int			error = 0;
     BITS32		maskQ;
@@ -825,7 +1121,7 @@
 	    {
 		unsigned int	newr;
 		newr = NEXT_VAL(unsigned int);
-		if (newr <= xTrue)
+		if (newr <= RepeatReflect)
 		    pPicture->repeat = newr;
 		else
 		{
@@ -893,6 +1189,8 @@
 		Pixmap	    pid;
 		PixmapPtr   pPixmap;
 		int	    clipType;
+                if (!pScreen)
+                    return BadDrawable;
 
 		if (vlist)
 		{
@@ -1019,7 +1317,8 @@
 	    break;
 	}
     }
-    (*ps->ChangePicture) (pPicture, maskQ);
+    if (ps)
+        (*ps->ChangePicture) (pPicture, maskQ);
     return error;
 }
 
@@ -1103,9 +1402,8 @@
 	{ 0x00000, xFixed1, 0x00000 },
 	{ 0x00000, 0x00000, xFixed1 },
     } };
-    ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
-    PictureScreenPtr	ps = GetPictureScreen(pScreen);
-    int			result;
+    PictureScreenPtr	ps = pPicture->pDrawable ? GetPictureScreen(pPicture->pDrawable->pScreen) : 0;
+    int			result = 0;
 
     if (transform && memcmp (transform, &identity, sizeof (PictTransform)) == 0)
 	transform = 0;
@@ -1129,6 +1427,7 @@
 	}
     }
     pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
+    if (ps)
     result = (*ps->ChangePictureTransform) (pPicture, transform);
     return result;
 }
@@ -1136,7 +1435,7 @@
 static void
 ValidateOnePicture (PicturePtr pPicture)
 {
-    if (pPicture->serialNumber != pPicture->pDrawable->serialNumber)
+    if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber)
     {
 	PictureScreenPtr    ps = GetPictureScreen(pPicture->pDrawable->pScreen);
 
@@ -1162,35 +1461,43 @@
 
     if (--pPicture->refcnt == 0)
     {
-	ScreenPtr	    pScreen = pPicture->pDrawable->pScreen;
-	PictureScreenPtr    ps = GetPictureScreen(pScreen);
+        if (!pPicture->pDrawable) {
+            if (pPicture->pSourcePict) {
+                if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
+                    xfree(pPicture->pSourcePict->linear.stops);
+                xfree(pPicture->pSourcePict);
+            }
+        } else {
+            ScreenPtr	    pScreen = pPicture->pDrawable->pScreen;
+            PictureScreenPtr    ps = GetPictureScreen(pScreen);
 
-	if (pPicture->alphaMap)
-	    FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
-	(*ps->DestroyPicture) (pPicture);
-	(*ps->DestroyPictureClip) (pPicture);
-	if (pPicture->transform)
-	    xfree (pPicture->transform);
-	if (pPicture->pDrawable->type == DRAWABLE_WINDOW)
-	{
-	    WindowPtr	pWindow = (WindowPtr) pPicture->pDrawable;
-	    PicturePtr	*pPrev;
+            if (pPicture->alphaMap)
+                FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
+            (*ps->DestroyPicture) (pPicture);
+            (*ps->DestroyPictureClip) (pPicture);
+            if (pPicture->transform)
+                xfree (pPicture->transform);
+            if (pPicture->pDrawable->type == DRAWABLE_WINDOW)
+            {
+                WindowPtr	pWindow = (WindowPtr) pPicture->pDrawable;
+                PicturePtr	*pPrev;
 
-	    for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr);
-		 *pPrev;
-		 pPrev = &(*pPrev)->pNext)
-	    {
-		if (*pPrev == pPicture)
-		{
-		    *pPrev = pPicture->pNext;
-		    break;
-		}
-	    }
-	}
-	else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP)
-	{
-	    (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable);
-	}
+                for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr);
+                     *pPrev;
+                     pPrev = &(*pPrev)->pNext)
+                {
+                    if (*pPrev == pPicture)
+                    {
+                        *pPrev = pPicture->pNext;
+                        break;
+                    }
+                }
+            }
+            else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP)
+            {
+                (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable);
+            }
+        }
 	xfree (pPicture);
     }
     return Success;

Index: render.c
===================================================================
RCS file: /cvs/xserver/xserver/render/render.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- render.c	2 Mar 2005 15:30:04 -0000	1.34
+++ render.c	29 Jun 2005 11:57:18 -0000	1.35
@@ -81,6 +81,10 @@
 static int ProcRenderSetPictureFilter (ClientPtr pClient);
 static int ProcRenderCreateAnimCursor (ClientPtr pClient);
 static int ProcRenderAddTraps (ClientPtr pClient);
+static int ProcRenderCreateSolidFill (ClientPtr pClient);
+static int ProcRenderCreateLinearGradient (ClientPtr pClient);
+static int ProcRenderCreateRadialGradient (ClientPtr pClient);
+static int ProcRenderCreateConicalGradient (ClientPtr pClient);
 
 static int ProcRenderDispatch (ClientPtr pClient);
 
@@ -115,6 +119,10 @@
 static int SProcRenderSetPictureFilter (ClientPtr pClient);
 static int SProcRenderCreateAnimCursor (ClientPtr pClient);
 static int SProcRenderAddTraps (ClientPtr pClient);
+static int SProcRenderCreateSolidFill (ClientPtr pClient);
+static int SProcRenderCreateLinearGradient (ClientPtr pClient);
+static int SProcRenderCreateRadialGradient (ClientPtr pClient);
+static int SProcRenderCreateConicalGradient (ClientPtr pClient);
 
 static int SProcRenderDispatch (ClientPtr pClient);
 
@@ -152,6 +160,10 @@
     ProcRenderSetPictureFilter,
     ProcRenderCreateAnimCursor,
     ProcRenderAddTraps,
+    ProcRenderCreateSolidFill,
+    ProcRenderCreateLinearGradient,
+    ProcRenderCreateRadialGradient,
+    ProcRenderCreateConicalGradient
 };
 
 int	(*SProcRenderVector[RenderNumberRequests])(ClientPtr) = {
@@ -188,6 +200,10 @@
     SProcRenderSetPictureFilter,
     SProcRenderCreateAnimCursor,
     SProcRenderAddTraps,
+    SProcRenderCreateSolidFill,
+    SProcRenderCreateLinearGradient,
+    SProcRenderCreateRadialGradient,
+    SProcRenderCreateConicalGradient
 };
 
 static void
@@ -643,6 +659,7 @@
     REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
     VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess,
 		    RenderErrBase + BadPicture);
+
     len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2);
     if (Ones(stuff->mask) != len)
 	return BadLength;
@@ -662,6 +679,9 @@
     REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
     VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess,
 		    RenderErrBase + BadPicture);
+    if (!pPicture->pDrawable)
+        return BadDrawable;
+
     nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq);
     if (nr & 4)
 	return BadLength;
@@ -713,14 +733,16 @@
 	client->errorValue = stuff->op;
 	return BadValue;
     }
+    VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess,
+		    RenderErrBase + BadPicture);
+    if (!pDst->pDrawable)
+        return BadDrawable;
     VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, 
 		    RenderErrBase + BadPicture);
     VERIFY_ALPHA (pMask, stuff->mask, client, SecurityReadAccess, 
 		  RenderErrBase + BadPicture);
-    VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, 
-		    RenderErrBase + BadPicture);
-    if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen ||
-	(pMask && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen))
+    if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) ||
+	(pMask && pMask->pDrawable && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen))
 	return BadMatch;
     CompositePicture (stuff->op,
 		      pSrc,
@@ -761,7 +783,9 @@
 		    RenderErrBase + BadPicture);
     VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, 
 		    RenderErrBase + BadPicture);
-    if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
+    if (!pDst->pDrawable)
+        return BadDrawable;
+    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
 	return BadMatch;
     if (stuff->maskFormat)
     {
@@ -806,7 +830,9 @@
 		    RenderErrBase + BadPicture);
     VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, 
 		    RenderErrBase + BadPicture);
-    if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
+    if (!pDst->pDrawable)
+        return BadDrawable;
+    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
 	return BadMatch;
     if (stuff->maskFormat)
     {
@@ -851,7 +877,9 @@
 		    RenderErrBase + BadPicture);
     VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, 
 		    RenderErrBase + BadPicture);
-    if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
+    if (!pDst->pDrawable)
+        return BadDrawable;
+    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
 	return BadMatch;
     if (stuff->maskFormat)
     {
@@ -896,7 +924,9 @@
 		    RenderErrBase + BadPicture);
     VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, 
 		    RenderErrBase + BadPicture);
-    if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
+    if (!pDst->pDrawable)
+        return BadDrawable;
+    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
 	return BadMatch;
     if (stuff->maskFormat)
     {
@@ -1223,7 +1253,9 @@
 		    RenderErrBase + BadPicture);
     VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess,
 		    RenderErrBase + BadPicture);
-    if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
+    if (!pDst->pDrawable)
+        return BadDrawable;
+    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
 	return BadMatch;
     if (stuff->maskFormat)
     {
@@ -1388,6 +1420,8 @@
     }
     VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, 
 		    RenderErrBase + BadPicture);
+    if (!pDst->pDrawable)
+        return BadDrawable;
     
     things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq);
     if (things & 4)
@@ -1452,6 +1486,8 @@
     
     VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, 
 		    RenderErrBase + BadPicture);
+    if (!pSrc->pDrawable)
+        return BadDrawable;
     pScreen = pSrc->pDrawable->pScreen;
     width = pSrc->pDrawable->width;
     height = pSrc->pDrawable->height;
@@ -1823,6 +1859,8 @@
     REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq);
     VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, 
 		    RenderErrBase + BadPicture);
+    if (!pPicture->pDrawable)
+        return BadDrawable;
     ntraps = (client->req_len << 2) - sizeof (xRenderAddTrapsReq);
     if (ntraps % sizeof (xTrap))
 	return BadLength;
@@ -1834,6 +1872,113 @@
     return client->noClientException;
 }
 
+static int ProcRenderCreateSolidFill(ClientPtr client)
+{
+    PicturePtr	    pPicture;
+    int		    error = 0;
+    REQUEST(xRenderCreateSolidFillReq);
+
+    REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
+
+    LEGAL_NEW_RESOURCE(stuff->pid, client);
+
+    pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error);
+    if (!pPicture)
+	return error;
+    if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
+	return BadAlloc;
+    return Success;
+}
+
+static int ProcRenderCreateLinearGradient (ClientPtr client)
+{
+    PicturePtr	    pPicture;
+    int		    len;
+    int		    error = 0;
+    xFixed          *stops;
+    xRenderColor   *colors;
+    REQUEST(xRenderCreateLinearGradientReq);
+
+    REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
+
+    LEGAL_NEW_RESOURCE(stuff->pid, client);
+
+    len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq);
+    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
+        return BadLength;
+
+    stops = (xFixed *)(stuff + 1);
+    colors = (xRenderColor *)(stops + stuff->nStops);
+
+    pPicture = CreateLinearGradientPicture (stuff->pid, &stuff->p1, &stuff->p2,
+                                            stuff->nStops, stops, colors, &error);
+    if (!pPicture)
+	return error;
+    if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
+	return BadAlloc;
+    return Success;
+}
+
+static int ProcRenderCreateRadialGradient (ClientPtr client)
+{
+    PicturePtr	    pPicture;
+    int		    len;
+    int		    error = 0;
+    xFixed          *stops;
+    xRenderColor   *colors;
+    REQUEST(xRenderCreateRadialGradientReq);
+
+    REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
+
+    LEGAL_NEW_RESOURCE(stuff->pid, client);
+
+    len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq);
+    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
+        return BadLength;
+
+    stops = (xFixed *)(stuff + 1);
+    colors = (xRenderColor *)(stops + stuff->nStops);
+
+    pPicture = CreateRadialGradientPicture (stuff->pid, &stuff->inner, &stuff->outer,
+                                            stuff->inner_radius, stuff->outer_radius,
+                                            stuff->nStops, stops, colors, &error);
+    if (!pPicture)
+	return error;
+    if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
+	return BadAlloc;
+    return Success;
+}
+
+static int ProcRenderCreateConicalGradient (ClientPtr client)
+{
+    PicturePtr	    pPicture;
+    int		    len;
+    int		    error = 0;
+    xFixed          *stops;
+    xRenderColor   *colors;
+    REQUEST(xRenderCreateConicalGradientReq);
+
+    REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
+
+    LEGAL_NEW_RESOURCE(stuff->pid, client);
+
+    len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq);
+    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
+        return BadLength;
+
+    stops = (xFixed *)(stuff + 1);
+    colors = (xRenderColor *)(stops + stuff->nStops);
+
+    pPicture = CreateConicalGradientPicture (stuff->pid, &stuff->center, stuff->angle,
+                                             stuff->nStops, stops, colors, &error);
+    if (!pPicture)
+	return error;
+    if (!AddResource (stuff->pid, PictureType, (pointer)pPicture))
+	return BadAlloc;
+    return Success;
+}
+
+
 static int
 ProcRenderDispatch (ClientPtr client)
 {
@@ -2315,6 +2460,115 @@
 }
 
 static int
+SProcRenderCreateSolidFill(ClientPtr client)
+{
+    register int n;
+    REQUEST (xRenderCreateSolidFillReq);
+    REQUEST_AT_LEAST_SIZE (xRenderCreateSolidFillReq);
+
+    swaps(&stuff->length, n);
+    swapl(&stuff->pid, n);
+    swaps(&stuff->color.alpha, n);
+    swaps(&stuff->color.red, n);
+    swaps(&stuff->color.green, n);
+    swaps(&stuff->color.blue, n);
+    return (*ProcRenderVector[stuff->renderReqType]) (client);
+}
+
+static void swapStops(void *stuff, int n)
+{
+    int i;
+    CARD32 *stops;
+    CARD16 *colors;
+    stops = (CARD32 *)(stuff);
+    for (i = 0; i < n; ++i) {
+        swapl(stops, n);
+        ++stops;
+    }
+    colors = (CARD16 *)(stops);
+    for (i = 0; i < 4*n; ++i) {
+        swaps(stops, n);
+        ++stops;
+    }
+}
+
+static int
+SProcRenderCreateLinearGradient (ClientPtr client)
+{
+    register int n;
+    int len;
+    REQUEST (xRenderCreateLinearGradientReq);
+    REQUEST_AT_LEAST_SIZE (xRenderCreateLinearGradientReq);
+
+    swaps(&stuff->length, n);
+    swapl(&stuff->pid, n);
+    swapl(&stuff->p1.x, n);
+    swapl(&stuff->p1.y, n);
+    swapl(&stuff->p2.x, n);
+    swapl(&stuff->p2.y, n);
+    swaps(&stuff->nStops, n);
+
+    len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq);
+    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
+        return BadLength;
+
+    swapStops(stuff+1, stuff->nStops);
+
+    return (*ProcRenderVector[stuff->renderReqType]) (client);
+}
+
+static int
+SProcRenderCreateRadialGradient (ClientPtr client)
+{
+    register int n;
+    int len;
+    REQUEST (xRenderCreateRadialGradientReq);
+    REQUEST_AT_LEAST_SIZE (xRenderCreateRadialGradientReq);
+
+    swaps(&stuff->length, n);
+    swapl(&stuff->pid, n);
+    swapl(&stuff->inner.x, n);
+    swapl(&stuff->inner.y, n);
+    swapl(&stuff->outer.x, n);
+    swapl(&stuff->outer.y, n);
+    swapl(&stuff->inner_radius, n);
+    swapl(&stuff->outer_radius, n);
+    swaps(&stuff->nStops, n);
+
+    len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq);
+    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
+        return BadLength;
+
+    swapStops(stuff+1, stuff->nStops);
+
+    return (*ProcRenderVector[stuff->renderReqType]) (client);
+}
+
+static int
+SProcRenderCreateConicalGradient (ClientPtr client)
+{
+    register int n;
+    int len;
+    REQUEST (xRenderCreateConicalGradientReq);
+    REQUEST_AT_LEAST_SIZE (xRenderCreateConicalGradientReq);
+
+    swaps(&stuff->length, n);
+    swapl(&stuff->pid, n);
+    swapl(&stuff->center.x, n);
+    swapl(&stuff->center.y, n);
+    swapl(&stuff->angle, n);
+    swaps(&stuff->nStops, n);
+
+    len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq);
+    if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
+        return BadLength;
+
+    swapStops(stuff+1, stuff->nStops);
+
+    return (*ProcRenderVector[stuff->renderReqType]) (client);
+}
+
+static int
 SProcRenderDispatch (ClientPtr client)
 {
     REQUEST(xReq);