summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fb/fbcompose.c416
-rw-r--r--render/picture.c29
-rw-r--r--render/picturestr.h4
3 files changed, 316 insertions, 133 deletions
diff --git a/fb/fbcompose.c b/fb/fbcompose.c
index 9c25a0f97..2bfe5ca3a 100644
--- a/fb/fbcompose.c
+++ b/fb/fbcompose.c
@@ -2634,6 +2634,8 @@ static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
fetch(bits, x, width, buffer, indexed);
}
+#define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
+
static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
{
FbBits *bits;
@@ -2653,177 +2655,323 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
x += xoff;
y += yoff;
- v.vector[0] = IntToxFixed(x - pict->pDrawable->x);
- v.vector[1] = IntToxFixed(y - pict->pDrawable->y);
+ v.vector[0] = IntToxFixed(x);
+ v.vector[1] = IntToxFixed(y);
v.vector[2] = xFixed1;
- unit.vector[0] = xFixed1;
- unit.vector[1] = 0;
- unit.vector[2] = xFixed1;
-
+ /* when using convolution filters one might get here without a transform */
if (pict->transform) {
- /* when using convolution filters one might get here without a transform */
- if (!PictureTransformPoint (pict->transform, &v))
- return;
- if (!PictureTransformPoint (pict->transform, &unit))
+ 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;
}
- if (pict->filter == PictFilterNearest) {
- if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
- box = pict->pCompositeClip->extents;
- for (i = 0; i < width; ++i) {
- v.vector[0] += unit.vector[0];
- v.vector[1] += unit.vector[1];
- y = xFixedToInt (v.vector[1]) + pict->pDrawable->y;
- x = xFixedToInt (v.vector[0]) + pict->pDrawable->x;
- if (pict->repeat)
- {
- y = mod (y, pict->pDrawable->height);
- x = mod (x, pict->pDrawable->width);
+ if (pict->filter == PictFilterNearest)
+ {
+ if (pict->repeat) {
+ if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
+ box = pict->pCompositeClip->extents;
+ for (i = 0; i < width; ++i) {
+ v.vector[0] += unit.vector[0];
+ v.vector[1] += unit.vector[1];
+ v.vector[2] += unit.vector[2];
+ if (!v.vector[2]) {
+ buffer[i] = 0;
+ continue;
+ }
+ y = MOD((v.vector[1]/v.vector[2]), pict->pDrawable->height);
+ x = MOD((v.vector[0]/v.vector[2]), pict->pDrawable->width);
+ buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
+ }
+ } else {
+ for (i = 0; i < width; ++i) {
+ v.vector[0] += unit.vector[0];
+ v.vector[1] += unit.vector[1];
+ v.vector[2] += unit.vector[2];
+ if (!v.vector[2]) {
+ buffer[i] = 0;
+ continue;
+ }
+ y = MOD((v.vector[1]/v.vector[2]), pict->pDrawable->height);
+ x = MOD((v.vector[0]/v.vector[2]), pict->pDrawable->width);
+ if (POINT_IN_REGION (0, pict->pCompositeClip, x, y, &box))
+ buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
+ else
+ buffer[i] = 0;
}
- buffer[i] = ((x < box.x1) | (x > box.x2) | (y < box.y1) | (y > box.y2)) ?
- 0 : fetch(bits + (y - pict->pDrawable->y)*stride, x - pict->pDrawable->x, indexed);
}
} else {
- for (i = 0; i < width; ++i) {
- v.vector[0] += unit.vector[0];
- v.vector[1] += unit.vector[1];
- y = xFixedToInt (v.vector[1]) + pict->pDrawable->y;
- x = xFixedToInt (v.vector[0]) + pict->pDrawable->x;
- if (pict->repeat)
- {
- y = mod (y, pict->pDrawable->height);
- x = mod (x, pict->pDrawable->width);
- }
- if (POINT_IN_REGION (0, pict->pCompositeClip, x, y, &box))
- buffer[i] = fetch(bits + (y - pict->pDrawable->y)*stride, x - pict->pDrawable->x, indexed);
- else
- buffer[i] = 0;
+ if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
+ box = pict->pCompositeClip->extents;
+ for (i = 0; i < width; ++i) {
+ v.vector[0] += unit.vector[0];
+ v.vector[1] += unit.vector[1];
+ v.vector[2] += unit.vector[2];
+ if (!v.vector[2]) {
+ buffer[i] = 0;
+ continue;
+ }
+ y = (v.vector[1]/v.vector[2]);
+ x = (v.vector[0]/v.vector[2]);
+ buffer[i] = ((x < box.x1) | (x >= box.x2) | (y < box.y1) | (y >= box.y2)) ?
+ 0 : fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
+ }
+ } else {
+ for (i = 0; i < width; ++i) {
+ v.vector[0] += unit.vector[0];
+ v.vector[1] += unit.vector[1];
+ v.vector[2] += unit.vector[2];
+ if (!v.vector[2]) {
+ buffer[i] = 0;
+ continue;
+ }
+ y = (v.vector[1]/v.vector[2]);
+ x = (v.vector[0]/v.vector[2]);
+ if (POINT_IN_REGION (0, pict->pCompositeClip, x, y, &box))
+ buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
+ else
+ buffer[i] = 0;
+ }
}
}
} else if (pict->filter == PictFilterBilinear) {
- if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
- box = pict->pCompositeClip->extents;
- for (i = 0; i < width; ++i) {
- int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
- FbBits *b;
- CARD32 tl, tr, bl, br;
- Bool x1_out, x2_out, y1_out, y2_out;
-
- v.vector[0] += unit.vector[0];
- v.vector[1] += unit.vector[1];
-
- x1 = xFixedToInt(v.vector[0]);
- x2 = x1 + 1;
- y1 = xFixedToInt(v.vector[1]);
- y2 = y1 + 1;
- if (pict->repeat) {
- x1 = mod (x1, pict->pDrawable->width);
- y1 = mod (y1, pict->pDrawable->height);
- x2 = mod (x2, pict->pDrawable->width);
- y2 = mod (y2, pict->pDrawable->height);
+ if (pict->repeat) {
+ if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
+ box = pict->pCompositeClip->extents;
+ for (i = 0; i < width; ++i) {
+ int x1, x2, y1, y2, distx, idistx, disty, idisty;
+ FbBits *b;
+ CARD32 tl, tr, bl, br;
+ xFixed_48_16 div;
+
+ v.vector[0] += unit.vector[0];
+ v.vector[1] += unit.vector[1];
+ v.vector[2] += unit.vector[2];
+
+ if (!v.vector[2]) {
+ buffer[i] = 0;
+ continue;
+ }
+ div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
+ x1 = div >> 16;
+ distx = ((xFixed)div >> 8) & 0xff;
+ x2 = x1 + 1;
+ div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
+ y1 = div >> 16;
+ y2 = y1 + 1;
+ disty = ((xFixed)div >> 8) & 0xff;
+
+ idistx = 256 - distx;
+ idisty = 256 - disty;
+
+ x1 = MOD (x1, pict->pDrawable->width);
+ x2 = MOD (x2, pict->pDrawable->width);
+ y1 = MOD (y1, pict->pDrawable->height);
+ y2 = MOD (y2, pict->pDrawable->height);
+
+ b = bits + (y1 + pict->pDrawable->y)*stride;
+
+ tl = fetch(b, x1 + pict->pDrawable->x, indexed);
+ tr = fetch(b, x2 + pict->pDrawable->x, indexed);
+ b = bits + (y2 + pict->pDrawable->y)*stride;
+ bl = fetch(b, x1 + pict->pDrawable->x, indexed);
+ br = fetch(b, x2 + pict->pDrawable->x, indexed);
+
+ FbByteAddMul_256(tl, idistx, tr, distx);
+ FbByteAddMul_256(bl, idistx, br, distx);
+ FbByteAddMul_256(tl, idisty, bl, disty);
+ buffer[i] = tl;
}
+ } else {
+ for (i = 0; i < width; ++i) {
+ int x1, x2, y1, y2, distx, idistx, disty, idisty;
+ FbBits *b;
+ CARD32 tl, tr, bl, br;
+ xFixed_48_16 div;
+
+ v.vector[0] += unit.vector[0];
+ v.vector[1] += unit.vector[1];
+ v.vector[2] += unit.vector[2];
+ if (!v.vector[2]) {
+ buffer[i] = 0;
+ continue;
+ }
- distx = ((v.vector[0] - (x1 << 16)) >> 8);
- disty = ((v.vector[1] - (y1 << 16)) >> 8);
- idistx = 256 - distx;
- idisty = 256 - disty;
-
- b = bits + (y1 - pict->pDrawable->y)*stride;
- x_off = x1 - pict->pDrawable->x;
-
- x1_out = (x1 < box.x1) | (x1 > box.x2);
- x2_out = (x2 < box.x1) | (x2 > box.x2);
- y1_out = (y1 < box.y1) | (y1 > box.y2);
- y2_out = (y2 < box.y1) | (y2 > box.y2);
-
- tl = x1_out|y1_out ? 0 : fetch(b, x_off, indexed);
- tr = x2_out|y1_out ? 0 : fetch(b, x_off + 1, indexed);
- b += stride;
- bl = x1_out|y2_out ? 0 : fetch(b, x_off, indexed);
- br = x2_out|y2_out ? 0 : fetch(b, x_off + 1, indexed);
-
- FbByteAddMul_256(tl, idistx, tr, distx);
- FbByteAddMul_256(bl, idistx, br, distx);
- FbByteAddMul_256(tl, idisty, bl, disty);
- buffer[i] = tl;
+ div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
+ x1 = div >> 16;
+ distx = ((xFixed)div >> 8) & 0xff;
+ x2 = x1 + 1;
+ div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
+ y1 = div >> 16;
+ y2 = y1 + 1;
+ disty = ((xFixed)div >> 8) & 0xff;
+
+ idistx = 256 - distx;
+ idisty = 256 - disty;
+
+ x1 = MOD (x1, pict->pDrawable->width);
+ x2 = MOD (x2, pict->pDrawable->width);
+ y1 = MOD (y1, pict->pDrawable->height);
+ y2 = MOD (y2, pict->pDrawable->height);
+
+ b = bits + (y1 + pict->pDrawable->y)*stride;
+
+ tl = POINT_IN_REGION(0, pict->pCompositeClip, x1, y1, &box)
+ ? fetch(b, x1 + pict->pDrawable->x, indexed) : 0;
+ tr = POINT_IN_REGION(0, pict->pCompositeClip, x2, y1, &box)
+ ? fetch(b, x2 + pict->pDrawable->x, indexed) : 0;
+ b = bits + (y2 + pict->pDrawable->y)*stride;
+ bl = POINT_IN_REGION(0, pict->pCompositeClip, x1, y2, &box)
+ ? fetch(b, x1 + pict->pDrawable->x, indexed) : 0;
+ br = POINT_IN_REGION(0, pict->pCompositeClip, x2, y2, &box)
+ ? fetch(b, x2 + pict->pDrawable->x, indexed) : 0;
+
+ FbByteAddMul_256(tl, idistx, tr, distx);
+ FbByteAddMul_256(bl, idistx, br, distx);
+ FbByteAddMul_256(tl, idisty, bl, disty);
+ buffer[i] = tl;
+ }
}
} else {
- for (i = 0; i < width; ++i) {
- int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
- FbBits *b;
- CARD32 tl, tr, bl, br;
-
- v.vector[0] += unit.vector[0];
- v.vector[1] += unit.vector[1];
-
- x1 = xFixedToInt(v.vector[0]);
- x2 = x1 + 1;
- y1 = xFixedToInt(v.vector[1]);
- y2 = y1 + 1;
- if (pict->repeat)
- {
- x1 = mod (x1, pict->pDrawable->width);
- y1 = mod (y1, pict->pDrawable->height);
- x2 = mod (x2, pict->pDrawable->width);
- y2 = mod (y2, pict->pDrawable->height);
+ if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
+ box = pict->pCompositeClip->extents;
+ for (i = 0; i < width; ++i) {
+ int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
+ FbBits *b;
+ CARD32 tl, tr, bl, br;
+ Bool x1_out, x2_out, y1_out, y2_out;
+ xFixed_48_16 div;
+
+ v.vector[0] += unit.vector[0];
+ v.vector[1] += unit.vector[1];
+ v.vector[2] += unit.vector[2];
+ if (!v.vector[2]) {
+ buffer[i] = 0;
+ continue;
+ }
+
+ div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
+ x1 = div >> 16;
+ distx = ((xFixed)div >> 8) & 0xff;
+ x2 = x1 + 1;
+ div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
+ y1 = div >> 16;
+ y2 = y1 + 1;
+ disty = ((xFixed)div >> 8) & 0xff;
+
+ idistx = 256 - distx;
+ idisty = 256 - disty;
+
+ b = bits + (y1 + pict->pDrawable->y)*stride;
+ x_off = x1 + pict->pDrawable->x;
+
+ x1_out = (x1 < box.x1) | (x1 >= box.x2);
+ x2_out = (x2 < box.x1) | (x2 >= box.x2);
+ y1_out = (y1 < box.y1) | (y1 >= box.y2);
+ y2_out = (y2 < box.y1) | (y2 >= box.y2);
+
+ tl = x1_out|y1_out ? 0 : fetch(b, x_off, indexed);
+ tr = x2_out|y1_out ? 0 : fetch(b, x_off + 1, indexed);
+ b += stride;
+ bl = x1_out|y2_out ? 0 : fetch(b, x_off, indexed);
+ br = x2_out|y2_out ? 0 : fetch(b, x_off + 1, indexed);
+
+ FbByteAddMul_256(tl, idistx, tr, distx);
+ FbByteAddMul_256(bl, idistx, br, distx);
+ FbByteAddMul_256(tl, idisty, bl, disty);
+ buffer[i] = tl;
}
+ } else {
+ for (i = 0; i < width; ++i) {
+ int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
+ FbBits *b;
+ CARD32 tl, tr, bl, br;
+ xFixed_48_16 div;
+
+ v.vector[0] += unit.vector[0];
+ v.vector[1] += unit.vector[1];
+ v.vector[2] += unit.vector[2];
+ if (!v.vector[2]) {
+ buffer[i] = 0;
+ continue;
+ }
- distx = ((v.vector[0] - (x1 << 16)) >> 8);
- disty = ((v.vector[1] - (y1 << 16)) >> 8);
- idistx = 256 - distx;
- idisty = 256 - disty;
-
- b = bits + (y1 - pict->pDrawable->y)*stride;
- x_off = x1 - pict->pDrawable->x;
-
- tl = POINT_IN_REGION(0, pict->pCompositeClip, x1, y1, &box)
- ? fetch(b, x_off, indexed) : 0;
- tr = POINT_IN_REGION(0, pict->pCompositeClip, x2, y1, &box)
- ? fetch(b, x_off + 1, indexed) : 0;
- b += stride;
- bl = POINT_IN_REGION(0, pict->pCompositeClip, x1, y2, &box)
- ? fetch(b, x_off, indexed) : 0;
- br = POINT_IN_REGION(0, pict->pCompositeClip, x2, y2, &box)
- ? fetch(b, x_off + 1, indexed) : 0;
-
- FbByteAddMul_256(tl, idistx, tr, distx);
- FbByteAddMul_256(bl, idistx, br, distx);
- FbByteAddMul_256(tl, idisty, bl, disty);
- buffer[i] = tl;
+ div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
+ x1 = div >> 16;
+ distx = ((xFixed)div >> 8) & 0xff;
+ x2 = x1 + 1;
+ div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
+ y1 = div >> 16;
+ y2 = y1 + 1;
+ disty = ((xFixed)div >> 8) & 0xff;
+
+ idistx = 256 - distx;
+ idisty = 256 - disty;
+
+ b = bits + (y1 + pict->pDrawable->y)*stride;
+ x_off = x1 + pict->pDrawable->x;
+
+ tl = POINT_IN_REGION(0, pict->pCompositeClip, x1, y1, &box)
+ ? fetch(b, x_off, indexed) : 0;
+ tr = POINT_IN_REGION(0, pict->pCompositeClip, x2, y1, &box)
+ ? fetch(b, x_off + 1, indexed) : 0;
+ b += stride;
+ bl = POINT_IN_REGION(0, pict->pCompositeClip, x1, y2, &box)
+ ? fetch(b, x_off, indexed) : 0;
+ br = POINT_IN_REGION(0, pict->pCompositeClip, x2, y2, &box)
+ ? fetch(b, x_off + 1, indexed) : 0;
+
+ FbByteAddMul_256(tl, idistx, tr, distx);
+ FbByteAddMul_256(bl, idistx, br, distx);
+ FbByteAddMul_256(tl, idisty, bl, disty);
+ buffer[i] = tl;
+ }
}
}
} else if (pict->filter == PictFilterConvolution) {
xFixed *params = pict->filter_params;
INT32 cwidth = xFixedToInt(params[0]);
INT32 cheight = xFixedToInt(params[1]);
- v.vector[0] -= params[0] >> 2;
- v.vector[1] -= params[1] >> 2;
+ int xoff = params[0] >> 1;
+ int yoff = params[1] >> 1;
params += 2;
for (i = 0; i < width; ++i) {
int x1, x2, y1, y2, x, y;
INT32 srtot, sgtot, sbtot, satot, sum;
xFixed *p = params;
+ xFixed_48_16 tmp;
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
+ v.vector[2] += unit.vector[2];
+ if (!v.vector[2]) {
+ buffer[i] = 0;
+ continue;
+ }
- x1 = xFixedToInt(v.vector[0]);
+ tmp = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2] - xoff;
+ x1 = xFixedToInt(tmp);
x2 = x1 + cwidth;
- y1 = xFixedToInt(v.vector[1]);
+ tmp = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2] - yoff;
+ y1 = xFixedToInt(tmp);
y2 = y1 + cheight;
srtot = sgtot = sbtot = satot = sum = 0;
for (y = y1; y < y2; y++) {
- int ty = (pict->repeat) ? mod (y, pict->pDrawable->height) : y;
+ int ty = (pict->repeat) ? MOD (y, pict->pDrawable->height) : y;
for (x = x1; x < x2; x++) {
- if (*params) {
- int tx = (pict->repeat) ? mod (x, pict->pDrawable->width) : x;
+ if (*p) {
+ int tx = (pict->repeat) ? 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);
+ FbBits *b = bits + (ty + pict->pDrawable->y)*stride;
+ CARD32 c = fetch(b, tx + pict->pDrawable->x, indexed);
srtot += Red(c) * *p;
sgtot += Green(c) * *p;
@@ -2964,7 +3112,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
fetchMask = fbFetchExternalAlpha;
else if (data->mask->repeat && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1)
fetchMask = fbFetchSolid;
- else if (!data->mask->transform && data->src->filter != PictFilterConvolution)
+ else if (!data->mask->transform && data->mask->filter != PictFilterConvolution)
fetchMask = fbFetch;
else
fetchMask = fbFetchTransformed;
@@ -3063,7 +3211,8 @@ fbCompositeGeneral (CARD8 op,
RegionRec region;
int n;
BoxPtr pbox;
- Bool srcRepeat = pSrc->repeat && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1);
+ Bool srcRepeat = pSrc->repeat && !pSrc->transform
+ && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1);
Bool maskRepeat = FALSE;
int w, h;
CARD32 _scanline_buffer[SCANLINE_BUFFER_LENGTH*3];
@@ -3072,7 +3221,8 @@ fbCompositeGeneral (CARD8 op,
if (pMask)
- maskRepeat = pMask->repeat && (pMask->pDrawable->width != 1 || pMask->pDrawable->height != 1);
+ maskRepeat = pMask->repeat && !pMask->transform
+ && (pMask->pDrawable->width != 1 || pMask->pDrawable->height != 1);
if (op == PictOpOver && !pMask && !pSrc->transform && !PICT_FORMAT_A(pSrc->format))
op = PictOpSrc;
diff --git a/render/picture.c b/render/picture.c
index 8b615c664..1d2301bb3 100644
--- a/render/picture.c
+++ b/render/picture.c
@@ -1485,6 +1485,35 @@ AddTraps (PicturePtr pPicture,
#define MIN_FIXED_48_16 (-((xFixed_48_16) 1 << 31))
Bool
+PictureTransformPoint3d (PictTransformPtr transform,
+ PictVectorPtr vector)
+{
+ PictVector result;
+ int i, j;
+ xFixed_32_32 partial;
+ xFixed_48_16 v;
+
+ for (j = 0; j < 3; j++)
+ {
+ v = 0;
+ for (i = 0; i < 3; i++)
+ {
+ partial = ((xFixed_48_16) transform->matrix[j][i] *
+ (xFixed_48_16) vector->vector[i]);
+ v += partial >> 16;
+ }
+ if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
+ return FALSE;
+ result.vector[j] = (xFixed) v;
+ }
+ if (!result.vector[2])
+ return FALSE;
+ *vector = result;
+ return TRUE;
+}
+
+
+Bool
PictureTransformPoint (PictTransformPtr transform,
PictVectorPtr vector)
{
diff --git a/render/picturestr.h b/render/picturestr.h
index 690e08f4d..a532e4e1c 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -527,6 +527,10 @@ Bool
PictureTransformPoint (PictTransformPtr transform,
PictVectorPtr vector);
+Bool
+PictureTransformPoint3d (PictTransformPtr transform,
+ PictVectorPtr vector);
+
void RenderExtensionInit (void);
Bool