mmx: add add_0565_0565
[profile/ivi/pixman.git] / pixman / pixman.c
index cdf4b75..8fb5356 100644 (file)
 
 #include <stdlib.h>
 
+static pixman_implementation_t *global_implementation;
+
+#ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
+static void __attribute__((constructor))
+pixman_constructor (void)
+{
+    global_implementation = _pixman_choose_implementation ();
+}
+#endif
+
 static force_inline pixman_implementation_t *
 get_implementation (void)
 {
-    static pixman_implementation_t *global_implementation;
-
+#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
     if (!global_implementation)
        global_implementation = _pixman_choose_implementation ();
-
+#endif
     return global_implementation;
 }
 
@@ -153,57 +162,6 @@ optimize_operator (pixman_op_t     op,
     return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
 }
 
-static void
-apply_workaround (pixman_image_t *image,
-                 int32_t *       x,
-                 int32_t *       y,
-                 uint32_t **     save_bits,
-                 int *           save_dx,
-                 int *           save_dy)
-{
-    if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
-    {
-       /* Some X servers generate images that point to the
-        * wrong place in memory, but then set the clip region
-        * to point to the right place. Because of an old bug
-        * in pixman, this would actually work.
-        *
-        * Here we try and undo the damage
-        */
-       int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
-       pixman_box32_t *extents;
-       uint8_t *t;
-       int dx, dy;
-       
-       extents = pixman_region32_extents (&(image->common.clip_region));
-       dx = extents->x1;
-       dy = extents->y1;
-       
-       *save_bits = image->bits.bits;
-       
-       *x -= dx;
-       *y -= dy;
-       pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
-       
-       t = (uint8_t *)image->bits.bits;
-       t += dy * image->bits.rowstride * 4 + dx * bpp;
-       image->bits.bits = (uint32_t *)t;
-       
-       *save_dx = dx;
-       *save_dy = dy;
-    }
-}
-
-static void
-unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
-{
-    if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
-    {
-       image->bits.bits = bits;
-       pixman_region32_translate (&image->common.clip_region, dx, dy);
-    }
-}
-
 /*
  * Computing composite region
  */
@@ -280,7 +238,7 @@ static pixman_bool_t
 pixman_compute_composite_region32 (pixman_region32_t * region,
                                    pixman_image_t *    src_image,
                                    pixman_image_t *    mask_image,
-                                   pixman_image_t *    dst_image,
+                                   pixman_image_t *    dest_image,
                                    int32_t             src_x,
                                    int32_t             src_y,
                                    int32_t             mask_x,
@@ -297,8 +255,8 @@ pixman_compute_composite_region32 (pixman_region32_t * region,
 
     region->extents.x1 = MAX (region->extents.x1, 0);
     region->extents.y1 = MAX (region->extents.y1, 0);
-    region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
-    region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
+    region->extents.x2 = MIN (region->extents.x2, dest_image->bits.width);
+    region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height);
 
     region->data = 0;
 
@@ -306,23 +264,40 @@ pixman_compute_composite_region32 (pixman_region32_t * region,
     if (region->extents.x1 >= region->extents.x2 ||
         region->extents.y1 >= region->extents.y2)
     {
+       region->extents.x1 = 0;
+       region->extents.x2 = 0;
+       region->extents.y1 = 0;
+       region->extents.y2 = 0;
        return FALSE;
     }
 
-    if (dst_image->common.have_clip_region)
+    if (dest_image->common.have_clip_region)
     {
-       if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
+       if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0))
            return FALSE;
     }
 
-    if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
+    if (dest_image->common.alpha_map)
     {
-       if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
-                                -dst_image->common.alpha_origin_x,
-                                -dst_image->common.alpha_origin_y))
+       if (!pixman_region32_intersect_rect (region, region,
+                                            dest_image->common.alpha_origin_x,
+                                            dest_image->common.alpha_origin_y,
+                                            dest_image->common.alpha_map->width,
+                                            dest_image->common.alpha_map->height))
        {
            return FALSE;
        }
+       if (!pixman_region32_not_empty (region))
+           return FALSE;
+       if (dest_image->common.alpha_map->common.have_clip_region)
+       {
+           if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region,
+                                    -dest_image->common.alpha_origin_x,
+                                    -dest_image->common.alpha_origin_y))
+           {
+               return FALSE;
+           }
+       }
     }
 
     /* clip against src */
@@ -360,345 +335,106 @@ pixman_compute_composite_region32 (pixman_region32_t * region,
     return TRUE;
 }
 
-static void
-walk_region_internal (pixman_implementation_t *imp,
-                      pixman_op_t              op,
-                      pixman_image_t *         src_image,
-                      pixman_image_t *         mask_image,
-                      pixman_image_t *         dst_image,
-                      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,
-                      pixman_bool_t            src_repeat,
-                      pixman_bool_t            mask_repeat,
-                      pixman_region32_t *      region,
-                      pixman_composite_func_t  composite_rect)
-{
-    int w, h, w_this, h_this;
-    int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
-    int src_dy = src_y - dest_y;
-    int src_dx = src_x - dest_x;
-    int mask_dy = mask_y - dest_y;
-    int mask_dx = mask_x - dest_x;
-    const pixman_box32_t *pbox;
-    int n;
-
-    pbox = pixman_region32_rectangles (region, &n);
-
-    /* Fast path for non-repeating sources */
-    if (!src_repeat && !mask_repeat)
-    {
-       while (n--)
-       {
-           (*composite_rect) (imp, op,
-                              src_image, mask_image, dst_image,
-                              pbox->x1 + src_dx,
-                              pbox->y1 + src_dy,
-                              pbox->x1 + mask_dx,
-                              pbox->y1 + mask_dy,
-                              pbox->x1,
-                              pbox->y1,
-                              pbox->x2 - pbox->x1,
-                              pbox->y2 - pbox->y1);
-           
-           pbox++;
-       }
-
-       return;
-    }
-    
-    while (n--)
-    {
-       h = pbox->y2 - pbox->y1;
-       y_src = pbox->y1 + src_dy;
-       y_msk = pbox->y1 + mask_dy;
-       y_dst = pbox->y1;
-
-       while (h)
-       {
-           h_this = h;
-           w = pbox->x2 - pbox->x1;
-           x_src = pbox->x1 + src_dx;
-           x_msk = pbox->x1 + mask_dx;
-           x_dst = pbox->x1;
-
-           if (mask_repeat)
-           {
-               y_msk = MOD (y_msk, mask_image->bits.height);
-               if (h_this > mask_image->bits.height - y_msk)
-                   h_this = mask_image->bits.height - y_msk;
-           }
-
-           if (src_repeat)
-           {
-               y_src = MOD (y_src, src_image->bits.height);
-               if (h_this > src_image->bits.height - y_src)
-                   h_this = src_image->bits.height - y_src;
-           }
-
-           while (w)
-           {
-               w_this = w;
-
-               if (mask_repeat)
-               {
-                   x_msk = MOD (x_msk, mask_image->bits.width);
-                   if (w_this > mask_image->bits.width - x_msk)
-                       w_this = mask_image->bits.width - x_msk;
-               }
-
-               if (src_repeat)
-               {
-                   x_src = MOD (x_src, src_image->bits.width);
-                   if (w_this > src_image->bits.width - x_src)
-                       w_this = src_image->bits.width - x_src;
-               }
-
-               (*composite_rect) (imp, op,
-                                  src_image, mask_image, dst_image,
-                                  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++;
-    }
-}
-
-#define N_CACHED_FAST_PATHS 8
-
 typedef struct
 {
-    struct
-    {
-       pixman_implementation_t *       imp;
-       pixman_fast_path_t              fast_path;
-    } cache [N_CACHED_FAST_PATHS];
-} cache_t;
-
-PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
-
-static force_inline pixman_bool_t
-lookup_composite_function (pixman_op_t                 op,
-                          pixman_format_code_t         src_format,
-                          uint32_t                     src_flags,
-                          pixman_format_code_t         mask_format,
-                          uint32_t                     mask_flags,
-                          pixman_format_code_t         dest_format,
-                          uint32_t                     dest_flags,
-                          pixman_implementation_t    **out_imp,
-                          pixman_composite_func_t     *out_func)
-{
-    pixman_implementation_t *imp;
-    cache_t *cache;
-    int i;
-
-    /* Check cache for fast paths */
-    cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
-
-    for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
-    {
-       const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
-
-       /* Note that we check for equality here, not whether
-        * the cached fast path matches. This is to prevent
-        * us from selecting an overly general fast path
-        * when a more specific one would work.
-        */
-       if (info->op == op                      &&
-           info->src_format == src_format      &&
-           info->mask_format == mask_format    &&
-           info->dest_format == dest_format    &&
-           info->src_flags == src_flags        &&
-           info->mask_flags == mask_flags      &&
-           info->dest_flags == dest_flags      &&
-           info->func)
-       {
-           *out_imp = cache->cache[i].imp;
-           *out_func = cache->cache[i].fast_path.func;
-
-           goto update_cache;
-       }
-    }
-
-    for (imp = get_implementation (); imp != NULL; imp = imp->delegate)
-    {
-       const pixman_fast_path_t *info = imp->fast_paths;
-
-       while (info->op != PIXMAN_OP_NONE)
-       {
-           if ((info->op == op || info->op == PIXMAN_OP_any)           &&
-               /* Formats */
-               ((info->src_format == src_format) ||
-                (info->src_format == PIXMAN_any))                      &&
-               ((info->mask_format == mask_format) ||
-                (info->mask_format == PIXMAN_any))                     &&
-               ((info->dest_format == dest_format) ||
-                (info->dest_format == PIXMAN_any))                     &&
-               /* Flags */
-               (info->src_flags & src_flags) == info->src_flags        &&
-               (info->mask_flags & mask_flags) == info->mask_flags     &&
-               (info->dest_flags & dest_flags) == info->dest_flags)
-           {
-               *out_imp = imp;
-               *out_func = info->func;
-
-               /* Set i to the last spot in the cache so that the
-                * move-to-front code below will work
-                */
-               i = N_CACHED_FAST_PATHS - 1;
-
-               goto update_cache;
-           }
-
-           ++info;
-       }
-    }
-    return FALSE;
-
-update_cache:
-    if (i)
-    {
-       while (i--)
-           cache->cache[i + 1] = cache->cache[i];
-
-       cache->cache[0].imp = *out_imp;
-       cache->cache[0].fast_path.op = op;
-       cache->cache[0].fast_path.src_format = src_format;
-       cache->cache[0].fast_path.src_flags = src_flags;
-       cache->cache[0].fast_path.mask_format = mask_format;
-       cache->cache[0].fast_path.mask_flags = mask_flags;
-       cache->cache[0].fast_path.dest_format = dest_format;
-       cache->cache[0].fast_path.dest_flags = dest_flags;
-       cache->cache[0].fast_path.func = *out_func;
-    }
-
-    return TRUE;
-}
+    pixman_fixed_48_16_t       x1;
+    pixman_fixed_48_16_t       y1;
+    pixman_fixed_48_16_t       x2;
+    pixman_fixed_48_16_t       y2;
+} box_48_16_t;
 
 static pixman_bool_t
-compute_sample_extents (pixman_transform_t *transform,
-                       pixman_box32_t *extents, int x, int y, 
-                       pixman_fixed_t x_off, pixman_fixed_t y_off,
-                       pixman_fixed_t width, pixman_fixed_t height)
+compute_transformed_extents (pixman_transform_t *transform,
+                            const pixman_box32_t *extents,
+                            box_48_16_t *transformed)
 {
-    pixman_fixed_t x1, y1, x2, y2;
     pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
+    pixman_fixed_t x1, y1, x2, y2;
+    int i;
 
-    /* We have checked earlier that (extents->x1 - x) etc. fit in a pixman_fixed_t */
-    x1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x1 - x) + pixman_fixed_1 / 2;
-    y1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y1 - y) + pixman_fixed_1 / 2;
-    x2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x2 - x) - pixman_fixed_1 / 2;
-    y2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y2 - y) - pixman_fixed_1 / 2;
+    x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
+    y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
+    x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
+    y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
 
     if (!transform)
     {
-       tx1 = (pixman_fixed_48_16_t)x1;
-       ty1 = (pixman_fixed_48_16_t)y1;
-       tx2 = (pixman_fixed_48_16_t)x2;
-       ty2 = (pixman_fixed_48_16_t)y2;
+       transformed->x1 = x1;
+       transformed->y1 = y1;
+       transformed->x2 = x2;
+       transformed->y2 = y2;
+
+       return TRUE;
     }
-    else
-    {
-       int i;
 
-       /* Silence GCC */
-       tx1 = ty1 = tx2 = ty2 = 0;
-    
-       for (i = 0; i < 4; ++i)
-       {
-           pixman_fixed_48_16_t tx, ty;
-           pixman_vector_t v;
+    tx1 = ty1 = INT64_MAX;
+    tx2 = ty2 = INT64_MIN;
 
-           v.vector[0] = (i & 0x01)? x1 : x2;
-           v.vector[1] = (i & 0x02)? y1 : y2;
-           v.vector[2] = pixman_fixed_1;
+    for (i = 0; i < 4; ++i)
+    {
+       pixman_fixed_48_16_t tx, ty;
+       pixman_vector_t v;
 
-           if (!pixman_transform_point (transform, &v))
-               return FALSE;
+       v.vector[0] = (i & 0x01)? x1 : x2;
+       v.vector[1] = (i & 0x02)? y1 : y2;
+       v.vector[2] = pixman_fixed_1;
 
-           tx = (pixman_fixed_48_16_t)v.vector[0];
-           ty = (pixman_fixed_48_16_t)v.vector[1];
+       if (!pixman_transform_point (transform, &v))
+           return FALSE;
 
-           if (i == 0)
-           {
-               tx1 = tx;
-               ty1 = ty;
-               tx2 = tx;
-               ty2 = ty;
-           }
-           else
-           {
-               if (tx < tx1)
-                   tx1 = tx;
-               if (ty < ty1)
-                   ty1 = ty;
-               if (tx > tx2)
-                   tx2 = tx;
-               if (ty > ty2)
-                   ty2 = ty;
-           }
-       }
+       tx = (pixman_fixed_48_16_t)v.vector[0];
+       ty = (pixman_fixed_48_16_t)v.vector[1];
+
+       if (tx < tx1)
+           tx1 = tx;
+       if (ty < ty1)
+           ty1 = ty;
+       if (tx > tx2)
+           tx2 = tx;
+       if (ty > ty2)
+           ty2 = ty;
     }
 
-    /* Expand the source area by a tiny bit so account of different rounding that
-     * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
-     * 0.5 so this won't cause the area computed to be overly pessimistic.
-     */
-    tx1 += x_off - 8 * pixman_fixed_e;
-    ty1 += y_off - 8 * pixman_fixed_e;
-    tx2 += x_off + width + 8 * pixman_fixed_e;
-    ty2 += y_off + height + 8 * pixman_fixed_e;
-
-    if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 ||
-       ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 ||
-       tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 ||
-       ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16)
-    {
-       return FALSE;
-    }
-    else
-    {
-       extents->x1 = pixman_fixed_to_int (tx1);
-       extents->y1 = pixman_fixed_to_int (ty1);
-       extents->x2 = pixman_fixed_to_int (tx2) + 1;
-       extents->y2 = pixman_fixed_to_int (ty2) + 1;
+    transformed->x1 = tx1;
+    transformed->y1 = ty1;
+    transformed->x2 = tx2;
+    transformed->y2 = ty2;
 
-       return TRUE;
-    }
+    return TRUE;
 }
 
 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
+#define ABS(f)      (((f) < 0)?  (-(f)) : (f))
+#define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
 
 static pixman_bool_t
-analyze_extent (pixman_image_t *image, int x, int y,
-               const pixman_box32_t *extents, uint32_t *flags)
+analyze_extent (pixman_image_t       *image,
+               const pixman_box32_t *extents,
+               uint32_t             *flags)
 {
     pixman_transform_t *transform;
-    pixman_fixed_t *params;
     pixman_fixed_t x_off, y_off;
     pixman_fixed_t width, height;
-    pixman_box32_t ex;
+    pixman_fixed_t *params;
+    box_48_16_t transformed;
+    pixman_box32_t exp_extents;
 
-    *flags |= FAST_PATH_COVERS_CLIP;
     if (!image)
        return TRUE;
 
+    /* Some compositing functions walk one step
+     * outside the destination rectangle, so we
+     * check here that the expanded-by-one source
+     * extents in destination space fits in 16 bits
+     */
+    if (!IS_16BIT (extents->x1 - 1)            ||
+       !IS_16BIT (extents->y1 - 1)             ||
+       !IS_16BIT (extents->x2 + 1)             ||
+       !IS_16BIT (extents->y2 + 1))
+    {
+       return FALSE;
+    }
+
     transform = image->common.transform;
     if (image->common.type == BITS)
     {
@@ -709,30 +445,16 @@ analyze_extent (pixman_image_t *image, int x, int y,
        if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff)
            return FALSE;
 
-       if (image->common.repeat == PIXMAN_REPEAT_NONE &&
-           (x > extents->x1 || y > extents->y1 ||
-            x + image->bits.width < extents->x2 ||
-            y + image->bits.height < extents->y2))
+       if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
+           extents->x1 >= 0 &&
+           extents->y1 >= 0 &&
+           extents->x2 <= image->bits.width &&
+           extents->y2 <= image->bits.height)
        {
-           (*flags) &= ~FAST_PATH_COVERS_CLIP;
+           *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
+           return TRUE;
        }
-    }
-
-    /* Some compositing functions walk one step
-     * outside the destination rectangle, so we
-     * check here that the expanded-by-one source
-     * extents in destination space fits in 16 bits
-     */
-    if (!IS_16BIT (extents->x1 - x - 1)                ||
-       !IS_16BIT (extents->y1 - y - 1)         ||
-       !IS_16BIT (extents->x2 - x + 1)         ||
-       !IS_16BIT (extents->y2 - y + 1))
-    {
-       return FALSE;
-    }
 
-    if (image->common.type == BITS)
-    {
        switch (image->common.filter)
        {
        case PIXMAN_FILTER_CONVOLUTION:
@@ -772,31 +494,58 @@ analyze_extent (pixman_image_t *image, int x, int y,
        height = 0;
     }
 
-    /* Check that the extents expanded by one don't overflow. This ensures that
-     * compositing functions can simply walk the source space using 16.16 variables
-     * without worrying about overflow.
-     */
-    ex.x1 = extents->x1 - 1;
-    ex.y1 = extents->y1 - 1;
-    ex.x2 = extents->x2 + 1;
-    ex.y2 = extents->y2 + 1;
-
-    if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
+    if (!compute_transformed_extents (transform, extents, &transformed))
        return FALSE;
 
-    if (image->type == BITS)
+    /* Expand the source area by a tiny bit so account of different rounding that
+     * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
+     * 0.5 so this won't cause the area computed to be overly pessimistic.
+     */
+    transformed.x1 -= 8 * pixman_fixed_e;
+    transformed.y1 -= 8 * pixman_fixed_e;
+    transformed.x2 += 8 * pixman_fixed_e;
+    transformed.y2 += 8 * pixman_fixed_e;
+
+    if (image->common.type == BITS)
     {
-       /* Check whether the non-expanded, transformed extent is entirely within
-        * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
-        */
-       ex = *extents;
-       if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
+       if (pixman_fixed_to_int (transformed.x1) >= 0                   &&
+           pixman_fixed_to_int (transformed.y1) >= 0                   &&
+           pixman_fixed_to_int (transformed.x2) < image->bits.width    &&
+           pixman_fixed_to_int (transformed.y2) < image->bits.height)
+       {
+           *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
+       }
+
+       if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0                &&
+           pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0                &&
+           pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
+           pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
        {
-           if (ex.x1 >= 0 && ex.y1 >= 0 && ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
-               *flags |= FAST_PATH_SAMPLES_COVER_CLIP;
+           *flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
        }
     }
 
+    /* Check we don't overflow when the destination extents are expanded by one.
+     * This ensures that compositing functions can simply walk the source space
+     * using 16.16 variables without worrying about overflow.
+     */
+    exp_extents = *extents;
+    exp_extents.x1 -= 1;
+    exp_extents.y1 -= 1;
+    exp_extents.x2 += 1;
+    exp_extents.y2 += 1;
+
+    if (!compute_transformed_extents (transform, &exp_extents, &transformed))
+       return FALSE;
+    
+    if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e)        ||
+       !IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e) ||
+       !IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width) ||
+       !IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
+    {
+       return FALSE;
+    }
+
     return TRUE;
 }
 
@@ -836,14 +585,7 @@ pixman_image_composite32 (pixman_op_t      op,
     pixman_format_code_t src_format, mask_format, dest_format;
     uint32_t src_flags, mask_flags, dest_flags;
     pixman_region32_t region;
-    pixman_box32_t *extents;
-    uint32_t *src_bits;
-    int src_dx, src_dy;
-    uint32_t *mask_bits;
-    int mask_dx, mask_dy;
-    uint32_t *dest_bits;
-    int dest_dx, dest_dy;
-    pixman_bool_t need_workaround;
+    pixman_box32_t extents;
     pixman_implementation_t *imp;
     pixman_composite_func_t func;
 
@@ -881,16 +623,6 @@ pixman_image_composite32 (pixman_op_t      op,
            src_format = mask_format = PIXMAN_rpixbuf;
     }
 
-    /* Check for workaround */
-    need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
-
-    if (need_workaround)
-    {
-       apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
-       apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
-       apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
-    }
-
     pixman_region32_init (&region);
 
     if (!pixman_compute_composite_region32 (
@@ -900,58 +632,90 @@ pixman_image_composite32 (pixman_op_t      op,
        goto out;
     }
 
-    extents = pixman_region32_extents (&region);
+    extents = *pixman_region32_extents (&region);
+
+    extents.x1 -= dest_x - src_x;
+    extents.y1 -= dest_y - src_y;
+    extents.x2 -= dest_x - src_x;
+    extents.y2 -= dest_y - src_y;
 
-    if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags))
+    if (!analyze_extent (src, &extents, &src_flags))
        goto out;
 
-    if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags))
+    extents.x1 -= src_x - mask_x;
+    extents.y1 -= src_y - mask_y;
+    extents.x2 -= src_x - mask_x;
+    extents.y2 -= src_y - mask_y;
+
+    if (!analyze_extent (mask, &extents, &mask_flags))
        goto out;
 
-    /* If the clip is within the source samples, and the samples are opaque,
-     * then the source is effectively opaque.
+    /* If the clip is within the source samples, and the samples are
+     * opaque, then the source is effectively opaque.
      */
-#define BOTH (FAST_PATH_SAMPLES_OPAQUE | FAST_PATH_SAMPLES_COVER_CLIP)
-
-    if ((src_flags & BOTH) == BOTH)
+#define NEAREST_OPAQUE (FAST_PATH_SAMPLES_OPAQUE |                     \
+                        FAST_PATH_NEAREST_FILTER |                     \
+                        FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
+#define BILINEAR_OPAQUE        (FAST_PATH_SAMPLES_OPAQUE |                     \
+                        FAST_PATH_BILINEAR_FILTER |                    \
+                        FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
+
+    if ((src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
+       (src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
+    {
        src_flags |= FAST_PATH_IS_OPAQUE;
-    
-    if ((mask_flags & BOTH) == BOTH)
+    }
+
+    if ((mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
+       (mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
+    {
        mask_flags |= FAST_PATH_IS_OPAQUE;
-    
+    }
+
     /*
      * Check if we can replace our operator by a simpler one
      * if the src or dest are opaque. The output operator should be
      * mathematically equivalent to the source.
      */
     op = optimize_operator (op, src_flags, mask_flags, dest_flags);
-    if (op == PIXMAN_OP_DST)
-       goto out;
 
-    if (lookup_composite_function (op,
-                                  src_format, src_flags,
-                                  mask_format, mask_flags,
-                                  dest_format, dest_flags,
-                                  &imp, &func))
+    if (_pixman_lookup_composite_function (
+           get_implementation (), op,
+           src_format, src_flags, mask_format, mask_flags, dest_format, dest_flags,
+           &imp, &func))
     {
-       walk_region_internal (imp, op,
-                             src, mask, dest,
-                             src_x, src_y, mask_x, mask_y,
-                             dest_x, dest_y,
-                             width, height,
-                             (src_flags & FAST_PATH_SIMPLE_REPEAT),
-                             (mask_flags & FAST_PATH_SIMPLE_REPEAT),
-                             &region, func);
-    }
+       pixman_composite_info_t info;
+       const pixman_box32_t *pbox;
+       int n;
 
-out:
-    if (need_workaround)
-    {
-       unapply_workaround (src, src_bits, src_dx, src_dy);
-       unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
-       unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
+       info.op = op;
+       info.src_image = src;
+       info.mask_image = mask;
+       info.dest_image = dest;
+       info.src_flags = src_flags;
+       info.mask_flags = mask_flags;
+       info.dest_flags = dest_flags;
+
+       pbox = pixman_region32_rectangles (&region, &n);
+
+       while (n--)
+       {
+           info.src_x = pbox->x1 + src_x - dest_x;
+           info.src_y = pbox->y1 + src_y - dest_y;
+           info.mask_x = pbox->x1 + mask_x - dest_x;
+           info.mask_y = pbox->y1 + mask_y - dest_y;
+           info.dest_x = pbox->x1;
+           info.dest_y = pbox->y1;
+           info.width = pbox->x2 - pbox->x1;
+           info.height = pbox->y2 - pbox->y1;
+
+           func (imp, &info);
+
+           pbox++;
+       }
     }
 
+out:
     pixman_region32_fini (&region);
 }
 
@@ -982,8 +746,8 @@ pixman_blt (uint32_t *src_bits,
             int       dst_bpp,
             int       src_x,
             int       src_y,
-            int       dst_x,
-            int       dst_y,
+            int       dest_x,
+            int       dest_y,
             int       width,
             int       height)
 {
@@ -991,7 +755,7 @@ pixman_blt (uint32_t *src_bits,
                                       src_bits, dst_bits, src_stride, dst_stride,
                                        src_bpp, dst_bpp,
                                        src_x, src_y,
-                                       dst_x, dst_y,
+                                       dest_x, dest_y,
                                        width, height);
 }
 
@@ -1032,9 +796,12 @@ color_to_pixel (pixman_color_t *     color,
           format == PIXMAN_x8b8g8r8     ||
           format == PIXMAN_b8g8r8a8     ||
           format == PIXMAN_b8g8r8x8     ||
+          format == PIXMAN_r8g8b8a8     ||
+          format == PIXMAN_r8g8b8x8     ||
           format == PIXMAN_r5g6b5       ||
           format == PIXMAN_b5g6r5       ||
-          format == PIXMAN_a8))
+          format == PIXMAN_a8           ||
+          format == PIXMAN_a1))
     {
        return FALSE;
     }
@@ -1053,8 +820,12 @@ color_to_pixel (pixman_color_t *     color,
            ((c & 0x0000ff00) <<  8) |
            ((c & 0x000000ff) << 24);
     }
+    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA)
+       c = ((c & 0xff000000) >> 24) | (c << 8);
 
-    if (format == PIXMAN_a8)
+    if (format == PIXMAN_a1)
+       c = c >> 31;
+    else if (format == PIXMAN_a8)
        c = c >> 24;
     else if (format == PIXMAN_r5g6b5 ||
              format == PIXMAN_b5g6r5)
@@ -1261,6 +1032,8 @@ pixman_format_supported_source (pixman_format_code_t format)
     case PIXMAN_x8b8g8r8:
     case PIXMAN_b8g8r8a8:
     case PIXMAN_b8g8r8x8:
+    case PIXMAN_r8g8b8a8:
+    case PIXMAN_r8g8b8x8:
     case PIXMAN_r8g8b8:
     case PIXMAN_b8g8r8:
     case PIXMAN_r5g6b5:
@@ -1336,7 +1109,7 @@ PIXMAN_EXPORT pixman_bool_t
 pixman_compute_composite_region (pixman_region16_t * region,
                                  pixman_image_t *    src_image,
                                  pixman_image_t *    mask_image,
-                                 pixman_image_t *    dst_image,
+                                 pixman_image_t *    dest_image,
                                  int16_t             src_x,
                                  int16_t             src_y,
                                  int16_t             mask_x,
@@ -1352,7 +1125,7 @@ pixman_compute_composite_region (pixman_region16_t * region,
     pixman_region32_init (&r32);
 
     retval = pixman_compute_composite_region32 (
-       &r32, src_image, mask_image, dst_image,
+       &r32, src_image, mask_image, dest_image,
        src_x, src_y, mask_x, mask_y, dest_x, dest_y,
        width, height);