pixman: Branch 'master' - 2 commits

Jeff Muizelaar jrmuizel at kemper.freedesktop.org
Mon Nov 24 14:45:06 PST 2008


 pixman/pixman-pict.c |  109 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 108 insertions(+), 1 deletion(-)

New commits:
commit 93d3ca61302ee8d3abc8f820217a885e1ba7e122
Author: Jeff Muizelaar <jmuizelaar at mozilla.com>
Date:   Mon Nov 24 15:11:24 2008 -0500

    Optimize rectilinear nearest-neighbour scaling
    
    Add a special case for a source transformation that is only a scale and
    preserves rectangular pixels and doesn't rotate the image. Currently, only
    SOURCE is special cased, however I plan to do more work in this area as needed.
    The biggest advantage the specialization currently has is writing directly to
    the destination surface instead of a temporary scanline buffer. However, it is
    still pretty unoptimized but I want to keep things simple for now.

diff --git a/pixman/pixman-pict.c b/pixman/pixman-pict.c
index 1388517..42a0454 100644
--- a/pixman/pixman-pict.c
+++ b/pixman/pixman-pict.c
@@ -1208,6 +1208,93 @@ fbCompositeSrc_8888xx888 (pixman_op_t op,
 }
 
 static void
+fbCompositeSrcScaleNearest (pixman_op_t op,
+		      pixman_image_t * pSrc,
+		      pixman_image_t * pMask,
+		      pixman_image_t * pDst,
+		      int16_t      xSrc,
+		      int16_t      ySrc,
+		      int16_t      xMask,
+		      int16_t      yMask,
+		      int16_t      xDst,
+		      int16_t      yDst,
+		      uint16_t     width,
+		      uint16_t     height)
+{
+    uint32_t       *dst;
+    uint32_t       *src;
+    int             dstStride, srcStride;
+    int             i, j;
+    pixman_vector_t v;
+
+    fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dst, 1);
+    /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be
+     * transformed from destination space to source space */
+    fbComposeGetStart (pSrc, 0, 0, uint32_t, srcStride, src, 1);
+
+    /* reference point is the center of the pixel */
+    v.vector[0] = pixman_int_to_fixed(xSrc) + pixman_fixed_1 / 2;
+    v.vector[1] = pixman_int_to_fixed(ySrc) + pixman_fixed_1 / 2;
+    v.vector[2] = pixman_fixed_1;
+
+    if (!pixman_transform_point_3d (pSrc->common.transform, &v))
+        return;
+
+    /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */
+    v.vector[0] -= pixman_fixed_e;
+    v.vector[1] -= pixman_fixed_e;
+
+    for (j = 0; j < height; j++) {
+        pixman_fixed_t vx = v.vector[0];
+        pixman_fixed_t vy = v.vector[1];
+        for (i = 0; i < width; ++i) {
+            pixman_bool_t inside_bounds;
+            uint32_t result;
+            int x, y;
+            x = vx >> 16;
+            y = vy >> 16;
+
+            /* apply the repeat function */
+            switch (pSrc->common.repeat) {
+                case PIXMAN_REPEAT_NORMAL:
+                    x = MOD (x, pSrc->bits.width);
+                    y = MOD (y, pSrc->bits.height);
+                    inside_bounds = TRUE;
+                    break;
+
+                case PIXMAN_REPEAT_PAD:
+                    x = CLIP (x, 0, pSrc->bits.width-1);
+                    y = CLIP (y, 0, pSrc->bits.height-1);
+                    inside_bounds = TRUE;
+                    break;
+
+                case PIXMAN_REPEAT_REFLECT:
+                case PIXMAN_REPEAT_NONE:
+                default:
+                    inside_bounds = (x >= 0 && x < pSrc->bits.width && y >= 0 && y < pSrc->bits.height);
+                    break;
+            }
+
+            if (inside_bounds) {
+                //XXX: we should move this multiplication out of the loop
+                result = READ(pSrc, src + y * srcStride + x);
+            } else {
+                result = 0;
+            }
+            WRITE(pDst, dst + i, result);
+
+            /* adjust the x location by a unit vector in the x direction:
+             * this is equivalent to transforming x+1 of the destination point to source space */
+            vx += pSrc->common.transform->matrix[0][0];
+        }
+        /* adjust the y location by a unit vector in the y direction
+         * this is equivalent to transforming y+1 of the destination point to source space */
+        v.vector[1] += pSrc->common.transform->matrix[1][1];
+        dst += dstStride;
+    }
+}
+
+static void
 pixman_walk_composite_region (pixman_op_t op,
 			      pixman_image_t * pSrc,
 			      pixman_image_t * pMask,
@@ -1854,7 +1941,27 @@ pixman_image_composite (pixman_op_t      op,
     if(op == PIXMAN_OP_DST)
         return;
 
-    if ((pSrc->type == BITS || pixman_image_can_get_solid (pSrc)) && (!pMask || pMask->type == BITS)
+    if (pSrc->type == BITS
+        && srcTransform
+        && !pMask
+        && op == PIXMAN_OP_SRC
+        && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
+        && (pSrc->common.filter == PIXMAN_FILTER_NEAREST)
+        && PIXMAN_FORMAT_BPP(pDst->bits.format) == 32
+        && pSrc->bits.format == pDst->bits.format
+        && pSrc->common.src_clip == &(pSrc->common.full_region)
+        && !pSrc->common.read_func && !pSrc->common.write_func
+        && !pDst->common.read_func && !pDst->common.write_func)
+    {
+        /* ensure that the transform matrix only has a scale */
+        if (pSrc->common.transform->matrix[0][1] == 0 &&
+            pSrc->common.transform->matrix[1][0] == 0 &&
+            pSrc->common.transform->matrix[2][0] == 0 &&
+            pSrc->common.transform->matrix[2][1] == 0 &&
+            pSrc->common.transform->matrix[2][2] == pixman_fixed_1) {
+            func = fbCompositeSrcScaleNearest;
+        }
+    } else if ((pSrc->type == BITS || pixman_image_can_get_solid (pSrc)) && (!pMask || pMask->type == BITS)
         && !srcTransform && !maskTransform
         && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
         && (pSrc->common.filter != PIXMAN_FILTER_CONVOLUTION)
commit 34fcbdf546c2e1c6d390c5fd7e7824bb4681987d
Author: Jeff Muizelaar <jmuizelaar at mozilla.com>
Date:   Mon Nov 24 15:11:01 2008 -0500


More information about the xorg-commit mailing list