Merge David Reveman's gradient optimization patch from pixman

This commit is contained in:
Soren Sandmann Pedersen 2007-04-19 18:19:34 -04:00
parent d0e55774e0
commit 0a9239ec25
3 changed files with 942 additions and 615 deletions

View File

@ -40,6 +40,65 @@
#include "mipict.h"
#include "fbpict.h"
static unsigned int
SourcePictureClassify (PicturePtr pict,
int x,
int y,
int width,
int height)
{
if (pict->pSourcePict->type == SourcePictTypeSolidFill)
{
pict->pSourcePict->solidFill.class = SourcePictClassHorizontal;
}
else if (pict->pSourcePict->type == SourcePictTypeLinear)
{
PictVector v;
xFixed_32_32 l;
xFixed_48_16 dx, dy, a, b, off;
xFixed_48_16 factors[4];
int i;
dx = pict->pSourcePict->linear.p2.x - pict->pSourcePict->linear.p1.x;
dy = pict->pSourcePict->linear.p2.y - pict->pSourcePict->linear.p1.y;
l = dx * dx + dy * dy;
if (l)
{
a = (dx << 32) / l;
b = (dy << 32) / l;
}
else
{
a = b = 0;
}
off = (-a * pict->pSourcePict->linear.p1.x
-b * pict->pSourcePict->linear.p1.y) >> 16;
for (i = 0; i < 3; i++)
{
v.vector[0] = IntToxFixed ((i % 2) * (width - 1) + x);
v.vector[1] = IntToxFixed ((i / 2) * (height - 1) + y);
v.vector[2] = xFixed1;
if (pict->transform)
{
if (!PictureTransformPoint3d (pict->transform, &v))
return SourcePictClassUnknown;
}
factors[i] = ((a * v.vector[0] + b * v.vector[1]) >> 16) + off;
}
if (factors[2] == factors[0])
pict->pSourcePict->linear.class = SourcePictClassHorizontal;
else if (factors[1] == factors[0])
pict->pSourcePict->linear.class = SourcePictClassVertical;
}
return pict->pSourcePict->solidFill.class;
}
#define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
#define SCANLINE_BUFFER_LENGTH 2048
@ -2634,7 +2693,7 @@ FbComposeFunctions composeFunctions = {
};
static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
{
FbBits *bits;
FbStride stride;
@ -2656,7 +2715,7 @@ static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffe
fbFinishAccess (pict->pDrawable);
}
static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
{
FbBits *bits;
FbStride stride;
@ -2679,40 +2738,75 @@ static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
#define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) : \
((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
static CARD32
xRenderColorMultToCard32 (xRenderColor *c)
{
return
((((CARD32) c->red * c->alpha) >> 24) << 16) |
((((CARD32) c->green * c->alpha) >> 24) << 8) |
((((CARD32) c->blue * c->alpha) >> 24) << 0) |
((((CARD32) c->alpha ) >> 8) << 24);
}
static CARD32 gradientPixel(const SourcePictPtr pGradient, xFixed_48_16 pos, unsigned int spread)
{
int ipos = (pos * PICT_GRADIENT_STOPTABLE_SIZE - 1) >> 16;
int ipos = (pos * pGradient->gradient.stopRange - 1) >> 16;
/* calculate the actual offset. */
if (ipos < 0 || ipos >= PICT_GRADIENT_STOPTABLE_SIZE) {
if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal) {
ipos = ipos % PICT_GRADIENT_STOPTABLE_SIZE;
ipos = ipos < 0 ? PICT_GRADIENT_STOPTABLE_SIZE + ipos : ipos;
if (ipos < 0 || ipos >= pGradient->gradient.stopRange)
{
if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal)
{
ipos = ipos % pGradient->gradient.stopRange;
ipos = ipos < 0 ? pGradient->gradient.stopRange + ipos : ipos;
}
else if (spread == RepeatReflect)
{
const int limit = pGradient->gradient.stopRange * 2 - 1;
} else if (spread == RepeatReflect) {
const int limit = PICT_GRADIENT_STOPTABLE_SIZE * 2 - 1;
ipos = ipos % limit;
ipos = ipos < 0 ? limit + ipos : ipos;
ipos = ipos >= PICT_GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos;
ipos = ipos >= pGradient->gradient.stopRange ? limit - ipos : ipos;
} else if (spread == RepeatPad) {
}
else if (spread == RepeatPad)
{
if (ipos < 0)
ipos = 0;
else if (ipos >= PICT_GRADIENT_STOPTABLE_SIZE)
ipos = PICT_GRADIENT_STOPTABLE_SIZE-1;
} else { /* RepeatNone */
else
ipos = pGradient->gradient.stopRange - 1;
}
else /* RepeatNone */
{
return 0;
}
}
assert(ipos >= 0);
assert(ipos < PICT_GRADIENT_STOPTABLE_SIZE);
if (pGradient->gradient.colorTableSize)
{
return pGradient->gradient.colorTable[ipos];
}
else
{
int i;
return pGradient->linear.colorTable[ipos];
if (ipos <= pGradient->gradient.stops->x)
return xRenderColorMultToCard32 (&pGradient->gradient.stops->color);
for (i = 1; i < pGradient->gradient.nstops; i++)
{
if (pGradient->gradient.stops[i].x >= ipos)
return PictureGradientColor (&pGradient->gradient.stops[i - 1],
&pGradient->gradient.stops[i],
ipos);
}
static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
return xRenderColorMultToCard32 (&pGradient->gradient.stops[--i].color);
}
}
static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
{
SourcePictPtr pGradient = pict->pSourcePict;
CARD32 *end = buffer + width;
@ -2761,14 +2855,58 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
t = ((a*v.vector[0] + b*v.vector[1]) >> 16) + off;
inc = (a * unit.vector[0] + b * unit.vector[1]) >> 16;
}
if (pGradient->linear.class == SourcePictClassVertical)
{
register CARD32 color;
color = gradientPixel (pGradient, t, pict->repeat);
while (buffer < end)
*buffer++ = color;
}
else
{
while (buffer < end) {
WRITE(buffer++, gradientPixel(pGradient, t, pict->repeatType));
if (!mask || *mask++ & maskBits)
{
*buffer = gradientPixel (pGradient, t, pict->repeat);
}
++buffer;
t += inc;
}
} else {
/* projective transformation */
while (buffer < end) {
}
}
else /* projective transformation */
{
xFixed_48_16 t;
if (pGradient->linear.class == SourcePictClassVertical)
{
register CARD32 color;
if (v.vector[2] == 0)
{
t = 0;
}
else
{
xFixed_48_16 x, y;
x = ((xFixed_48_16) v.vector[0] << 16) / v.vector[2];
y = ((xFixed_48_16) v.vector[1] << 16) / v.vector[2];
t = ((a * x + b * y) >> 16) + off;
}
color = gradientPixel (pGradient, t, pict->repeat);
while (buffer < end)
*buffer++ = color;
}
else
{
while (buffer < end)
{
if (!mask || *mask++ & maskBits)
{
if (v.vector[2] == 0) {
t = 0;
} else {
@ -2777,12 +2915,15 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
y = ((xFixed_48_16)v.vector[1] << 16) / v.vector[2];
t = ((a*x + b*y) >> 16) + off;
}
WRITE(buffer++, gradientPixel(pGradient, t, pict->repeatType));
*buffer = gradientPixel(pGradient, t, pict->repeat);
}
++buffer;
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
}
}
}
} else {
/* radial or conical */
Bool affine = TRUE;
@ -2817,14 +2958,20 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
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);
double b, c, det, s;
if (!mask || *mask++ & maskBits)
{
b = 2*(rx*pGradient->radial.dx + ry*pGradient->radial.dy);
c = -(rx*rx + ry*ry);
det = (b * b) - (4 * pGradient->radial.a * c);
s = (-b + sqrt(det))/(2. * pGradient->radial.a);
WRITE(buffer, gradientPixel(pGradient,
(xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
pict->repeatType));
}
++buffer;
rx += cx;
ry += cy;
}
@ -2832,6 +2979,9 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
while (buffer < end) {
double x, y;
double b, c, det, s;
if (!mask || *mask++ & maskBits)
{
if (rz != 0) {
x = rx/rz;
y = ry/rz;
@ -2844,10 +2994,12 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
c = -(x*x + y*y);
det = (b * b) - (4 * pGradient->radial.a * c);
s = (-b + sqrt(det))/(2. * pGradient->radial.a);
WRITE(buffer, gradientPixel(pGradient,
*buffer = gradientPixel(pGradient,
(xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
pict->repeatType));
pict->repeat);
}
++buffer;
rx += cx;
ry += cy;
rz += cz;
@ -2860,17 +3012,25 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
ry -= pGradient->conical.center.y/65536.;
while (buffer < end) {
double angle = atan2(ry, rx) + a;
WRITE(buffer, gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
pict->repeatType));
double angle;
if (!mask || *mask++ & maskBits)
{
angle = atan2(ry, rx) + a;
*buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
pict->repeat);
}
++buffer;
rx += cx;
ry += cy;
}
} else {
while (buffer < end) {
double x, y, angle;
if (!mask || *mask++ & maskBits)
{
if (rz != 0) {
x = rx/rz;
y = ry/rz;
@ -2880,8 +3040,9 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
x -= pGradient->conical.center.x/65536.;
y -= pGradient->conical.center.y/65536.;
angle = atan2(y, x) + a;
WRITE(buffer, gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
pict->repeatType));
*buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
pict->repeat);
}
++buffer;
rx += cx;
ry += cy;
@ -2892,9 +3053,7 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
}
}
static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
{
FbBits *bits;
FbStride stride;
@ -2943,8 +3102,10 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
if (pict->repeatType == RepeatNormal) {
if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
if (!v.vector[2]) {
WRITE(buffer + i, 0);
buffer[i] = 0;
} else {
if (!affine) {
y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
@ -2953,16 +3114,20 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
y = MOD(v.vector[1]>>16, pict->pDrawable->height);
x = MOD(v.vector[0]>>16, pict->pDrawable->width);
}
WRITE(buffer + i, fetch(bits + (y + dy)*stride, x + dx, indexed));
buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
}
}
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
}
} else {
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
if (!v.vector[2]) {
WRITE(buffer + i, 0);
buffer[i] = 0;
} else {
if (!affine) {
y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
@ -2971,11 +3136,13 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
y = MOD(v.vector[1]>>16, pict->pDrawable->height);
x = MOD(v.vector[0]>>16, pict->pDrawable->width);
}
if (POINT_IN_REGION (0, pict->pCompositeClip, x + dx, y + dy, &box))
WRITE(buffer + i, fetch(bits + (y + dy)*stride, x + dx, indexed));
if (POINT_IN_REGION (0, pict->pCompositeClip, x, y, &box))
buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
else
WRITE(buffer + i, 0);
buffer[i] = 0;
}
}
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
@ -2985,6 +3152,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
box = pict->pCompositeClip->extents;
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
if (!v.vector[2]) {
WRITE(buffer + i, 0);
} else {
@ -2998,12 +3167,15 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
WRITE(buffer + i, ((x < box.x1-dx) | (x >= box.x2-dx) | (y < box.y1-dy) | (y >= box.y2-dy)) ?
0 : fetch(bits + (y + dy)*stride, x + dx, indexed));
}
}
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
}
} else {
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
if (!v.vector[2]) {
WRITE(buffer + i, 0);
} else {
@ -3019,6 +3191,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
else
WRITE(buffer + i, 0);
}
}
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
@ -3035,6 +3208,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
if (pict->repeatType == RepeatNormal) {
if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
if (!v.vector[2]) {
WRITE(buffer + i, 0);
} else {
@ -3090,12 +3265,15 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
WRITE(buffer + i, r);
}
}
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
}
} else {
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
if (!v.vector[2]) {
WRITE(buffer + i, 0);
} else {
@ -3155,6 +3333,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
WRITE(buffer + i, r);
}
}
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
@ -3164,6 +3344,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
box = pict->pCompositeClip->extents;
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
if (!v.vector[2]) {
WRITE(buffer + i, 0);
} else {
@ -3221,12 +3403,16 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
WRITE(buffer + i, r);
}
}
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
}
} else {
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
if (!v.vector[2]) {
WRITE(buffer + i, 0);
} else {
@ -3282,6 +3468,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
WRITE(buffer + i, r);
}
}
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
@ -3296,6 +3484,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
int yoff = (params[1] - xFixed1) >> 1;
params += 2;
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
if (!v.vector[2]) {
WRITE(buffer + i, 0);
} else {
@ -3352,6 +3542,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
(sgtot << 8) |
(sbtot )));
}
}
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
@ -3362,28 +3553,33 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
}
static void fbFetchExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
static void fbFetchExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
{
int i;
CARD32 _alpha_buffer[SCANLINE_BUFFER_LENGTH];
CARD32 *alpha_buffer = _alpha_buffer;
if (!pict->alphaMap) {
fbFetchTransformed(pict, x, y, width, buffer);
fbFetchTransformed(pict, x, y, width, buffer, mask, maskBits);
return;
}
if (width > SCANLINE_BUFFER_LENGTH)
alpha_buffer = (CARD32 *) malloc(width*sizeof(CARD32));
fbFetchTransformed(pict, x, y, width, buffer);
fbFetchTransformed(pict->alphaMap, x - pict->alphaOrigin.x, y - pict->alphaOrigin.y, width, alpha_buffer);
fbFetchTransformed(pict, x, y, width, buffer, mask, maskBits);
fbFetchTransformed(pict->alphaMap, x - pict->alphaOrigin.x,
y - pict->alphaOrigin.y, width, alpha_buffer,
mask, maskBits);
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
int a = alpha_buffer[i]>>24;
WRITE(buffer + i, (a << 24)
| (div_255(Red(READ(buffer + i)) * a) << 16)
| (div_255(Green(READ(buffer + i)) * a) << 8)
| (div_255(Blue(READ(buffer + i)) * a)));
}
}
if (alpha_buffer != _alpha_buffer)
free(alpha_buffer);
@ -3450,7 +3646,7 @@ static void fbStoreExternalAlpha(PicturePtr pict, int x, int y, int width, CARD3
}
typedef void (*scanStoreProc)(PicturePtr , int , int , int , CARD32 *);
typedef void (*scanFetchProc)(PicturePtr , int , int , int , CARD32 *);
typedef void (*scanFetchProc)(PicturePtr , int , int , int , CARD32 * , CARD32 *, CARD32);
static void
fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
@ -3460,17 +3656,30 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
int i;
scanStoreProc store;
scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
unsigned int srcClass = SourcePictClassUnknown;
unsigned int maskClass = SourcePictClassUnknown;
FbBits *bits;
FbStride stride;
int xoff, yoff;
if (data->op == PictOpClear)
fetchSrc = NULL;
else if (!data->src->pDrawable) {
if (data->src->pSourcePict)
{
fetchSrc = fbFetchSourcePict;
srcClass = SourcePictureClassify (data->src,
data->xSrc, data->ySrc,
data->width, data->height);
}
} else if (data->src->alphaMap)
fetchSrc = fbFetchExternalAlpha;
else if (data->src->repeatType == RepeatNormal &&
data->src->pDrawable->width == 1 && data->src->pDrawable->height == 1)
{
fetchSrc = fbFetchSolid;
srcClass = SourcePictClassHorizontal;
}
else if (!data->src->transform && data->src->filter != PictFilterConvolution)
fetchSrc = fbFetch;
else
@ -3481,10 +3690,18 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
if (data->mask->pSourcePict)
fetchMask = fbFetchSourcePict;
} else if (data->mask->alphaMap)
{
fetchMask = fbFetchExternalAlpha;
maskClass = SourcePictureClassify (data->mask,
data->xMask, data->yMask,
data->width, data->height);
}
else if (data->mask->repeatType == RepeatNormal
&& data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1)
{
fetchMask = fbFetchSolid;
maskClass = SourcePictClassHorizontal;
}
else if (!data->mask->transform && data->mask->filter != PictFilterConvolution)
fetchMask = fbFetch;
else
@ -3493,76 +3710,204 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
fetchMask = NULL;
}
if (data->dest->alphaMap) {
if (data->dest->alphaMap)
{
fetchDest = fbFetchExternalAlpha;
store = fbStoreExternalAlpha;
} else {
fetchDest = fbFetch;
store = fbStore;
}
if (data->op == PictOpClear || data->op == PictOpSrc)
fetchDest = NULL;
}
else
{
fetchDest = fbFetch;
store = fbStore;
if (fetchSrc && fetchMask && data->mask && data->mask->componentAlpha && PICT_FORMAT_RGB(data->mask->format)) {
switch (data->op) {
case PictOpClear:
case PictOpSrc:
fetchDest = NULL;
/* fall-through */
case PictOpAdd:
case PictOpOver:
switch (data->dest->format) {
case PICT_a8r8g8b8:
case PICT_x8r8g8b8:
store = NULL;
break;
default:
break;
}
break;
}
}
if (!store)
{
int bpp;
fbGetDrawable (data->dest->pDrawable, bits, stride, bpp, xoff, yoff);
}
else
{
bits = NULL;
stride = 0;
xoff = yoff = 0;
}
if (fetchSrc &&
fetchMask &&
data->mask &&
data->mask->componentAlpha &&
PICT_FORMAT_RGB (data->mask->format))
{
CARD32 *mask_buffer = dest_buffer + data->width;
CombineFuncC compose = composeFunctions.combineC[data->op];
if (!compose)
return;
for (i = 0; i < data->height; ++i)
{
for (i = 0; i < data->height; ++i) {
/* fill first half of scanline with source */
fetchSrc(data->src, data->xSrc, data->ySrc + i, data->width, src_buffer);
fetchMask(data->mask, data->xMask, data->yMask + i, data->width, mask_buffer);
if (fetchSrc)
{
if (fetchMask)
{
/* fetch mask before source so that fetching of
source can be optimized */
fetchMask (data->mask, data->xMask, data->yMask + i,
data->width, mask_buffer, 0, 0);
if (maskClass == SourcePictClassHorizontal)
fetchMask = NULL;
}
if (srcClass == SourcePictClassHorizontal)
{
fetchSrc (data->src, data->xSrc, data->ySrc + i,
data->width, src_buffer, 0, 0);
fetchSrc = NULL;
}
else
{
fetchSrc (data->src, data->xSrc, data->ySrc + i,
data->width, src_buffer, mask_buffer,
0xffffffff);
}
}
else if (fetchMask)
{
fetchMask (data->mask, data->xMask, data->yMask + i,
data->width, mask_buffer, 0, 0);
}
if (store)
{
/* fill dest into second half of scanline */
if (fetchDest)
fetchDest(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer);
fetchDest (data->dest, data->xDest, data->yDest + i,
data->width, dest_buffer, 0, 0);
/* blend */
compose (dest_buffer, src_buffer, mask_buffer, data->width);
/* write back */
store(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer);
store (data->dest, data->xDest, data->yDest + i, data->width,
dest_buffer);
}
} else {
else
{
/* blend */
compose (bits + (data->yDest + i+ yoff) * stride +
data->xDest + xoff,
src_buffer, mask_buffer, data->width);
}
}
}
else
{
CARD32 *src_mask_buffer = 0, *mask_buffer = 0;
CombineFuncU compose = composeFunctions.combineU[data->op];
if (!compose)
return;
if (fetchSrc == fbFetchSolid && (!fetchMask || fetchMask == fbFetchSolid)) {
fetchSrc(data->src, data->xSrc, data->ySrc, data->width, src_buffer);
if (fetchMask) {
fetchMask(data->mask, data->xMask, data->yMask, data->width, dest_buffer);
composeFunctions.combineMaskU(src_buffer, dest_buffer, data->width);
}
fetchSrc = NULL;
if (fetchMask)
mask_buffer = dest_buffer + data->width;
for (i = 0; i < data->height; ++i) {
/* fill first half of scanline with source */
if (fetchSrc)
{
if (fetchMask)
{
/* fetch mask before source so that fetching of
source can be optimized */
fetchMask (data->mask, data->xMask, data->yMask + i,
data->width, mask_buffer, 0, 0);
if (maskClass == SourcePictClassHorizontal)
fetchMask = NULL;
}
for (i = 0; i < data->height; ++i)
if (srcClass == SourcePictClassHorizontal)
{
/* fill first half of scanline with source */
if (fetchSrc) {
fetchSrc(data->src, data->xSrc, data->ySrc + i, data->width, src_buffer);
fetchSrc (data->src, data->xSrc, data->ySrc + i,
data->width, src_buffer, 0, 0);
/* add in mask */
if (fetchMask) {
fetchMask(data->mask, data->xMask, data->yMask + i, data->width, dest_buffer);
composeFunctions.combineMaskU(src_buffer, dest_buffer, data->width);
if (mask_buffer)
{
fbCombineInU (mask_buffer, src_buffer, data->width);
src_mask_buffer = mask_buffer;
}
else
src_mask_buffer = src_buffer;
fetchSrc = NULL;
}
else
{
fetchSrc (data->src, data->xSrc, data->ySrc + i,
data->width, src_buffer, mask_buffer,
0xff000000);
if (mask_buffer)
composeFunctions.combineMaskU (src_buffer,
mask_buffer,
data->width);
src_mask_buffer = src_buffer;
}
}
else if (fetchMask)
{
fetchMask (data->mask, data->xMask, data->yMask + i,
data->width, mask_buffer, 0, 0);
fbCombineInU (mask_buffer, src_buffer, data->width);
src_mask_buffer = mask_buffer;
}
if (store)
{
/* fill dest into second half of scanline */
if (fetchDest)
fetchDest(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer);
fetchDest (data->dest, data->xDest, data->yDest + i,
data->width, dest_buffer, 0, 0);
/* blend */
compose(dest_buffer, src_buffer, data->width);
compose (dest_buffer, src_mask_buffer, data->width);
/* write back */
store(data->dest, data->xDest, data->yDest + i, data->width, dest_buffer);
store (data->dest, data->xDest, data->yDest + i, data->width,
dest_buffer);
}
else
{
/* blend */
compose (bits + (data->yDest + i+ yoff) * stride +
data->xDest + xoff,
src_mask_buffer, data->width);
}
}
}
}

View File

@ -890,54 +890,22 @@ static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a,
return x;
}
static void initGradientColorTable(SourcePictPtr pGradient, int *error)
CARD32
PictureGradientColor (PictGradientStopPtr stop1,
PictGradientStopPtr stop2,
CARD32 x)
{
int begin_pos, end_pos;
xFixed incr, dpos;
int pos, current_stop;
PictGradientStopPtr stops = pGradient->linear.stops;
int nstops = pGradient->linear.nstops;
CARD32 current_color, next_color;
int dist, idist;
/* 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;
current_color = xRenderColorToCard32 (stop1->color);
next_color = xRenderColorToCard32 (stop2->color);
pos = 0; /* The position in the color table. */
dist = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x));
idist = 256 - dist;
/* Up to first point */
while (pos <= begin_pos) {
pGradient->linear.colorTable[pos] = xRenderColorToCard32(stops[0].color);
++pos;
}
incr = (1<<16)/ PICT_GRADIENT_STOPTABLE_SIZE; /* the double increment. */
dpos = incr * pos; /* The position in terms of 0-1. */
current_stop = 0; /* We always interpolate between current and current + 1. */
/* Gradient area */
while (pos < end_pos) {
unsigned int current_color = xRenderColorToCard32(stops[current_stop].color);
unsigned int next_color = xRenderColorToCard32(stops[current_stop + 1].color);
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;
}
return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist,
next_color, dist));
}
static void initGradient(SourcePictPtr pGradient, int stopCount,
@ -953,26 +921,30 @@ static void initGradient(SourcePictPtr pGradient, int stopCount,
dpos = -1;
for (i = 0; i < stopCount; ++i) {
if (stopPoints[i] <= dpos || stopPoints[i] > (1<<16)) {
if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) {
*error = BadValue;
return;
}
dpos = stopPoints[i];
}
pGradient->linear.stops = xalloc(stopCount*sizeof(PictGradientStop));
if (!pGradient->linear.stops) {
pGradient->gradient.stops = xalloc(stopCount*sizeof(PictGradientStop));
if (!pGradient->gradient.stops) {
*error = BadAlloc;
return;
}
pGradient->linear.nstops = stopCount;
pGradient->gradient.nstops = stopCount;
for (i = 0; i < stopCount; ++i) {
pGradient->linear.stops[i].x = stopPoints[i];
pGradient->linear.stops[i].color = stopColors[i];
pGradient->gradient.stops[i].x = stopPoints[i];
pGradient->gradient.stops[i].color = stopColors[i];
}
initGradientColorTable(pGradient, error);
pGradient->gradient.class = SourcePictClassUnknown;
pGradient->gradient.stopRange = 0xffff;
pGradient->gradient.colorTable = NULL;
pGradient->gradient.colorTableSize = 0;
}
static PicturePtr createSourcePicture(void)
@ -980,9 +952,9 @@ static PicturePtr createSourcePicture(void)
PicturePtr pPicture;
pPicture = (PicturePtr) xalloc(sizeof(PictureRec));
pPicture->pDrawable = 0;
pPicture->format = PICT_a8r8g8b8;
pPicture->pFormat = 0;
pPicture->pNext = 0;
pPicture->format = PICT_a8r8g8b8;
pPicture->devPrivates = 0;
SetPictureToDefaults(pPicture);
@ -1027,10 +999,6 @@ CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2,
*error = BadAlloc;
return 0;
}
if (p1->x == p2->x && p1->y == p2->y) {
*error = BadValue;
return 0;
}
pPicture->id = pid;
pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictLinearGradient));
@ -1072,14 +1040,6 @@ CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer
*error = BadAlloc;
return 0;
}
{
double dx = (double)(inner->x - outer->x);
double dy = (double)(inner->y - outer->y);
if (sqrt(dx*dx + dy*dy) + (double)(innerRadius) > (double)(outerRadius)) {
*error = BadValue;
return 0;
}
}
pPicture->id = pid;
pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictRadialGradient));
@ -1627,13 +1587,17 @@ FreePicture (pointer value,
{
if (pPicture->transform)
xfree (pPicture->transform);
if (!pPicture->pDrawable) {
if (pPicture->pSourcePict) {
if (pPicture->pSourcePict)
{
if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
xfree(pPicture->pSourcePict->linear.stops);
xfree(pPicture->pSourcePict);
}
} else {
if (pPicture->pDrawable)
{
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
PictureScreenPtr ps = GetPictureScreen(pScreen);

View File

@ -68,8 +68,13 @@ typedef struct _PictTransform {
#define SourcePictTypeRadial 2
#define SourcePictTypeConical 3
#define SourcePictClassUnknown 0
#define SourcePictClassHorizontal 1
#define SourcePictClassVertical 2
typedef struct _PictSolidFill {
unsigned int type;
unsigned int class;
CARD32 color;
} PictSolidFill, *PictSolidFillPtr;
@ -80,16 +85,22 @@ typedef struct _PictGradientStop {
typedef struct _PictGradient {
unsigned int type;
unsigned int class;
int nstops;
PictGradientStopPtr stops;
CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
int stopRange;
CARD32 *colorTable;
int colorTableSize;
} PictGradient, *PictGradientPtr;
typedef struct _PictLinearGradient {
unsigned int type;
unsigned int class;
int nstops;
PictGradientStopPtr stops;
CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
int stopRange;
CARD32 *colorTable;
int colorTableSize;
xPointFixed p1;
xPointFixed p2;
} PictLinearGradient, *PictLinearGradientPtr;
@ -98,7 +109,6 @@ typedef struct _PictRadialGradient {
unsigned int type;
int nstops;
PictGradientStopPtr stops;
CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
double fx;
double fy;
double dx;
@ -110,9 +120,12 @@ typedef struct _PictRadialGradient {
typedef struct _PictConicalGradient {
unsigned int type;
unsigned int class;
int nstops;
PictGradientStopPtr stops;
CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE];
int stopRange;
CARD32 *colorTable;
int colorTableSize;
xPointFixed center;
xFixed angle;
} PictConicalGradient, *PictConicalGradientPtr;
@ -624,6 +637,11 @@ Bool
PictureTransformPoint3d (PictTransformPtr transform,
PictVectorPtr vector);
CARD32
PictureGradientColor (PictGradientStopPtr stop1,
PictGradientStopPtr stop2,
CARD32 x);
void RenderExtensionInit (void);
Bool