From: Søren Sandmann Pedersen <s...@redhat.com>

The generated fetchers for NEAREST, BILINEAR, and
SEPARABLE_CONVOLUTION filters are fast paths and so they belong in
pixman-fast-path.c
---
 pixman/pixman-bits-image.c |  530 --------------------------------------------
 pixman/pixman-fast-path.c  |  530 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 530 insertions(+), 530 deletions(-)

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 35247f9..f9121a3 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -505,472 +505,6 @@ bits_image_fetch_general (pixman_iter_t  *iter,
     return buffer;
 }
 
-typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
-
-static force_inline void
-bits_image_fetch_separable_convolution_affine (pixman_image_t * image,
-                                              int              offset,
-                                              int              line,
-                                              int              width,
-                                              uint32_t *       buffer,
-                                              const uint32_t * mask,
-
-                                              convert_pixel_t  convert_pixel,
-                                              pixman_format_code_t     format,
-                                              pixman_repeat_t  repeat_mode)
-{
-    bits_image_t *bits = &image->bits;
-    pixman_fixed_t *params = image->common.filter_params;
-    int cwidth = pixman_fixed_to_int (params[0]);
-    int cheight = pixman_fixed_to_int (params[1]);
-    int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
-    int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
-    int x_phase_bits = pixman_fixed_to_int (params[2]);
-    int y_phase_bits = pixman_fixed_to_int (params[3]);
-    int x_phase_shift = 16 - x_phase_bits;
-    int y_phase_shift = 16 - y_phase_bits;
-    pixman_fixed_t vx, vy;
-    pixman_fixed_t ux, uy;
-    pixman_vector_t v;
-    int k;
-
-    /* reference point is the center of the pixel */
-    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
-    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
-    v.vector[2] = pixman_fixed_1;
-
-    if (!pixman_transform_point_3d (image->common.transform, &v))
-       return;
-
-    ux = image->common.transform->matrix[0][0];
-    uy = image->common.transform->matrix[1][0];
-
-    vx = v.vector[0];
-    vy = v.vector[1];
-
-    for (k = 0; k < width; ++k)
-    {
-       pixman_fixed_t *y_params;
-       int satot, srtot, sgtot, sbtot;
-       pixman_fixed_t x, y;
-       int32_t x1, x2, y1, y2;
-       int32_t px, py;
-       int i, j;
-
-       if (mask && !mask[k])
-           goto next;
-
-       /* Round x and y to the middle of the closest phase before continuing. 
This
-        * ensures that the convolution matrix is aligned right, since it was
-        * positioned relative to a particular phase (and not relative to 
whatever
-        * exact fraction we happen to get here).
-        */
-       x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 
1);
-       y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 
1);
-
-       px = (x & 0xffff) >> x_phase_shift;
-       py = (y & 0xffff) >> y_phase_shift;
-
-       x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
-       y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
-       x2 = x1 + cwidth;
-       y2 = y1 + cheight;
-
-       satot = srtot = sgtot = sbtot = 0;
-
-       y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
-
-       for (i = y1; i < y2; ++i)
-       {
-           pixman_fixed_t fy = *y_params++;
-
-           if (fy)
-           {
-               pixman_fixed_t *x_params = params + 4 + px * cwidth;
-
-               for (j = x1; j < x2; ++j)
-               {
-                   pixman_fixed_t fx = *x_params++;
-                   int rx = j;
-                   int ry = i;
-                   
-                   if (fx)
-                   {
-                       pixman_fixed_t f;
-                       uint32_t pixel, mask;
-                       uint8_t *row;
-
-                       mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
-
-                       if (repeat_mode != PIXMAN_REPEAT_NONE)
-                       {
-                           repeat (repeat_mode, &rx, bits->width);
-                           repeat (repeat_mode, &ry, bits->height);
-
-                           row = (uint8_t *)bits->bits + bits->rowstride * 4 * 
ry;
-                           pixel = convert_pixel (row, rx) | mask;
-                       }
-                       else
-                       {
-                           if (rx < 0 || ry < 0 || rx >= bits->width || ry >= 
bits->height)
-                           {
-                               pixel = 0;
-                           }
-                           else
-                           {
-                               row = (uint8_t *)bits->bits + bits->rowstride * 
4 * ry;
-                               pixel = convert_pixel (row, rx) | mask;
-                           }
-                       }
-
-                       f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16;
-                       srtot += (int)RED_8 (pixel) * f;
-                       sgtot += (int)GREEN_8 (pixel) * f;
-                       sbtot += (int)BLUE_8 (pixel) * f;
-                       satot += (int)ALPHA_8 (pixel) * f;
-                   }
-               }
-           }
-       }
-
-       satot = (satot + 0x8000) >> 16;
-       srtot = (srtot + 0x8000) >> 16;
-       sgtot = (sgtot + 0x8000) >> 16;
-       sbtot = (sbtot + 0x8000) >> 16;
-
-       satot = CLIP (satot, 0, 0xff);
-       srtot = CLIP (srtot, 0, 0xff);
-       sgtot = CLIP (sgtot, 0, 0xff);
-       sbtot = CLIP (sbtot, 0, 0xff);
-
-       buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
-
-    next:
-       vx += ux;
-       vy += uy;
-    }
-}
-
-static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
-static force_inline void
-bits_image_fetch_bilinear_affine (pixman_image_t * image,
-                                 int              offset,
-                                 int              line,
-                                 int              width,
-                                 uint32_t *       buffer,
-                                 const uint32_t * mask,
-
-                                 convert_pixel_t       convert_pixel,
-                                 pixman_format_code_t  format,
-                                 pixman_repeat_t       repeat_mode)
-{
-    pixman_fixed_t x, y;
-    pixman_fixed_t ux, uy;
-    pixman_vector_t v;
-    bits_image_t *bits = &image->bits;
-    int i;
-
-    /* reference point is the center of the pixel */
-    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
-    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
-    v.vector[2] = pixman_fixed_1;
-
-    if (!pixman_transform_point_3d (image->common.transform, &v))
-       return;
-
-    ux = image->common.transform->matrix[0][0];
-    uy = image->common.transform->matrix[1][0];
-
-    x = v.vector[0];
-    y = v.vector[1];
-
-    for (i = 0; i < width; ++i)
-    {
-       int x1, y1, x2, y2;
-       uint32_t tl, tr, bl, br;
-       int32_t distx, disty;
-       int width = image->bits.width;
-       int height = image->bits.height;
-       const uint8_t *row1;
-       const uint8_t *row2;
-
-       if (mask && !mask[i])
-           goto next;
-
-       x1 = x - pixman_fixed_1 / 2;
-       y1 = y - pixman_fixed_1 / 2;
-
-       distx = pixman_fixed_to_bilinear_weight (x1);
-       disty = pixman_fixed_to_bilinear_weight (y1);
-
-       y1 = pixman_fixed_to_int (y1);
-       y2 = y1 + 1;
-       x1 = pixman_fixed_to_int (x1);
-       x2 = x1 + 1;
-
-       if (repeat_mode != PIXMAN_REPEAT_NONE)
-       {
-           uint32_t mask;
-
-           mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
-
-           repeat (repeat_mode, &x1, width);
-           repeat (repeat_mode, &y1, height);
-           repeat (repeat_mode, &x2, width);
-           repeat (repeat_mode, &y2, height);
-
-           row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
-           row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
-
-           tl = convert_pixel (row1, x1) | mask;
-           tr = convert_pixel (row1, x2) | mask;
-           bl = convert_pixel (row2, x1) | mask;
-           br = convert_pixel (row2, x2) | mask;
-       }
-       else
-       {
-           uint32_t mask1, mask2;
-           int bpp;
-
-           /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
-            * which means if you use it in expressions, those
-            * expressions become unsigned themselves. Since
-            * the variables below can be negative in some cases,
-            * that will lead to crashes on 64 bit architectures.
-            *
-            * So this line makes sure bpp is signed
-            */
-           bpp = PIXMAN_FORMAT_BPP (format);
-
-           if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
-           {
-               buffer[i] = 0;
-               goto next;
-           }
-
-           if (y2 == 0)
-           {
-               row1 = zero;
-               mask1 = 0;
-           }
-           else
-           {
-               row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
-               row1 += bpp / 8 * x1;
-
-               mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
-           }
-
-           if (y1 == height - 1)
-           {
-               row2 = zero;
-               mask2 = 0;
-           }
-           else
-           {
-               row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
-               row2 += bpp / 8 * x1;
-
-               mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
-           }
-
-           if (x2 == 0)
-           {
-               tl = 0;
-               bl = 0;
-           }
-           else
-           {
-               tl = convert_pixel (row1, 0) | mask1;
-               bl = convert_pixel (row2, 0) | mask2;
-           }
-
-           if (x1 == width - 1)
-           {
-               tr = 0;
-               br = 0;
-           }
-           else
-           {
-               tr = convert_pixel (row1, 1) | mask1;
-               br = convert_pixel (row2, 1) | mask2;
-           }
-       }
-
-       buffer[i] = bilinear_interpolation (
-           tl, tr, bl, br, distx, disty);
-
-    next:
-       x += ux;
-       y += uy;
-    }
-}
-
-static force_inline void
-bits_image_fetch_nearest_affine (pixman_image_t * image,
-                                int              offset,
-                                int              line,
-                                int              width,
-                                uint32_t *       buffer,
-                                const uint32_t * mask,
-                                
-                                convert_pixel_t        convert_pixel,
-                                pixman_format_code_t   format,
-                                pixman_repeat_t        repeat_mode)
-{
-    pixman_fixed_t x, y;
-    pixman_fixed_t ux, uy;
-    pixman_vector_t v;
-    bits_image_t *bits = &image->bits;
-    int i;
-
-    /* reference point is the center of the pixel */
-    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
-    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
-    v.vector[2] = pixman_fixed_1;
-
-    if (!pixman_transform_point_3d (image->common.transform, &v))
-       return;
-
-    ux = image->common.transform->matrix[0][0];
-    uy = image->common.transform->matrix[1][0];
-
-    x = v.vector[0];
-    y = v.vector[1];
-
-    for (i = 0; i < width; ++i)
-    {
-       int width, height, x0, y0;
-       const uint8_t *row;
-
-       if (mask && !mask[i])
-           goto next;
-       
-       width = image->bits.width;
-       height = image->bits.height;
-       x0 = pixman_fixed_to_int (x - pixman_fixed_e);
-       y0 = pixman_fixed_to_int (y - pixman_fixed_e);
-
-       if (repeat_mode == PIXMAN_REPEAT_NONE &&
-           (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
-       {
-           buffer[i] = 0;
-       }
-       else
-       {
-           uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
-
-           if (repeat_mode != PIXMAN_REPEAT_NONE)
-           {
-               repeat (repeat_mode, &x0, width);
-               repeat (repeat_mode, &y0, height);
-           }
-
-           row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
-
-           buffer[i] = convert_pixel (row, x0) | mask;
-       }
-
-    next:
-       x += ux;
-       y += uy;
-    }
-}
-
-static force_inline uint32_t
-convert_a8r8g8b8 (const uint8_t *row, int x)
-{
-    return *(((uint32_t *)row) + x);
-}
-
-static force_inline uint32_t
-convert_x8r8g8b8 (const uint8_t *row, int x)
-{
-    return *(((uint32_t *)row) + x);
-}
-
-static force_inline uint32_t
-convert_a8 (const uint8_t *row, int x)
-{
-    return *(row + x) << 24;
-}
-
-static force_inline uint32_t
-convert_r5g6b5 (const uint8_t *row, int x)
-{
-    return convert_0565_to_0888 (*((uint16_t *)row + x));
-}
-
-#define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode)  \
-    static uint32_t *                                                  \
-    bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t   
*iter, \
-                                                           const uint32_t * 
mask) \
-    {                                                                  \
-       bits_image_fetch_separable_convolution_affine (                 \
-           iter->image,                                                \
-           iter->x, iter->y++,                                         \
-           iter->width,                                                \
-           iter->buffer, mask,                                         \
-           convert_ ## format,                                         \
-           PIXMAN_ ## format,                                          \
-           repeat_mode);                                               \
-                                                                       \
-       return iter->buffer;                                            \
-    }
-
-#define MAKE_BILINEAR_FETCHER(name, format, repeat_mode)               \
-    static uint32_t *                                                  \
-    bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t   *iter,  \
-                                              const uint32_t * mask)   \
-    {                                                                  \
-       bits_image_fetch_bilinear_affine (iter->image,                  \
-                                         iter->x, iter->y++,           \
-                                         iter->width,                  \
-                                         iter->buffer, mask,           \
-                                         convert_ ## format,           \
-                                         PIXMAN_ ## format,            \
-                                         repeat_mode);                 \
-       return iter->buffer;                                            \
-    }
-
-#define MAKE_NEAREST_FETCHER(name, format, repeat_mode)                        
\
-    static uint32_t *                                                  \
-    bits_image_fetch_nearest_affine_ ## name (pixman_iter_t   *iter,   \
-                                             const uint32_t * mask)    \
-    {                                                                  \
-       bits_image_fetch_nearest_affine (iter->image,                   \
-                                        iter->x, iter->y++,            \
-                                        iter->width,                   \
-                                        iter->buffer, mask,            \
-                                        convert_ ## format,            \
-                                        PIXMAN_ ## format,             \
-                                        repeat_mode);                  \
-       return iter->buffer;                                            \
-    }
-
-#define MAKE_FETCHERS(name, format, repeat_mode)                       \
-    MAKE_NEAREST_FETCHER (name, format, repeat_mode)                   \
-    MAKE_BILINEAR_FETCHER (name, format, repeat_mode)                  \
-    MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode)
-
-MAKE_FETCHERS (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD)
-MAKE_FETCHERS (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE)
-MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
-MAKE_FETCHERS (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL)
-MAKE_FETCHERS (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD)
-MAKE_FETCHERS (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE)
-MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
-MAKE_FETCHERS (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL)
-MAKE_FETCHERS (pad_a8,           a8,       PIXMAN_REPEAT_PAD)
-MAKE_FETCHERS (none_a8,          a8,       PIXMAN_REPEAT_NONE)
-MAKE_FETCHERS (reflect_a8,      a8,       PIXMAN_REPEAT_REFLECT)
-MAKE_FETCHERS (normal_a8,       a8,       PIXMAN_REPEAT_NORMAL)
-MAKE_FETCHERS (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD)
-MAKE_FETCHERS (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE)
-MAKE_FETCHERS (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT)
-MAKE_FETCHERS (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL)
-
 static void
 replicate_pixel_32 (bits_image_t *   bits,
                    int              x,
@@ -1166,70 +700,6 @@ static const fetcher_info_t fetcher_info[] =
       bits_image_fetch_untransformed_float
     },
 
-#define GENERAL_BILINEAR_FLAGS                                         \
-    (FAST_PATH_NO_ALPHA_MAP            |                               \
-     FAST_PATH_NO_ACCESSORS            |                               \
-     FAST_PATH_HAS_TRANSFORM           |                               \
-     FAST_PATH_AFFINE_TRANSFORM                |                               
\
-     FAST_PATH_BILINEAR_FILTER)
-
-#define GENERAL_NEAREST_FLAGS                                          \
-    (FAST_PATH_NO_ALPHA_MAP            |                               \
-     FAST_PATH_NO_ACCESSORS            |                               \
-     FAST_PATH_HAS_TRANSFORM           |                               \
-     FAST_PATH_AFFINE_TRANSFORM                |                               
\
-     FAST_PATH_NEAREST_FILTER)
-
-#define GENERAL_SEPARABLE_CONVOLUTION_FLAGS                            \
-    (FAST_PATH_NO_ALPHA_MAP            |                               \
-     FAST_PATH_NO_ACCESSORS            |                               \
-     FAST_PATH_HAS_TRANSFORM           |                               \
-     FAST_PATH_AFFINE_TRANSFORM        |                               \
-     FAST_PATH_SEPARABLE_CONVOLUTION_FILTER)
-    
-#define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat)   \
-    { PIXMAN_ ## format,                                               \
-      GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
-      bits_image_fetch_separable_convolution_affine_ ## name,          \
-      _pixman_image_get_scanline_generic_float                        \
-    },
-
-#define BILINEAR_AFFINE_FAST_PATH(name, format, repeat)                        
\
-    { PIXMAN_ ## format,                                               \
-      GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,                
\
-      bits_image_fetch_bilinear_affine_ ## name,                       \
-      _pixman_image_get_scanline_generic_float                         \
-    },
-
-#define NEAREST_AFFINE_FAST_PATH(name, format, repeat)                 \
-    { PIXMAN_ ## format,                                               \
-      GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,         \
-      bits_image_fetch_nearest_affine_ ## name,                                
\
-      _pixman_image_get_scanline_generic_float                         \
-    },
-
-#define AFFINE_FAST_PATHS(name, format, repeat)                                
\
-    SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat)       \
-    BILINEAR_AFFINE_FAST_PATH(name, format, repeat)                    \
-    NEAREST_AFFINE_FAST_PATH(name, format, repeat)
-    
-    AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
-    AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
-    AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
-    AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL)
-    AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD)
-    AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE)
-    AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
-    AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL)
-    AFFINE_FAST_PATHS (pad_a8, a8, PAD)
-    AFFINE_FAST_PATHS (none_a8, a8, NONE)
-    AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT)
-    AFFINE_FAST_PATHS (normal_a8, a8, NORMAL)
-    AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD)
-    AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE)
-    AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT)
-    AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL)
-
     /* Affine, no alpha */
     { PIXMAN_any,
       (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | 
FAST_PATH_AFFINE_TRANSFORM),
diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c
index 1624cc3..b06d1b2 100644
--- a/pixman/pixman-fast-path.c
+++ b/pixman/pixman-fast-path.c
@@ -2696,6 +2696,472 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t 
*iter,
     return iter->buffer;
 }
 
+typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
+
+static force_inline void
+bits_image_fetch_separable_convolution_affine (pixman_image_t * image,
+                                              int              offset,
+                                              int              line,
+                                              int              width,
+                                              uint32_t *       buffer,
+                                              const uint32_t * mask,
+
+                                              convert_pixel_t  convert_pixel,
+                                              pixman_format_code_t     format,
+                                              pixman_repeat_t  repeat_mode)
+{
+    bits_image_t *bits = &image->bits;
+    pixman_fixed_t *params = image->common.filter_params;
+    int cwidth = pixman_fixed_to_int (params[0]);
+    int cheight = pixman_fixed_to_int (params[1]);
+    int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
+    int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
+    int x_phase_bits = pixman_fixed_to_int (params[2]);
+    int y_phase_bits = pixman_fixed_to_int (params[3]);
+    int x_phase_shift = 16 - x_phase_bits;
+    int y_phase_shift = 16 - y_phase_bits;
+    pixman_fixed_t vx, vy;
+    pixman_fixed_t ux, uy;
+    pixman_vector_t v;
+    int k;
+
+    /* reference point is the center of the pixel */
+    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
+    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
+    v.vector[2] = pixman_fixed_1;
+
+    if (!pixman_transform_point_3d (image->common.transform, &v))
+       return;
+
+    ux = image->common.transform->matrix[0][0];
+    uy = image->common.transform->matrix[1][0];
+
+    vx = v.vector[0];
+    vy = v.vector[1];
+
+    for (k = 0; k < width; ++k)
+    {
+       pixman_fixed_t *y_params;
+       int satot, srtot, sgtot, sbtot;
+       pixman_fixed_t x, y;
+       int32_t x1, x2, y1, y2;
+       int32_t px, py;
+       int i, j;
+
+       if (mask && !mask[k])
+           goto next;
+
+       /* Round x and y to the middle of the closest phase before continuing. 
This
+        * ensures that the convolution matrix is aligned right, since it was
+        * positioned relative to a particular phase (and not relative to 
whatever
+        * exact fraction we happen to get here).
+        */
+       x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 
1);
+       y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 
1);
+
+       px = (x & 0xffff) >> x_phase_shift;
+       py = (y & 0xffff) >> y_phase_shift;
+
+       x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
+       y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
+       x2 = x1 + cwidth;
+       y2 = y1 + cheight;
+
+       satot = srtot = sgtot = sbtot = 0;
+
+       y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
+
+       for (i = y1; i < y2; ++i)
+       {
+           pixman_fixed_t fy = *y_params++;
+
+           if (fy)
+           {
+               pixman_fixed_t *x_params = params + 4 + px * cwidth;
+
+               for (j = x1; j < x2; ++j)
+               {
+                   pixman_fixed_t fx = *x_params++;
+                   int rx = j;
+                   int ry = i;
+                   
+                   if (fx)
+                   {
+                       pixman_fixed_t f;
+                       uint32_t pixel, mask;
+                       uint8_t *row;
+
+                       mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
+
+                       if (repeat_mode != PIXMAN_REPEAT_NONE)
+                       {
+                           repeat (repeat_mode, &rx, bits->width);
+                           repeat (repeat_mode, &ry, bits->height);
+
+                           row = (uint8_t *)bits->bits + bits->rowstride * 4 * 
ry;
+                           pixel = convert_pixel (row, rx) | mask;
+                       }
+                       else
+                       {
+                           if (rx < 0 || ry < 0 || rx >= bits->width || ry >= 
bits->height)
+                           {
+                               pixel = 0;
+                           }
+                           else
+                           {
+                               row = (uint8_t *)bits->bits + bits->rowstride * 
4 * ry;
+                               pixel = convert_pixel (row, rx) | mask;
+                           }
+                       }
+
+                       f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16;
+                       srtot += (int)RED_8 (pixel) * f;
+                       sgtot += (int)GREEN_8 (pixel) * f;
+                       sbtot += (int)BLUE_8 (pixel) * f;
+                       satot += (int)ALPHA_8 (pixel) * f;
+                   }
+               }
+           }
+       }
+
+       satot = (satot + 0x8000) >> 16;
+       srtot = (srtot + 0x8000) >> 16;
+       sgtot = (sgtot + 0x8000) >> 16;
+       sbtot = (sbtot + 0x8000) >> 16;
+
+       satot = CLIP (satot, 0, 0xff);
+       srtot = CLIP (srtot, 0, 0xff);
+       sgtot = CLIP (sgtot, 0, 0xff);
+       sbtot = CLIP (sbtot, 0, 0xff);
+
+       buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
+
+    next:
+       vx += ux;
+       vy += uy;
+    }
+}
+
+static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+static force_inline void
+bits_image_fetch_bilinear_affine (pixman_image_t * image,
+                                 int              offset,
+                                 int              line,
+                                 int              width,
+                                 uint32_t *       buffer,
+                                 const uint32_t * mask,
+
+                                 convert_pixel_t       convert_pixel,
+                                 pixman_format_code_t  format,
+                                 pixman_repeat_t       repeat_mode)
+{
+    pixman_fixed_t x, y;
+    pixman_fixed_t ux, uy;
+    pixman_vector_t v;
+    bits_image_t *bits = &image->bits;
+    int i;
+
+    /* reference point is the center of the pixel */
+    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
+    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
+    v.vector[2] = pixman_fixed_1;
+
+    if (!pixman_transform_point_3d (image->common.transform, &v))
+       return;
+
+    ux = image->common.transform->matrix[0][0];
+    uy = image->common.transform->matrix[1][0];
+
+    x = v.vector[0];
+    y = v.vector[1];
+
+    for (i = 0; i < width; ++i)
+    {
+       int x1, y1, x2, y2;
+       uint32_t tl, tr, bl, br;
+       int32_t distx, disty;
+       int width = image->bits.width;
+       int height = image->bits.height;
+       const uint8_t *row1;
+       const uint8_t *row2;
+
+       if (mask && !mask[i])
+           goto next;
+
+       x1 = x - pixman_fixed_1 / 2;
+       y1 = y - pixman_fixed_1 / 2;
+
+       distx = pixman_fixed_to_bilinear_weight (x1);
+       disty = pixman_fixed_to_bilinear_weight (y1);
+
+       y1 = pixman_fixed_to_int (y1);
+       y2 = y1 + 1;
+       x1 = pixman_fixed_to_int (x1);
+       x2 = x1 + 1;
+
+       if (repeat_mode != PIXMAN_REPEAT_NONE)
+       {
+           uint32_t mask;
+
+           mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
+
+           repeat (repeat_mode, &x1, width);
+           repeat (repeat_mode, &y1, height);
+           repeat (repeat_mode, &x2, width);
+           repeat (repeat_mode, &y2, height);
+
+           row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
+           row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
+
+           tl = convert_pixel (row1, x1) | mask;
+           tr = convert_pixel (row1, x2) | mask;
+           bl = convert_pixel (row2, x1) | mask;
+           br = convert_pixel (row2, x2) | mask;
+       }
+       else
+       {
+           uint32_t mask1, mask2;
+           int bpp;
+
+           /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
+            * which means if you use it in expressions, those
+            * expressions become unsigned themselves. Since
+            * the variables below can be negative in some cases,
+            * that will lead to crashes on 64 bit architectures.
+            *
+            * So this line makes sure bpp is signed
+            */
+           bpp = PIXMAN_FORMAT_BPP (format);
+
+           if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
+           {
+               buffer[i] = 0;
+               goto next;
+           }
+
+           if (y2 == 0)
+           {
+               row1 = zero;
+               mask1 = 0;
+           }
+           else
+           {
+               row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
+               row1 += bpp / 8 * x1;
+
+               mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
+           }
+
+           if (y1 == height - 1)
+           {
+               row2 = zero;
+               mask2 = 0;
+           }
+           else
+           {
+               row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
+               row2 += bpp / 8 * x1;
+
+               mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
+           }
+
+           if (x2 == 0)
+           {
+               tl = 0;
+               bl = 0;
+           }
+           else
+           {
+               tl = convert_pixel (row1, 0) | mask1;
+               bl = convert_pixel (row2, 0) | mask2;
+           }
+
+           if (x1 == width - 1)
+           {
+               tr = 0;
+               br = 0;
+           }
+           else
+           {
+               tr = convert_pixel (row1, 1) | mask1;
+               br = convert_pixel (row2, 1) | mask2;
+           }
+       }
+
+       buffer[i] = bilinear_interpolation (
+           tl, tr, bl, br, distx, disty);
+
+    next:
+       x += ux;
+       y += uy;
+    }
+}
+
+static force_inline void
+bits_image_fetch_nearest_affine (pixman_image_t * image,
+                                int              offset,
+                                int              line,
+                                int              width,
+                                uint32_t *       buffer,
+                                const uint32_t * mask,
+                                
+                                convert_pixel_t        convert_pixel,
+                                pixman_format_code_t   format,
+                                pixman_repeat_t        repeat_mode)
+{
+    pixman_fixed_t x, y;
+    pixman_fixed_t ux, uy;
+    pixman_vector_t v;
+    bits_image_t *bits = &image->bits;
+    int i;
+
+    /* reference point is the center of the pixel */
+    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
+    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
+    v.vector[2] = pixman_fixed_1;
+
+    if (!pixman_transform_point_3d (image->common.transform, &v))
+       return;
+
+    ux = image->common.transform->matrix[0][0];
+    uy = image->common.transform->matrix[1][0];
+
+    x = v.vector[0];
+    y = v.vector[1];
+
+    for (i = 0; i < width; ++i)
+    {
+       int width, height, x0, y0;
+       const uint8_t *row;
+
+       if (mask && !mask[i])
+           goto next;
+       
+       width = image->bits.width;
+       height = image->bits.height;
+       x0 = pixman_fixed_to_int (x - pixman_fixed_e);
+       y0 = pixman_fixed_to_int (y - pixman_fixed_e);
+
+       if (repeat_mode == PIXMAN_REPEAT_NONE &&
+           (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
+       {
+           buffer[i] = 0;
+       }
+       else
+       {
+           uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
+
+           if (repeat_mode != PIXMAN_REPEAT_NONE)
+           {
+               repeat (repeat_mode, &x0, width);
+               repeat (repeat_mode, &y0, height);
+           }
+
+           row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
+
+           buffer[i] = convert_pixel (row, x0) | mask;
+       }
+
+    next:
+       x += ux;
+       y += uy;
+    }
+}
+
+static force_inline uint32_t
+convert_a8r8g8b8 (const uint8_t *row, int x)
+{
+    return *(((uint32_t *)row) + x);
+}
+
+static force_inline uint32_t
+convert_x8r8g8b8 (const uint8_t *row, int x)
+{
+    return *(((uint32_t *)row) + x);
+}
+
+static force_inline uint32_t
+convert_a8 (const uint8_t *row, int x)
+{
+    return *(row + x) << 24;
+}
+
+static force_inline uint32_t
+convert_r5g6b5 (const uint8_t *row, int x)
+{
+    return convert_0565_to_0888 (*((uint16_t *)row + x));
+}
+
+#define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode)  \
+    static uint32_t *                                                  \
+    bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t   
*iter, \
+                                                           const uint32_t * 
mask) \
+    {                                                                  \
+       bits_image_fetch_separable_convolution_affine (                 \
+           iter->image,                                                \
+           iter->x, iter->y++,                                         \
+           iter->width,                                                \
+           iter->buffer, mask,                                         \
+           convert_ ## format,                                         \
+           PIXMAN_ ## format,                                          \
+           repeat_mode);                                               \
+                                                                       \
+       return iter->buffer;                                            \
+    }
+
+#define MAKE_BILINEAR_FETCHER(name, format, repeat_mode)               \
+    static uint32_t *                                                  \
+    bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t   *iter,  \
+                                              const uint32_t * mask)   \
+    {                                                                  \
+       bits_image_fetch_bilinear_affine (iter->image,                  \
+                                         iter->x, iter->y++,           \
+                                         iter->width,                  \
+                                         iter->buffer, mask,           \
+                                         convert_ ## format,           \
+                                         PIXMAN_ ## format,            \
+                                         repeat_mode);                 \
+       return iter->buffer;                                            \
+    }
+
+#define MAKE_NEAREST_FETCHER(name, format, repeat_mode)                        
\
+    static uint32_t *                                                  \
+    bits_image_fetch_nearest_affine_ ## name (pixman_iter_t   *iter,   \
+                                             const uint32_t * mask)    \
+    {                                                                  \
+       bits_image_fetch_nearest_affine (iter->image,                   \
+                                        iter->x, iter->y++,            \
+                                        iter->width,                   \
+                                        iter->buffer, mask,            \
+                                        convert_ ## format,            \
+                                        PIXMAN_ ## format,             \
+                                        repeat_mode);                  \
+       return iter->buffer;                                            \
+    }
+
+#define MAKE_FETCHERS(name, format, repeat_mode)                       \
+    MAKE_NEAREST_FETCHER (name, format, repeat_mode)                   \
+    MAKE_BILINEAR_FETCHER (name, format, repeat_mode)                  \
+    MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode)
+
+MAKE_FETCHERS (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD)
+MAKE_FETCHERS (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE)
+MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
+MAKE_FETCHERS (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL)
+MAKE_FETCHERS (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD)
+MAKE_FETCHERS (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE)
+MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
+MAKE_FETCHERS (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL)
+MAKE_FETCHERS (pad_a8,           a8,       PIXMAN_REPEAT_PAD)
+MAKE_FETCHERS (none_a8,          a8,       PIXMAN_REPEAT_NONE)
+MAKE_FETCHERS (reflect_a8,      a8,       PIXMAN_REPEAT_REFLECT)
+MAKE_FETCHERS (normal_a8,       a8,       PIXMAN_REPEAT_NORMAL)
+MAKE_FETCHERS (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD)
+MAKE_FETCHERS (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE)
+MAKE_FETCHERS (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT)
+MAKE_FETCHERS (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL)
+
 #define IMAGE_FLAGS                                                    \
     (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM |               \
      FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
@@ -2747,6 +3213,70 @@ static const pixman_iter_info_t fast_iters[] =
       NULL, bits_image_fetch_bilinear_no_repeat_8888, NULL
     },
 
+#define GENERAL_BILINEAR_FLAGS                                         \
+    (FAST_PATH_NO_ALPHA_MAP            |                               \
+     FAST_PATH_NO_ACCESSORS            |                               \
+     FAST_PATH_HAS_TRANSFORM           |                               \
+     FAST_PATH_AFFINE_TRANSFORM                |                               
\
+     FAST_PATH_BILINEAR_FILTER)
+
+#define GENERAL_NEAREST_FLAGS                                          \
+    (FAST_PATH_NO_ALPHA_MAP            |                               \
+     FAST_PATH_NO_ACCESSORS            |                               \
+     FAST_PATH_HAS_TRANSFORM           |                               \
+     FAST_PATH_AFFINE_TRANSFORM                |                               
\
+     FAST_PATH_NEAREST_FILTER)
+
+#define GENERAL_SEPARABLE_CONVOLUTION_FLAGS                            \
+    (FAST_PATH_NO_ALPHA_MAP            |                               \
+     FAST_PATH_NO_ACCESSORS            |                               \
+     FAST_PATH_HAS_TRANSFORM           |                               \
+     FAST_PATH_AFFINE_TRANSFORM        |                               \
+     FAST_PATH_SEPARABLE_CONVOLUTION_FILTER)
+    
+#define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat)   \
+    { PIXMAN_ ## format,                                               \
+      ITER_NARROW | ITER_SRC,                                          \
+      GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
+      NULL, bits_image_fetch_separable_convolution_affine_ ## name, NULL \
+    },
+
+#define BILINEAR_AFFINE_FAST_PATH(name, format, repeat)                        
\
+    { PIXMAN_ ## format,                                               \
+      ITER_NARROW | ITER_SRC,                                          \
+      GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,                
\
+      NULL, bits_image_fetch_bilinear_affine_ ## name, NULL,           \
+    },
+
+#define NEAREST_AFFINE_FAST_PATH(name, format, repeat)                 \
+    { PIXMAN_ ## format,                                               \
+      ITER_NARROW | ITER_SRC,                                          \
+      GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,         \
+      NULL, bits_image_fetch_nearest_affine_ ## name, NULL             \
+    },
+
+#define AFFINE_FAST_PATHS(name, format, repeat)                                
\
+    SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat)       \
+    BILINEAR_AFFINE_FAST_PATH(name, format, repeat)                    \
+    NEAREST_AFFINE_FAST_PATH(name, format, repeat)
+    
+    AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
+    AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
+    AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
+    AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL)
+    AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD)
+    AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE)
+    AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
+    AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL)
+    AFFINE_FAST_PATHS (pad_a8, a8, PAD)
+    AFFINE_FAST_PATHS (none_a8, a8, NONE)
+    AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT)
+    AFFINE_FAST_PATHS (normal_a8, a8, NORMAL)
+    AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD)
+    AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE)
+    AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT)
+    AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL)
+
     { PIXMAN_null },
 };
 
-- 
1.7.1

_______________________________________________
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman

Reply via email to