summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Knoll <lars@trolltech.com>2005-07-01 10:05:43 +0000
committerLars Knoll <lars@trolltech.com>2005-07-01 10:05:43 +0000
commitb5b2a0522efd61bd99b5d5d75cdd27960cd1c7e1 (patch)
tree455e2c8151f463288783b6e4e8fa29939cde4d3c
parent30c019e847adef6f7f3963df8ef1f3f994669a54 (diff)
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.
-rw-r--r--fb/fbcompose.c267
-rw-r--r--fb/fbpict.c21
-rw-r--r--fb/fbpict.h4
-rw-r--r--hw/xfree86/xaa/xaaPict.c36
-rw-r--r--render/mipict.c16
-rw-r--r--render/picture.c371
-rw-r--r--render/picturestr.h103
-rw-r--r--render/render.c272
8 files changed, 990 insertions, 100 deletions
diff --git a/fb/fbcompose.c b/fb/fbcompose.c
index 2bfe5ca3a..394c349e8 100644
--- a/fb/fbcompose.c
+++ b/fb/fbcompose.c
@@ -34,6 +34,7 @@
#include "picturestr.h"
#include "mipict.h"
#include "fbpict.h"
+#include <math.h>
#define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
@@ -2636,6 +2637,219 @@ static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
#define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
+
+static CARD32 gradientPixel(const SourcePictPtr pGradient, xFixed_48_16 pos, unsigned int spread)
+{
+ int ipos = (pos * PICT_GRADIENT_STOPTABLE_SIZE - 1) >> 16;
+
+ /* calculate the actual offset. */
+ if (ipos < 0 || ipos >= PICT_GRADIENT_STOPTABLE_SIZE) {
+ if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal) {
+ ipos = ipos % PICT_GRADIENT_STOPTABLE_SIZE;
+ ipos = ipos < 0 ? PICT_GRADIENT_STOPTABLE_SIZE + ipos : ipos;
+
+ } else if (spread == RepeatReflect) {
+ const int limit = PICT_GRADIENT_STOPTABLE_SIZE * 2 - 1;
+ ipos = ipos % limit;
+ ipos = ipos < 0 ? limit + ipos : ipos;
+ ipos = ipos >= PICT_GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos;
+
+ } else if (spread == RepeatPad) {
+ if (ipos < 0)
+ ipos = 0;
+ else if (ipos >= PICT_GRADIENT_STOPTABLE_SIZE)
+ ipos = PICT_GRADIENT_STOPTABLE_SIZE-1;
+ } else { /* RepeatNone */
+ return 0;
+ }
+ }
+
+ assert(ipos >= 0);
+ assert(ipos < PICT_GRADIENT_STOPTABLE_SIZE);
+
+ return pGradient->linear.colorTable[ipos];
+}
+
+static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
+{
+ SourcePictPtr pGradient = pict->pSourcePict;
+ CARD32 *end = buffer + width;
+
+ if (pGradient->type == SourcePictTypeSolidFill) {
+ register CARD32 color = pGradient->solidFill.color;
+ while (buffer < end) {
+ *buffer++ = color;
+ }
+ } else if (pGradient->type == SourcePictTypeLinear) {
+ PictVector v, unit;
+ xFixed_32_32 l;
+ xFixed_48_16 dx, dy, a, b, off;
+
+ v.vector[0] = IntToxFixed(x);
+ v.vector[1] = IntToxFixed(y);
+ v.vector[2] = xFixed1;
+ if (pict->transform) {
+ if (!PictureTransformPoint3d (pict->transform, &v))
+ return;
+ unit.vector[0] = pict->transform->matrix[0][0];
+ unit.vector[1] = pict->transform->matrix[1][0];
+ unit.vector[2] = pict->transform->matrix[2][0];
+ } else {
+ unit.vector[0] = xFixed1;
+ unit.vector[1] = 0;
+ unit.vector[2] = 0;
+ }
+
+ dx = pGradient->linear.p2.x - pGradient->linear.p1.x;
+ dy = pGradient->linear.p2.y - pGradient->linear.p1.y;
+ l = dx*dx + dy*dy;
+ if (l != 0) {
+ a = (dx << 32) / l;
+ b = (dy << 32) / l;
+ off = (-a*pGradient->linear.p1.x - b*pGradient->linear.p1.y)>>16;
+ }
+ if (l == 0 || (unit.vector[2] == 0 && v.vector[2] == xFixed1)) {
+ xFixed_48_16 inc, t;
+ /* affine transformation only */
+ if (l == 0) {
+ t = 0;
+ inc = 0;
+ } else {
+ t = ((a*v.vector[0] + b*v.vector[1]) >> 16) + off;
+ inc = (a * unit.vector[0] + b * unit.vector[1]) >> 16;
+ }
+ while (buffer < end) {
+ *buffer++ = gradientPixel(pGradient, t, pict->repeat);
+ t += inc;
+ }
+ } else {
+ /* projective transformation */
+ while (buffer < end) {
+ xFixed_48_16 t;
+ if (v.vector[2] == 0) {
+ t = 0;
+ } else {
+ xFixed_48_16 x, y;
+ x = ((xFixed_48_16)v.vector[0] << 16) / v.vector[2];
+ y = ((xFixed_48_16)v.vector[1] << 16) / v.vector[2];
+ t = ((a*x + b*y) >> 16) + off;
+ }
+ *buffer++ = gradientPixel(pGradient, t, pict->repeat);
+ v.vector[0] += unit.vector[0];
+ v.vector[1] += unit.vector[1];
+ v.vector[2] += unit.vector[2];
+ }
+ }
+ } else {
+ /* radial or conical */
+ Bool projective = FALSE;
+ double cx = 1.;
+ double cy = 0.;
+ double cz = 0.;
+ double rx = x;
+ double ry = y;
+ double rz = 1.;
+
+ if (pict->transform) {
+ PictVector v;
+ v.vector[0] = IntToxFixed(x);
+ v.vector[1] = IntToxFixed(y);
+ v.vector[2] = xFixed1;
+ if (!PictureTransformPoint3d (pict->transform, &v))
+ return;
+
+ cx = pict->transform->matrix[0][0]/65536.;
+ cy = pict->transform->matrix[1][0]/65536.;
+ cz = pict->transform->matrix[2][0]/65536.;
+ rx = v.vector[0]/65536.;
+ ry = v.vector[1]/65536.;
+ rz = v.vector[2]/65536.;
+ projective = pict->transform->matrix[2][0] != 0 || v.vector[2] != xFixed1;
+ }
+
+ if (pGradient->type == SourcePictTypeRadial) {
+ if (!projective) {
+ rx -= pGradient->radial.fx;
+ ry -= pGradient->radial.fy;
+
+ while (buffer < end) {
+ double b = 2*(rx*pGradient->radial.dx + ry*pGradient->radial.dy);
+ double c = -(rx*rx + ry*ry);
+ double det = (b * b) - (4 * pGradient->radial.a * c);
+ double s = (-b + sqrt(det))/(2. * pGradient->radial.a);
+ *buffer = gradientPixel(pGradient,
+ (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
+ pict->repeat);
+ ++buffer;
+ rx += cx;
+ ry += cy;
+ }
+ } else {
+ while (buffer < end) {
+ double x, y;
+ double b, c, det, s;
+ if (rz != 0) {
+ x = rx/rz;
+ y = ry/rz;
+ } else {
+ x = y = 0.;
+ }
+ x -= pGradient->radial.fx;
+ y -= pGradient->radial.fy;
+ b = 2*(x*pGradient->radial.dx + y*pGradient->radial.dy);
+ c = -(x*x + y*y);
+ det = (b * b) - (4 * pGradient->radial.a * c);
+ s = (-b + sqrt(det))/(2. * pGradient->radial.a);
+ *buffer = gradientPixel(pGradient,
+ (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
+ pict->repeat);
+ ++buffer;
+ rx += cx;
+ ry += cy;
+ rz += cz;
+ }
+ }
+ } else /* SourcePictTypeConical */ {
+ double a = pGradient->conical.angle/(180.*65536);
+ if (!projective) {
+ rx -= pGradient->conical.center.x/65536.;
+ ry -= pGradient->conical.center.y/65536.;
+
+ while (buffer < end) {
+ double angle = atan2(ry, rx) + a;
+ *buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
+ pict->repeat);
+ ++buffer;
+ rx += cx;
+ ry += cy;
+ }
+ } else {
+
+ while (buffer < end) {
+ double x, y, 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;
+ *buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
+ pict->repeat);
+ ++buffer;
+ rx += cx;
+ ry += cy;
+ rz += cz;
+ }
+ }
+ }
+ }
+}
+
+
+
static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
{
FbBits *bits;
@@ -2674,7 +2888,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
if (pict->filter == PictFilterNearest)
{
- if (pict->repeat) {
+ if (pict->repeat == RepeatNormal) {
if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
box = pict->pCompositeClip->extents;
for (i = 0; i < width; ++i) {
@@ -2741,7 +2955,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
}
}
} else if (pict->filter == PictFilterBilinear) {
- if (pict->repeat) {
+ if (pict->repeat == RepeatNormal) {
if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
box = pict->pCompositeClip->extents;
for (i = 0; i < width; ++i) {
@@ -2943,7 +3157,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
params += 2;
for (i = 0; i < width; ++i) {
int x1, x2, y1, y2, x, y;
- INT32 srtot, sgtot, sbtot, satot, sum;
+ INT32 srtot, sgtot, sbtot, satot;
xFixed *p = params;
xFixed_48_16 tmp;
@@ -2962,13 +3176,13 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
y1 = xFixedToInt(tmp);
y2 = y1 + cheight;
- srtot = sgtot = sbtot = satot = sum = 0;
+ srtot = sgtot = sbtot = satot = 0;
for (y = y1; y < y2; y++) {
- int ty = (pict->repeat) ? MOD (y, pict->pDrawable->height) : y;
+ int ty = (pict->repeat == RepeatNormal) ? MOD (y, pict->pDrawable->height) : y;
for (x = x1; x < x2; x++) {
if (*p) {
- int tx = (pict->repeat) ? MOD (x, pict->pDrawable->width) : x;
+ int tx = (pict->repeat == RepeatNormal) ? MOD (x, pict->pDrawable->width) : x;
if (POINT_IN_REGION (0, pict->pCompositeClip, tx, ty, &box)) {
FbBits *b = bits + (ty + pict->pDrawable->y)*stride;
CARD32 c = fetch(b, tx + pict->pDrawable->x, indexed);
@@ -2978,22 +3192,15 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
sbtot += Blue(c) * *p;
satot += Alpha(c) * *p;
}
- sum += *p;
}
p++;
}
}
- if (sum) {
- satot /= sum;
- srtot /= sum;
- sgtot /= sum;
- sbtot /= sum;
- }
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;
+ if (srtot < 0) srtot = 0; else if (srtot > satot) srtot = satot;
+ if (sgtot < 0) sgtot = 0; else if (sgtot > satot) sgtot = satot;
+ if (sbtot < 0) sbtot = 0; else if (sbtot > satot) sbtot = satot;
buffer[i] = ((satot << 24) |
(srtot << 16) |
@@ -3094,13 +3301,17 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
CARD32 *dest_buffer = src_buffer + data->width;
int i;
scanStoreProc store;
- scanFetchProc fetchSrc, fetchMask, fetchDest;
+ scanFetchProc fetchSrc = 0, fetchMask = 0, fetchDest = 0;
if (data->op == PictOpClear)
fetchSrc = 0;
- else if (data->src->alphaMap)
+ else if (!data->src->pDrawable) {
+ if (data->src->pSourcePict)
+ fetchSrc = fbFetchSourcePict;
+ } else if (data->src->alphaMap)
fetchSrc = fbFetchExternalAlpha;
- else if (data->src->repeat && data->src->pDrawable->width == 1 && data->src->pDrawable->height == 1)
+ else if (data->src->repeat == RepeatNormal &&
+ data->src->pDrawable->width == 1 && data->src->pDrawable->height == 1)
fetchSrc = fbFetchSolid;
else if (!data->src->transform && data->src->filter != PictFilterConvolution)
fetchSrc = fbFetch;
@@ -3108,9 +3319,13 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
fetchSrc = fbFetchTransformed;
if (data->mask && data->op != PictOpClear) {
- if (data->mask->alphaMap)
+ if (!data->mask->pDrawable) {
+ if (data->mask->pSourcePict)
+ fetchMask = fbFetchSourcePict;
+ } else if (data->mask->alphaMap)
fetchMask = fbFetchExternalAlpha;
- else if (data->mask->repeat && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1)
+ else if (data->mask->repeat == RepeatNormal
+ && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1)
fetchMask = fbFetchSolid;
else if (!data->mask->transform && data->mask->filter != PictFilterConvolution)
fetchMask = fbFetch;
@@ -3211,17 +3426,19 @@ fbCompositeGeneral (CARD8 op,
RegionRec region;
int n;
BoxPtr pbox;
- Bool srcRepeat = pSrc->repeat && !pSrc->transform
- && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1);
+ Bool srcRepeat = FALSE;
Bool maskRepeat = FALSE;
int w, h;
CARD32 _scanline_buffer[SCANLINE_BUFFER_LENGTH*3];
CARD32 *scanline_buffer = _scanline_buffer;
FbComposeData compose_data;
+ if (pSrc->pDrawable)
+ srcRepeat = pSrc->repeat == RepeatNormal && !pSrc->transform
+ && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1);
- if (pMask)
- maskRepeat = pMask->repeat && !pMask->transform
+ if (pMask && pMask->pDrawable)
+ maskRepeat = pMask->repeat == RepeatNormal && !pMask->transform
&& (pMask->pDrawable->width != 1 || pMask->pDrawable->height != 1);
if (op == PictOpOver && !pMask && !pSrc->transform && !PICT_FORMAT_A(pSrc->format))
diff --git a/fb/fbpict.c b/fb/fbpict.c
index 8b284082f..c269b5eae 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -838,7 +838,7 @@ fbComposite (CARD8 op,
int n;
BoxPtr pbox;
CompositeFunc func = 0;
- Bool srcRepeat = pSrc->repeat;
+ Bool srcRepeat = pSrc->pDrawable && pSrc->repeat == RepeatNormal;
Bool maskRepeat = FALSE;
Bool srcAlphaMap = pSrc->alphaMap != 0;
Bool maskAlphaMap = FALSE;
@@ -848,20 +848,23 @@ fbComposite (CARD8 op,
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
- xSrc += pSrc->pDrawable->x;
- ySrc += pSrc->pDrawable->y;
- if (pMask)
+ if (pSrc->pDrawable) {
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ }
+ if (pMask && pMask->pDrawable)
{
xMask += pMask->pDrawable->x;
yMask += pMask->pDrawable->y;
- maskRepeat = pMask->repeat;
+ maskRepeat = pMask->repeat == RepeatNormal;
maskAlphaMap = pMask->alphaMap != 0;
}
- if (!pSrc->transform && !(pMask && pMask->transform)
- && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
- && (pSrc->filter != PictFilterConvolution)
- && (!pMask || pMask->filter != PictFilterConvolution))
+ if (pSrc->pDrawable && (!pMask || pMask->pDrawable)
+ && !pSrc->transform && !(pMask && pMask->transform)
+ && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
+ && (pSrc->filter != PictFilterConvolution)
+ && (!pMask || pMask->filter != PictFilterConvolution))
switch (op) {
case PictOpSrc:
#ifdef USE_MMX
diff --git a/fb/fbpict.h b/fb/fbpict.h
index b957dd40a..3e751e9f0 100644
--- a/fb/fbpict.h
+++ b/fb/fbpict.h
@@ -224,11 +224,11 @@
#define FbByteAdd(x, y) do { \
CARD32 t; \
CARD32 r = (x & 0xff00ff) + (y & 0xff00ff); \
- r |= 0 - ((r >> 8) & 0xff00ff); \
+ r |= 0x1000100 - ((r >> 8) & 0xff00ff); \
r &= 0xff00ff; \
\
t = ((x >> 8) & 0xff00ff) + ((y >> 8) & 0xff00ff); \
- t |= 0 - ((t >> 8) & 0xff00ff); \
+ t |= 0x1000100 - ((t >> 8) & 0xff00ff); \
r |= (t & 0xff00ff) << 8; \
x = r; \
} while (0)
diff --git a/hw/xfree86/xaa/xaaPict.c b/hw/xfree86/xaa/xaaPict.c
index b9ca27cd8..c84a59d83 100644
--- a/hw/xfree86/xaa/xaaPict.c
+++ b/hw/xfree86/xaa/xaaPict.c
@@ -504,21 +504,22 @@ XAAComposite (CARD8 op,
if((op == PictOpSrc) && !pMask && infoRec->pScrn->vtSema &&
infoRec->ScreenToScreenBitBlt &&
+ pSrc->pDrawable &&
DRAWABLE_IS_ON_CARD(pSrc->pDrawable) &&
DRAWABLE_IS_ON_CARD(pDst->pDrawable) &&
!pSrc->transform && !pSrc->repeat && (pSrc->format == pDst->format))
{
XAACompositeSrcCopy(pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height);
- } else if(!infoRec->Composite ||
- !(*infoRec->Composite)(op, pSrc, pMask, pDst,
- xSrc, ySrc, xMask, yMask, xDst, yDst,
- width, height))
+ } else if(!pSrc->pDrawable || (pMask && !pMask->pDrawable) ||
+ !infoRec->Composite ||
+ !(*infoRec->Composite)(op, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask, xDst, yDst,
+ width, height))
{
- if((pSrc->pDrawable->type == DRAWABLE_WINDOW ||
- pDst->pDrawable->type == DRAWABLE_WINDOW ||
- IS_OFFSCREEN_PIXMAP(pSrc->pDrawable) ||
- IS_OFFSCREEN_PIXMAP(pDst->pDrawable))
- && infoRec->pScrn->vtSema) {
+ if(infoRec->pScrn->vtSema &&
+ ((pSrc->pDrawable &&
+ (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) ||
+ pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) {
SYNC_CHECK(pDst->pDrawable);
}
(*GetPictureScreen(pScreen)->Composite) (op,
@@ -745,17 +746,16 @@ XAAGlyphs (CARD8 op,
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
XAA_RENDER_PROLOGUE(pScreen, Glyphs);
- if(!infoRec->Glyphs ||
+ if(!pSrc->pDrawable || !infoRec->Glyphs ||
!(*infoRec->Glyphs)(op, pSrc, pDst, maskFormat,
- xSrc, ySrc, nlist, list, glyphs))
+ xSrc, ySrc, nlist, list, glyphs))
{
- if(((pSrc->pDrawable->type == DRAWABLE_WINDOW) ||
- (pDst->pDrawable->type == DRAWABLE_WINDOW) ||
- IS_OFFSCREEN_PIXMAP(pSrc->pDrawable) ||
- IS_OFFSCREEN_PIXMAP(pDst->pDrawable))
- && infoRec->pScrn->vtSema) {
- SYNC_CHECK(pDst->pDrawable);
- }
+ if(infoRec->pScrn->vtSema &&
+ ((pSrc->pDrawable &&
+ (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) ||
+ pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) {
+ SYNC_CHECK(pDst->pDrawable);
+ }
(*GetPictureScreen(pScreen)->Glyphs) (op, pSrc, pDst, maskFormat,
xSrc, ySrc, nlist, list, glyphs);
}
diff --git a/render/mipict.c b/render/mipict.c
index 5b2da0f37..a16e88cd9 100644
--- a/render/mipict.c
+++ b/render/mipict.c
@@ -296,7 +296,7 @@ miClipPictureSrc (RegionPtr pRegion,
int dy)
{
/* XXX what to do with clipping from transformed pictures? */
- if (pPicture->transform)
+ if (pPicture->transform || !pPicture->pDrawable)
return TRUE;
if (pPicture->repeat)
{
@@ -331,7 +331,12 @@ miCompositeSourceValidate (PicturePtr pPicture,
CARD16 height)
{
DrawablePtr pDrawable = pPicture->pDrawable;
- ScreenPtr pScreen = pDrawable->pScreen;
+ ScreenPtr pScreen;
+
+ if (!pDrawable)
+ return;
+
+ pScreen = pDrawable->pScreen;
if (pScreen->SourceValidate)
{
@@ -521,8 +526,13 @@ miFillColor (CARD32 pixel, int bits)
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)
diff --git a/render/picture.c b/render/picture.c
index 1d2301bb3..b10b8c4d0 100644
--- a/render/picture.c
+++ b/render/picture.c
@@ -762,6 +762,7 @@ SetPictureToDefaults (PicturePtr pPicture)
pPicture->serialNumber = GC_CHANGE_SERIAL_BIT;
pPicture->stateChanges = (1 << (CPLastBit+1)) - 1;
+ pPicture->pSourcePict = 0;
}
PicturePtr
@@ -845,6 +846,301 @@ CreatePicture (Picture pid,
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 = 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)
@@ -856,8 +1152,8 @@ ChangePicture (PicturePtr pPicture,
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;
@@ -875,7 +1171,7 @@ ChangePicture (PicturePtr pPicture,
{
unsigned int newr;
newr = NEXT_VAL(unsigned int);
- if (newr <= xTrue)
+ if (newr <= RepeatReflect)
pPicture->repeat = newr;
else
{
@@ -943,6 +1239,8 @@ ChangePicture (PicturePtr pPicture,
Pixmap pid;
PixmapPtr pPixmap;
int clipType;
+ if (!pScreen)
+ return BadDrawable;
if (vlist)
{
@@ -1069,7 +1367,8 @@ ChangePicture (PicturePtr pPicture,
break;
}
}
- (*ps->ChangePicture) (pPicture, maskQ);
+ if (ps)
+ (*ps->ChangePicture) (pPicture, maskQ);
return error;
}
@@ -1268,7 +1567,7 @@ CopyPicture (PicturePtr pSrc,
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);
@@ -1294,35 +1593,43 @@ FreePicture (pointer value,
if (--pPicture->refcnt == 0)
{
- 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;
-
- 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);
- }
+ 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->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);
+ }
+ }
xfree (pPicture);
}
return Success;
diff --git a/render/picturestr.h b/render/picturestr.h
index a532e4e1c..58b840c6d 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -62,6 +62,70 @@ typedef struct _PictTransform {
xFixed matrix[3][3];
} PictTransform, *PictTransformPtr;
+#define PICT_GRADIENT_STOPTABLE_SIZE 1024
+#define SourcePictTypeSolidFill 0
+#define SourcePictTypeLinear 1
+#define SourcePictTypeRadial 2
+#define SourcePictTypeConical 3
+
+typedef struct _PictSolidFill {
+ unsigned int type;
+ CARD32 color;
+} PictSolidFill, *PictSolidFillPtr;
+
+typedef struct _PictGradientStop {
+ xFixed x;
+ xRenderColor color;
+} PictGradientStop, *PictGradientStopPtr;
+
+typedef struct _PictGradient {
+ unsigned int type;
+ int nstops;
+ PictGradientStopPtr stops;
+ CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
+} PictGradient, *PictGradientPtr;
+
+typedef struct _PictLinearGradient {
+ unsigned int type;
+ int nstops;
+ PictGradientStopPtr stops;
+ CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
+ xPointFixed p1;
+ xPointFixed p2;
+} PictLinearGradient, *PictLinearGradientPtr;
+
+typedef struct _PictRadialGradient {
+ unsigned int type;
+ int nstops;
+ PictGradientStopPtr stops;
+ CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
+ double fx;
+ double fy;
+ double dx;
+ double dy;
+ double a;
+ double m;
+ double b;
+} PictRadialGradient, *PictRadialGradientPtr;
+
+typedef struct _PictConicalGradient {
+ unsigned int type;
+ int nstops;
+ PictGradientStopPtr stops;
+ CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
+ xPointFixed center;
+ xFixed angle;
+} PictConicalGradient, *PictConicalGradientPtr;
+
+typedef union _SourcePict {
+ unsigned int type;
+ PictSolidFill solidFill;
+ PictGradient gradient;
+ PictLinearGradient linear;
+ PictRadialGradient radial;
+ PictConicalGradient conical;
+} SourcePict, *SourcePictPtr;
+
typedef struct _Picture {
DrawablePtr pDrawable;
PictFormatPtr pFormat;
@@ -70,7 +134,7 @@ typedef struct _Picture {
CARD32 id;
PicturePtr pNext; /* chain on same drawable */
- unsigned int repeat : 1;
+ unsigned int repeat : 2;
unsigned int graphicsExposures : 1;
unsigned int subWindowMode : 1;
unsigned int polyEdge : 1;
@@ -78,7 +142,7 @@ typedef struct _Picture {
unsigned int freeCompClip : 1;
unsigned int clientClipType : 2;
unsigned int componentAlpha : 1;
- unsigned int unused : 23;
+ unsigned int unused : 22;
PicturePtr alphaMap;
DDXPointRec alphaOrigin;
@@ -100,6 +164,7 @@ typedef struct _Picture {
int filter;
xFixed *filter_params;
int filter_nparams;
+ SourcePictPtr pSourcePict;
} PictureRec;
typedef Bool (*PictFilterValidateParamsProcPtr) (PicturePtr pPicture, int id,
@@ -546,6 +611,40 @@ AddTraps (PicturePtr pPicture,
int ntraps,
xTrap *traps);
+PicturePtr
+CreateSolidPicture (Picture pid,
+ xRenderColor *color,
+ int *error);
+
+PicturePtr
+CreateLinearGradientPicture (Picture pid,
+ xPointFixed *p1,
+ xPointFixed *p2,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors,
+ int *error);
+
+PicturePtr
+CreateRadialGradientPicture (Picture pid,
+ xPointFixed *inner,
+ xPointFixed *outer,
+ xFixed innerRadius,
+ xFixed outerRadius,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors,
+ int *error);
+
+PicturePtr
+CreateConicalGradientPicture (Picture pid,
+ xPointFixed *center,
+ xFixed angle,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors,
+ int *error);
+
#ifdef PANORAMIX
void PanoramiXRenderInit (void);
void PanoramiXRenderReset (void);
diff --git a/render/render.c b/render/render.c
index aeaeaa2a5..1d1506d8b 100644
--- a/render/render.c
+++ b/render/render.c
@@ -79,6 +79,10 @@ static int ProcRenderQueryFilters (ClientPtr pClient);
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);
@@ -113,6 +117,10 @@ static int SProcRenderQueryFilters (ClientPtr pClient);
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);
@@ -150,6 +158,10 @@ int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = {
ProcRenderSetPictureFilter,
ProcRenderCreateAnimCursor,
ProcRenderAddTraps,
+ ProcRenderCreateSolidFill,
+ ProcRenderCreateLinearGradient,
+ ProcRenderCreateRadialGradient,
+ ProcRenderCreateConicalGradient
};
int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = {
@@ -186,6 +198,10 @@ int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = {
SProcRenderSetPictureFilter,
SProcRenderCreateAnimCursor,
SProcRenderAddTraps,
+ SProcRenderCreateSolidFill,
+ SProcRenderCreateLinearGradient,
+ SProcRenderCreateRadialGradient,
+ SProcRenderCreateConicalGradient
};
static void
@@ -647,6 +663,7 @@ ProcRenderChangePicture (ClientPtr client)
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;
@@ -666,6 +683,9 @@ ProcRenderSetPictureClipRectangles (ClientPtr client)
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;
@@ -717,14 +737,16 @@ ProcRenderComposite (ClientPtr client)
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,
@@ -765,7 +787,9 @@ ProcRenderTrapezoids (ClientPtr client)
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)
{
@@ -810,7 +834,9 @@ ProcRenderTriangles (ClientPtr client)
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)
{
@@ -855,7 +881,9 @@ ProcRenderTriStrip (ClientPtr client)
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)
{
@@ -900,7 +928,9 @@ ProcRenderTriFan (ClientPtr client)
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)
{
@@ -1226,7 +1256,9 @@ ProcRenderCompositeGlyphs (ClientPtr client)
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)
{
@@ -1391,6 +1423,8 @@ ProcRenderFillRectangles (ClientPtr client)
}
VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess,
RenderErrBase + BadPicture);
+ if (!pDst->pDrawable)
+ return BadDrawable;
things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq);
if (things & 4)
@@ -1455,6 +1489,8 @@ ProcRenderCreateCursor (ClientPtr client)
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;
@@ -1826,6 +1862,8 @@ ProcRenderAddTraps (ClientPtr client)
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;
@@ -1837,6 +1875,113 @@ ProcRenderAddTraps (ClientPtr client)
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)
{
@@ -2318,6 +2463,115 @@ SProcRenderAddTraps (ClientPtr client)
}
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);
+ swapl(&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);
+ swapl(&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);
+ swapl(&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);