[PATCH] [pixman-compose.c] Refactor fbFetchTransformed()

Antoine Azar cairo at antoineazar.com
Tue Jan 29 02:53:03 PST 2008


---
 pixman/pixman-compose.c |  969 ++++++++++++++++++++++++++---------------------
 pixman/pixman-private.h |    2 +
 2 files changed, 540 insertions(+), 431 deletions(-)

diff --git a/pixman/pixman-compose.c b/pixman/pixman-compose.c
index e240850..973541e 100644
--- a/pixman/pixman-compose.c
+++ b/pixman/pixman-compose.c
@@ -3678,19 +3678,516 @@ static void pixmanFetchSourcePict(source_image_t * pict, int x, int y, int width
     }
 }
 
-static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
+/*
+ * Fetch from region strategies
+ */
+typedef FASTCALL uint32_t (*fetchFromRegionProc)(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box);
+
+static inline uint32_t
+fbFetchFromNoRegion(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box)
+{
+    return fetch (pict, x, y);
+}
+
+static uint32_t
+fbFetchFromNRectangles(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box)
+{
+    if (pixman_region_contains_point (pict->common.src_clip, x, y, box))
+        return fbFetchFromNoRegion(pict, x, y, buffer, fetch, box);
+    else
+        return 0;
+}
+
+static uint32_t
+fbFetchFromOneRectangle(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box)
+{
+    pixman_box16_t box2 = *box;
+    return ((x < box2.x1) | (x >= box2.x2) | (y < box2.y1) | (y >= box2.y2)) ?
+        0 : fbFetchFromNoRegion(pict, x, y, buffer, fetch, box);
+}
+
+/*
+ * Fetching Algorithms
+ */
+static void
+fbFetchTransformed_Nearest_Normal(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
+{
+    pixman_box16_t* box = NULL;
+    fetchPixelProc   fetch;
+    fetchFromRegionProc fetchFromRegion;
+    int x, y, i;
+
+    /* initialize the two function pointers */
+    fetch = fetchPixelProcForPicture(pict);
+
+    if(pixman_region_n_rects (pict->common.src_clip) == 1)
+        fetchFromRegion = fbFetchFromNoRegion;
+    else
+        fetchFromRegion = fbFetchFromNRectangles;
+
+    for ( i = 0; i < width; ++i)
+    {
+        if (!mask || mask[i] & maskBits)
+        {
+            if (!v.vector[2])
+            {
+                *(buffer + i) = 0;
+            }
+            else
+            {
+                if (!affine)
+                {
+                    y = MOD(DIV(v.vector[1],v.vector[2]), pict->height);
+                    x = MOD(DIV(v.vector[0],v.vector[2]), pict->width);
+                }
+                else
+                {
+                    y = MOD(v.vector[1]>>16, pict->height);
+                    x = MOD(v.vector[0]>>16, pict->width);
+                }
+                *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box);
+            }
+        }
+
+        v.vector[0] += unit.vector[0];
+        v.vector[1] += unit.vector[1];
+        v.vector[2] += unit.vector[2];
+    }
+}
+
+static void
+fbFetchTransformed_Nearest_Pad(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
+{
+    pixman_box16_t *box = NULL;
+    fetchPixelProc   fetch;
+    fetchFromRegionProc fetchFromRegion;
+    int x, y, i;
+
+    /* initialize the two function pointers */
+    fetch = fetchPixelProcForPicture(pict);
+
+    if(pixman_region_n_rects (pict->common.src_clip) == 1)
+        fetchFromRegion = fbFetchFromNoRegion;
+    else
+        fetchFromRegion = fbFetchFromNRectangles;
+
+    for (i = 0; i < width; ++i)
+    {
+        if (!mask || mask[i] & maskBits)
+        {
+            if (!v.vector[2])
+            {
+                *(buffer + i) = 0;
+            }
+            else
+            {
+                if (!affine)
+                {
+                    y = CLIP(DIV(v.vector[1], v.vector[2]), 0, pict->height-1);
+                    x = CLIP(DIV(v.vector[0], v.vector[2]), 0, pict->width-1);
+                }
+                else
+                {
+                    y = CLIP(v.vector[1]>>16, 0, pict->height-1);
+                    x = CLIP(v.vector[0]>>16, 0, pict->width-1);
+                }
+
+                *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box);
+            }
+        }
+
+        v.vector[0] += unit.vector[0];
+        v.vector[1] += unit.vector[1];
+        v.vector[2] += unit.vector[2];
+    }
+}
+
+static void
+fbFetchTransformed_Nearest_General(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
+{
+    pixman_box16_t *box;
+    fetchPixelProc   fetch;
+    fetchFromRegionProc fetchFromRegion;
+    int x, y, i;
+
+    /* initialize the two function pointers */
+    fetch = fetchPixelProcForPicture(pict);
+
+    if(pixman_region_n_rects (pict->common.src_clip) == 1)
+    {
+        box = &(pict->common.src_clip->extents);
+        fetchFromRegion = fbFetchFromOneRectangle;
+    }
+    else
+    {
+        fetchFromRegion = fbFetchFromNRectangles;
+    }
+
+    for (i = 0; i < width; ++i) {
+        if (!mask || mask[i] & maskBits)
+        {
+            if (!v.vector[2]) {
+                *(buffer + i) = 0;
+            } else {
+                if (!affine) {
+                    y = DIV(v.vector[1],v.vector[2]);
+                    x = DIV(v.vector[0],v.vector[2]);
+                } else {
+                    y = v.vector[1]>>16;
+                    x = v.vector[0]>>16;
+                }
+                *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box);
+            }
+        }
+        v.vector[0] += unit.vector[0];
+        v.vector[1] += unit.vector[1];
+        v.vector[2] += unit.vector[2];
+    }
+}
+
+static void
+fbFetchTransformed_Bilinear_Normal(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
+{
+    pixman_box16_t *box = NULL;
+    fetchPixelProc   fetch;
+    fetchFromRegionProc fetchFromRegion;
+    int i;
+
+    /* initialize the two function pointers */
+    fetch = fetchPixelProcForPicture(pict);
+
+    if(pixman_region_n_rects (pict->common.src_clip) == 1)
+        fetchFromRegion = fbFetchFromNoRegion;
+    else
+        fetchFromRegion = fbFetchFromNRectangles;
+
+    for (i = 0; i < width; ++i) {
+        if (!mask || mask[i] & maskBits)
+        {
+            if (!v.vector[2]) {
+                *(buffer + i) = 0;
+            } else {
+                int x1, x2, y1, y2, distx, idistx, disty, idisty;
+                uint32_t tl, tr, bl, br, r;
+                uint32_t ft, fb;
+
+                if (!affine) {
+                    pixman_fixed_48_16_t div;
+                    div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
+                    x1 = div >> 16;
+                    distx = ((pixman_fixed_t)div >> 8) & 0xff;
+                    div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
+                    y1 = div >> 16;
+                    disty = ((pixman_fixed_t)div >> 8) & 0xff;
+                } else {
+                    x1 = v.vector[0] >> 16;
+                    distx = (v.vector[0] >> 8) & 0xff;
+                    y1 = v.vector[1] >> 16;
+                    disty = (v.vector[1] >> 8) & 0xff;
+                }
+                x2 = x1 + 1;
+                y2 = y1 + 1;
+
+                idistx = 256 - distx;
+                idisty = 256 - disty;
+
+                x1 = MOD (x1, pict->width);
+                x2 = MOD (x2, pict->width);
+                y1 = MOD (y1, pict->height);
+                y2 = MOD (y2, pict->height);
+
+                tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box);
+                tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box);
+                bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box);
+                br = fetchFromRegion(pict, x2, y2, buffer, fetch, box);
+
+                ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+                fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+                r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+                ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+                fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+                r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+                ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+                fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+                r |= (((ft * idisty + fb * disty)) & 0xff0000);
+                ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+                fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+                r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+                *(buffer + i) = r;
+            }
+        }
+        v.vector[0] += unit.vector[0];
+        v.vector[1] += unit.vector[1];
+        v.vector[2] += unit.vector[2];
+    }
+}
+
+static void
+fbFetchTransformed_Bilinear_Pad(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
+{
+    pixman_box16_t *box = NULL;
+    fetchPixelProc   fetch;
+    fetchFromRegionProc fetchFromRegion;
+    int i;
+
+    /* initialize the two function pointers */
+    fetch = fetchPixelProcForPicture(pict);
+
+    if(pixman_region_n_rects (pict->common.src_clip) == 1)
+        fetchFromRegion = fbFetchFromNoRegion;
+    else
+        fetchFromRegion = fbFetchFromNRectangles;
+
+    for (i = 0; i < width; ++i) {
+        if (!mask || mask[i] & maskBits)
+        {
+            if (!v.vector[2]) {
+                *(buffer + i) = 0;
+            } else {
+                int x1, x2, y1, y2, distx, idistx, disty, idisty;
+                uint32_t tl, tr, bl, br, r;
+                uint32_t ft, fb;
+
+                if (!affine) {
+                    pixman_fixed_48_16_t div;
+                    div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
+                    x1 = div >> 16;
+                    distx = ((pixman_fixed_t)div >> 8) & 0xff;
+                    div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
+                    y1 = div >> 16;
+                    disty = ((pixman_fixed_t)div >> 8) & 0xff;
+                } else {
+                    x1 = v.vector[0] >> 16;
+                    distx = (v.vector[0] >> 8) & 0xff;
+                    y1 = v.vector[1] >> 16;
+                    disty = (v.vector[1] >> 8) & 0xff;
+                }
+                x2 = x1 + 1;
+                y2 = y1 + 1;
+
+                idistx = 256 - distx;
+                idisty = 256 - disty;
+
+                x1 = CLIP (x1, 0, pict->width-1);
+                x2 = CLIP (x2, 0, pict->width-1);
+                y1 = CLIP (y1, 0, pict->height-1);
+                y2 = CLIP (y2, 0, pict->height-1);
+
+                tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box);
+                tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box);
+                bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box);
+                br = fetchFromRegion(pict, x2, y2, buffer, fetch, box);
+
+                ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+                fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+                r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+                ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+                fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+                r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+                ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+                fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+                r |= (((ft * idisty + fb * disty)) & 0xff0000);
+                ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+                fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+                r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+                *(buffer + i) = r;
+            }
+        }
+        v.vector[0] += unit.vector[0];
+        v.vector[1] += unit.vector[1];
+        v.vector[2] += unit.vector[2];
+    }
+}
+
+static void
+fbFetchTransformed_Bilinear_General(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
+{
+    pixman_box16_t *box;
+    fetchPixelProc   fetch;
+    fetchFromRegionProc fetchFromRegion;
+    int i;
+
+    /* initialize the two function pointers */
+    fetch = fetchPixelProcForPicture(pict);
+
+    if(pixman_region_n_rects (pict->common.src_clip) == 1)
+    {
+        box = &(pict->common.src_clip->extents);
+        fetchFromRegion = fbFetchFromOneRectangle;
+    }
+    else
+    {
+        fetchFromRegion = fbFetchFromNRectangles;
+    }
+
+    for (i = 0; i < width; ++i)
+    {
+        if (!mask || mask[i] & maskBits)
+        {
+            if (!v.vector[2]) {
+                *(buffer + i) = 0;
+            } else {
+                int x1, x2, y1, y2, distx, idistx, disty, idisty;
+                uint32_t tl, tr, bl, br, r;
+                uint32_t ft, fb;
+
+                if (!affine) {
+                    pixman_fixed_48_16_t div;
+                    div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
+                    x1 = div >> 16;
+                    distx = ((pixman_fixed_t)div >> 8) & 0xff;
+                    div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
+                    y1 = div >> 16;
+                    disty = ((pixman_fixed_t)div >> 8) & 0xff;
+                } else {
+                    x1 = v.vector[0] >> 16;
+                    distx = (v.vector[0] >> 8) & 0xff;
+                    y1 = v.vector[1] >> 16;
+                    disty = (v.vector[1] >> 8) & 0xff;
+                }
+                x2 = x1 + 1;
+                y2 = y1 + 1;
+
+                idistx = 256 - distx;
+                idisty = 256 - disty;
+
+                tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box);
+                tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box);
+                bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box);
+                br = fetchFromRegion(pict, x2, y2, buffer, fetch, box);
+
+                ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
+                fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
+                r = (((ft * idisty + fb * disty) >> 16) & 0xff);
+                ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
+                fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
+                r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
+                ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
+                fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
+                r |= (((ft * idisty + fb * disty)) & 0xff0000);
+                ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
+                fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
+                r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
+                *(buffer + i) = r;
+            }
+        }
+
+        v.vector[0] += unit.vector[0];
+        v.vector[1] += unit.vector[1];
+        v.vector[2] += unit.vector[2];
+    }
+}
+
+static void
+fbFetchTransformed_Convolution(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit)
+{
+    pixman_box16_t *box = NULL;
+    fetchPixelProc fetch;
+    int i;
+
+    pixman_fixed_t *params = pict->common.filter_params;
+    int32_t cwidth = pixman_fixed_to_int(params[0]);
+    int32_t cheight = pixman_fixed_to_int(params[1]);
+    int xoff = (params[0] - pixman_fixed_1) >> 1;
+    int yoff = (params[1] - pixman_fixed_1) >> 1;
+    fetch = fetchPixelProcForPicture(pict);
+
+    params += 2;
+    for (i = 0; i < width; ++i) {
+        if (!mask || mask[i] & maskBits)
+        {
+            if (!v.vector[2]) {
+                *(buffer + i) = 0;
+            } else {
+                int x1, x2, y1, y2, x, y;
+                int32_t srtot, sgtot, sbtot, satot;
+                pixman_fixed_t *p = params;
+
+                if (!affine) {
+                    pixman_fixed_48_16_t tmp;
+                    tmp = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2] - xoff;
+                    x1 = pixman_fixed_to_int(tmp);
+                    tmp = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2] - yoff;
+                    y1 = pixman_fixed_to_int(tmp);
+                } else {
+                    x1 = pixman_fixed_to_int(v.vector[0] - xoff);
+                    y1 = pixman_fixed_to_int(v.vector[1] - yoff);
+                }
+                x2 = x1 + cwidth;
+                y2 = y1 + cheight;
+
+                srtot = sgtot = sbtot = satot = 0;
+
+                for (y = y1; y < y2; y++) {
+                    int ty;
+                    switch (pict->common.repeat) {
+                        case PIXMAN_REPEAT_NORMAL:
+                            ty = MOD (y, pict->height);
+                            break;
+                        case PIXMAN_REPEAT_PAD:
+                            ty = CLIP (y, 0, pict->height-1);
+                            break;
+                        default:
+                            ty = y;
+                    }
+                    for (x = x1; x < x2; x++) {
+                        if (*p) {
+                            int tx;
+                            switch (pict->common.repeat) {
+                                case PIXMAN_REPEAT_NORMAL:
+                                    tx = MOD (x, pict->width);
+                                    break;
+                                case PIXMAN_REPEAT_PAD:
+                                    tx = CLIP (x, 0, pict->width-1);
+                                    break;
+                                default:
+                                    tx = x;
+                            }
+                            if (pixman_region_contains_point (pict->common.src_clip, tx, ty, box)) {
+                                uint32_t c = fetch(pict, tx, ty);
+
+                                srtot += Red(c) * *p;
+                                sgtot += Green(c) * *p;
+                                sbtot += Blue(c) * *p;
+                                satot += Alpha(c) * *p;
+                            }
+                        }
+                        p++;
+                    }
+                }
+
+                satot >>= 16;
+                srtot >>= 16;
+                sgtot >>= 16;
+                sbtot >>= 16;
+
+                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;
+
+                *(buffer + i) = ((satot << 24) |
+                                 (srtot << 16) |
+                                 (sgtot <<  8) |
+                                 (sbtot       ));
+            }
+        }
+        v.vector[0] += unit.vector[0];
+        v.vector[1] += unit.vector[1];
+        v.vector[2] += unit.vector[2];
+    }
+}
+
+static void
+fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
 {
     uint32_t     *bits;
     int32_t    stride;
-    fetchPixelProc   fetch;
-    pixman_vector_t	v;
-    pixman_vector_t  unit;
     int         i;
-    pixman_box16_t box;
+    pixman_vector_t v;
+    pixman_vector_t unit;
     pixman_bool_t affine = TRUE;
 
-    fetch = fetchPixelProcForPicture(pict);
-
     bits = pict->bits;
     stride = pict->rowstride;
 
@@ -3703,7 +4200,7 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
     if (pict->common.transform)
     {
         if (!pixman_transform_point_3d (pict->common.transform, &v))
-	{
+        {
             fbFinishAccess (pict->pDrawable);
             return;
         }
@@ -3721,104 +4218,18 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
 
     if (pict->common.filter == PIXMAN_FILTER_NEAREST || pict->common.filter == PIXMAN_FILTER_FAST)
     {
-        if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) {
-            if (pixman_region_n_rects (pict->common.src_clip) == 1) {
-		for (i = 0; i < width; ++i) {
-		    if (!mask || mask[i] & maskBits)
-		    {
-			if (!v.vector[2]) {
-			    *(buffer + i) = 0;
-			} else {
-			    if (!affine) {
-				y = MOD(DIV(v.vector[1],v.vector[2]), pict->height);
-				x = MOD(DIV(v.vector[0],v.vector[2]), pict->width);
-			    } else {
-				y = MOD(v.vector[1]>>16, pict->height);
-				x = MOD(v.vector[0]>>16, pict->width);
-			    }
-			    *(buffer + i) = fetch(pict, x, y);
-			}
-		    }
-
-                    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]) {
-			    *(buffer + i) = 0;
-			} else {
-			    if (!affine) {
-				y = MOD(DIV(v.vector[1],v.vector[2]), pict->height);
-				x = MOD(DIV(v.vector[0],v.vector[2]), pict->width);
-			    } else {
-				y = MOD(v.vector[1]>>16, pict->height);
-				x = MOD(v.vector[0]>>16, pict->width);
-			    }
-			    if (pixman_region_contains_point (pict->common.src_clip, x, y, &box))
-				*(buffer + i) = fetch (pict, x, y);
-			    else
-				*(buffer + i) = 0;
-			}
-		    }
+        if (pict->common.repeat == PIXMAN_REPEAT_NORMAL)
+        {
+            fbFetchTransformed_Nearest_Normal(pict, width, buffer, mask, maskBits, affine, v, unit);
 
-                    v.vector[0] += unit.vector[0];
-                    v.vector[1] += unit.vector[1];
-                    v.vector[2] += unit.vector[2];
-                }
-            }
-        } else {
-            if (pixman_region_n_rects(pict->common.src_clip) == 1) {
-                box = pict->common.src_clip->extents;
-                for (i = 0; i < width; ++i) {
-		    if (!mask || mask[i] & maskBits)
-		    {
-			if (!v.vector[2]) {
-			    *(buffer + i) = 0;
-			} else {
-			    if (!affine) {
-				y = DIV(v.vector[1],v.vector[2]);
-				x = DIV(v.vector[0],v.vector[2]);
-			    } else {
-				y = v.vector[1]>>16;
-				x = v.vector[0]>>16;
-			    }
-			    *(buffer + i) = ((x < box.x1) | (x >= box.x2) | (y < box.y1) | (y >= box.y2)) ?
-				0 : fetch(pict, x, y);
-			}
-		    }
-                    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]) {
-			    *(buffer + i) = 0;
-			} else {
-			    if (!affine) {
-				y = DIV(v.vector[1],v.vector[2]);
-				x = DIV(v.vector[0],v.vector[2]);
-			    } else {
-				y = v.vector[1]>>16;
-				x = v.vector[0]>>16;
-			    }
-			    if (pixman_region_contains_point (pict->common.src_clip, x, y, &box))
-				*(buffer + i) = fetch(pict, x, y);
-			    else
-				*(buffer + i) = 0;
-			}
-		    }
-                    v.vector[0] += unit.vector[0];
-                    v.vector[1] += unit.vector[1];
-                    v.vector[2] += unit.vector[2];
-                }
-            }
+        }
+        else if (pict->common.repeat == PIXMAN_REPEAT_PAD)
+        {
+            fbFetchTransformed_Nearest_Pad(pict, width, buffer, mask, maskBits, affine, v, unit);
+        }
+        else
+        {
+            fbFetchTransformed_Nearest_General(pict, width, buffer, mask, maskBits, affine, v, unit);
         }
     } else if (pict->common.filter == PIXMAN_FILTER_BILINEAR	||
 	       pict->common.filter == PIXMAN_FILTER_GOOD	||
@@ -3830,336 +4241,30 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
         unit.vector[0] -= unit.vector[2] / 2;
         unit.vector[1] -= unit.vector[2] / 2;
 
-        if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) {
-            if (pixman_region_n_rects(pict->common.src_clip) == 1) {
-                for (i = 0; i < width; ++i) {
-                    if (!mask || mask[i] & maskBits)
-		    {
-			if (!v.vector[2]) {
-			    *(buffer + i) = 0;
-			} else {
-			    int x1, x2, y1, y2, distx, idistx, disty, idisty;
-			    uint32_t tl, tr, bl, br, r;
-			    uint32_t ft, fb;
-
-			    if (!affine) {
-				pixman_fixed_48_16_t div;
-				div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
-				x1 = div >> 16;
-				distx = ((pixman_fixed_t)div >> 8) & 0xff;
-				div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
-				y1 = div >> 16;
-				disty = ((pixman_fixed_t)div >> 8) & 0xff;
-			    } else {
-				x1 = v.vector[0] >> 16;
-				distx = (v.vector[0] >> 8) & 0xff;
-				y1 = v.vector[1] >> 16;
-				disty = (v.vector[1] >> 8) & 0xff;
-			    }
-			    x2 = x1 + 1;
-			    y2 = y1 + 1;
-
-			    idistx = 256 - distx;
-			    idisty = 256 - disty;
-
-			    x1 = MOD (x1, pict->width);
-			    x2 = MOD (x2, pict->width);
-			    y1 = MOD (y1, pict->height);
-			    y2 = MOD (y2, pict->height);
-
-			    tl = fetch(pict, x1, y1);
-			    tr = fetch(pict, x2, y1);
-			    bl = fetch(pict, x1, y2);
-			    br = fetch(pict, x2, y2);
-
-			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
-			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
-			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
-			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
-			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
-			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
-			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
-			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
-			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
-			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
-			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
-			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
-			    *(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]) {
-			    *(buffer + i) = 0;
-			} else {
-			    int x1, x2, y1, y2, distx, idistx, disty, idisty;
-			    uint32_t tl, tr, bl, br, r;
-			    uint32_t ft, fb;
-
-			    if (!affine) {
-				pixman_fixed_48_16_t div;
-				div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
-				x1 = div >> 16;
-				distx = ((pixman_fixed_t)div >> 8) & 0xff;
-				div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
-				y1 = div >> 16;
-				disty = ((pixman_fixed_t)div >> 8) & 0xff;
-			    } else {
-				x1 = v.vector[0] >> 16;
-				distx = (v.vector[0] >> 8) & 0xff;
-				y1 = v.vector[1] >> 16;
-				disty = (v.vector[1] >> 8) & 0xff;
-			    }
-			    x2 = x1 + 1;
-			    y2 = y1 + 1;
-
-			    idistx = 256 - distx;
-			    idisty = 256 - disty;
-
-			    x1 = MOD (x1, pict->width);
-			    x2 = MOD (x2, pict->width);
-			    y1 = MOD (y1, pict->height);
-			    y2 = MOD (y2, pict->height);
-
-			    tl = pixman_region_contains_point(pict->common.src_clip, x1, y1, &box)
-				? fetch(pict, x1, y1) : 0;
-			    tr = pixman_region_contains_point(pict->common.src_clip, x2, y1, &box)
-				? fetch(pict, x2, y1) : 0;
-			    bl = pixman_region_contains_point(pict->common.src_clip, x1, y2, &box)
-				? fetch(pict, x1, y2) : 0;
-			    br = pixman_region_contains_point(pict->common.src_clip, x2, y2, &box)
-				? fetch(pict, x2, y2) : 0;
-
-			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
-			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
-			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
-			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
-			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
-			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
-			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
-			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
-			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
-			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
-			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
-			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
-			    *(buffer + i) = r;
-			}
-		    }
-
-                    v.vector[0] += unit.vector[0];
-                    v.vector[1] += unit.vector[1];
-                    v.vector[2] += unit.vector[2];
-                }
-            }
-        } else {
-            if (pixman_region_n_rects(pict->common.src_clip) == 1) {
-                box = pict->common.src_clip->extents;
-                for (i = 0; i < width; ++i) {
-		    if (!mask || mask[i] & maskBits)
-		    {
-			if (!v.vector[2]) {
-			    *(buffer + i) = 0;
-			} else {
-			    int x1, x2, y1, y2, distx, idistx, disty, idisty;
-			    uint32_t tl, tr, bl, br, r;
-			    pixman_bool_t x1_out, x2_out, y1_out, y2_out;
-			    uint32_t ft, fb;
-
-			    if (!affine) {
-				pixman_fixed_48_16_t div;
-				div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
-				x1 = div >> 16;
-				distx = ((pixman_fixed_t)div >> 8) & 0xff;
-				div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
-				y1 = div >> 16;
-				disty = ((pixman_fixed_t)div >> 8) & 0xff;
-			    } else {
-				x1 = v.vector[0] >> 16;
-				distx = (v.vector[0] >> 8) & 0xff;
-				y1 = v.vector[1] >> 16;
-				disty = (v.vector[1] >> 8) & 0xff;
-			    }
-			    x2 = x1 + 1;
-			    y2 = y1 + 1;
-
-			    idistx = 256 - distx;
-			    idisty = 256 - disty;
-
-			    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(pict, x1, y1);
-			    tr = x2_out|y1_out ? 0 : fetch(pict, x2, y1);
-			    bl = x1_out|y2_out ? 0 : fetch(pict, x1, y2);
-			    br = x2_out|y2_out ? 0 : fetch(pict, x2, y2);
-
-			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
-			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
-			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
-			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
-			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
-			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
-			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
-			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
-			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
-			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
-			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
-			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
-			    *(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]) {
-			    *(buffer + i) = 0;
-			} else {
-			    int x1, x2, y1, y2, distx, idistx, disty, idisty;
-			    uint32_t tl, tr, bl, br, r;
-			    uint32_t ft, fb;
-
-			    if (!affine) {
-				pixman_fixed_48_16_t div;
-				div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2];
-				x1 = div >> 16;
-				distx = ((pixman_fixed_t)div >> 8) & 0xff;
-				div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2];
-				y1 = div >> 16;
-				disty = ((pixman_fixed_t)div >> 8) & 0xff;
-			    } else {
-				x1 = v.vector[0] >> 16;
-				distx = (v.vector[0] >> 8) & 0xff;
-				y1 = v.vector[1] >> 16;
-				disty = (v.vector[1] >> 8) & 0xff;
-			    }
-			    x2 = x1 + 1;
-			    y2 = y1 + 1;
-
-			    idistx = 256 - distx;
-			    idisty = 256 - disty;
-
-			    tl = pixman_region_contains_point(pict->common.src_clip, x1, y1, &box)
-				? fetch(pict, x1, y1) : 0;
-			    tr = pixman_region_contains_point(pict->common.src_clip, x2, y1, &box)
-				? fetch(pict, x2, y1) : 0;
-			    bl = pixman_region_contains_point(pict->common.src_clip, x1, y2, &box)
-				? fetch(pict, x1, y2) : 0;
-			    br = pixman_region_contains_point(pict->common.src_clip, x2, y2, &box)
-				? fetch(pict, x2, y2) : 0;
-
-			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
-			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
-			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
-			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
-			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
-			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
-			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
-			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
-			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
-			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
-			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
-			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
-			    *(buffer + i) = r;
-			}
-		    }
-
-                    v.vector[0] += unit.vector[0];
-                    v.vector[1] += unit.vector[1];
-                    v.vector[2] += unit.vector[2];
-                }
-            }
+        if (pict->common.repeat == PIXMAN_REPEAT_NORMAL)
+        {
+            fbFetchTransformed_Bilinear_Normal(pict, width, buffer, mask, maskBits, affine, v, unit);
         }
-    } else if (pict->common.filter == PIXMAN_FILTER_CONVOLUTION) {
-        pixman_fixed_t *params = pict->common.filter_params;
-        int32_t cwidth = pixman_fixed_to_int(params[0]);
-        int32_t cheight = pixman_fixed_to_int(params[1]);
-        int xoff = (params[0] - pixman_fixed_1) >> 1;
-	int yoff = (params[1] - pixman_fixed_1) >> 1;
-        params += 2;
-        for (i = 0; i < width; ++i) {
-	    if (!mask || mask[i] & maskBits)
-	    {
-		if (!v.vector[2]) {
-		    *(buffer + i) = 0;
-		} else {
-		    int x1, x2, y1, y2, x, y;
-		    int32_t srtot, sgtot, sbtot, satot;
-		    pixman_fixed_t *p = params;
-
-		    if (!affine) {
-			pixman_fixed_48_16_t tmp;
-			tmp = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2] - xoff;
-			x1 = pixman_fixed_to_int(tmp);
-			tmp = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2] - yoff;
-			y1 = pixman_fixed_to_int(tmp);
-		    } else {
-			x1 = pixman_fixed_to_int(v.vector[0] - xoff);
-			y1 = pixman_fixed_to_int(v.vector[1] - yoff);
-		    }
-		    x2 = x1 + cwidth;
-		    y2 = y1 + cheight;
-
-		    srtot = sgtot = sbtot = satot = 0;
-
-		    for (y = y1; y < y2; y++) {
-			int ty = (pict->common.repeat == PIXMAN_REPEAT_NORMAL) ? MOD (y, pict->height) : y;
-			for (x = x1; x < x2; x++) {
-			    if (*p) {
-				int tx = (pict->common.repeat == PIXMAN_REPEAT_NORMAL) ? MOD (x, pict->width) : x;
-				if (pixman_region_contains_point (pict->common.src_clip, tx, ty, &box)) {
-				    uint32_t c = fetch(pict, tx, ty);
-
-				    srtot += Red(c) * *p;
-				    sgtot += Green(c) * *p;
-				    sbtot += Blue(c) * *p;
-				    satot += Alpha(c) * *p;
-				}
-			    }
-			    p++;
-			}
-		    }
-
-		    satot >>= 16;
-		    srtot >>= 16;
-		    sgtot >>= 16;
-		    sbtot >>= 16;
-
-		    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;
-
-		    *(buffer + i) = ((satot << 24) |
-				     (srtot << 16) |
-				     (sgtot <<  8) |
-				     (sbtot       ));
-		}
-	    }
-            v.vector[0] += unit.vector[0];
-            v.vector[1] += unit.vector[1];
-            v.vector[2] += unit.vector[2];
+        else if (pict->common.repeat == PIXMAN_REPEAT_PAD)
+        {
+            fbFetchTransformed_Bilinear_Pad(pict, width, buffer, mask, maskBits, affine, v, unit);
         }
+        else
+        {
+            fbFetchTransformed_Bilinear_General(pict, width, buffer, mask, maskBits, affine, v, unit);
+        }
+    }
+    else if (pict->common.filter == PIXMAN_FILTER_CONVOLUTION)
+    {
+        fbFetchTransformed_Convolution(pict, width, buffer, mask, maskBits, affine, v, unit);
     }
 
     fbFinishAccess (pict->pDrawable);
 }
 
 
-static void fbFetchExternalAlpha(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
+static void
+fbFetchExternalAlpha(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits)
 {
     int i;
     uint32_t _alpha_buffer[SCANLINE_BUFFER_LENGTH];
@@ -4191,7 +4296,8 @@ static void fbFetchExternalAlpha(bits_image_t * pict, int x, int y, int width, u
         free(alpha_buffer);
 }
 
-static void fbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buffer)
+static void
+fbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buffer)
 {
     uint32_t *bits;
     int32_t stride;
@@ -4205,7 +4311,8 @@ static void fbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buff
     fbFinishAccess (pict->pDrawable);
 }
 
-static void fbStoreExternalAlpha(bits_image_t * pict, int x, int y, int width, uint32_t *buffer)
+static void
+fbStoreExternalAlpha(bits_image_t * pict, int x, int y, int width, uint32_t *buffer)
 {
     uint32_t *bits, *alpha_bits;
     int32_t stride, astride;
@@ -4284,7 +4391,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
 	{
 	    fetchSrc = (scanFetchProc)fbFetchExternalAlpha;
 	}
-	else if (bits->common.repeat == PIXMAN_REPEAT_NORMAL &&
+	else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&
 		 bits->width == 1 &&
 		 bits->height == 1)
 	{
@@ -4322,7 +4429,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
 	    {
 		fetchMask = (scanFetchProc)fbFetchExternalAlpha;
 	    }
-	    else if (bits->common.repeat == PIXMAN_REPEAT_NORMAL &&
+	    else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&
 		     bits->width == 1 && bits->height == 1)
 	    {
 		fetchMask = (scanFetchProc)fbFetchSolid;
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 7ddb635..10bb8fc 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -600,6 +600,8 @@ union pixman_image
 #define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :		\
 		  ((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
 
+#define CLIP(a,b,c) ((a) < (b) ? (b) : ((a) > (c) ? (c) : (a)))
+
 #if 0
 /* FIXME: the MOD macro above is equivalent, but faster I think */
 #define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
-- 
1.5.3


--45Z9DzgjV8m4Oswq--


More information about the cairo mailing list