Initial fast path implementation
authorSøren Sandmann Pedersen <sandmann@redhat.com>
Wed, 13 May 2009 12:51:09 +0000 (08:51 -0400)
committerSøren Sandmann Pedersen <sandmann@redhat.com>
Sat, 23 May 2009 16:05:01 +0000 (12:05 -0400)
Move fbSrcScaleNearest() here, and move
_pixman_walk_composite_region() to pixman-utils.c

pixman/pixman-fast-path.c
pixman/pixman-general.c
pixman/pixman-mmx.c
pixman/pixman-pict.c
pixman/pixman-private.h
pixman/pixman-utils.c

index 62a39d1..8025233 100644 (file)
@@ -1071,3 +1071,165 @@ static const FastPathInfo c_fast_path_array[] =
 };
 
 const FastPathInfo *const c_fast_paths = c_fast_path_array;
+
+static void
+fbCompositeSrcScaleNearest (pixman_implementation_t *imp,
+                           pixman_op_t     op,
+                           pixman_image_t *pSrc,
+                           pixman_image_t *pMask,
+                           pixman_image_t *pDst,
+                           int32_t         xSrc,
+                           int32_t         ySrc,
+                           int32_t         xMask,
+                           int32_t         yMask,
+                           int32_t         xDst,
+                           int32_t         yDst,
+                           int32_t        width,
+                           int32_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:
+               x = MOD (x, pSrc->bits.width * 2);
+               if (x >= pSrc->bits.width)
+                   x = pSrc->bits.width * 2 - x - 1;
+               y = MOD (y, pSrc->bits.height * 2);
+               if (y >= pSrc->bits.height)
+                   y = pSrc->bits.height * 2 - y - 1;
+               inside_bounds = TRUE;
+               break;
+               
+           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
+fast_path_composite (pixman_implementation_t *imp,
+                    pixman_op_t     op,
+                    pixman_image_t *src,
+                    pixman_image_t *mask,
+                    pixman_image_t *dest,
+                    int32_t         src_x,
+                    int32_t         src_y,
+                    int32_t         mask_x,
+                    int32_t         mask_y,
+                    int32_t         dest_x,
+                    int32_t         dest_y,
+                    int32_t        width,
+                    int32_t        height)
+{
+    if (src->type == BITS
+        && src->common.transform
+        && !mask
+        && op == PIXMAN_OP_SRC
+        && !src->common.alpha_map && !dest->common.alpha_map
+        && (src->common.filter == PIXMAN_FILTER_NEAREST)
+        && PIXMAN_FORMAT_BPP(dest->bits.format) == 32
+        && src->bits.format == dest->bits.format
+        && src->common.src_clip == &(src->common.full_region)
+        && !src->common.read_func && !src->common.write_func
+        && !dest->common.read_func && !dest->common.write_func)
+    {
+        /* ensure that the transform matrix only has a scale */
+        if (src->common.transform->matrix[0][1] == 0 &&
+            src->common.transform->matrix[1][0] == 0 &&
+            src->common.transform->matrix[2][0] == 0 &&
+            src->common.transform->matrix[2][1] == 0 &&
+            src->common.transform->matrix[2][2] == pixman_fixed_1)
+       {
+           _pixman_walk_composite_region (imp, op,
+                                          src, mask, dest,
+                                          src_x, src_y,
+                                          mask_x, mask_y,
+                                          dest_x, dest_y,
+                                          width, height,
+                                          FALSE, FALSE, 
+                                          fbCompositeSrcScaleNearest);
+           return;
+       }
+    }
+
+    _pixman_implementation_composite (imp->delegate, op,
+                                     src, mask, dest,
+                                     src_x, src_y,
+                                     mask_x, mask_y,
+                                     dest_x, dest_y,
+                                     width, height);
+}
+
+pixman_implementation_t *
+_pixman_implementation_create_fast_path (pixman_implementation_t *toplevel)
+{
+    pixman_implementation_t *general = _pixman_implementation_create_general (NULL);
+    pixman_implementation_t *imp = _pixman_implementation_create (toplevel, general);
+
+    imp->composite = fast_path_composite;
+    
+    return imp;
+}
index 734dfce..f507aad 100644 (file)
@@ -318,197 +318,6 @@ general_composite_rect (const FbComposeData *data)
 #include "pixman-combine32.h"
 
 static void
-fbCompositeSrcScaleNearest (pixman_implementation_t *imp,
-                           pixman_op_t     op,
-                           pixman_image_t *pSrc,
-                           pixman_image_t *pMask,
-                           pixman_image_t *pDst,
-                           int32_t         xSrc,
-                           int32_t         ySrc,
-                           int32_t         xMask,
-                           int32_t         yMask,
-                           int32_t         xDst,
-                           int32_t         yDst,
-                           int32_t        width,
-                           int32_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:
-                   x = MOD (x, pSrc->bits.width * 2);
-                   if (x >= pSrc->bits.width)
-                           x = pSrc->bits.width * 2 - x - 1;
-                   y = MOD (y, pSrc->bits.height * 2);
-                   if (y >= pSrc->bits.height)
-                           y = pSrc->bits.height * 2 - y - 1;
-                   inside_bounds = TRUE;
-                   break;
-
-                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_implementation_t *imp,
-                             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,
-                             pixman_bool_t srcRepeat,
-                             pixman_bool_t maskRepeat,
-                             pixman_composite_func_t compositeRect)
-{
-    int                    n;
-    const pixman_box32_t *pbox;
-    int                    w, h, w_this, h_this;
-    int                    x_msk, y_msk, x_src, y_src, x_dst, y_dst;
-    pixman_region32_t reg;
-    pixman_region32_t *region;
-
-    pixman_region32_init (&reg);
-    if (!pixman_compute_composite_region32 (&reg, pSrc, pMask, pDst,
-                                           xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
-    {
-       return;
-    }
-
-    region = &reg;
-
-    pbox = pixman_region32_rectangles (region, &n);
-    while (n--)
-    {
-       h = pbox->y2 - pbox->y1;
-       y_src = pbox->y1 - yDst + ySrc;
-       y_msk = pbox->y1 - yDst + yMask;
-       y_dst = pbox->y1;
-       while (h)
-       {
-           h_this = h;
-           w = pbox->x2 - pbox->x1;
-           x_src = pbox->x1 - xDst + xSrc;
-           x_msk = pbox->x1 - xDst + xMask;
-           x_dst = pbox->x1;
-           if (maskRepeat)
-           {
-               y_msk = MOD (y_msk, pMask->bits.height);
-               if (h_this > pMask->bits.height - y_msk)
-                   h_this = pMask->bits.height - y_msk;
-           }
-           if (srcRepeat)
-           {
-               y_src = MOD (y_src, pSrc->bits.height);
-               if (h_this > pSrc->bits.height - y_src)
-                   h_this = pSrc->bits.height - y_src;
-           }
-           while (w)
-           {
-               w_this = w;
-               if (maskRepeat)
-               {
-                   x_msk = MOD (x_msk, pMask->bits.width);
-                   if (w_this > pMask->bits.width - x_msk)
-                       w_this = pMask->bits.width - x_msk;
-               }
-               if (srcRepeat)
-               {
-                   x_src = MOD (x_src, pSrc->bits.width);
-                   if (w_this > pSrc->bits.width - x_src)
-                       w_this = pSrc->bits.width - x_src;
-               }
-               (*compositeRect) (imp,
-                                 op, pSrc, pMask, pDst,
-                                 x_src, y_src, x_msk, y_msk, x_dst, y_dst,
-                                 w_this, h_this);
-               w -= w_this;
-               x_src += w_this;
-               x_msk += w_this;
-               x_dst += w_this;
-           }
-           h -= h_this;
-           y_src += h_this;
-           y_msk += h_this;
-           y_dst += h_this;
-       }
-       pbox++;
-    }
-    pixman_region32_fini (&reg);
-}
-
-static void
 pixman_image_composite_rect  (pixman_implementation_t *imp,
                              pixman_op_t                   op,
                              pixman_image_t               *src,
@@ -702,29 +511,7 @@ general_composite (pixman_implementation_t *       imp,
        }
     }
 
-    if (src->type == BITS
-        && srcTransform
-        && !mask
-        && op == PIXMAN_OP_SRC
-        && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
-        && (src->common.filter == PIXMAN_FILTER_NEAREST)
-        && PIXMAN_FORMAT_BPP(dest->bits.format) == 32
-        && src->bits.format == dest->bits.format
-        && src->common.src_clip == &(src->common.full_region)
-        && !src->common.read_func && !src->common.write_func
-        && !dest->common.read_func && !dest->common.write_func)
-    {
-        /* ensure that the transform matrix only has a scale */
-        if (src->common.transform->matrix[0][1] == 0 &&
-            src->common.transform->matrix[1][0] == 0 &&
-            src->common.transform->matrix[2][0] == 0 &&
-            src->common.transform->matrix[2][1] == 0 &&
-            src->common.transform->matrix[2][2] == pixman_fixed_1) {
-            func = fbCompositeSrcScaleNearest;
-            /* Like the general path, fbCompositeSrcScaleNearest handles all the repeat types itself */
-            srcRepeat = FALSE;
-        }
-    } else if ((src->type == BITS || pixman_image_can_get_solid (src)) && (!mask || mask->type == BITS)
+    if ((src->type == BITS || pixman_image_can_get_solid (src)) && (!mask || mask->type == BITS)
         && !srcTransform && !maskTransform
         && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
         && (src->common.filter != PIXMAN_FILTER_CONVOLUTION)
@@ -836,7 +623,7 @@ general_composite (pixman_implementation_t *        imp,
            maskRepeat = FALSE;
     }
 
-    pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y,
+    _pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y,
                                  mask_x, mask_y, dest_x, dest_y, width, height,
                                  srcRepeat, maskRepeat, func);
 }
index 05b0a9c..8f18b06 100644 (file)
@@ -3143,7 +3143,7 @@ const FastPathInfo *const mmx_fast_paths = mmx_fast_path_array;
 pixman_implementation_t *
 _pixman_implementation_create_mmx (pixman_implementation_t *toplevel)
 {
-    pixman_implementation_t *general = _pixman_implementation_create_general (NULL);
+    pixman_implementation_t *general = _pixman_implementation_create_fast_path (NULL);
     pixman_implementation_t *imp = _pixman_implementation_create (toplevel, general);
 
     /* check if we have MMX support and initialize accordingly */
index a76ce21..18ec4f8 100644 (file)
@@ -127,7 +127,7 @@ pixman_image_composite (pixman_op_t      op,
         return;
 
     if (!imp)
-       imp = _pixman_implementation_create_general (NULL);
+       imp = _pixman_implementation_create_fast_path (NULL);
 
     _pixman_implementation_composite (imp, op,
                                      src, mask, dest,
index e660be6..a8c6ce4 100644 (file)
@@ -896,6 +896,24 @@ typedef void (* pixman_composite_func_t)  (pixman_implementation_t *       imp,
                                           int32_t                      width,
                                           int32_t                      height);
 
+void
+_pixman_walk_composite_region (pixman_implementation_t *imp,
+                             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,
+                             pixman_bool_t srcRepeat,
+                             pixman_bool_t maskRepeat,
+                              pixman_composite_func_t compositeRect);
+
 /* These "formats" both have depth 0, so they
  * will never clash with any real ones
  */
@@ -981,6 +999,8 @@ _pixman_implementation_composite (pixman_implementation_t * imp,
 /* Specific implementations */
 pixman_implementation_t *
 _pixman_implementation_create_general (pixman_implementation_t *toplevel);
+pixman_implementation_t *
+_pixman_implementation_create_fast_path (pixman_implementation_t *toplevel);
 #ifdef USE_MMX
 pixman_implementation_t *
 _pixman_implementation_create_mmx (pixman_implementation_t *toplevel);
index cdf0220..e445c3c 100644 (file)
@@ -593,3 +593,98 @@ pixman_format_supported_source (pixman_format_code_t format)
        return FALSE;
     }
 }
+
+void
+_pixman_walk_composite_region (pixman_implementation_t *imp,
+                             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,
+                             pixman_bool_t srcRepeat,
+                             pixman_bool_t maskRepeat,
+                             pixman_composite_func_t compositeRect)
+{
+    int                    n;
+    const pixman_box32_t *pbox;
+    int                    w, h, w_this, h_this;
+    int                    x_msk, y_msk, x_src, y_src, x_dst, y_dst;
+    pixman_region32_t reg;
+    pixman_region32_t *region;
+
+    pixman_region32_init (&reg);
+    if (!pixman_compute_composite_region32 (&reg, pSrc, pMask, pDst,
+                                           xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
+    {
+       return;
+    }
+
+    region = &reg;
+
+    pbox = pixman_region32_rectangles (region, &n);
+    while (n--)
+    {
+       h = pbox->y2 - pbox->y1;
+       y_src = pbox->y1 - yDst + ySrc;
+       y_msk = pbox->y1 - yDst + yMask;
+       y_dst = pbox->y1;
+       while (h)
+       {
+           h_this = h;
+           w = pbox->x2 - pbox->x1;
+           x_src = pbox->x1 - xDst + xSrc;
+           x_msk = pbox->x1 - xDst + xMask;
+           x_dst = pbox->x1;
+           if (maskRepeat)
+           {
+               y_msk = MOD (y_msk, pMask->bits.height);
+               if (h_this > pMask->bits.height - y_msk)
+                   h_this = pMask->bits.height - y_msk;
+           }
+           if (srcRepeat)
+           {
+               y_src = MOD (y_src, pSrc->bits.height);
+               if (h_this > pSrc->bits.height - y_src)
+                   h_this = pSrc->bits.height - y_src;
+           }
+           while (w)
+           {
+               w_this = w;
+               if (maskRepeat)
+               {
+                   x_msk = MOD (x_msk, pMask->bits.width);
+                   if (w_this > pMask->bits.width - x_msk)
+                       w_this = pMask->bits.width - x_msk;
+               }
+               if (srcRepeat)
+               {
+                   x_src = MOD (x_src, pSrc->bits.width);
+                   if (w_this > pSrc->bits.width - x_src)
+                       w_this = pSrc->bits.width - x_src;
+               }
+               (*compositeRect) (imp,
+                                 op, pSrc, pMask, pDst,
+                                 x_src, y_src, x_msk, y_msk, x_dst, y_dst,
+                                 w_this, h_this);
+               w -= w_this;
+               x_src += w_this;
+               x_msk += w_this;
+               x_dst += w_this;
+           }
+           h -= h_this;
+           y_src += h_this;
+           y_msk += h_this;
+           y_dst += h_this;
+       }
+       pbox++;
+    }
+    pixman_region32_fini (&reg);
+}
+