Fix projective transformations in fbcompose.c Bugfix for convolution

filters
This commit is contained in:
Lars Knoll 2005-06-15 14:51:12 +00:00
parent bd54b96034
commit c6166ee741
3 changed files with 305 additions and 122 deletions

View File

@ -2634,6 +2634,8 @@ static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
fetch(bits, x, width, buffer, indexed); 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) static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
{ {
FbBits *bits; FbBits *bits;
@ -2653,177 +2655,323 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
x += xoff; x += xoff;
y += yoff; y += yoff;
v.vector[0] = IntToxFixed(x - pict->pDrawable->x); v.vector[0] = IntToxFixed(x);
v.vector[1] = IntToxFixed(y - pict->pDrawable->y); v.vector[1] = IntToxFixed(y);
v.vector[2] = xFixed1; v.vector[2] = xFixed1;
unit.vector[0] = xFixed1; /* when using convolution filters one might get here without a transform */
unit.vector[1] = 0;
unit.vector[2] = xFixed1;
if (pict->transform) { if (pict->transform) {
/* when using convolution filters one might get here without a transform */ if (!PictureTransformPoint3d (pict->transform, &v))
if (!PictureTransformPoint (pict->transform, &v))
return;
if (!PictureTransformPoint (pict->transform, &unit))
return; 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 (pict->filter == PictFilterNearest)
if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) { {
box = pict->pCompositeClip->extents; if (pict->repeat) {
for (i = 0; i < width; ++i) { if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
v.vector[0] += unit.vector[0]; box = pict->pCompositeClip->extents;
v.vector[1] += unit.vector[1]; for (i = 0; i < width; ++i) {
y = xFixedToInt (v.vector[1]) + pict->pDrawable->y; v.vector[0] += unit.vector[0];
x = xFixedToInt (v.vector[0]) + pict->pDrawable->x; v.vector[1] += unit.vector[1];
if (pict->repeat) v.vector[2] += unit.vector[2];
{ if (!v.vector[2]) {
y = mod (y, pict->pDrawable->height); buffer[i] = 0;
x = mod (x, pict->pDrawable->width); 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 { } else {
for (i = 0; i < width; ++i) { if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
v.vector[0] += unit.vector[0]; box = pict->pCompositeClip->extents;
v.vector[1] += unit.vector[1]; for (i = 0; i < width; ++i) {
y = xFixedToInt (v.vector[1]) + pict->pDrawable->y; v.vector[0] += unit.vector[0];
x = xFixedToInt (v.vector[0]) + pict->pDrawable->x; v.vector[1] += unit.vector[1];
if (pict->repeat) v.vector[2] += unit.vector[2];
{ if (!v.vector[2]) {
y = mod (y, pict->pDrawable->height); buffer[i] = 0;
x = mod (x, pict->pDrawable->width); continue;
} }
if (POINT_IN_REGION (0, pict->pCompositeClip, x, y, &box)) y = (v.vector[1]/v.vector[2]);
buffer[i] = fetch(bits + (y - pict->pDrawable->y)*stride, x - pict->pDrawable->x, indexed); x = (v.vector[0]/v.vector[2]);
else buffer[i] = ((x < box.x1) | (x >= box.x2) | (y < box.y1) | (y >= box.y2)) ?
buffer[i] = 0; 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) { } else if (pict->filter == PictFilterBilinear) {
if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) { if (pict->repeat) {
box = pict->pCompositeClip->extents; if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
for (i = 0; i < width; ++i) { box = pict->pCompositeClip->extents;
int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off; for (i = 0; i < width; ++i) {
FbBits *b; int x1, x2, y1, y2, distx, idistx, disty, idisty;
CARD32 tl, tr, bl, br; FbBits *b;
Bool x1_out, x2_out, y1_out, y2_out; CARD32 tl, tr, bl, br;
xFixed_48_16 div;
v.vector[0] += unit.vector[0]; v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1]; v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
x1 = xFixedToInt(v.vector[0]); if (!v.vector[2]) {
x2 = x1 + 1; buffer[i] = 0;
y1 = xFixedToInt(v.vector[1]); continue;
y2 = y1 + 1; }
if (pict->repeat) { div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
x1 = mod (x1, pict->pDrawable->width); x1 = div >> 16;
y1 = mod (y1, pict->pDrawable->height); distx = ((xFixed)div >> 8) & 0xff;
x2 = mod (x2, pict->pDrawable->width); x2 = x1 + 1;
y2 = mod (y2, pict->pDrawable->height); 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;
distx = ((v.vector[0] - (x1 << 16)) >> 8); v.vector[0] += unit.vector[0];
disty = ((v.vector[1] - (y1 << 16)) >> 8); v.vector[1] += unit.vector[1];
idistx = 256 - distx; v.vector[2] += unit.vector[2];
idisty = 256 - disty; if (!v.vector[2]) {
buffer[i] = 0;
continue;
}
b = bits + (y1 - pict->pDrawable->y)*stride; div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
x_off = x1 - pict->pDrawable->x; 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;
x1_out = (x1 < box.x1) | (x1 > box.x2); idistx = 256 - distx;
x2_out = (x2 < box.x1) | (x2 > box.x2); idisty = 256 - disty;
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); x1 = MOD (x1, pict->pDrawable->width);
tr = x2_out|y1_out ? 0 : fetch(b, x_off + 1, indexed); x2 = MOD (x2, pict->pDrawable->width);
b += stride; y1 = MOD (y1, pict->pDrawable->height);
bl = x1_out|y2_out ? 0 : fetch(b, x_off, indexed); y2 = MOD (y2, pict->pDrawable->height);
br = x2_out|y2_out ? 0 : fetch(b, x_off + 1, indexed);
FbByteAddMul_256(tl, idistx, tr, distx); b = bits + (y1 + pict->pDrawable->y)*stride;
FbByteAddMul_256(bl, idistx, br, distx);
FbByteAddMul_256(tl, idisty, bl, disty); tl = POINT_IN_REGION(0, pict->pCompositeClip, x1, y1, &box)
buffer[i] = tl; ? 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 { } else {
for (i = 0; i < width; ++i) { if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off; box = pict->pCompositeClip->extents;
FbBits *b; for (i = 0; i < width; ++i) {
CARD32 tl, tr, bl, br; 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[0] += unit.vector[0];
v.vector[1] += unit.vector[1]; 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]); div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
x2 = x1 + 1; x1 = div >> 16;
y1 = xFixedToInt(v.vector[1]); distx = ((xFixed)div >> 8) & 0xff;
y2 = y1 + 1; x2 = x1 + 1;
if (pict->repeat) div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
{ y1 = div >> 16;
x1 = mod (x1, pict->pDrawable->width); y2 = y1 + 1;
y1 = mod (y1, pict->pDrawable->height); disty = ((xFixed)div >> 8) & 0xff;
x2 = mod (x2, pict->pDrawable->width);
y2 = mod (y2, pict->pDrawable->height); 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;
distx = ((v.vector[0] - (x1 << 16)) >> 8); v.vector[0] += unit.vector[0];
disty = ((v.vector[1] - (y1 << 16)) >> 8); v.vector[1] += unit.vector[1];
idistx = 256 - distx; v.vector[2] += unit.vector[2];
idisty = 256 - disty; if (!v.vector[2]) {
buffer[i] = 0;
continue;
}
b = bits + (y1 - pict->pDrawable->y)*stride; div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
x_off = x1 - pict->pDrawable->x; 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;
tl = POINT_IN_REGION(0, pict->pCompositeClip, x1, y1, &box) idistx = 256 - distx;
? fetch(b, x_off, indexed) : 0; idisty = 256 - disty;
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); b = bits + (y1 + pict->pDrawable->y)*stride;
FbByteAddMul_256(bl, idistx, br, distx); x_off = x1 + pict->pDrawable->x;
FbByteAddMul_256(tl, idisty, bl, disty);
buffer[i] = tl; 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) { } else if (pict->filter == PictFilterConvolution) {
xFixed *params = pict->filter_params; xFixed *params = pict->filter_params;
INT32 cwidth = xFixedToInt(params[0]); INT32 cwidth = xFixedToInt(params[0]);
INT32 cheight = xFixedToInt(params[1]); INT32 cheight = xFixedToInt(params[1]);
v.vector[0] -= params[0] >> 2; int xoff = params[0] >> 1;
v.vector[1] -= params[1] >> 2; int yoff = params[1] >> 1;
params += 2; params += 2;
for (i = 0; i < width; ++i) { for (i = 0; i < width; ++i) {
int x1, x2, y1, y2, x, y; int x1, x2, y1, y2, x, y;
INT32 srtot, sgtot, sbtot, satot, sum; INT32 srtot, sgtot, sbtot, satot, sum;
xFixed *p = params; xFixed *p = params;
xFixed_48_16 tmp;
v.vector[0] += unit.vector[0]; v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1]; 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; 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; y2 = y1 + cheight;
srtot = sgtot = sbtot = satot = sum = 0; srtot = sgtot = sbtot = satot = sum = 0;
for (y = y1; y < y2; y++) { 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++) { for (x = x1; x < x2; x++) {
if (*params) { if (*p) {
int tx = (pict->repeat) ? mod (x, pict->pDrawable->width) : x; int tx = (pict->repeat) ? MOD (x, pict->pDrawable->width) : x;
if (POINT_IN_REGION (0, pict->pCompositeClip, tx, ty, &box)) { if (POINT_IN_REGION (0, pict->pCompositeClip, tx, ty, &box)) {
FbBits *b = bits + (ty - pict->pDrawable->y)*stride; FbBits *b = bits + (ty + pict->pDrawable->y)*stride;
CARD32 c = fetch(b, tx - pict->pDrawable->x, indexed); CARD32 c = fetch(b, tx + pict->pDrawable->x, indexed);
srtot += Red(c) * *p; srtot += Red(c) * *p;
sgtot += Green(c) * *p; sgtot += Green(c) * *p;
@ -2964,7 +3112,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
fetchMask = fbFetchExternalAlpha; fetchMask = fbFetchExternalAlpha;
else if (data->mask->repeat && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1) else if (data->mask->repeat && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1)
fetchMask = fbFetchSolid; fetchMask = fbFetchSolid;
else if (!data->mask->transform && data->src->filter != PictFilterConvolution) else if (!data->mask->transform && data->mask->filter != PictFilterConvolution)
fetchMask = fbFetch; fetchMask = fbFetch;
else else
fetchMask = fbFetchTransformed; fetchMask = fbFetchTransformed;
@ -3063,7 +3211,8 @@ fbCompositeGeneral (CARD8 op,
RegionRec region; RegionRec region;
int n; int n;
BoxPtr pbox; 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; Bool maskRepeat = FALSE;
int w, h; int w, h;
CARD32 _scanline_buffer[SCANLINE_BUFFER_LENGTH*3]; CARD32 _scanline_buffer[SCANLINE_BUFFER_LENGTH*3];
@ -3072,7 +3221,8 @@ fbCompositeGeneral (CARD8 op,
if (pMask) 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)) if (op == PictOpOver && !pMask && !pSrc->transform && !PICT_FORMAT_A(pSrc->format))
op = PictOpSrc; op = PictOpSrc;

View File

@ -1484,6 +1484,35 @@ AddTraps (PicturePtr pPicture,
#define MAX_FIXED_48_16 ((xFixed_48_16) 0x7fffffff) #define MAX_FIXED_48_16 ((xFixed_48_16) 0x7fffffff)
#define MIN_FIXED_48_16 (-((xFixed_48_16) 1 << 31)) #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 Bool
PictureTransformPoint (PictTransformPtr transform, PictureTransformPoint (PictTransformPtr transform,
PictVectorPtr vector) PictVectorPtr vector)

View File

@ -527,6 +527,10 @@ Bool
PictureTransformPoint (PictTransformPtr transform, PictureTransformPoint (PictTransformPtr transform,
PictVectorPtr vector); PictVectorPtr vector);
Bool
PictureTransformPoint3d (PictTransformPtr transform,
PictVectorPtr vector);
void RenderExtensionInit (void); void RenderExtensionInit (void);
Bool Bool