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 #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; + 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); - } + 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) { @@ -2317,6 +2462,115 @@ SProcRenderAddTraps (ClientPtr client) return (*ProcRenderVector[stuff->renderReqType]) (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) {