Bug 836171. Update pixman to 0.27.4
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Mon, 04 Feb 2013 15:16:01 -0500
changeset 130670 17b8b22c24f89516062a27af9b2d434fc4d5314b
parent 130669 aa0b91c746654dd34e67257b3ab6fd9055e5cf58
child 130671 01836b9cdcf1f5c95cd99b25f6bb46aa6e457fdc
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs836171
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 836171. Update pixman to 0.27.4 Andrea Canciani (2): mmx: Fix x86 build on MSVC build: Improve win32 build system Benny Siegert (1): configure.ac: PIXMAN_LINK_WITH_ENV fix Matt Turner (3): build: Remove useless DEP_CFLAGS/DEP_LIBS variables sse2: mark pack_565_2x128_128 as static force_inline iwmmxt: Don't define dummy _mm_empty for >=gcc-4.8 Nemanja Lukic (7): MIPS: DSPr2: Added fast-paths for OVER operation: - over_8888_n_8888 - over_8888_8_8888 MIPS: DSPr2: Added fast-paths for OVER operation: - over_8888_n_0565 - over_8888_8_0565 MIPS: DSPr2: Added fast-paths for OVER operation: - over_0565_n_0565 - over_0565_8_0565 MIPS: DSPr2: Added OVER combiner and two new fast paths: - over_8888_8888 - over_8888_8888_8888 MIPS: DSPr2: Added fast-paths for ADD operation: - add_n_8_8 - add_n_8_8888 - add_8_8_8 MIPS: DSPr2: Added more fast-paths for ADD operation: - add_0565_8_0565 - add_8888_8_8888 - add_8888_n_8888 MIPS: DSPr2: Added more fast-paths for ADD operation: - add_8888_8888_8888 - add_8_8 - add_8888_8888 Siarhei Siamashka (4): Add scaled nearest repeat fast paths MIPS: skip runtime detection for DSPr2 if -mdspr2 option is in CFLAGS Add missing force_inline to in() function used for C fast paths Workaround for FTBFS with gcc 4.6 (http://gcc.gnu.org/PR54965) Søren Sandmann Pedersen (44): Post-release version bump to 0.27.3 Define TIMER_BEGIN and TIMER_END even when timers are not enabled Make show_image() cope with more formats demos: Add srgb_trap_test.c Remove pointless declaration of _pixman_image_get_scanline_generic_64() Remove obsolete TODO file pixel_checker: Move sRGB conversion into get_limits() test/utils.c: Use pow(), not powf() in sRGB conversion routines implementation: Write lookup_combiner() in a less convoluted way. Move blt delegation into pixman-implementation.c Move fill delegation into pixman-implementation.c Move delegation of src/dest iter init into pixman-implementation.c Rename _pixman_lookup_composite_function() to _pixman_implementation_lookup_composite() _pixman_implementation_create(): Initialize implementation with memset() implementation: Rename delegate to fallback Add PIXMAN_x8b8g8r8 and PIXMAN_a8b8g8r8 formats to scaling-test Fix bug in fast_composite_scaled_nearest() Fix bugs in component alpha combiners for separable PDF operators Add rotate-test.c test program Fix bugs in pixman-image.c pixman-combine.c.template: Formatting clean-ups affine-test: Print out the transformation matrix when verbose test: Add inifinite-loop test Fix for infinite-loop test rotate-test: Call image_endian_swap() in make_image() Make pixman.h more const-correct glyph-test: Prepare for floating point blitters-test: Prepare for floating point Add pixman-combine-float.c Add combiner test pixman-utils.c, pixman-private.h: Add floating point conversion routines pixman-access.c: Add floating point accessor functions Switch the wide pipeline over to using floating point Remove 64 bit pipeline Don't auto-generate pixman-combine32.[ch] anymore Speed up pixman_expand_to_float() Remove BUILT_SOURCES Only regard images as pixbufs if they have identity transformations region: Formatting fix region: Remove overlap argument from pixman_op() Add new pixman_image_create_bits_no_clear() API pixman_composite_trapezoids(): Factor out extents computation pixman_composite_trapezoids(): don't clip to extents for some operators Pre-release version bump to 0.27.4
gfx/cairo/libpixman/src/Makefile.in
gfx/cairo/libpixman/src/pixman-access.c
gfx/cairo/libpixman/src/pixman-arm-neon.c
gfx/cairo/libpixman/src/pixman-bits-image.c
gfx/cairo/libpixman/src/pixman-combine-float.c
gfx/cairo/libpixman/src/pixman-combine32.c
gfx/cairo/libpixman/src/pixman-combine32.h
gfx/cairo/libpixman/src/pixman-conical-gradient.c
gfx/cairo/libpixman/src/pixman-fast-path.c
gfx/cairo/libpixman/src/pixman-general.c
gfx/cairo/libpixman/src/pixman-glyph.c
gfx/cairo/libpixman/src/pixman-image.c
gfx/cairo/libpixman/src/pixman-implementation.c
gfx/cairo/libpixman/src/pixman-linear-gradient.c
gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S
gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h
gfx/cairo/libpixman/src/pixman-mips-dspr2.c
gfx/cairo/libpixman/src/pixman-mips-dspr2.h
gfx/cairo/libpixman/src/pixman-mips.c
gfx/cairo/libpixman/src/pixman-mmx.c
gfx/cairo/libpixman/src/pixman-noop.c
gfx/cairo/libpixman/src/pixman-private.h
gfx/cairo/libpixman/src/pixman-radial-gradient.c
gfx/cairo/libpixman/src/pixman-region.c
gfx/cairo/libpixman/src/pixman-solid-fill.c
gfx/cairo/libpixman/src/pixman-srgb.c
gfx/cairo/libpixman/src/pixman-sse2.c
gfx/cairo/libpixman/src/pixman-trap.c
gfx/cairo/libpixman/src/pixman-utils.c
gfx/cairo/libpixman/src/pixman.c
gfx/cairo/libpixman/src/pixman.h
--- a/gfx/cairo/libpixman/src/Makefile.in
+++ b/gfx/cairo/libpixman/src/Makefile.in
@@ -83,17 +83,17 @@ endif
 CSRCS	= \
 	pixman-access.c \
 	pixman-access-accessors.c \
 	pixman-arm.c \
 	pixman-bits-image.c \
 	pixman.c \
 	pixman-combine16.c \
 	pixman-combine32.c \
-	pixman-combine64.c \
+	pixman-combine-float.c \
 	pixman-conical-gradient.c \
 	pixman-edge.c \
 	pixman-edge-accessors.c \
 	pixman-fast-path.c \
 	pixman-general.c \
 	pixman-gradient-walker.c \
 	pixman-glyph.c \
 	pixman-image.c \
@@ -102,17 +102,16 @@ CSRCS	= \
 	pixman-matrix.c \
 	pixman-mips.c \
 	pixman-noop.c \
 	pixman-ppc.c \
 	pixman-radial-gradient.c \
 	pixman-region16.c \
 	pixman-region32.c \
 	pixman-solid-fill.c \
-	pixman-srgb.c \
 	pixman-trap.c \
 	pixman-utils.c \
 	pixman-x86.c \
 	$(NULL)
 
 ifdef USE_MMX
 CSRCS += pixman-mmx.c
 DEFINES += -DUSE_MMX
--- a/gfx/cairo/libpixman/src/pixman-access.c
+++ b/gfx/cairo/libpixman/src/pixman-access.c
@@ -26,16 +26,17 @@
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <math.h>
 
 #include "pixman-accessor.h"
 #include "pixman-private.h"
 
 #define CONVERT_RGB24_TO_Y15(s)						\
     (((((s) >> 16) & 0xff) * 153 +					\
       (((s) >>  8) & 0xff) * 301 +					\
       (((s)      ) & 0xff) * 58) >> 2)
@@ -501,142 +502,238 @@ MAKE_ACCESSORS(c4);
 MAKE_ACCESSORS(r1g2b1);
 MAKE_ACCESSORS(b1g2r1);
 MAKE_ACCESSORS(a1r1g1b1);
 MAKE_ACCESSORS(a1b1g1r1);
 MAKE_ACCESSORS(a1);
 MAKE_ACCESSORS(g1);
 
 /********************************** Fetch ************************************/
+/* Table mapping sRGB-encoded 8 bit numbers to linearly encoded
+ * floating point numbers. We assume that single precision
+ * floating point follows the IEEE 754 format.
+ */
+static const uint32_t to_linear_u[256] =
+{
+    0x00000000, 0x399f22b4, 0x3a1f22b4, 0x3a6eb40e, 0x3a9f22b4, 0x3ac6eb61,
+    0x3aeeb40e, 0x3b0b3e5d, 0x3b1f22b4, 0x3b33070b, 0x3b46eb61, 0x3b5b518a,
+    0x3b70f18a, 0x3b83e1c5, 0x3b8fe614, 0x3b9c87fb, 0x3ba9c9b5, 0x3bb7ad6d,
+    0x3bc63547, 0x3bd5635f, 0x3be539bd, 0x3bf5ba70, 0x3c0373b5, 0x3c0c6152,
+    0x3c15a703, 0x3c1f45bc, 0x3c293e68, 0x3c3391f4, 0x3c3e4149, 0x3c494d43,
+    0x3c54b6c7, 0x3c607eb1, 0x3c6ca5df, 0x3c792d22, 0x3c830aa8, 0x3c89af9e,
+    0x3c9085db, 0x3c978dc5, 0x3c9ec7c0, 0x3ca63432, 0x3cadd37d, 0x3cb5a601,
+    0x3cbdac20, 0x3cc5e639, 0x3cce54ab, 0x3cd6f7d2, 0x3cdfd00e, 0x3ce8ddb9,
+    0x3cf2212c, 0x3cfb9ac1, 0x3d02a569, 0x3d0798dc, 0x3d0ca7e4, 0x3d11d2ae,
+    0x3d171963, 0x3d1c7c2e, 0x3d21fb3a, 0x3d2796af, 0x3d2d4ebb, 0x3d332380,
+    0x3d39152b, 0x3d3f23e3, 0x3d454fd0, 0x3d4b991c, 0x3d51ffeb, 0x3d588466,
+    0x3d5f26b7, 0x3d65e6fe, 0x3d6cc564, 0x3d73c210, 0x3d7add25, 0x3d810b65,
+    0x3d84b793, 0x3d88732e, 0x3d8c3e48, 0x3d9018f4, 0x3d940343, 0x3d97fd48,
+    0x3d9c0714, 0x3da020b9, 0x3da44a48, 0x3da883d6, 0x3daccd70, 0x3db12728,
+    0x3db59110, 0x3dba0b38, 0x3dbe95b2, 0x3dc3308f, 0x3dc7dbe0, 0x3dcc97b4,
+    0x3dd1641c, 0x3dd6412a, 0x3ddb2eec, 0x3de02d75, 0x3de53cd3, 0x3dea5d16,
+    0x3def8e52, 0x3df4d091, 0x3dfa23e5, 0x3dff885e, 0x3e027f06, 0x3e05427f,
+    0x3e080ea2, 0x3e0ae376, 0x3e0dc104, 0x3e10a752, 0x3e139669, 0x3e168e50,
+    0x3e198f0e, 0x3e1c98ab, 0x3e1fab2e, 0x3e22c6a0, 0x3e25eb08, 0x3e29186a,
+    0x3e2c4ed0, 0x3e2f8e42, 0x3e32d6c4, 0x3e362861, 0x3e39831e, 0x3e3ce702,
+    0x3e405416, 0x3e43ca5e, 0x3e4749e4, 0x3e4ad2ae, 0x3e4e64c2, 0x3e520027,
+    0x3e55a4e6, 0x3e595303, 0x3e5d0a8a, 0x3e60cb7c, 0x3e6495e0, 0x3e6869bf,
+    0x3e6c4720, 0x3e702e08, 0x3e741e7f, 0x3e78188c, 0x3e7c1c34, 0x3e8014c0,
+    0x3e822039, 0x3e84308b, 0x3e8645b8, 0x3e885fc3, 0x3e8a7eb0, 0x3e8ca281,
+    0x3e8ecb3a, 0x3e90f8df, 0x3e932b72, 0x3e9562f6, 0x3e979f6f, 0x3e99e0e0,
+    0x3e9c274e, 0x3e9e72b8, 0x3ea0c322, 0x3ea31892, 0x3ea57308, 0x3ea7d28a,
+    0x3eaa3718, 0x3eaca0b7, 0x3eaf0f69, 0x3eb18332, 0x3eb3fc16, 0x3eb67a15,
+    0x3eb8fd34, 0x3ebb8576, 0x3ebe12de, 0x3ec0a56e, 0x3ec33d2a, 0x3ec5da14,
+    0x3ec87c30, 0x3ecb2380, 0x3ecdd008, 0x3ed081ca, 0x3ed338c9, 0x3ed5f508,
+    0x3ed8b68a, 0x3edb7d52, 0x3ede4962, 0x3ee11abe, 0x3ee3f168, 0x3ee6cd64,
+    0x3ee9aeb6, 0x3eec955d, 0x3eef815d, 0x3ef272ba, 0x3ef56976, 0x3ef86594,
+    0x3efb6717, 0x3efe6e02, 0x3f00bd2b, 0x3f02460c, 0x3f03d1a5, 0x3f055ff8,
+    0x3f06f105, 0x3f0884ce, 0x3f0a1b54, 0x3f0bb499, 0x3f0d509f, 0x3f0eef65,
+    0x3f1090ef, 0x3f12353c, 0x3f13dc50, 0x3f15862a, 0x3f1732cc, 0x3f18e237,
+    0x3f1a946d, 0x3f1c4970, 0x3f1e013f, 0x3f1fbbde, 0x3f21794c, 0x3f23398c,
+    0x3f24fca0, 0x3f26c286, 0x3f288b42, 0x3f2a56d3, 0x3f2c253d, 0x3f2df680,
+    0x3f2fca9d, 0x3f31a195, 0x3f337b6a, 0x3f35581e, 0x3f3737b1, 0x3f391a24,
+    0x3f3aff7a, 0x3f3ce7b2, 0x3f3ed2d0, 0x3f40c0d2, 0x3f42b1bc, 0x3f44a58e,
+    0x3f469c49, 0x3f4895ee, 0x3f4a9280, 0x3f4c91ff, 0x3f4e946c, 0x3f5099c8,
+    0x3f52a216, 0x3f54ad55, 0x3f56bb88, 0x3f58ccae, 0x3f5ae0cb, 0x3f5cf7de,
+    0x3f5f11ec, 0x3f612ef0, 0x3f634eef, 0x3f6571ea, 0x3f6797e1, 0x3f69c0d6,
+    0x3f6beccb, 0x3f6e1bc0, 0x3f704db6, 0x3f7282af, 0x3f74baac, 0x3f76f5ae,
+    0x3f7933b6, 0x3f7b74c6, 0x3f7db8de, 0x3f800000
+};
 
-/* Expects a uint64_t buffer */
+static const float * const to_linear = (const float *)to_linear_u;
+
+static uint8_t
+to_srgb (float f)
+{
+    uint8_t low = 0;
+    uint8_t high = 255;
+
+    while (high - low > 1)
+    {
+	uint8_t mid = (low + high) / 2;
+
+	if (to_linear[mid] > f)
+	    high = mid;
+	else
+	    low = mid;
+    }
+
+    if (to_linear[high] - f < f - to_linear[low])
+	return high;
+    else
+	return low;
+}
+
 static void
-fetch_scanline_a2r10g10b10 (pixman_image_t *image,
-                            int             x,
-                            int             y,
-                            int             width,
-                            uint32_t *      b,
-                            const uint32_t *mask)
+fetch_scanline_a8r8g8b8_sRGB_float (pixman_image_t *image,
+				    int             x,
+				    int             y,
+				    int             width,
+				    uint32_t *      b,
+				    const uint32_t *mask)
 {
     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
     const uint32_t *pixel = bits + x;
     const uint32_t *end = pixel + width;
-    uint64_t *buffer = (uint64_t *)b;
+    argb_t *buffer = (argb_t *)b;
+
+    while (pixel < end)
+    {
+	uint32_t p = READ (image, pixel++);
+	argb_t *argb = buffer;
+
+	argb->a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
+
+	argb->r = to_linear [(p >> 16) & 0xff];
+	argb->g = to_linear [(p >>  8) & 0xff];
+	argb->b = to_linear [(p >>  0) & 0xff];
+
+	buffer++;
+    }
+}
+
+/* Expects a float buffer */
+static void
+fetch_scanline_a2r10g10b10_float (pixman_image_t *image,
+				  int             x,
+				  int             y,
+				  int             width,
+				  uint32_t *      b,
+				  const uint32_t *mask)
+{
+    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
+    const uint32_t *pixel = bits + x;
+    const uint32_t *end = pixel + width;
+    argb_t *buffer = (argb_t *)b;
 
     while (pixel < end)
     {
 	uint32_t p = READ (image, pixel++);
 	uint64_t a = p >> 30;
 	uint64_t r = (p >> 20) & 0x3ff;
 	uint64_t g = (p >> 10) & 0x3ff;
 	uint64_t b = p & 0x3ff;
 
-	r = r << 6 | r >> 4;
-	g = g << 6 | g >> 4;
-	b = b << 6 | b >> 4;
+	buffer->a = pixman_unorm_to_float (a, 2);
+	buffer->r = pixman_unorm_to_float (r, 10);
+	buffer->g = pixman_unorm_to_float (g, 10);
+	buffer->b = pixman_unorm_to_float (b, 10);
 
-	a <<= 14;
-	a |= a >> 2;
-	a |= a >> 4;
-	a |= a >> 8;
-
-	*buffer++ = a << 48 | r << 32 | g << 16 | b;
+	buffer++;
     }
 }
 
-/* Expects a uint64_t buffer */
+/* Expects a float buffer */
 static void
-fetch_scanline_x2r10g10b10 (pixman_image_t *image,
-                            int             x,
-                            int             y,
-                            int             width,
-                            uint32_t *      b,
-                            const uint32_t *mask)
+fetch_scanline_x2r10g10b10_float (pixman_image_t *image,
+				  int             x,
+				  int             y,
+				  int             width,
+				  uint32_t *      b,
+				  const uint32_t *mask)
 {
     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
     const uint32_t *pixel = (uint32_t *)bits + x;
     const uint32_t *end = pixel + width;
-    uint64_t *buffer = (uint64_t *)b;
-    
+    argb_t *buffer = (argb_t *)b;
+
     while (pixel < end)
     {
 	uint32_t p = READ (image, pixel++);
 	uint64_t r = (p >> 20) & 0x3ff;
 	uint64_t g = (p >> 10) & 0x3ff;
 	uint64_t b = p & 0x3ff;
-	
-	r = r << 6 | r >> 4;
-	g = g << 6 | g >> 4;
-	b = b << 6 | b >> 4;
-	
-	*buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b;
+
+	buffer->a = 1.0;
+	buffer->r = pixman_unorm_to_float (r, 10);
+	buffer->g = pixman_unorm_to_float (g, 10);
+	buffer->b = pixman_unorm_to_float (b, 10);
+
+	buffer++;
     }
 }
 
-/* Expects a uint64_t buffer */
+/* Expects a float buffer */
 static void
-fetch_scanline_a2b10g10r10 (pixman_image_t *image,
-                            int             x,
-                            int             y,
-                            int             width,
-                            uint32_t *      b,
-                            const uint32_t *mask)
+fetch_scanline_a2b10g10r10_float (pixman_image_t *image,
+				  int             x,
+				  int             y,
+				  int             width,
+				  uint32_t *      b,
+				  const uint32_t *mask)
 {
     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
     const uint32_t *pixel = bits + x;
     const uint32_t *end = pixel + width;
-    uint64_t *buffer = (uint64_t *)b;
-    
+    argb_t *buffer = (argb_t *)b;
+
     while (pixel < end)
     {
 	uint32_t p = READ (image, pixel++);
 	uint64_t a = p >> 30;
 	uint64_t b = (p >> 20) & 0x3ff;
 	uint64_t g = (p >> 10) & 0x3ff;
 	uint64_t r = p & 0x3ff;
-	
-	r = r << 6 | r >> 4;
-	g = g << 6 | g >> 4;
-	b = b << 6 | b >> 4;
-	
-	a <<= 14;
-	a |= a >> 2;
-	a |= a >> 4;
-	a |= a >> 8;
 
-	*buffer++ = a << 48 | r << 32 | g << 16 | b;
+	buffer->a = pixman_unorm_to_float (a, 2);
+	buffer->r = pixman_unorm_to_float (r, 10);
+	buffer->g = pixman_unorm_to_float (g, 10);
+	buffer->b = pixman_unorm_to_float (b, 10);
+
+	buffer++;
     }
 }
 
-/* Expects a uint64_t buffer */
+/* Expects a float buffer */
 static void
-fetch_scanline_x2b10g10r10 (pixman_image_t *image,
-                            int             x,
-                            int             y,
-                            int             width,
-                            uint32_t *      b,
-                            const uint32_t *mask)
+fetch_scanline_x2b10g10r10_float (pixman_image_t *image,
+				  int             x,
+				  int             y,
+				  int             width,
+				  uint32_t *      b,
+				  const uint32_t *mask)
 {
     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
     const uint32_t *pixel = (uint32_t *)bits + x;
     const uint32_t *end = pixel + width;
-    uint64_t *buffer = (uint64_t *)b;
-    
+    argb_t *buffer = (argb_t *)b;
+
     while (pixel < end)
     {
 	uint32_t p = READ (image, pixel++);
 	uint64_t b = (p >> 20) & 0x3ff;
 	uint64_t g = (p >> 10) & 0x3ff;
 	uint64_t r = p & 0x3ff;
-	
-	r = r << 6 | r >> 4;
-	g = g << 6 | g >> 4;
-	b = b << 6 | b >> 4;
-	
-	*buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b;
+
+	buffer->a = 1.0;
+	buffer->r = pixman_unorm_to_float (r, 10);
+	buffer->g = pixman_unorm_to_float (g, 10);
+	buffer->b = pixman_unorm_to_float (b, 10);
+
+	buffer++;
     }
 }
 
 static void
 fetch_scanline_yuy2 (pixman_image_t *image,
                      int             x,
                      int             line,
                      int             width,
@@ -703,102 +800,114 @@ fetch_scanline_yv12 (pixman_image_t *ima
 	    (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
 	    (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
 	    (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
     }
 }
 
 /**************************** Pixel wise fetching *****************************/
 
-/* Despite the type, expects a uint64_t buffer */
-static uint64_t
-fetch_pixel_a2r10g10b10 (bits_image_t *image,
-			 int		  offset,
-			 int           line)
+static argb_t
+fetch_pixel_x2r10g10b10_float (bits_image_t *image,
+			       int	   offset,
+			       int           line)
+{
+    uint32_t *bits = image->bits + line * image->rowstride;
+    uint32_t p = READ (image, bits + offset);
+    uint64_t r = (p >> 20) & 0x3ff;
+    uint64_t g = (p >> 10) & 0x3ff;
+    uint64_t b = p & 0x3ff;
+    argb_t argb;
+
+    argb.a = 1.0;
+    argb.r = pixman_unorm_to_float (r, 10);
+    argb.g = pixman_unorm_to_float (g, 10);
+    argb.b = pixman_unorm_to_float (b, 10);
+
+    return argb;
+}
+
+static argb_t
+fetch_pixel_a2r10g10b10_float (bits_image_t *image,
+			       int	     offset,
+			       int           line)
 {
     uint32_t *bits = image->bits + line * image->rowstride;
     uint32_t p = READ (image, bits + offset);
     uint64_t a = p >> 30;
     uint64_t r = (p >> 20) & 0x3ff;
     uint64_t g = (p >> 10) & 0x3ff;
     uint64_t b = p & 0x3ff;
-
-    r = r << 6 | r >> 4;
-    g = g << 6 | g >> 4;
-    b = b << 6 | b >> 4;
+    argb_t argb;
 
-    a <<= 14;
-    a |= a >> 2;
-    a |= a >> 4;
-    a |= a >> 8;
+    argb.a = pixman_unorm_to_float (a, 2);
+    argb.r = pixman_unorm_to_float (r, 10);
+    argb.g = pixman_unorm_to_float (g, 10);
+    argb.b = pixman_unorm_to_float (b, 10);
 
-    return a << 48 | r << 32 | g << 16 | b;
+    return argb;
 }
 
-/* Despite the type, this function expects a uint64_t buffer */
-static uint64_t
-fetch_pixel_x2r10g10b10 (bits_image_t *image,
-			 int	   offset,
-			 int           line)
-{
-    uint32_t *bits = image->bits + line * image->rowstride;
-    uint32_t p = READ (image, bits + offset);
-    uint64_t r = (p >> 20) & 0x3ff;
-    uint64_t g = (p >> 10) & 0x3ff;
-    uint64_t b = p & 0x3ff;
-    
-    r = r << 6 | r >> 4;
-    g = g << 6 | g >> 4;
-    b = b << 6 | b >> 4;
-    
-    return 0xffffULL << 48 | r << 32 | g << 16 | b;
-}
-
-/* Despite the type, expects a uint64_t buffer */
-static uint64_t
-fetch_pixel_a2b10g10r10 (bits_image_t *image,
-			 int           offset,
-			 int           line)
+static argb_t
+fetch_pixel_a2b10g10r10_float (bits_image_t *image,
+			       int           offset,
+			       int           line)
 {
     uint32_t *bits = image->bits + line * image->rowstride;
     uint32_t p = READ (image, bits + offset);
     uint64_t a = p >> 30;
     uint64_t b = (p >> 20) & 0x3ff;
     uint64_t g = (p >> 10) & 0x3ff;
     uint64_t r = p & 0x3ff;
-    
-    r = r << 6 | r >> 4;
-    g = g << 6 | g >> 4;
-    b = b << 6 | b >> 4;
-    
-    a <<= 14;
-    a |= a >> 2;
-    a |= a >> 4;
-    a |= a >> 8;
-    
-    return a << 48 | r << 32 | g << 16 | b;
+    argb_t argb;
+
+    argb.a = pixman_unorm_to_float (a, 2);
+    argb.r = pixman_unorm_to_float (r, 10);
+    argb.g = pixman_unorm_to_float (g, 10);
+    argb.b = pixman_unorm_to_float (b, 10);
+
+    return argb;
 }
 
-/* Despite the type, this function expects a uint64_t buffer */
-static uint64_t
-fetch_pixel_x2b10g10r10 (bits_image_t *image,
-			 int           offset,
-			 int           line)
+static argb_t
+fetch_pixel_x2b10g10r10_float (bits_image_t *image,
+			       int           offset,
+			       int           line)
 {
     uint32_t *bits = image->bits + line * image->rowstride;
     uint32_t p = READ (image, bits + offset);
     uint64_t b = (p >> 20) & 0x3ff;
     uint64_t g = (p >> 10) & 0x3ff;
     uint64_t r = p & 0x3ff;
-    
-    r = r << 6 | r >> 4;
-    g = g << 6 | g >> 4;
-    b = b << 6 | b >> 4;
-    
-    return 0xffffULL << 48 | r << 32 | g << 16 | b;
+    argb_t argb;
+
+    argb.a = 1.0;
+    argb.r = pixman_unorm_to_float (r, 10);
+    argb.g = pixman_unorm_to_float (g, 10);
+    argb.b = pixman_unorm_to_float (b, 10);
+
+    return argb;
+}
+
+static argb_t
+fetch_pixel_a8r8g8b8_sRGB_float (bits_image_t *image,
+				 int	       offset,
+				 int           line)
+{
+    uint32_t *bits = image->bits + line * image->rowstride;
+    uint32_t p = READ (image, bits + offset);
+    argb_t argb;
+
+    argb.a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
+
+    argb.r = to_linear [(p >> 16) & 0xff];
+    argb.g = to_linear [(p >>  8) & 0xff];
+    argb.b = to_linear [(p >>  0) & 0xff];
+
+    return argb;
 }
 
 static uint32_t
 fetch_pixel_yuy2 (bits_image_t *image,
 		  int           offset,
 		  int           line)
 {
     const uint32_t *bits = image->bits + image->rowstride * line;
@@ -849,98 +958,140 @@ fetch_pixel_yv12 (bits_image_t *image,
 	(r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
 	(g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
 	(b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
 }
 
 /*********************************** Store ************************************/
 
 static void
-store_scanline_a2r10g10b10 (bits_image_t *  image,
-                            int             x,
-                            int             y,
-                            int             width,
-                            const uint32_t *v)
+store_scanline_a2r10g10b10_float (bits_image_t *  image,
+				  int             x,
+				  int             y,
+				  int             width,
+				  const uint32_t *v)
 {
     uint32_t *bits = image->bits + image->rowstride * y;
     uint32_t *pixel = bits + x;
-    uint64_t *values = (uint64_t *)v;
+    argb_t *values = (argb_t *)v;
     int i;
-    
+
     for (i = 0; i < width; ++i)
     {
+	uint16_t a, r, g, b;
+
+	a = pixman_float_to_unorm (values[i].a, 2);
+	r = pixman_float_to_unorm (values[i].r, 10);
+	g = pixman_float_to_unorm (values[i].g, 10);
+	b = pixman_float_to_unorm (values[i].b, 10);
+
 	WRITE (image, pixel++,
-	       ((values[i] >> 32) & 0xc0000000) |
-	       ((values[i] >> 18) & 0x3ff00000) |
-	       ((values[i] >> 12) & 0xffc00) | 
-	       ((values[i] >> 6) & 0x3ff));    
+	       (a << 30) | (r << 20) | (g << 10) | b);
+    }
+}
+
+static void
+store_scanline_x2r10g10b10_float (bits_image_t *  image,
+				  int             x,
+				  int             y,
+				  int             width,
+				  const uint32_t *v)
+{
+    uint32_t *bits = image->bits + image->rowstride * y;
+    uint32_t *pixel = bits + x;
+    argb_t *values = (argb_t *)v;
+    int i;
+
+    for (i = 0; i < width; ++i)
+    {
+	uint16_t r, g, b;
+
+	r = pixman_float_to_unorm (values[i].r, 10);
+	g = pixman_float_to_unorm (values[i].g, 10);
+	b = pixman_float_to_unorm (values[i].b, 10);
+
+	WRITE (image, pixel++,
+	       (r << 20) | (g << 10) | b);
     }
 }
 
 static void
-store_scanline_x2r10g10b10 (bits_image_t *  image,
-                            int             x,
-                            int             y,
-                            int             width,
-                            const uint32_t *v)
+store_scanline_a2b10g10r10_float (bits_image_t *  image,
+				  int             x,
+				  int             y,
+				  int             width,
+				  const uint32_t *v)
 {
     uint32_t *bits = image->bits + image->rowstride * y;
-    uint64_t *values = (uint64_t *)v;
     uint32_t *pixel = bits + x;
+    argb_t *values = (argb_t *)v;
     int i;
-    
+
     for (i = 0; i < width; ++i)
     {
+	uint16_t a, r, g, b;
+
+	a = pixman_float_to_unorm (values[i].a, 2);
+	r = pixman_float_to_unorm (values[i].r, 10);
+	g = pixman_float_to_unorm (values[i].g, 10);
+	b = pixman_float_to_unorm (values[i].b, 10);
+
 	WRITE (image, pixel++,
-	       ((values[i] >> 18) & 0x3ff00000) | 
-	       ((values[i] >> 12) & 0xffc00) |
-	       ((values[i] >> 6) & 0x3ff));
+	       (a << 30) | (b << 20) | (g << 10) | r);
     }
 }
 
 static void
-store_scanline_a2b10g10r10 (bits_image_t *  image,
-                            int             x,
-                            int             y,
-                            int             width,
-                            const uint32_t *v)
+store_scanline_x2b10g10r10_float (bits_image_t *  image,
+				  int             x,
+				  int             y,
+				  int             width,
+				  const uint32_t *v)
 {
     uint32_t *bits = image->bits + image->rowstride * y;
     uint32_t *pixel = bits + x;
-    uint64_t *values = (uint64_t *)v;
+    argb_t *values = (argb_t *)v;
     int i;
-    
+
     for (i = 0; i < width; ++i)
     {
+	uint16_t r, g, b;
+
+	r = pixman_float_to_unorm (values[i].r, 10);
+	g = pixman_float_to_unorm (values[i].g, 10);
+	b = pixman_float_to_unorm (values[i].b, 10);
+
 	WRITE (image, pixel++,
-	       ((values[i] >> 32) & 0xc0000000) |
-	       ((values[i] >> 38) & 0x3ff) |
-	       ((values[i] >> 12) & 0xffc00) |
-	       ((values[i] << 14) & 0x3ff00000));
+	       (b << 20) | (g << 10) | r);
     }
 }
 
 static void
-store_scanline_x2b10g10r10 (bits_image_t *  image,
-                            int             x,
-                            int             y,
-                            int             width,
-                            const uint32_t *v)
+store_scanline_a8r8g8b8_sRGB_float (bits_image_t *  image,
+				    int             x,
+				    int             y,
+				    int             width,
+				    const uint32_t *v)
 {
     uint32_t *bits = image->bits + image->rowstride * y;
-    uint64_t *values = (uint64_t *)v;
     uint32_t *pixel = bits + x;
+    argb_t *values = (argb_t *)v;
     int i;
-    
+
     for (i = 0; i < width; ++i)
     {
+	uint8_t a, r, g, b;
+
+	a = pixman_float_to_unorm (values[i].a, 8);
+	r = to_srgb (values[i].r);
+	g = to_srgb (values[i].g);
+	b = to_srgb (values[i].b);
+
 	WRITE (image, pixel++,
-	       ((values[i] >> 38) & 0x3ff) |
-	       ((values[i] >> 12) & 0xffc00) |
-	       ((values[i] << 14) & 0x3ff00000));
+	       (a << 24) | (r << 16) | (g << 8) | b);
     }
 }
 
 static void
 store_scanline_16 (bits_image_t *  image,
 		   int             x,
 		   int             y,
 		   int             width,
@@ -973,102 +1124,56 @@ fetch_scanline_16 (pixman_image_t *image
     for (i = 0; i < width; ++i)
     {
 	*buffer++ = READ (image, pixel++);
     }
 }
 
 
 /*
- * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit
- * store proc. Despite the type, this function expects a uint64_t buffer.
+ * Contracts a floating point image to 32bpp and then stores it using a
+ * regular 32-bit store proc. Despite the type, this function expects an
+ * argb_t buffer.
  */
 static void
-store_scanline_generic_64 (bits_image_t *  image,
-                           int             x,
-                           int             y,
-                           int             width,
-                           const uint32_t *values)
+store_scanline_generic_float (bits_image_t *  image,
+			      int             x,
+			      int             y,
+			      int             width,
+			      const uint32_t *values)
 {
     uint32_t *argb8_pixels;
-    
+
     assert (image->common.type == BITS);
-    
+
     argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t));
     if (!argb8_pixels)
 	return;
-    
+
     /* Contract the scanline.  We could do this in place if values weren't
      * const.
      */
-    pixman_contract (argb8_pixels, (uint64_t *)values, width);
-    
+    pixman_contract_from_float (argb8_pixels, (argb_t *)values, width);
+
     image->store_scanline_32 (image, x, y, width, argb8_pixels);
-    
+
     free (argb8_pixels);
 }
 
-/* Despite the type, this function expects both buffer
- * and mask to be uint64_t
- */
 static void
-fetch_scanline_generic_64 (pixman_image_t *image,
-                           int             x,
-                           int             y,
-                           int             width,
-                           uint32_t *      buffer,
-                           const uint32_t *mask)
+fetch_scanline_generic_float (pixman_image_t *image,
+			      int	      x,
+			      int	      y,
+			      int	      width,
+			      uint32_t *      buffer,
+			      const uint32_t *mask)
 {
-    pixman_format_code_t format;
-
-    /* Fetch the pixels into the first half of buffer and then expand them in
-     * place.
-     */
     image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL);
 
-    format = image->bits.format;
-    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR	||
-	PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
-    {
-	/* Indexed formats are mapped to a8r8g8b8 with full
-	 * precision, so when expanding we shouldn't correct
-	 * for the width of the channels
-	 */
-
-	format = PIXMAN_a8r8g8b8;
-    }
-
-    pixman_expand ((uint64_t *)buffer, buffer, format, width);
-}
-
-/* Despite the type, this function expects a uint64_t *buffer */
-static uint64_t
-fetch_pixel_generic_64 (bits_image_t *image,
-			int	      offset,
-			int           line)
-{
-    uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
-    uint64_t result;
-    pixman_format_code_t format;
-
-    format = image->format;
-    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR	||
-	PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
-    {
-	/* Indexed formats are mapped to a8r8g8b8 with full
-	 * precision, so when expanding we shouldn't correct
-	 * for the width of the channels
-	 */
-
-	format = PIXMAN_a8r8g8b8;
-    }
-
-    pixman_expand ((uint64_t *)&result, &pixel32, format, 1);
-
-    return result;
+    pixman_expand_to_float ((argb_t *)buffer, buffer, image->bits.format, width);
 }
 
 /* The 32_sRGB paths should be deleted after narrow processing
  * is no longer invoked for formats that are considered wide.
  * (Also see fetch_pixel_generic_lossy_32) */
 static void
 fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image,
                                  int             x,
@@ -1079,72 +1184,52 @@ fetch_scanline_a8r8g8b8_32_sRGB (pixman_
 {
     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
     const uint32_t *pixel = (uint32_t *)bits + x;
     const uint32_t *end = pixel + width;
     uint32_t tmp;
     
     while (pixel < end)
     {
+	uint8_t a, r, g, b;
+
 	tmp = READ (image, pixel++);
-	*buffer++ =                 (tmp >> 24)               << 24
-		  | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16
-		  | (srgb_to_linear[(tmp >>  8) & 0xff] >> 8) <<  8
-		  | (srgb_to_linear[(tmp >>  0) & 0xff] >> 8) <<  0;
-    }
-}
 
-static void
-fetch_scanline_a8r8g8b8_64_sRGB (pixman_image_t *image,
-                                 int             x,
-                                 int             y,
-                                 int             width,
-                                 uint32_t       *b,
-                                 const uint32_t *mask)
-{
-    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
-    const uint32_t *pixel = (uint32_t *)bits + x;
-    const uint32_t *end = pixel + width;
-    uint64_t *buffer = (uint64_t *)b;
-    uint32_t tmp;
-    
-    while (pixel < end)
-    {
-	tmp = READ (image, pixel++);
-	*buffer++ = (uint64_t)               ((tmp >> 24) * 257)  << 48
-		  | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32
-		  | (uint64_t) srgb_to_linear[(tmp >>  8) & 0xff] << 16
-		  | (uint64_t) srgb_to_linear[(tmp >>  0) & 0xff] <<  0;
+	a = (tmp >> 24) & 0xff;
+	r = (tmp >> 16) & 0xff;
+	g = (tmp >> 8) & 0xff;
+	b = (tmp >> 0) & 0xff;
+
+	r = to_linear[r] * 255.0f + 0.5f;
+	g = to_linear[g] * 255.0f + 0.5f;
+	b = to_linear[b] * 255.0f + 0.5f;
+
+	*buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0);
     }
 }
 
 static uint32_t
 fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image,
 			      int           offset,
 			      int           line)
 {
     uint32_t *bits = image->bits + line * image->rowstride;
     uint32_t tmp = READ (image, bits + offset);
-    return                 (tmp >> 24)               << 24
-	 | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16
-	 | (srgb_to_linear[(tmp >>  8) & 0xff] >> 8) <<  8
-	 | (srgb_to_linear[(tmp >>  0) & 0xff] >> 8) <<  0;
-}
+    uint8_t a, r, g, b;
 
-static uint64_t
-fetch_pixel_a8r8g8b8_64_sRGB (bits_image_t *image,
-			      int           offset,
-			      int	    line)
-{
-    uint32_t *bits = image->bits + line * image->rowstride;
-    uint32_t tmp = READ (image, bits + offset);
-    return (uint64_t)               ((tmp >> 24) * 257)  << 48
-	 | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32
-	 | (uint64_t) srgb_to_linear[(tmp >>  8) & 0xff] << 16
-	 | (uint64_t) srgb_to_linear[(tmp >>  0) & 0xff] <<  0;
+    a = (tmp >> 24) & 0xff;
+    r = (tmp >> 16) & 0xff;
+    g = (tmp >> 8) & 0xff;
+    b = (tmp >> 0) & 0xff;
+
+    r = to_linear[r] * 255.0f + 0.5f;
+    g = to_linear[g] * 255.0f + 0.5f;
+    b = to_linear[b] * 255.0f + 0.5f;
+
+    return (a << 24) | (r << 16) | (g << 8) | (b << 0);
 }
 
 static void
 store_scanline_a8r8g8b8_32_sRGB (bits_image_t   *image,
                                  int             x,
                                  int             y,
                                  int             width,
                                  const uint32_t *v)
@@ -1152,100 +1237,101 @@ store_scanline_a8r8g8b8_32_sRGB (bits_im
     uint32_t *bits = image->bits + image->rowstride * y;
     uint64_t *values = (uint64_t *)v;
     uint32_t *pixel = bits + x;
     uint64_t tmp;
     int i;
     
     for (i = 0; i < width; ++i)
     {
+	uint8_t a, r, g, b;
+
 	tmp = values[i];
-	WRITE (image, pixel++,
-		  ((uint32_t)     (tmp >> 24     )          << 24)
-		| (linear_to_srgb[(tmp >> 16 << 4) & 0xfff] << 16)
-		| (linear_to_srgb[(tmp >>  8 << 4) & 0xfff] <<  8)
-		| (linear_to_srgb[(tmp >>  0 << 4) & 0xfff] <<  0));
+
+	a = (tmp >> 24) & 0xff;
+	r = (tmp >> 16) & 0xff;
+	g = (tmp >> 8) & 0xff;
+	b = (tmp >> 0) & 0xff;
+
+	r = to_srgb (r * (1/255.0f));
+	g = to_srgb (g * (1/255.0f));
+	b = to_srgb (b * (1/255.0f));
+	
+	WRITE (image, pixel++, a | (r << 16) | (g << 8) | (b << 0));
     }
 }
 
-static void
-store_scanline_a8r8g8b8_64_sRGB (bits_image_t  *image,
-                                int             x,
-                                int             y,
-                                int             width,
-                                const uint32_t *v)
+static argb_t
+fetch_pixel_generic_float (bits_image_t *image,
+			   int		 offset,
+			   int           line)
 {
-    uint32_t *bits = image->bits + image->rowstride * y;
-    uint64_t *values = (uint64_t *)v;
-    uint32_t *pixel = bits + x;
-    uint64_t tmp;
-    int i;
-    
-    for (i = 0; i < width; ++i)
-    {
-	tmp = values[i];
-	WRITE (image, pixel++,
-		  ((uint32_t)     (tmp >> 56)          << 24)
-		| (linear_to_srgb[(tmp >> 36) & 0xfff] << 16)
-		| (linear_to_srgb[(tmp >> 20) & 0xfff] <<  8)
-		| (linear_to_srgb[(tmp >>  4) & 0xfff] <<  0));
-    }
+    uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
+    argb_t f;
+
+    pixman_expand_to_float (&f, &pixel32, image->format, 1);
+
+    return f;
 }
 
 /*
  * XXX: The transformed fetch path only works at 32-bpp so far.  When all
  * paths have wide versions, this can be removed.
  *
  * WARNING: This function loses precision!
  */
 static uint32_t
 fetch_pixel_generic_lossy_32 (bits_image_t *image,
 			      int           offset,
 			      int           line)
 {
-    uint64_t pixel64 = image->fetch_pixel_64 (image, offset, line);
+    argb_t pixel64 = image->fetch_pixel_float (image, offset, line);
     uint32_t result;
 
-    pixman_contract (&result, &pixel64, 1);
+    pixman_contract_from_float (&result, &pixel64, 1);
 
     return result;
 }
 
 typedef struct
 {
     pixman_format_code_t	format;
     fetch_scanline_t		fetch_scanline_16;
     fetch_scanline_t		fetch_scanline_32;
-    fetch_scanline_t		fetch_scanline_64;
+    fetch_scanline_t		fetch_scanline_float;
     fetch_pixel_32_t		fetch_pixel_32;
-    fetch_pixel_64_t		fetch_pixel_64;
+    fetch_pixel_float_t		fetch_pixel_float;
     store_scanline_t		store_scanline_16;
     store_scanline_t		store_scanline_32;
-    store_scanline_t		store_scanline_64;
+    store_scanline_t		store_scanline_float;
 } format_info_t;
 
 #define FORMAT_INFO(format) 						\
     {									\
 	PIXMAN_ ## format,						\
 	    NULL,							\
 	    fetch_scanline_ ## format,					\
-	    fetch_scanline_generic_64,					\
-	    fetch_pixel_ ## format, fetch_pixel_generic_64,		\
+	    fetch_scanline_generic_float,				\
+	    fetch_pixel_ ## format,					\
+	    fetch_pixel_generic_float,					\
 	    NULL,							\
-	    store_scanline_ ## format, store_scanline_generic_64	\
+	    store_scanline_ ## format,					\
+	    store_scanline_generic_float				\
     }
 #define FORMAT_INFO16(format) 						\
     {									\
 	PIXMAN_ ## format,						\
 	    fetch_scanline_16,						\
 	    fetch_scanline_ ## format,					\
-	    fetch_scanline_generic_64,					\
-	    fetch_pixel_ ## format, fetch_pixel_generic_64,		\
+	    fetch_scanline_generic_float,				\
+	    fetch_pixel_ ## format,					\
+	    fetch_pixel_generic_float,					\
 	    store_scanline_16,						\
-	    store_scanline_ ## format, store_scanline_generic_64	\
+	    store_scanline_ ## format,					\
+	    store_scanline_generic_float				\
     }
 
 
 static const format_info_t accessors[] =
 {
 /* 32 bpp formats */
     FORMAT_INFO (a8r8g8b8),
     FORMAT_INFO (x8r8g8b8),
@@ -1254,20 +1340,20 @@ static const format_info_t accessors[] =
     FORMAT_INFO (b8g8r8a8),
     FORMAT_INFO (b8g8r8x8),
     FORMAT_INFO (r8g8b8a8),
     FORMAT_INFO (r8g8b8x8),
     FORMAT_INFO (x14r6g6b6),
 
 /* sRGB formats */
   { PIXMAN_a8r8g8b8_sRGB,
-    fetch_scanline_a8r8g8b8_32_sRGB,
-    fetch_scanline_a8r8g8b8_64_sRGB,
-    fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_64_sRGB,
-    store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_64_sRGB },
+    fetch_scanline_a8r8g8b8_32_sRGB, fetch_scanline_a8r8g8b8_sRGB_float,
+    fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_sRGB_float,
+    store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_sRGB_float,
+  },
 
 /* 24bpp formats */
     FORMAT_INFO (r8g8b8),
     FORMAT_INFO (b8g8r8),
     
 /* 16bpp formats */
     FORMAT_INFO16 (r5g6b5),
     FORMAT_INFO16 (b5g6r5),
@@ -1317,66 +1403,66 @@ static const format_info_t accessors[] =
     
 /* 1bpp formats */
     FORMAT_INFO (a1),
     FORMAT_INFO (g1),
     
 /* Wide formats */
     
     { PIXMAN_a2r10g10b10,
-      NULL, NULL, fetch_scanline_a2r10g10b10,
-      fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10,
-      NULL, store_scanline_a2r10g10b10 },
-    
+      NULL, NULL, fetch_scanline_a2r10g10b10_float,
+      fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float,
+      NULL, NULL, store_scanline_a2r10g10b10_float },
+
     { PIXMAN_x2r10g10b10,
-      NULL, NULL, fetch_scanline_x2r10g10b10,
-      fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10,
-      NULL, store_scanline_x2r10g10b10 },
-    
+      NULL, NULL, fetch_scanline_x2r10g10b10_float,
+      fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10_float,
+      NULL, NULL, store_scanline_x2r10g10b10_float },
+
     { PIXMAN_a2b10g10r10,
-      NULL, NULL, fetch_scanline_a2b10g10r10,
-      fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10,
-      NULL, store_scanline_a2b10g10r10 },
-    
+      NULL, NULL, fetch_scanline_a2b10g10r10_float,
+      fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10_float,
+      NULL, NULL, store_scanline_a2b10g10r10_float },
+
     { PIXMAN_x2b10g10r10,
-      NULL, NULL, fetch_scanline_x2b10g10r10,
-      fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10,
-      NULL, store_scanline_x2b10g10r10 },
-    
+      NULL, NULL, fetch_scanline_x2b10g10r10_float,
+      fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10_float,
+      NULL, NULL, store_scanline_x2b10g10r10_float },
+
 /* YUV formats */
     { PIXMAN_yuy2,
-      NULL, fetch_scanline_yuy2, fetch_scanline_generic_64,
-      fetch_pixel_yuy2, fetch_pixel_generic_64,
-      NULL, NULL },
-    
+      NULL, fetch_scanline_yuy2, fetch_scanline_generic_float,
+      fetch_pixel_yuy2, fetch_pixel_generic_float,
+      NULL, NULL, NULL },
+
     { PIXMAN_yv12,
-      NULL, fetch_scanline_yv12, fetch_scanline_generic_64,
-      fetch_pixel_yv12, fetch_pixel_generic_64,
-      NULL, NULL },
+      NULL, fetch_scanline_yv12, fetch_scanline_generic_float,
+      fetch_pixel_yv12, fetch_pixel_generic_float,
+      NULL, NULL, NULL },
     
     { PIXMAN_null },
 };
 
 static void
 setup_accessors (bits_image_t *image)
 {
     const format_info_t *info = accessors;
     
     while (info->format != PIXMAN_null)
     {
 	if (info->format == image->format)
 	{
 	    image->fetch_scanline_16 = info->fetch_scanline_16;
 	    image->fetch_scanline_32 = info->fetch_scanline_32;
-	    image->fetch_scanline_64 = info->fetch_scanline_64;
+	    image->fetch_scanline_float = info->fetch_scanline_float;
 	    image->fetch_pixel_32 = info->fetch_pixel_32;
-	    image->fetch_pixel_64 = info->fetch_pixel_64;
+	    image->fetch_pixel_float = info->fetch_pixel_float;
 	    image->store_scanline_16 = info->store_scanline_16;
 	    image->store_scanline_32 = info->store_scanline_32;
-	    image->store_scanline_64 = info->store_scanline_64;
+	    image->store_scanline_float = info->store_scanline_float;
 	    
 	    return;
 	}
 	
 	info++;
     }
 }
 
--- a/gfx/cairo/libpixman/src/pixman-arm-neon.c
+++ b/gfx/cairo/libpixman/src/pixman-arm-neon.c
@@ -195,24 +195,25 @@ pixman_composite_src_n_0565_asm_neon (in
 void
 pixman_composite_src_n_8888_asm_neon (int32_t   w,
                                       int32_t   h,
                                       uint32_t *dst,
                                       int32_t   dst_stride,
                                       uint32_t  src);
 
 static pixman_bool_t
-pixman_fill_neon (uint32_t *bits,
-                  int       stride,
-                  int       bpp,
-                  int       x,
-                  int       y,
-                  int       width,
-                  int       height,
-                  uint32_t  _xor)
+arm_neon_fill (pixman_implementation_t *imp,
+               uint32_t *               bits,
+               int                      stride,
+               int                      bpp,
+               int                      x,
+               int                      y,
+               int                      width,
+               int                      height,
+	       uint32_t                 _xor)
 {
     /* stride is always multiple of 32bit units in pixman */
     uint32_t byte_stride = stride * sizeof(uint32_t);
 
     switch (bpp)
     {
     case 8:
 	pixman_composite_src_n_8_asm_neon (
@@ -239,28 +240,29 @@ pixman_fill_neon (uint32_t *bits,
 		_xor);
 	return TRUE;
     default:
 	return FALSE;
     }
 }
 
 static pixman_bool_t
-pixman_blt_neon (uint32_t *src_bits,
-                 uint32_t *dst_bits,
-                 int       src_stride,
-                 int       dst_stride,
-                 int       src_bpp,
-                 int       dst_bpp,
-                 int       src_x,
-                 int       src_y,
-                 int       dest_x,
-                 int       dest_y,
-                 int       width,
-                 int       height)
+arm_neon_blt (pixman_implementation_t *imp,
+              uint32_t *               src_bits,
+              uint32_t *               dst_bits,
+              int                      src_stride,
+              int                      dst_stride,
+              int                      src_bpp,
+              int                      dst_bpp,
+              int                      src_x,
+              int                      src_y,
+              int                      dest_x,
+              int                      dest_y,
+              int                      width,
+              int                      height)
 {
     if (src_bpp != dst_bpp)
 	return FALSE;
 
     switch (src_bpp)
     {
     case 16:
 	pixman_composite_src_0565_0565_asm_neon (
@@ -458,63 +460,16 @@ static const pixman_fast_path_t arm_neon
     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
 
     SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_0565),
 
     { PIXMAN_OP_NONE },
 };
 
-static pixman_bool_t
-arm_neon_blt (pixman_implementation_t *imp,
-              uint32_t *               src_bits,
-              uint32_t *               dst_bits,
-              int                      src_stride,
-              int                      dst_stride,
-              int                      src_bpp,
-              int                      dst_bpp,
-              int                      src_x,
-              int                      src_y,
-              int                      dest_x,
-              int                      dest_y,
-              int                      width,
-              int                      height)
-{
-    if (!pixman_blt_neon (
-            src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
-            src_x, src_y, dest_x, dest_y, width, height))
-
-    {
-	return _pixman_implementation_blt (
-	    imp->delegate,
-	    src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
-	    src_x, src_y, dest_x, dest_y, width, height);
-    }
-
-    return TRUE;
-}
-
-static pixman_bool_t
-arm_neon_fill (pixman_implementation_t *imp,
-               uint32_t *               bits,
-               int                      stride,
-               int                      bpp,
-               int                      x,
-               int                      y,
-               int                      width,
-               int                      height,
-               uint32_t xor)
-{
-    if (pixman_fill_neon (bits, stride, bpp, x, y, width, height, xor))
-	return TRUE;
-
-    return _pixman_implementation_fill (
-	imp->delegate, bits, stride, bpp, x, y, width, height, xor);
-}
-
 #define BIND_COMBINE_U(name)                                             \
 void                                                                     \
 pixman_composite_scanline_##name##_mask_asm_neon (int32_t         w,     \
                                                   const uint32_t *dst,   \
                                                   const uint32_t *src,   \
                                                   const uint32_t *mask); \
                                                                          \
 void                                                                     \
--- a/gfx/cairo/libpixman/src/pixman-bits-image.c
+++ b/gfx/cairo/libpixman/src/pixman-bits-image.c
@@ -31,53 +31,28 @@
 #endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "pixman-private.h"
 #include "pixman-combine32.h"
 #include "pixman-inlines.h"
 
-/*
- * By default, just evaluate the image at 32bpp and expand.  Individual image
- * types can plug in a better scanline getter if they want to. For example
- * we  could produce smoother gradients by evaluating them at higher color
- * depth, but that's a project for the future.
- */
 static uint32_t *
-_pixman_image_get_scanline_generic_64 (pixman_iter_t * iter,
-                                       const uint32_t *mask)
+_pixman_image_get_scanline_generic_float (pixman_iter_t * iter,
+					  const uint32_t *mask)
 {
-    int             width  = iter->width;
-    uint32_t *      buffer = iter->buffer;
-
     pixman_iter_get_scanline_t fetch_32 = iter->data;
-    uint32_t *mask8 = NULL;
+    uint32_t *buffer = iter->buffer;
 
-    /* Contract the mask image, if one exists, so that the 32-bit fetch
-     * function can use it.
-     */
-    if (mask)
-    {
-	mask8 = pixman_malloc_ab (width, sizeof(uint32_t));
-	if (!mask8)
-	    return buffer;
+    fetch_32 (iter, NULL);
 
-	pixman_contract (mask8, (uint64_t *)mask, width);
-    }
-
-    /* Fetch the source image into the first half of buffer. */
-    fetch_32 (iter, mask8);
+    pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
 
-    /* Expand from 32bpp to 64bpp in place. */
-    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, width);
-
-    free (mask8);
-
-    return buffer;
+    return iter->buffer;
 }
 
 /* Fetch functions */
 
 static force_inline uint32_t
 fetch_pixel_no_alpha (bits_image_t *image,
 		      int x, int y, pixman_bool_t check_bounds)
 {
@@ -960,27 +935,27 @@ replicate_pixel_32 (bits_image_t *   bit
     color = bits->fetch_pixel_32 (bits, x, y);
 
     end = buffer + width;
     while (buffer < end)
 	*(buffer++) = color;
 }
 
 static void
-replicate_pixel_64 (bits_image_t *   bits,
-		    int              x,
-		    int              y,
-		    int              width,
-		    uint32_t *       b)
+replicate_pixel_float (bits_image_t *   bits,
+		       int              x,
+		       int              y,
+		       int              width,
+		       uint32_t *       b)
 {
-    uint64_t color;
-    uint64_t *buffer = (uint64_t *)b;
-    uint64_t *end;
+    argb_t color;
+    argb_t *buffer = (argb_t *)b;
+    argb_t *end;
 
-    color = bits->fetch_pixel_64 (bits, x, y);
+    color = bits->fetch_pixel_float (bits, x, y);
 
     end = buffer + width;
     while (buffer < end)
 	*(buffer++) = color;
 }
 
 static void
 bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
@@ -989,46 +964,46 @@ bits_image_fetch_untransformed_repeat_no
                                             int           y,
                                             int           width,
                                             uint32_t *    buffer)
 {
     uint32_t w;
 
     if (y < 0 || y >= image->height)
     {
-	memset (buffer, 0, width * (wide? 8 : 4));
+	memset (buffer, 0, width * (wide? sizeof (argb_t) : 4));
 	return;
     }
 
     if (x < 0)
     {
 	w = MIN (width, -x);
 
-	memset (buffer, 0, w * (wide ? 8 : 4));
+	memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4));
 
 	width -= w;
-	buffer += w * (wide? 2 : 1);
+	buffer += w * (wide? 4 : 1);
 	x += w;
     }
 
     if (x < image->width)
     {
 	w = MIN (width, image->width - x);
 
 	if (wide)
-	    image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+	    image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
 	else
 	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
 
 	width -= w;
-	buffer += w * (wide? 2 : 1);
+	buffer += w * (wide? 4 : 1);
 	x += w;
     }
 
-    memset (buffer, 0, width * (wide ? 8 : 4));
+    memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4));
 }
 
 static void
 bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
                                               pixman_bool_t wide,
                                               int           x,
                                               int           y,
                                               int           width,
@@ -1040,38 +1015,38 @@ bits_image_fetch_untransformed_repeat_no
 	y += image->height;
 
     while (y >= image->height)
 	y -= image->height;
 
     if (image->width == 1)
     {
 	if (wide)
-	    replicate_pixel_64 (image, 0, y, width, buffer);
+	    replicate_pixel_float (image, 0, y, width, buffer);
 	else
 	    replicate_pixel_32 (image, 0, y, width, buffer);
 
 	return;
     }
 
     while (width)
     {
 	while (x < 0)
 	    x += image->width;
 	while (x >= image->width)
 	    x -= image->width;
 
 	w = MIN (width, image->width - x);
 
 	if (wide)
-	    image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+	    image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
 	else
 	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
 
-	buffer += w * (wide? 2 : 1);
+	buffer += w * (wide? 4 : 1);
 	x += w;
 	width -= w;
     }
 }
 
 static uint32_t *
 bits_image_fetch_untransformed_32 (pixman_iter_t * iter,
 				   const uint32_t *mask)
@@ -1093,19 +1068,18 @@ bits_image_fetch_untransformed_32 (pixma
 	    &image->bits, FALSE, x, y, width, buffer);
     }
 
     iter->y++;
     return buffer;
 }
 
 static uint32_t *
-bits_image_fetch_untransformed_64 (pixman_iter_t * iter,
-                                   const uint32_t *mask)
-				   
+bits_image_fetch_untransformed_float (pixman_iter_t * iter,
+				      const uint32_t *mask)
 {
     pixman_image_t *image  = iter->image;
     int             x      = iter->x;
     int             y      = iter->y;
     int             width  = iter->width;
     uint32_t *      buffer = iter->buffer;
 
     if (image->common.repeat == PIXMAN_REPEAT_NONE)
@@ -1118,60 +1092,56 @@ bits_image_fetch_untransformed_64 (pixma
 	bits_image_fetch_untransformed_repeat_normal (
 	    &image->bits, TRUE, x, y, width, buffer);
     }
 
     iter->y++;
     return buffer;
 }
 
-static uint32_t *
-_pixman_image_get_scanline_generic_64 (pixman_iter_t   *iter,
-				       const uint32_t * mask);
-
 typedef struct
 {
     pixman_format_code_t	format;
     uint32_t			flags;
     pixman_iter_get_scanline_t	get_scanline_32;
-    pixman_iter_get_scanline_t	get_scanline_64;
+    pixman_iter_get_scanline_t  get_scanline_float;
 } fetcher_info_t;
 
 static const fetcher_info_t fetcher_info[] =
 {
     { PIXMAN_any,
       (FAST_PATH_NO_ALPHA_MAP			|
        FAST_PATH_ID_TRANSFORM			|
        FAST_PATH_NO_CONVOLUTION_FILTER		|
        FAST_PATH_NO_PAD_REPEAT			|
        FAST_PATH_NO_REFLECT_REPEAT),
       bits_image_fetch_untransformed_32,
-      bits_image_fetch_untransformed_64
+      bits_image_fetch_untransformed_float
     },
 
 #define FAST_BILINEAR_FLAGS						\
     (FAST_PATH_NO_ALPHA_MAP		|				\
      FAST_PATH_NO_ACCESSORS		|				\
      FAST_PATH_HAS_TRANSFORM		|				\
      FAST_PATH_AFFINE_TRANSFORM		|				\
      FAST_PATH_X_UNIT_POSITIVE		|				\
      FAST_PATH_Y_UNIT_ZERO		|				\
      FAST_PATH_NONE_REPEAT		|				\
      FAST_PATH_BILINEAR_FILTER)
 
     { PIXMAN_a8r8g8b8,
       FAST_BILINEAR_FLAGS,
       bits_image_fetch_bilinear_no_repeat_8888,
-      _pixman_image_get_scanline_generic_64
+      _pixman_image_get_scanline_generic_float
     },
 
     { PIXMAN_x8r8g8b8,
       FAST_BILINEAR_FLAGS,
       bits_image_fetch_bilinear_no_repeat_8888,
-      _pixman_image_get_scanline_generic_64
+      _pixman_image_get_scanline_generic_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)
@@ -1182,24 +1152,24 @@ static const fetcher_info_t fetcher_info
      FAST_PATH_HAS_TRANSFORM		|				\
      FAST_PATH_AFFINE_TRANSFORM		|				\
      FAST_PATH_NEAREST_FILTER)
 
 #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_64				\
+      _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_64				\
+      bits_image_fetch_nearest_affine_ ## name,				\
+      _pixman_image_get_scanline_generic_float				\
     },
 
 #define AFFINE_FAST_PATHS(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)
@@ -1217,21 +1187,25 @@ static const fetcher_info_t fetcher_info
     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),
       bits_image_fetch_affine_no_alpha,
-      _pixman_image_get_scanline_generic_64
+      _pixman_image_get_scanline_generic_float
     },
 
     /* General */
-    { PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 },
+    { PIXMAN_any,
+      0,
+      bits_image_fetch_general,
+      _pixman_image_get_scanline_generic_float
+    },
 
     { PIXMAN_null },
 };
 
 static void
 bits_image_property_changed (pixman_image_t *image)
 {
     _pixman_bits_image_setup_accessors (&image->bits);
@@ -1251,17 +1225,17 @@ void
 	{
 	    if (iter->iter_flags & ITER_NARROW)
 	    {
 		iter->get_scanline = info->get_scanline_32;
 	    }
 	    else
 	    {
 		iter->data = info->get_scanline_32;
-		iter->get_scanline = info->get_scanline_64;
+		iter->get_scanline = info->get_scanline_float;
 	    }
 	    return;
 	}
     }
 
     /* Just in case we somehow didn't find a scanline function */
     iter->get_scanline = _pixman_iter_get_scanline_noop;
 }
@@ -1320,40 +1294,37 @@ dest_get_scanline_narrow (pixman_iter_t 
 
 static uint32_t *
 dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 {
     bits_image_t *  image  = &iter->image->bits;
     int             x      = iter->x;
     int             y      = iter->y;
     int             width  = iter->width;
-    uint64_t *	    buffer = (uint64_t *)iter->buffer;
+    argb_t *	    buffer = (argb_t *)iter->buffer;
 
-    image->fetch_scanline_64 (
+    image->fetch_scanline_float (
 	(pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
     if (image->common.alpha_map)
     {
-	uint64_t *alpha;
+	argb_t *alpha;
 
-	if ((alpha = malloc (width * sizeof (uint64_t))))
+	if ((alpha = malloc (width * sizeof (argb_t))))
 	{
 	    int i;
 
 	    x -= image->common.alpha_origin_x;
 	    y -= image->common.alpha_origin_y;
 
-	    image->common.alpha_map->fetch_scanline_64 (
+	    image->common.alpha_map->fetch_scanline_float (
 		(pixman_image_t *)image->common.alpha_map,
 		x, y, width, (uint32_t *)alpha, mask);
 
 	    for (i = 0; i < width; ++i)
-	    {
-		buffer[i] &= ~0xffff000000000000ULL;
-		buffer[i] |= (alpha[i] & 0xffff000000000000ULL);
-	    }
+		buffer[i].a = alpha[i].a;
 
 	    free (alpha);
 	}
     }
 
     return iter->buffer;
 }
 
@@ -1398,24 +1369,24 @@ static void
 dest_write_back_wide (pixman_iter_t *iter)
 {
     bits_image_t *  image  = &iter->image->bits;
     int             x      = iter->x;
     int             y      = iter->y;
     int             width  = iter->width;
     const uint32_t *buffer = iter->buffer;
 
-    image->store_scanline_64 (image, x, y, width, buffer);
+    image->store_scanline_float (image, x, y, width, buffer);
 
     if (image->common.alpha_map)
     {
 	x -= image->common.alpha_origin_x;
 	y -= image->common.alpha_origin_y;
 
-	image->common.alpha_map->store_scanline_64 (
+	image->common.alpha_map->store_scanline_float (
 	    image->common.alpha_map, x, y, width, buffer);
     }
 
     iter->y++;
 }
 
 void
 _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
@@ -1453,17 +1424,18 @@ void
 	iter->write_back = dest_write_back_wide;
     }
 }
 
 static uint32_t *
 create_bits (pixman_format_code_t format,
              int                  width,
              int                  height,
-             int *		  rowstride_bytes)
+             int *		  rowstride_bytes,
+	     pixman_bool_t	  clear)
 {
     int stride;
     size_t buf_size;
     int bpp;
 
     /* what follows is a long-winded way, avoiding any possibility of integer
      * overflows, of saying:
      * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
@@ -1485,34 +1457,38 @@ create_bits (pixman_format_code_t format
     if (_pixman_multiply_overflows_size (height, stride))
 	return NULL;
 
     buf_size = height * stride;
 
     if (rowstride_bytes)
 	*rowstride_bytes = stride;
 
-    return calloc (buf_size, 1);
+    if (clear)
+	return calloc (buf_size, 1);
+    else
+	return malloc (buf_size);
 }
 
 pixman_bool_t
 _pixman_bits_image_init (pixman_image_t *     image,
                          pixman_format_code_t format,
                          int                  width,
                          int                  height,
                          uint32_t *           bits,
-                         int                  rowstride)
+                         int                  rowstride,
+			 pixman_bool_t	      clear)
 {
     uint32_t *free_me = NULL;
 
     if (!bits && width && height)
     {
 	int rowstride_bytes;
 
-	free_me = bits = create_bits (format, width, height, &rowstride_bytes);
+	free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear);
 
 	if (!bits)
 	    return FALSE;
 
 	rowstride = rowstride_bytes / (int) sizeof (uint32_t);
     }
 
     _pixman_image_init (image);
@@ -1530,38 +1506,65 @@ pixman_bool_t
 
     image->common.property_changed = bits_image_property_changed;
 
     _pixman_image_reset_clip_region (image);
 
     return TRUE;
 }
 
-PIXMAN_EXPORT pixman_image_t *
-pixman_image_create_bits (pixman_format_code_t format,
-                          int                  width,
-                          int                  height,
-                          uint32_t *           bits,
-                          int                  rowstride_bytes)
+static pixman_image_t *
+create_bits_image_internal (pixman_format_code_t format,
+			    int                  width,
+			    int                  height,
+			    uint32_t *           bits,
+			    int                  rowstride_bytes,
+			    pixman_bool_t	 clear)
 {
     pixman_image_t *image;
 
     /* must be a whole number of uint32_t's
      */
     return_val_if_fail (
 	bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
 
     return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
 
     image = _pixman_image_allocate ();
 
     if (!image)
 	return NULL;
 
     if (!_pixman_bits_image_init (image, format, width, height, bits,
-				  rowstride_bytes / (int) sizeof (uint32_t)))
+				  rowstride_bytes / (int) sizeof (uint32_t),
+				  clear))
     {
 	free (image);
 	return NULL;
     }
 
     return image;
 }
+
+/* If bits is NULL, a buffer will be allocated and initialized to 0 */
+PIXMAN_EXPORT pixman_image_t *
+pixman_image_create_bits (pixman_format_code_t format,
+                          int                  width,
+                          int                  height,
+                          uint32_t *           bits,
+                          int                  rowstride_bytes)
+{
+    return create_bits_image_internal (
+	format, width, height, bits, rowstride_bytes, TRUE);
+}
+
+
+/* If bits is NULL, a buffer will be allocated and _not_ initialized */
+PIXMAN_EXPORT pixman_image_t *
+pixman_image_create_bits_no_clear (pixman_format_code_t format,
+				   int                  width,
+				   int                  height,
+				   uint32_t *           bits,
+				   int                  rowstride_bytes)
+{
+    return create_bits_image_internal (
+	format, width, height, bits, rowstride_bytes, FALSE);
+}
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/libpixman/src/pixman-combine-float.c
@@ -0,0 +1,1010 @@
+/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
+/*
+ * Copyright © 2010, 2012 Soren Sandmann Pedersen
+ * Copyright © 2010, 2012 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Soren Sandmann Pedersen (sandmann@cs.au.dk)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <string.h>
+#include <float.h>
+
+#include "pixman-private.h"
+
+/* Workaround for http://gcc.gnu.org/PR54965 */
+/* GCC 4.6 has problems with force_inline, so just use normal inline instead */
+#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 6)
+#undef force_inline
+#define force_inline __inline__
+#endif
+
+typedef float (* combine_channel_t) (float sa, float s, float da, float d);
+
+static force_inline void
+combine_inner (pixman_bool_t component,
+	       float *dest, const float *src, const float *mask, int n_pixels,
+	       combine_channel_t combine_a, combine_channel_t combine_c)
+{
+    int i;
+
+    if (!mask)
+    {
+	for (i = 0; i < 4 * n_pixels; i += 4)
+	{
+	    float sa = src[i + 0];
+	    float sr = src[i + 1];
+	    float sg = src[i + 2];
+	    float sb = src[i + 3];
+	    
+	    float da = dest[i + 0];
+	    float dr = dest[i + 1];
+	    float dg = dest[i + 2];
+	    float db = dest[i + 3];					
+	    
+	    dest[i + 0] = combine_a (sa, sa, da, da);
+	    dest[i + 1] = combine_c (sa, sr, da, dr);
+	    dest[i + 2] = combine_c (sa, sg, da, dg);
+	    dest[i + 3] = combine_c (sa, sb, da, db);
+	}
+    }
+    else
+    {
+	for (i = 0; i < 4 * n_pixels; i += 4)
+	{
+	    float sa, sr, sg, sb;
+	    float ma, mr, mg, mb;
+	    float da, dr, dg, db;
+	    
+	    sa = src[i + 0];
+	    sr = src[i + 1];
+	    sg = src[i + 2];
+	    sb = src[i + 3];
+	    
+	    if (component)
+	    {
+		ma = mask[i + 0];
+		mr = mask[i + 1];
+		mg = mask[i + 2];
+		mb = mask[i + 3];
+
+		sr *= mr;
+		sg *= mg;
+		sb *= mb;
+
+		ma *= sa;
+		mr *= sa;
+		mg *= sa;
+		mb *= sa;
+		
+		sa = ma;
+	    }
+	    else
+	    {
+		ma = mask[i + 0];
+
+		sa *= ma;
+		sr *= ma;
+		sg *= ma;
+		sb *= ma;
+
+		ma = mr = mg = mb = sa;
+	    }
+	    
+	    da = dest[i + 0];
+	    dr = dest[i + 1];
+	    dg = dest[i + 2];
+	    db = dest[i + 3];
+	    
+	    dest[i + 0] = combine_a (ma, sa, da, da);
+	    dest[i + 1] = combine_c (mr, sr, da, dr);
+	    dest[i + 2] = combine_c (mg, sg, da, dg);
+	    dest[i + 3] = combine_c (mb, sb, da, db);
+	}
+    }
+}
+
+#define MAKE_COMBINER(name, component, combine_a, combine_c)		\
+    static void								\
+    combine_ ## name ## _float (pixman_implementation_t *imp,		\
+				pixman_op_t              op,		\
+				float                   *dest,		\
+				const float             *src,		\
+				const float             *mask,		\
+				int		         n_pixels)	\
+    {									\
+	combine_inner (component, dest, src, mask, n_pixels,		\
+		       combine_a, combine_c);				\
+    }
+
+#define MAKE_COMBINERS(name, combine_a, combine_c)			\
+    MAKE_COMBINER(name ## _ca, TRUE, combine_a, combine_c)		\
+    MAKE_COMBINER(name ## _u, FALSE, combine_a, combine_c)
+
+
+/*
+ * Porter/Duff operators
+ */
+typedef enum
+{
+    ZERO,
+    ONE,
+    SRC_ALPHA,
+    DEST_ALPHA,
+    INV_SA,
+    INV_DA,
+    SA_OVER_DA,
+    DA_OVER_SA,
+    INV_SA_OVER_DA,
+    INV_DA_OVER_SA,
+    ONE_MINUS_SA_OVER_DA,
+    ONE_MINUS_DA_OVER_SA,
+    ONE_MINUS_INV_DA_OVER_SA,
+    ONE_MINUS_INV_SA_OVER_DA
+} combine_factor_t;
+
+#define CLAMP(f)					\
+    (((f) < 0)? 0 : (((f) > 1.0) ? 1.0 : (f)))
+
+static force_inline float
+get_factor (combine_factor_t factor, float sa, float da)
+{
+    float f = -1;
+
+    switch (factor)
+    {
+    case ZERO:
+	f = 0.0f;
+	break;
+
+    case ONE:
+	f = 1.0f;
+	break;
+
+    case SRC_ALPHA:
+	f = sa;
+	break;
+
+    case DEST_ALPHA:
+	f = da;
+	break;
+
+    case INV_SA:
+	f = 1 - sa;
+	break;
+
+    case INV_DA:
+	f = 1 - da;
+	break;
+
+    case SA_OVER_DA:
+	if (da == 0.0f)
+	    f = 1.0f;
+	else
+	    f = CLAMP (sa / da);
+	break;
+
+    case DA_OVER_SA:
+	if (sa == 0.0f)
+	    f = 1.0f;
+	else
+	    f = CLAMP (da / sa);
+	break;
+
+    case INV_SA_OVER_DA:
+	if (da == 0.0f)
+	    f = 1.0f;
+	else
+	    f = CLAMP ((1.0f - sa) / da);
+	break;
+
+    case INV_DA_OVER_SA:
+	if (sa == 0.0f)
+	    f = 1.0f;
+	else
+	    f = CLAMP ((1.0f - da) / sa);
+	break;
+
+    case ONE_MINUS_SA_OVER_DA:
+	if (da == 0.0f)
+	    f = 0.0f;
+	else
+	    f = CLAMP (1.0f - sa / da);
+	break;
+
+    case ONE_MINUS_DA_OVER_SA:
+	if (sa == 0.0f)
+	    f = 0.0f;
+	else
+	    f = CLAMP (1.0f - da / sa);
+	break;
+
+    case ONE_MINUS_INV_DA_OVER_SA:
+	if (sa == 0.0f)
+	    f = 0.0f;
+	else
+	    f = CLAMP (1.0f - (1.0f - da) / sa);
+	break;
+
+    case ONE_MINUS_INV_SA_OVER_DA:
+	if (da == 0.0f)
+	    f = 0.0f;
+	else
+	    f = CLAMP (1.0f - (1.0f - sa) / da);
+	break;
+    }
+
+    return f;
+}
+
+#define MAKE_PD_COMBINERS(name, a, b)					\
+    static float force_inline						\
+    pd_combine_ ## name (float sa, float s, float da, float d)		\
+    {									\
+	const float fa = get_factor (a, sa, da);			\
+	const float fb = get_factor (b, sa, da);			\
+									\
+	return MIN (1.0f, s * fa + d * fb);				\
+    }									\
+    									\
+    MAKE_COMBINERS(name, pd_combine_ ## name, pd_combine_ ## name)
+
+MAKE_PD_COMBINERS (clear,			ZERO,				ZERO)
+MAKE_PD_COMBINERS (src,				ONE,				ZERO)
+MAKE_PD_COMBINERS (dst,				ZERO,				ONE)
+MAKE_PD_COMBINERS (over,			ONE,				INV_SA)
+MAKE_PD_COMBINERS (over_reverse,		INV_DA,				ONE)
+MAKE_PD_COMBINERS (in,				DEST_ALPHA,			ZERO)
+MAKE_PD_COMBINERS (in_reverse,			ZERO,				SRC_ALPHA)
+MAKE_PD_COMBINERS (out,				INV_DA,				ZERO)
+MAKE_PD_COMBINERS (out_reverse,			ZERO,				INV_SA)
+MAKE_PD_COMBINERS (atop,			DEST_ALPHA,			INV_SA)
+MAKE_PD_COMBINERS (atop_reverse,		INV_DA,				SRC_ALPHA)
+MAKE_PD_COMBINERS (xor,				INV_DA,				INV_SA)
+MAKE_PD_COMBINERS (add,				ONE,				ONE)
+
+MAKE_PD_COMBINERS (saturate,			INV_DA_OVER_SA,			ONE)
+
+MAKE_PD_COMBINERS (disjoint_clear,		ZERO,				ZERO)
+MAKE_PD_COMBINERS (disjoint_src,		ONE,				ZERO)
+MAKE_PD_COMBINERS (disjoint_dst,		ZERO,				ONE)
+MAKE_PD_COMBINERS (disjoint_over,		ONE,				INV_SA_OVER_DA)
+MAKE_PD_COMBINERS (disjoint_over_reverse,	INV_DA_OVER_SA,			ONE)
+MAKE_PD_COMBINERS (disjoint_in,			ONE_MINUS_INV_DA_OVER_SA,	ZERO)
+MAKE_PD_COMBINERS (disjoint_in_reverse,		ZERO,				ONE_MINUS_INV_SA_OVER_DA)
+MAKE_PD_COMBINERS (disjoint_out,		INV_DA_OVER_SA,			ZERO)
+MAKE_PD_COMBINERS (disjoint_out_reverse,	ZERO,				INV_SA_OVER_DA)
+MAKE_PD_COMBINERS (disjoint_atop,		ONE_MINUS_INV_DA_OVER_SA,	INV_SA_OVER_DA)
+MAKE_PD_COMBINERS (disjoint_atop_reverse,	INV_DA_OVER_SA,			ONE_MINUS_INV_SA_OVER_DA)
+MAKE_PD_COMBINERS (disjoint_xor,		INV_DA_OVER_SA,			INV_SA_OVER_DA)
+
+MAKE_PD_COMBINERS (conjoint_clear,		ZERO,				ZERO)
+MAKE_PD_COMBINERS (conjoint_src,		ONE,				ZERO)
+MAKE_PD_COMBINERS (conjoint_dst,		ZERO,				ONE)
+MAKE_PD_COMBINERS (conjoint_over,		ONE,				ONE_MINUS_SA_OVER_DA)
+MAKE_PD_COMBINERS (conjoint_over_reverse,	ONE_MINUS_DA_OVER_SA,		ONE)
+MAKE_PD_COMBINERS (conjoint_in,			DA_OVER_SA,			ZERO)
+MAKE_PD_COMBINERS (conjoint_in_reverse,		ZERO,				SA_OVER_DA)
+MAKE_PD_COMBINERS (conjoint_out,		ONE_MINUS_DA_OVER_SA,		ZERO)
+MAKE_PD_COMBINERS (conjoint_out_reverse,	ZERO,				ONE_MINUS_SA_OVER_DA)
+MAKE_PD_COMBINERS (conjoint_atop,		DA_OVER_SA,			ONE_MINUS_SA_OVER_DA)
+MAKE_PD_COMBINERS (conjoint_atop_reverse,	ONE_MINUS_DA_OVER_SA,		SA_OVER_DA)
+MAKE_PD_COMBINERS (conjoint_xor,		ONE_MINUS_DA_OVER_SA,		ONE_MINUS_SA_OVER_DA)
+
+/*
+ * PDF blend modes:
+ *
+ * The following blend modes have been taken from the PDF ISO 32000
+ * specification, which at this point in time is available from
+ * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
+ * The relevant chapters are 11.3.5 and 11.3.6.
+ * The formula for computing the final pixel color given in 11.3.6 is:
+ * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
+ * with B() being the blend function.
+ * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
+ *
+ * These blend modes should match the SVG filter draft specification, as
+ * it has been designed to mirror ISO 32000. Note that at the current point
+ * no released draft exists that shows this, as the formulas have not been
+ * updated yet after the release of ISO 32000.
+ *
+ * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
+ * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
+ * argument. Note that this implementation operates on premultiplied colors,
+ * while the PDF specification does not. Therefore the code uses the formula
+ * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
+ */
+
+#define MAKE_SEPARABLE_PDF_COMBINERS(name)				\
+    static force_inline float						\
+    combine_ ## name ## _a (float sa, float s, float da, float d)	\
+    {									\
+	return da + sa - da * sa;					\
+    }									\
+    									\
+    static force_inline float						\
+    combine_ ## name ## _c (float sa, float s, float da, float d)	\
+    {									\
+	float f = (1 - sa) * d + (1 - da) * s;				\
+									\
+	return f + blend_ ## name (sa, s, da, d);			\
+    }									\
+    									\
+    MAKE_COMBINERS (name, combine_ ## name ## _a, combine_ ## name ## _c)
+
+static force_inline float
+blend_multiply (float sa, float s, float da, float d)
+{
+    return d * s;
+}
+
+static force_inline float
+blend_screen (float sa, float s, float da, float d)
+{
+    return d * sa + s * da - s * d;
+}
+
+static force_inline float
+blend_overlay (float sa, float s, float da, float d)
+{
+    if (2 * d < da)
+	return 2 * s * d;
+    else
+	return sa * da - 2 * (da - d) * (sa - s);
+}
+
+static force_inline float
+blend_darken (float sa, float s, float da, float d)
+{
+    s = s * da;
+    d = d * sa;
+
+    if (s > d)
+	return d;
+    else
+	return s;
+}
+
+static force_inline float
+blend_lighten (float sa, float s, float da, float d)
+{
+    s = s * da;
+    d = d * sa;
+
+    if (s > d)
+	return s;
+    else
+	return d;
+}
+
+static force_inline float
+blend_color_dodge (float sa, float s, float da, float d)
+{
+    if (d == 0.0f)
+	return 0.0f;
+    else if (d * sa >= sa * da - s * da)
+	return sa * da;
+    else if (sa - s == 0.0f)
+	return sa * da;
+    else
+	return sa * sa * d / (sa - s);
+}
+
+static force_inline float
+blend_color_burn (float sa, float s, float da, float d)
+{
+    if (d >= da)
+	return sa * da;
+    else if (sa * (da - d) >= s * da)
+	return 0.0f;
+    else if (s == 0.0f)
+	return 0.0f;
+    else
+	return sa * (da - sa * (da - d) / s);
+}
+
+static force_inline float
+blend_hard_light (float sa, float s, float da, float d)
+{
+    if (2 * s < sa)
+	return 2 * s * d;
+    else
+	return sa * da - 2 * (da - d) * (sa - s);
+}
+
+static force_inline float
+blend_soft_light (float sa, float s, float da, float d)
+{
+    if (2 * s < sa)
+    {
+	if (da == 0.0f)
+	    return d * sa;
+	else
+	    return d * sa - d * (da - d) * (sa - 2 * s) / da;
+    }
+    else
+    {
+	if (da == 0.0f)
+	{
+	    return 0.0f;
+	}
+	else
+	{
+	    if (4 * d <= da)
+		return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3);
+	    else
+		return d * sa + (sqrtf (d * da) - d) * (2 * s - sa);
+	}
+    }
+}
+
+static force_inline float
+blend_difference (float sa, float s, float da, float d)
+{
+    float dsa = d * sa;
+    float sda = s * da;
+
+    if (sda < dsa)
+	return dsa - sda;
+    else
+	return sda - dsa;
+}
+
+static force_inline float
+blend_exclusion (float sa, float s, float da, float d)
+{
+    return s * da + d * sa - 2 * d * s;
+}
+
+MAKE_SEPARABLE_PDF_COMBINERS (multiply)
+MAKE_SEPARABLE_PDF_COMBINERS (screen)
+MAKE_SEPARABLE_PDF_COMBINERS (overlay)
+MAKE_SEPARABLE_PDF_COMBINERS (darken)
+MAKE_SEPARABLE_PDF_COMBINERS (lighten)
+MAKE_SEPARABLE_PDF_COMBINERS (color_dodge)
+MAKE_SEPARABLE_PDF_COMBINERS (color_burn)
+MAKE_SEPARABLE_PDF_COMBINERS (hard_light)
+MAKE_SEPARABLE_PDF_COMBINERS (soft_light)
+MAKE_SEPARABLE_PDF_COMBINERS (difference)
+MAKE_SEPARABLE_PDF_COMBINERS (exclusion)
+
+/*
+ * PDF nonseperable blend modes.
+ *
+ * These are implemented using the following functions to operate in Hsl
+ * space, with Cmax, Cmid, Cmin referring to the max, mid and min value
+ * of the red, green and blue components.
+ *
+ * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
+ *
+ * clip_color (C):
+ *   l = LUM (C)
+ *   min = Cmin
+ *   max = Cmax
+ *   if n < 0.0
+ *     C = l + (((C – l) × l) ⁄     (l – min))
+ *   if x > 1.0
+ *     C = l + (((C – l) × (1 – l)) (max – l))
+ *   return C
+ *
+ * set_lum (C, l):
+ *   d = l – LUM (C)
+ *   C += d
+ *   return clip_color (C)
+ *
+ * SAT (C) = CH_MAX (C) - CH_MIN (C)
+ *
+ * set_sat (C, s):
+ *  if Cmax > Cmin
+ *    Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
+ *    Cmax = s
+ *  else
+ *    Cmid = Cmax = 0.0
+ *  Cmin = 0.0
+ *  return C
+ */
+
+/* For premultiplied colors, we need to know what happens when C is
+ * multiplied by a real number. LUM and SAT are linear:
+ *
+ *    LUM (r × C) = r × LUM (C)		SAT (r × C) = r × SAT (C)
+ *
+ * If we extend clip_color with an extra argument a and change
+ *
+ *        if x >= 1.0
+ *
+ * into
+ *
+ *        if x >= a
+ *
+ * then clip_color is also linear:
+ *
+ *     r * clip_color (C, a) = clip_color (r_c, ra);
+ *
+ * for positive r.
+ *
+ * Similarly, we can extend set_lum with an extra argument that is just passed
+ * on to clip_color:
+ *
+ *     r × set_lum ( C, l, a)
+ *
+ *   = r × clip_color ( C + l - LUM (C), a)
+ *
+ *   = clip_color ( r * C + r × l - LUM (r × C), r * a)
+ *
+ *   = set_lum ( r * C, r * l, r * a)
+ *
+ * Finally, set_sat:
+ *
+ *     r * set_sat (C, s) = set_sat (x * C, r * s)
+ *
+ * The above holds for all non-zero x because they x'es in the fraction for
+ * C_mid cancel out. Specifically, it holds for x = r:
+ *
+ *     r * set_sat (C, s) = set_sat (r_c, rs)
+ *
+ *
+ *
+ *
+ * So, for the non-separable PDF blend modes, we have (using s, d for
+ * non-premultiplied colors, and S, D for premultiplied:
+ *
+ *   Color:
+ *
+ *     a_s * a_d * B(s, d)
+ *   = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
+ *   = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
+ *
+ *
+ *   Luminosity:
+ *
+ *     a_s * a_d * B(s, d)
+ *   = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
+ *   = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
+ *
+ *
+ *   Saturation:
+ *
+ *     a_s * a_d * B(s, d)
+ *   = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
+ *   = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
+ *                                        a_s * LUM (D), a_s * a_d)
+ *   = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
+ *
+ *   Hue:
+ *
+ *     a_s * a_d * B(s, d)
+ *   = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
+ *   = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
+ *
+ */
+
+typedef struct
+{
+    float	r;
+    float	g;
+    float	b;
+} rgb_t;
+
+static force_inline float
+minf (float a, float b)
+{
+    return a < b? a : b;
+}
+
+static force_inline float
+maxf (float a, float b)
+{
+    return a > b? a : b;
+}
+
+static force_inline float
+channel_min (const rgb_t *c)
+{
+    return minf (minf (c->r, c->g), c->b);
+}
+
+static force_inline float
+channel_max (const rgb_t *c)
+{
+    return maxf (maxf (c->r, c->g), c->b);
+}
+
+static force_inline float
+get_lum (const rgb_t *c)
+{
+    return c->r * 0.3f + c->g * 0.59f + c->b * 0.11f;
+}
+
+static force_inline float
+get_sat (const rgb_t *c)
+{
+    return channel_max (c) - channel_min (c);
+}
+
+static void
+clip_color (rgb_t *color, float a)
+{
+    float l = get_lum (color);
+    float n = channel_min (color);
+    float x = channel_max (color);
+
+    if (n < 0.0f)
+    {
+	if ((l - n) < 4 * FLT_EPSILON)
+	{
+	    color->r = 0.0f;
+	    color->g = 0.0f;
+	    color->b = 0.0f;
+	}
+	else
+	{
+	    color->r = l + (((color->r - l) * l) / (l - n));
+	    color->g = l + (((color->g - l) * l) / (l - n));
+	    color->b = l + (((color->b - l) * l) / (l - n));
+	}
+    }
+    if (x > a)
+    {
+	if ((x - l) < 4 * FLT_EPSILON)
+	{
+	    color->r = a;
+	    color->g = a;
+	    color->b = a;
+	}
+	else
+	{
+	    color->r = l + (((color->r - l) * (a - l) / (x - l)));
+	    color->g = l + (((color->g - l) * (a - l) / (x - l)));
+	    color->b = l + (((color->b - l) * (a - l) / (x - l)));
+	}
+    }
+}
+
+static void
+set_lum (rgb_t *color, float sa, float l)
+{
+    float d = l - get_lum (color);
+
+    color->r = color->r + d;
+    color->g = color->g + d;
+    color->b = color->b + d;
+
+    clip_color (color, sa);
+}
+
+static void
+set_sat (rgb_t *src, float sat)
+{
+    float *max, *mid, *min;
+
+    if (src->r > src->g)
+    {
+	if (src->r > src->b)
+	{
+	    max = &(src->r);
+
+	    if (src->g > src->b)
+	    {
+		mid = &(src->g);
+		min = &(src->b);
+	    }
+	    else
+	    {
+		mid = &(src->b);
+		min = &(src->g);
+	    }
+	}
+	else
+	{
+	    max = &(src->b);
+	    mid = &(src->r);
+	    min = &(src->g);
+	}
+    }
+    else
+    {
+	if (src->r > src->b)
+	{
+	    max = &(src->g);
+	    mid = &(src->r);
+	    min = &(src->b);
+	}
+	else
+	{
+	    min = &(src->r);
+
+	    if (src->g > src->b)
+	    {
+		max = &(src->g);
+		mid = &(src->b);
+	    }
+	    else
+	    {
+		max = &(src->b);
+		mid = &(src->g);
+	    }
+	}
+    }
+
+    if (*max > *min)
+    {
+	*mid = (((*mid - *min) * sat) / (*max - *min));
+	*max = sat;
+    }
+    else
+    {
+	*mid = *max = 0.0f;
+    }
+
+    *min = 0.0f;
+}
+
+/*
+ * Hue:
+ * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
+ */
+static force_inline void
+blend_hsl_hue (rgb_t *res,
+	       const rgb_t *dest, float da,
+	       const rgb_t *src, float sa)
+{
+    res->r = src->r * da;
+    res->g = src->g * da;
+    res->b = src->b * da;
+
+    set_sat (res, get_sat (dest) * sa);
+    set_lum (res, sa * da, get_lum (dest) * sa);
+}
+
+/*
+ * Saturation:
+ * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
+ */
+static force_inline void
+blend_hsl_saturation (rgb_t *res,
+		      const rgb_t *dest, float da,
+		      const rgb_t *src, float sa)
+{
+    res->r = dest->r * sa;
+    res->g = dest->g * sa;
+    res->b = dest->b * sa;
+
+    set_sat (res, get_sat (src) * da);
+    set_lum (res, sa * da, get_lum (dest) * sa);
+}
+
+/*
+ * Color:
+ * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
+ */
+static force_inline void
+blend_hsl_color (rgb_t *res,
+		 const rgb_t *dest, float da,
+		 const rgb_t *src, float sa)
+{
+    res->r = src->r * da;
+    res->g = src->g * da;
+    res->b = src->b * da;
+
+    set_lum (res, sa * da, get_lum (dest) * sa);
+}
+
+/*
+ * Luminosity:
+ * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
+ */
+static force_inline void
+blend_hsl_luminosity (rgb_t *res,
+		      const rgb_t *dest, float da,
+		      const rgb_t *src, float sa)
+{
+    res->r = dest->r * sa;
+    res->g = dest->g * sa;
+    res->b = dest->b * sa;
+
+    set_lum (res, sa * da, get_lum (src) * da);
+}
+
+#define MAKE_NON_SEPARABLE_PDF_COMBINERS(name)				\
+    static void								\
+    combine_ ## name ## _u_float (pixman_implementation_t *imp,		\
+				  pixman_op_t              op,		\
+				  float                   *dest,	\
+				  const float             *src,		\
+				  const float             *mask,	\
+				  int		           n_pixels)	\
+    {									\
+    	int i;								\
+									\
+	for (i = 0; i < 4 * n_pixels; i += 4)				\
+	{								\
+	    float sa, da;						\
+	    rgb_t sc, dc, rc;						\
+									\
+	    sa = src[i + 0];						\
+	    sc.r = src[i + 1];						\
+	    sc.g = src[i + 2];						\
+	    sc.b = src[i + 3];						\
+									\
+	    da = dest[i + 0];						\
+	    dc.r = dest[i + 1];						\
+	    dc.g = dest[i + 2];						\
+	    dc.b = dest[i + 3];						\
+									\
+	    if (mask)							\
+	    {								\
+		float ma = mask[i + 0];					\
+									\
+		/* Component alpha is not supported for HSL modes */	\
+		sa *= ma;						\
+		sc.r *= ma;						\
+		sc.g *= ma;						\
+		sc.g *= ma;						\
+	    }								\
+									\
+	    blend_ ## name (&rc, &dc, da, &sc, sa);			\
+									\
+	    dest[i + 0] = sa + da - sa * da;				\
+	    dest[i + 1] = (1 - sa) * dc.r + (1 - da) * sc.r + rc.r;	\
+	    dest[i + 2] = (1 - sa) * dc.g + (1 - da) * sc.g + rc.g;	\
+	    dest[i + 3] = (1 - sa) * dc.b + (1 - da) * sc.b + rc.b;	\
+	}								\
+    }
+
+MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_hue)
+MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_saturation)
+MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_color)
+MAKE_NON_SEPARABLE_PDF_COMBINERS(hsl_luminosity)
+
+void
+_pixman_setup_combiner_functions_float (pixman_implementation_t *imp)
+{
+    /* Unified alpha */
+    imp->combine_float[PIXMAN_OP_CLEAR] = combine_clear_u_float;
+    imp->combine_float[PIXMAN_OP_SRC] = combine_src_u_float;
+    imp->combine_float[PIXMAN_OP_DST] = combine_dst_u_float;
+    imp->combine_float[PIXMAN_OP_OVER] = combine_over_u_float;
+    imp->combine_float[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_IN] = combine_in_u_float;
+    imp->combine_float[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_OUT] = combine_out_u_float;
+    imp->combine_float[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_ATOP] = combine_atop_u_float;
+    imp->combine_float[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_XOR] = combine_xor_u_float;
+    imp->combine_float[PIXMAN_OP_ADD] = combine_add_u_float;
+    imp->combine_float[PIXMAN_OP_SATURATE] = combine_saturate_u_float;
+
+    /* Disjoint, unified */
+    imp->combine_float[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u_float;
+
+    /* Conjoint, unified */
+    imp->combine_float[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u_float;
+    imp->combine_float[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u_float;
+
+    /* PDF operators, unified */
+    imp->combine_float[PIXMAN_OP_MULTIPLY] = combine_multiply_u_float;
+    imp->combine_float[PIXMAN_OP_SCREEN] = combine_screen_u_float;
+    imp->combine_float[PIXMAN_OP_OVERLAY] = combine_overlay_u_float;
+    imp->combine_float[PIXMAN_OP_DARKEN] = combine_darken_u_float;
+    imp->combine_float[PIXMAN_OP_LIGHTEN] = combine_lighten_u_float;
+    imp->combine_float[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u_float;
+    imp->combine_float[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u_float;
+    imp->combine_float[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u_float;
+    imp->combine_float[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u_float;
+    imp->combine_float[PIXMAN_OP_DIFFERENCE] = combine_difference_u_float;
+    imp->combine_float[PIXMAN_OP_EXCLUSION] = combine_exclusion_u_float;
+
+    imp->combine_float[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u_float;
+    imp->combine_float[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u_float;
+    imp->combine_float[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u_float;
+    imp->combine_float[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u_float;
+
+    /* Component alpha combiners */
+    imp->combine_float_ca[PIXMAN_OP_CLEAR] = combine_clear_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_SRC] = combine_src_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DST] = combine_dst_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_OVER] = combine_over_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_IN] = combine_in_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_OUT] = combine_out_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_ATOP] = combine_atop_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_XOR] = combine_xor_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_ADD] = combine_add_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca_float;
+
+    /* Disjoint CA */
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_disjoint_clear_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_SRC] = combine_disjoint_src_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_DST] = combine_disjoint_dst_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_disjoint_over_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca_float;
+
+    /* Conjoint CA */
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_conjoint_clear_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_SRC] = combine_conjoint_src_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_DST] = combine_conjoint_dst_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca_float;
+
+    /* PDF operators CA */
+    imp->combine_float_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_SCREEN] = combine_screen_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DARKEN] = combine_darken_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca_float;
+    imp->combine_float_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca_float;
+
+    /* It is not clear that these make sense, so make them noops for now */
+    imp->combine_float_ca[PIXMAN_OP_HSL_HUE] = combine_dst_u_float;
+    imp->combine_float_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst_u_float;
+    imp->combine_float_ca[PIXMAN_OP_HSL_COLOR] = combine_dst_u_float;
+    imp->combine_float_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst_u_float;
+}
--- a/gfx/cairo/libpixman/src/pixman-combine32.c
+++ b/gfx/cairo/libpixman/src/pixman-combine32.c
@@ -1,24 +1,42 @@
-/* WARNING: This file is generated by combine.pl from combine.inc.
-   Please edit one of those files rather than this one. */
-
-#line 1 "pixman-combine.c.template"
+/*
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ *             2005 Lars Knoll & Zack Rusin, Trolltech
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #include <math.h>
 #include <string.h>
 
 #include "pixman-private.h"
-
 #include "pixman-combine32.h"
 
-/*** per channel helper functions ***/
+/* component alpha helper functions */
 
 static void
 combine_mask_ca (uint32_t *src, uint32_t *mask)
 {
     uint32_t a = *mask;
 
     uint32_t x;
     uint16_t xa;
@@ -90,25 +108,21 @@ combine_mask_alpha_ca (const uint32_t *s
 
     UN8x4_MUL_UN8 (a, x);
     *(mask) = a;
 }
 
 /*
  * There are two ways of handling alpha -- either as a single unified value or
  * a separate value for each component, hence each macro must have two
- * versions.  The unified alpha version has a 'U' at the end of the name,
- * the component version has a 'C'.  Similarly, functions which deal with
+ * versions.  The unified alpha version has a 'u' at the end of the name,
+ * the component version has a 'ca'.  Similarly, functions which deal with
  * this difference will have two versions using the same convention.
  */
 
-/*
- * All of the composing functions
- */
-
 static force_inline uint32_t
 combine_mask (const uint32_t *src, const uint32_t *mask, int i)
 {
     uint32_t s, m;
 
     if (mask)
     {
 	m = *(mask + i) >> A_SHIFT;
@@ -153,29 +167,30 @@ combine_src_u (pixman_implementation_t *
                uint32_t *                dest,
                const uint32_t *          src,
                const uint32_t *          mask,
                int                      width)
 {
     int i;
 
     if (!mask)
+    {
 	memcpy (dest, src, width * sizeof (uint32_t));
+    }
     else
     {
 	for (i = 0; i < width; ++i)
 	{
 	    uint32_t s = combine_mask (src, mask, i);
 
 	    *(dest + i) = s;
 	}
     }
 }
 
-/* if the Src is opaque, call combine_src_u */
 static void
 combine_over_u (pixman_implementation_t *imp,
                 pixman_op_t              op,
                 uint32_t *                dest,
                 const uint32_t *          src,
                 const uint32_t *          mask,
                 int                      width)
 {
@@ -187,17 +202,16 @@ combine_over_u (pixman_implementation_t 
 	uint32_t d = *(dest + i);
 	uint32_t ia = ALPHA_8 (~s);
 
 	UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
 	*(dest + i) = d;
     }
 }
 
-/* if the Dst is opaque, this is a noop */
 static void
 combine_over_reverse_u (pixman_implementation_t *imp,
                         pixman_op_t              op,
                         uint32_t *                dest,
                         const uint32_t *          src,
                         const uint32_t *          mask,
                         int                      width)
 {
@@ -208,17 +222,16 @@ combine_over_reverse_u (pixman_implement
 	uint32_t s = combine_mask (src, mask, i);
 	uint32_t d = *(dest + i);
 	uint32_t ia = ALPHA_8 (~*(dest + i));
 	UN8x4_MUL_UN8_ADD_UN8x4 (s, ia, d);
 	*(dest + i) = s;
     }
 }
 
-/* if the Dst is opaque, call combine_src_u */
 static void
 combine_in_u (pixman_implementation_t *imp,
               pixman_op_t              op,
               uint32_t *                dest,
               const uint32_t *          src,
               const uint32_t *          mask,
               int                      width)
 {
@@ -228,17 +241,16 @@ combine_in_u (pixman_implementation_t *i
     {
 	uint32_t s = combine_mask (src, mask, i);
 	uint32_t a = ALPHA_8 (*(dest + i));
 	UN8x4_MUL_UN8 (s, a);
 	*(dest + i) = s;
     }
 }
 
-/* if the Src is opaque, this is a noop */
 static void
 combine_in_reverse_u (pixman_implementation_t *imp,
                       pixman_op_t              op,
                       uint32_t *                dest,
                       const uint32_t *          src,
                       const uint32_t *          mask,
                       int                      width)
 {
@@ -249,17 +261,16 @@ combine_in_reverse_u (pixman_implementat
 	uint32_t s = combine_mask (src, mask, i);
 	uint32_t d = *(dest + i);
 	uint32_t a = ALPHA_8 (s);
 	UN8x4_MUL_UN8 (d, a);
 	*(dest + i) = d;
     }
 }
 
-/* if the Dst is opaque, call combine_clear */
 static void
 combine_out_u (pixman_implementation_t *imp,
                pixman_op_t              op,
                uint32_t *                dest,
                const uint32_t *          src,
                const uint32_t *          mask,
                int                      width)
 {
@@ -269,17 +280,16 @@ combine_out_u (pixman_implementation_t *
     {
 	uint32_t s = combine_mask (src, mask, i);
 	uint32_t a = ALPHA_8 (~*(dest + i));
 	UN8x4_MUL_UN8 (s, a);
 	*(dest + i) = s;
     }
 }
 
-/* if the Src is opaque, call combine_clear */
 static void
 combine_out_reverse_u (pixman_implementation_t *imp,
                        pixman_op_t              op,
                        uint32_t *                dest,
                        const uint32_t *          src,
                        const uint32_t *          mask,
                        int                      width)
 {
@@ -290,19 +300,16 @@ combine_out_reverse_u (pixman_implementa
 	uint32_t s = combine_mask (src, mask, i);
 	uint32_t d = *(dest + i);
 	uint32_t a = ALPHA_8 (~s);
 	UN8x4_MUL_UN8 (d, a);
 	*(dest + i) = d;
     }
 }
 
-/* if the Src is opaque, call combine_in_u */
-/* if the Dst is opaque, call combine_over_u */
-/* if both the Src and Dst are opaque, call combine_src_u */
 static void
 combine_atop_u (pixman_implementation_t *imp,
                 pixman_op_t              op,
                 uint32_t *                dest,
                 const uint32_t *          src,
                 const uint32_t *          mask,
                 int                      width)
 {
@@ -315,19 +322,16 @@ combine_atop_u (pixman_implementation_t 
 	uint32_t dest_a = ALPHA_8 (d);
 	uint32_t src_ia = ALPHA_8 (~s);
 
 	UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_a, d, src_ia);
 	*(dest + i) = s;
     }
 }
 
-/* if the Src is opaque, call combine_over_reverse_u */
-/* if the Dst is opaque, call combine_in_reverse_u */
-/* if both the Src and Dst are opaque, call combine_dst_u */
 static void
 combine_atop_reverse_u (pixman_implementation_t *imp,
                         pixman_op_t              op,
                         uint32_t *                dest,
                         const uint32_t *          src,
                         const uint32_t *          mask,
                         int                      width)
 {
@@ -340,19 +344,16 @@ combine_atop_reverse_u (pixman_implement
 	uint32_t src_a = ALPHA_8 (s);
 	uint32_t dest_ia = ALPHA_8 (~d);
 
 	UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_a);
 	*(dest + i) = s;
     }
 }
 
-/* if the Src is opaque, call combine_over_u */
-/* if the Dst is opaque, call combine_over_reverse_u */
-/* if both the Src and Dst are opaque, call combine_clear */
 static void
 combine_xor_u (pixman_implementation_t *imp,
                pixman_op_t              op,
                uint32_t *                dest,
                const uint32_t *          src,
                const uint32_t *          mask,
                int                      width)
 {
@@ -384,19 +385,16 @@ combine_add_u (pixman_implementation_t *
     {
 	uint32_t s = combine_mask (src, mask, i);
 	uint32_t d = *(dest + i);
 	UN8x4_ADD_UN8x4 (d, s);
 	*(dest + i) = d;
     }
 }
 
-/* if the Src is opaque, call combine_add_u */
-/* if the Dst is opaque, call combine_add_u */
-/* if both the Src and Dst are opaque, call combine_add_u */
 static void
 combine_saturate_u (pixman_implementation_t *imp,
                     pixman_op_t              op,
                     uint32_t *                dest,
                     const uint32_t *          src,
                     const uint32_t *          mask,
                     int                      width)
 {
@@ -443,17 +441,16 @@ combine_saturate_u (pixman_implementatio
  * while the PDF specification does not. Therefore the code uses the formula
  * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
  */
 
 /*
  * Multiply
  * B(Dca, ad, Sca, as) = Dca.Sca
  */
-
 static void
 combine_multiply_u (pixman_implementation_t *imp,
                     pixman_op_t              op,
                     uint32_t *                dest,
                     const uint32_t *          src,
                     const uint32_t *          mask,
                     int                      width)
 {
@@ -488,17 +485,17 @@ combine_multiply_ca (pixman_implementati
     for (i = 0; i < width; ++i)
     {
 	uint32_t m = *(mask + i);
 	uint32_t s = *(src + i);
 	uint32_t d = *(dest + i);
 	uint32_t r = d;
 	uint32_t dest_ia = ALPHA_8 (~d);
 
-	combine_mask_value_ca (&s, &m);
+	combine_mask_ca (&s, &m);
 
 	UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (r, ~m, s, dest_ia);
 	UN8x4_MUL_UN8x4 (d, s);
 	UN8x4_ADD_UN8x4 (r, d);
 
 	*(dest + i) = r;
     }
 }
@@ -545,17 +542,17 @@ combine_multiply_ca (pixman_implementati
 	for (i = 0; i < width; ++i) {					\
 	    uint32_t m = *(mask + i);					\
 	    uint32_t s = *(src + i);					\
 	    uint32_t d = *(dest + i);					\
 	    uint8_t da = ALPHA_8 (d);					\
 	    uint8_t ida = ~da;						\
 	    uint32_t result;						\
             								\
-	    combine_mask_value_ca (&s, &m);				\
+	    combine_mask_ca (&s, &m);					\
             								\
 	    result = d;							\
 	    UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (result, ~m, s, ida);     \
             								\
 	    result +=							\
 	        (DIV_ONE_UN8 (ALPHA_8 (m) * (uint32_t)da) << A_SHIFT) +	\
 	        (blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m)) << R_SHIFT) + \
 	        (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)) << G_SHIFT) + \
@@ -1578,19 +1575,18 @@ combine_conjoint_xor_u (pixman_implement
                         uint32_t *                dest,
                         const uint32_t *          src,
                         const uint32_t *          mask,
                         int                      width)
 {
     combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR);
 }
 
-/************************************************************************/
-/*********************** Per Channel functions **************************/
-/************************************************************************/
+
+/* Component alpha combiners */
 
 static void
 combine_clear_ca (pixman_implementation_t *imp,
                   pixman_op_t              op,
                   uint32_t *                dest,
                   const uint32_t *          src,
                   const uint32_t *          mask,
                   int                      width)
@@ -2457,9 +2453,8 @@ void
     imp->combine_32_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca;
 
     /* It is not clear that these make sense, so make them noops for now */
     imp->combine_32_ca[PIXMAN_OP_HSL_HUE] = combine_dst;
     imp->combine_32_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst;
     imp->combine_32_ca[PIXMAN_OP_HSL_COLOR] = combine_dst;
     imp->combine_32_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst;
 }
-
--- a/gfx/cairo/libpixman/src/pixman-combine32.h
+++ b/gfx/cairo/libpixman/src/pixman-combine32.h
@@ -1,13 +1,8 @@
-/* WARNING: This file is generated by combine.pl from combine.inc.
-   Please edit one of those files rather than this one. */
-
-#line 1 "pixman-combine.c.template"
-
 #define COMPONENT_SIZE 8
 #define MASK 0xff
 #define ONE_HALF 0x80
 
 #define A_SHIFT 8 * 3
 #define R_SHIFT 8 * 2
 #define G_SHIFT 8
 #define A_MASK 0xff000000
--- a/gfx/cairo/libpixman/src/pixman-conical-gradient.c
+++ b/gfx/cairo/libpixman/src/pixman-conical-gradient.c
@@ -160,32 +160,33 @@ conical_get_scanline_narrow (pixman_iter
     return iter->buffer;
 }
 
 static uint32_t *
 conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 {
     uint32_t *buffer = conical_get_scanline_narrow (iter, NULL);
 
-    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
+    pixman_expand_to_float (
+	(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
 
     return buffer;
 }
 
 void
 _pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
 {
     if (iter->iter_flags & ITER_NARROW)
 	iter->get_scanline = conical_get_scanline_narrow;
     else
 	iter->get_scanline = conical_get_scanline_wide;
 }
 
 PIXMAN_EXPORT pixman_image_t *
-pixman_image_create_conical_gradient (pixman_point_fixed_t *        center,
+pixman_image_create_conical_gradient (const pixman_point_fixed_t *  center,
                                       pixman_fixed_t                angle,
                                       const pixman_gradient_stop_t *stops,
                                       int                           n_stops)
 {
     pixman_image_t *image = _pixman_image_allocate ();
     conical_gradient_t *conical;
 
     if (!image)
--- a/gfx/cairo/libpixman/src/pixman-fast-path.c
+++ b/gfx/cairo/libpixman/src/pixman-fast-path.c
@@ -85,17 +85,17 @@ over (uint32_t src,
 {
     uint32_t a = ~src >> 24;
 
     UN8x4_MUL_UN8_ADD_UN8x4 (dest, a, src);
 
     return dest;
 }
 
-static uint32_t
+static force_inline uint32_t
 in (uint32_t x,
     uint8_t  y)
 {
     uint16_t a = y;
 
     UN8x4_MUL_UN8 (x, a);
 
     return x;
@@ -1475,17 +1475,17 @@ fast_composite_tiled_repeat (pixman_impl
 	mask_flags = info->mask_flags;
     }
     else
     {
 	mask_format = PIXMAN_null;
 	mask_flags = FAST_PATH_IS_OPAQUE;
     }
 
-    if (_pixman_lookup_composite_function (
+    if (_pixman_implementation_lookup_composite (
 	    imp->toplevel, info->op,
 	    src_image->common.extended_format_code, src_flags,
 	    mask_format, mask_flags,
 	    dest_image->common.extended_format_code, info->dest_flags,
 	    &imp, &func))
     {
 	int32_t sx, sy;
 	int32_t width_remain;
@@ -1513,17 +1513,18 @@ fast_composite_tiled_repeat (pixman_impl
 
 	    while (src_width < REPEAT_MIN_WIDTH && src_width <= sx)
 		src_width += src_image->bits.width;
 
 	    src_stride = (src_width * (src_bpp >> 3) + 3) / (int) sizeof (uint32_t);
 
 	    /* Initialize/validate stack-allocated temporary image */
 	    _pixman_bits_image_init (&extended_src_image, src_image->bits.format,
-				     src_width, 1, &extended_src[0], src_stride);
+				     src_width, 1, &extended_src[0], src_stride,
+				     FALSE);
 	    _pixman_image_validate (&extended_src_image);
 
 	    info2.src_image = &extended_src_image;
 	    need_src_extension = TRUE;
 	}
 	else
 	{
 	    src_width = src_image->bits.width;
@@ -1675,17 +1676,17 @@ FAST_NEAREST_MAINLOOP (565_565_pad_SRC,
 
 static force_inline uint32_t
 fetch_nearest (pixman_repeat_t src_repeat,
 	       pixman_format_code_t format,
 	       uint32_t *src, int x, int src_width)
 {
     if (repeat (src_repeat, &x, src_width))
     {
-	if (format == PIXMAN_x8r8g8b8)
+	if (format == PIXMAN_x8r8g8b8 || format == PIXMAN_x8b8g8r8)
 	    return *(src + x) | 0xff000000;
 	else
 	    return *(src + x);
     }
     else
     {
 	return 0;
     }
@@ -2413,19 +2414,17 @@ fast_path_fill (pixman_implementation_t 
 	pixman_fill16 (bits, stride, x, y, width, height, xor);
 	break;
 
     case 32:
 	pixman_fill32 (bits, stride, x, y, width, height, xor);
 	break;
 
     default:
-	return _pixman_implementation_fill (
-	    imp->delegate, bits, stride, bpp, x, y, width, height, xor);
-	break;
+	return FALSE;
     }
 
     return TRUE;
 }
 
 pixman_implementation_t *
 _pixman_implementation_create_fast_path (pixman_implementation_t *fallback)
 {
--- a/gfx/cairo/libpixman/src/pixman-general.c
+++ b/gfx/cairo/libpixman/src/pixman-general.c
@@ -32,45 +32,51 @@
 #include <string.h>
 #include <math.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "pixman-private.h"
 
-static void
+static pixman_bool_t
 general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
 {
     pixman_image_t *image = iter->image;
 
     if (image->type == SOLID)
 	_pixman_solid_fill_iter_init (image, iter);
     else if (image->type == LINEAR)
 	_pixman_linear_gradient_iter_init (image, iter);
     else if (image->type == RADIAL)
 	_pixman_radial_gradient_iter_init (image, iter);
     else if (image->type == CONICAL)
 	_pixman_conical_gradient_iter_init (image, iter);
     else if (image->type == BITS)
 	_pixman_bits_image_src_iter_init (image, iter);
     else
 	_pixman_log_error (FUNC, "Pixman bug: unknown image type\n");
+
+    return TRUE;
 }
 
-static void
+static pixman_bool_t
 general_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
 {
     if (iter->image->type == BITS)
     {
 	_pixman_bits_image_dest_iter_init (iter->image, iter);
+
+	return TRUE;
     }
     else
     {
 	_pixman_log_error (FUNC, "Trying to write to a non-writable image");
+
+	return FALSE;
     }
 }
 
 typedef struct op_info_t op_info_t;
 struct op_info_t
 {
     uint8_t src, dst;
 };
@@ -120,17 +126,17 @@ general_composite_rect  (pixman_implemen
 	(dest_image->common.flags & FAST_PATH_NARROW_FORMAT))
     {
 	narrow = ITER_NARROW;
 	Bpp = 4;
     }
     else
     {
 	narrow = 0;
-	Bpp = 8;
+	Bpp = 16;
     }
 
     // XXX: This special casing is bad. Ideally, we'd keep the general code general perhaps
     // by having it deal more specifically with different intermediate formats
     if (
 	(dest_image->common.flags & FAST_PATH_16_FORMAT && (src_image->type == LINEAR || src_image->type == RADIAL)) &&
 	( op == PIXMAN_OP_SRC ||
          (op == PIXMAN_OP_OVER && (src_image->common.flags & FAST_PATH_IS_OPAQUE))
@@ -149,16 +155,24 @@ general_composite_rect  (pixman_implemen
 	if (!scanline_buffer)
 	    return;
     }
 
     src_buffer = scanline_buffer;
     mask_buffer = src_buffer + width * Bpp;
     dest_buffer = mask_buffer + width * Bpp;
 
+    if (!narrow)
+    {
+	/* To make sure there aren't any NANs in the buffers */
+	memset (src_buffer, 0, width * Bpp);
+	memset (mask_buffer, 0, width * Bpp);
+	memset (dest_buffer, 0, width * Bpp);
+    }
+    
     /* src iter */
     src_iter_flags = narrow | op_flags[op].src | rgb16;
 
     _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image,
 					  src_x, src_y, width, height,
 					  src_buffer, src_iter_flags, info->src_flags);
 
     /* mask iter */
@@ -210,59 +224,23 @@ general_composite_rect  (pixman_implemen
 }
 
 static const pixman_fast_path_t general_fast_path[] =
 {
     { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any,	0, PIXMAN_any, 0, general_composite_rect },
     { PIXMAN_OP_NONE }
 };
 
-static pixman_bool_t
-general_blt (pixman_implementation_t *imp,
-             uint32_t *               src_bits,
-             uint32_t *               dst_bits,
-             int                      src_stride,
-             int                      dst_stride,
-             int                      src_bpp,
-             int                      dst_bpp,
-             int                      src_x,
-             int                      src_y,
-             int                      dest_x,
-             int                      dest_y,
-             int                      width,
-             int                      height)
-{
-    /* We can't blit unless we have sse2 or mmx */
-
-    return FALSE;
-}
-
-static pixman_bool_t
-general_fill (pixman_implementation_t *imp,
-              uint32_t *               bits,
-              int                      stride,
-              int                      bpp,
-              int                      x,
-              int                      y,
-              int                      width,
-              int                      height,
-              uint32_t xor)
-{
-    return FALSE;
-}
-
 pixman_implementation_t *
 _pixman_implementation_create_general (void)
 {
     pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
 
     _pixman_setup_combiner_functions_16 (imp);
     _pixman_setup_combiner_functions_32 (imp);
-    _pixman_setup_combiner_functions_64 (imp);
+    _pixman_setup_combiner_functions_float (imp);
 
-    imp->blt = general_blt;
-    imp->fill = general_fill;
     imp->src_iter_init = general_src_iter_init;
     imp->dest_iter_init = general_dest_iter_init;
 
     return imp;
 }
 
--- a/gfx/cairo/libpixman/src/pixman-glyph.c
+++ b/gfx/cairo/libpixman/src/pixman-glyph.c
@@ -349,17 +349,17 @@ pixman_glyph_get_extents (pixman_glyph_c
 }
 
 /* This function returns a format that is suitable for use as a mask for the
  * set of glyphs in question.
  */
 PIXMAN_EXPORT pixman_format_code_t
 pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache,
 			      int		    n_glyphs,
-			      pixman_glyph_t *      glyphs)
+			      const pixman_glyph_t *glyphs)
 {
     pixman_format_code_t format = PIXMAN_a1;
     int i;
 
     for (i = 0; i < n_glyphs; ++i)
     {
 	const glyph_t *glyph = glyphs[i].glyph;
 	pixman_format_code_t glyph_format = glyph->image->bits.format;
@@ -396,17 +396,17 @@ pixman_composite_glyphs_no_mask (pixman_
 				 pixman_image_t        *src,
 				 pixman_image_t        *dest,
 				 int32_t                src_x,
 				 int32_t                src_y,
 				 int32_t                dest_x,
 				 int32_t                dest_y,
 				 pixman_glyph_cache_t  *cache,
 				 int                    n_glyphs,
-				 pixman_glyph_t        *glyphs)
+				 const pixman_glyph_t  *glyphs)
 {
     pixman_region32_t region;
     pixman_format_code_t glyph_format = PIXMAN_null;
     uint32_t glyph_flags = 0;
     pixman_format_code_t dest_format;
     uint32_t dest_flags;
     pixman_composite_func_t func = NULL;
     pixman_implementation_t *implementation = NULL;
@@ -459,17 +459,17 @@ pixman_composite_glyphs_no_mask (pixman_
 	    if (box32_intersect (&composite_box, pbox, &glyph_box))
 	    {
 		if (glyph_img->common.extended_format_code != glyph_format	||
 		    glyph_img->common.flags != glyph_flags)
 		{
 		    glyph_format = glyph_img->common.extended_format_code;
 		    glyph_flags = glyph_img->common.flags;
 		    
-		    _pixman_lookup_composite_function (
+		    _pixman_implementation_lookup_composite (
 			get_implementation(), op,
 			src->common.extended_format_code, src->common.flags,
 			glyph_format, glyph_flags | extra,
 			dest_format, dest_flags,
 			&implementation, &func);
 
 		    if (!func)
 			goto out;
@@ -497,17 +497,17 @@ pixman_composite_glyphs_no_mask (pixman_
 out:
     pixman_region32_fini (&region);
 }
 
 static void
 add_glyphs (pixman_glyph_cache_t *cache,
 	    pixman_image_t *dest,
 	    int off_x, int off_y,
-	    int n_glyphs, pixman_glyph_t *glyphs)
+	    int n_glyphs, const pixman_glyph_t *glyphs)
 {
     pixman_format_code_t glyph_format = PIXMAN_null;
     uint32_t glyph_flags = 0;
     pixman_composite_func_t func = NULL;
     pixman_implementation_t *implementation = NULL;
     uint32_t dest_format;
     uint32_t dest_flags;
     pixman_box32_t dest_box;
@@ -555,33 +555,33 @@ add_glyphs (pixman_glyph_cache_t *cache,
 		info.mask_flags = FAST_PATH_IS_OPAQUE;
 		info.mask_image = NULL;
 		white_src = FALSE;
 	    }
 	    else
 	    {
 		if (!white_img)
 		{
-		    pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff };
+		    static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff };
 
 		    if (!(white_img = pixman_image_create_solid_fill (&white)))
 			goto out;
 
 		    _pixman_image_validate (white_img);
 		}
 
 		src_format = PIXMAN_solid;
 		mask_format = glyph_format;
 		info.src_flags = white_img->common.flags;
 		info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
 		info.src_image = white_img;
 		white_src = TRUE;
 	    }
 
-	    _pixman_lookup_composite_function (
+	    _pixman_implementation_lookup_composite (
 		get_implementation(), PIXMAN_OP_ADD,
 		src_format, info.src_flags,
 		mask_format, info.mask_flags,
 		dest_format, dest_flags,
 		&implementation, &func);
 
 	    if (!func)
 		goto out;
@@ -646,17 +646,17 @@ pixman_composite_glyphs (pixman_op_t    
 			 int32_t		mask_x,
 			 int32_t		mask_y,
 			 int32_t                dest_x,
 			 int32_t                dest_y,
 			 int32_t                width,
 			 int32_t                height,
 			 pixman_glyph_cache_t  *cache,
 			 int			n_glyphs,
-			 pixman_glyph_t        *glyphs)
+			 const pixman_glyph_t  *glyphs)
 {
     pixman_image_t *mask;
 
     if (!(mask = pixman_image_create_bits (mask_format, width, height, NULL, -1)))
 	return;
 
     if (PIXMAN_FORMAT_A   (mask_format) != 0 &&
 	PIXMAN_FORMAT_RGB (mask_format) != 0)
--- a/gfx/cairo/libpixman/src/pixman-image.c
+++ b/gfx/cairo/libpixman/src/pixman-image.c
@@ -296,19 +296,19 @@ compute_image_info (pixman_image_t *imag
 		flags |= FAST_PATH_SCALE_TRANSFORM;
 	    }
 	    else if (image->common.transform->matrix[0][0] == 0 &&
 	             image->common.transform->matrix[1][1] == 0)
 	    {
 		pixman_fixed_t m01 = image->common.transform->matrix[0][1];
 		pixman_fixed_t m10 = image->common.transform->matrix[1][0];
 
-		if (m01 == -1 && m10 == 1)
+		if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1)
 		    flags |= FAST_PATH_ROTATE_90_TRANSFORM;
-		else if (m01 == 1 && m10 == -1)
+		else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1)
 		    flags |= FAST_PATH_ROTATE_270_TRANSFORM;
 	    }
 	}
 
 	if (image->common.transform->matrix[0][0] > 0)
 	    flags |= FAST_PATH_X_UNIT_POSITIVE;
 
 	if (image->common.transform->matrix[1][0] == 0)
--- a/gfx/cairo/libpixman/src/pixman-implementation.c
+++ b/gfx/cairo/libpixman/src/pixman-implementation.c
@@ -22,135 +22,192 @@
  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 #include <stdlib.h>
 #include "pixman-private.h"
 
-static pixman_bool_t
-delegate_blt (pixman_implementation_t * imp,
-              uint32_t *                src_bits,
-              uint32_t *                dst_bits,
-              int                       src_stride,
-              int                       dst_stride,
-              int                       src_bpp,
-              int                       dst_bpp,
-              int                       src_x,
-              int                       src_y,
-              int                       dest_x,
-              int                       dest_y,
-              int                       width,
-              int                       height)
-{
-    return _pixman_implementation_blt (
-	imp->delegate, src_bits, dst_bits, src_stride, dst_stride,
-	src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
-	width, height);
-}
-
-static pixman_bool_t
-delegate_fill (pixman_implementation_t *imp,
-               uint32_t *               bits,
-               int                      stride,
-               int                      bpp,
-               int                      x,
-               int                      y,
-               int                      width,
-               int                      height,
-               uint32_t                 xor)
-{
-    return _pixman_implementation_fill (
-	imp->delegate, bits, stride, bpp, x, y, width, height, xor);
-}
-
-static void
-delegate_src_iter_init (pixman_implementation_t *imp,
-			pixman_iter_t *	         iter)
-{
-    imp->delegate->src_iter_init (imp->delegate, iter);
-}
-
-static void
-delegate_dest_iter_init (pixman_implementation_t *imp,
-			 pixman_iter_t *	  iter)
-{
-    imp->delegate->dest_iter_init (imp->delegate, iter);
-}
-
 pixman_implementation_t *
-_pixman_implementation_create (pixman_implementation_t *delegate,
+_pixman_implementation_create (pixman_implementation_t *fallback,
 			       const pixman_fast_path_t *fast_paths)
 {
-    pixman_implementation_t *imp = malloc (sizeof (pixman_implementation_t));
-    pixman_implementation_t *d;
-    int i;
-
-    if (!imp)
-	return NULL;
+    pixman_implementation_t *imp;
 
     assert (fast_paths);
 
-    /* Make sure the whole delegate chain has the right toplevel */
-    imp->delegate = delegate;
-    for (d = imp; d != NULL; d = d->delegate)
-	d->toplevel = imp;
+    if ((imp = malloc (sizeof (pixman_implementation_t))))
+    {
+	pixman_implementation_t *d;
+
+	memset (imp, 0, sizeof *imp);
 
-    /* Fill out function pointers with ones that just delegate
-     */
-    imp->blt = delegate_blt;
-    imp->fill = delegate_fill;
-    imp->src_iter_init = delegate_src_iter_init;
-    imp->dest_iter_init = delegate_dest_iter_init;
-
-    imp->fast_paths = fast_paths;
-
-    for (i = 0; i < PIXMAN_N_OPERATORS; ++i)
-    {
-	imp->combine_16[i] = NULL;
-	imp->combine_32[i] = NULL;
-	imp->combine_64[i] = NULL;
-	imp->combine_32_ca[i] = NULL;
-	imp->combine_64_ca[i] = NULL;
+	imp->fallback = fallback;
+	imp->fast_paths = fast_paths;
+	
+	/* Make sure the whole fallback chain has the right toplevel */
+	for (d = imp; d != NULL; d = d->fallback)
+	    d->toplevel = imp;
     }
 
     return imp;
 }
 
+#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);
+
+pixman_bool_t
+_pixman_implementation_lookup_composite (pixman_implementation_t  *toplevel,
+					 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 = toplevel; imp != NULL; imp = imp->fallback)
+    {
+	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_combine_32_func_t
 _pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
 					pixman_op_t		 op,
 					pixman_bool_t		 component_alpha,
 					pixman_bool_t		 narrow,
 					pixman_bool_t		 rgb16)
 {
-    pixman_combine_32_func_t f;
+    while (imp)
+    {
+	pixman_combine_32_func_t f = NULL;
 
-    do
-    {
-	pixman_combine_32_func_t (*combiners[]) =
+	switch ((narrow << 1) | component_alpha)
 	{
-	    (pixman_combine_32_func_t *)imp->combine_64,
-	    (pixman_combine_32_func_t *)imp->combine_64_ca,
-	    imp->combine_32,
-	    imp->combine_32_ca,
-	    (pixman_combine_32_func_t *)imp->combine_16,
-	    NULL,
-	};
-        if (rgb16) {
-            f = combiners[4][op];
-        } else {
-            f = combiners[component_alpha + (narrow << 1)][op];
-        }
-	imp = imp->delegate;
+	case 0: /* not narrow, not component alpha */
+	    f = (pixman_combine_32_func_t)imp->combine_float[op];
+	    break;
+	    
+	case 1: /* not narrow, component_alpha */
+	    f = (pixman_combine_32_func_t)imp->combine_float_ca[op];
+	    break;
+
+	case 2: /* narrow, not component alpha */
+	    f = imp->combine_32[op];
+	    break;
+
+	case 3: /* narrow, component_alpha */
+	    f = imp->combine_32_ca[op];
+	    break;
+	}
+	if (rgb16)
+	    f = (pixman_combine_32_func_t *)imp->combine_16[op];
+
+	if (f)
+	    return f;
+
+	imp = imp->fallback;
     }
-    while (!f);
 
-    return f;
+    return NULL;
 }
 
 pixman_bool_t
 _pixman_implementation_blt (pixman_implementation_t * imp,
                             uint32_t *                src_bits,
                             uint32_t *                dst_bits,
                             int                       src_stride,
                             int                       dst_stride,
@@ -158,36 +215,58 @@ pixman_bool_t
                             int                       dst_bpp,
                             int                       src_x,
                             int                       src_y,
                             int                       dest_x,
                             int                       dest_y,
                             int                       width,
                             int                       height)
 {
-    return (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
-			src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
-			width, height);
+    while (imp)
+    {
+	if (imp->blt &&
+	    (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
+			 src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
+			 width, height))
+	{
+	    return TRUE;
+	}
+
+	imp = imp->fallback;
+    }
+
+    return FALSE;
 }
 
 pixman_bool_t
 _pixman_implementation_fill (pixman_implementation_t *imp,
                              uint32_t *               bits,
                              int                      stride,
                              int                      bpp,
                              int                      x,
                              int                      y,
                              int                      width,
                              int                      height,
                              uint32_t                 xor)
 {
-    return (*imp->fill) (imp, bits, stride, bpp, x, y, width, height, xor);
+    while (imp)
+    {
+	if (imp->fill &&
+	    ((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, xor)))
+	{
+	    return TRUE;
+	}
+
+	imp = imp->fallback;
+    }
+
+    return FALSE;
 }
 
-void
+pixman_bool_t
 _pixman_implementation_src_iter_init (pixman_implementation_t	*imp,
 				      pixman_iter_t             *iter,
 				      pixman_image_t		*image,
 				      int			 x,
 				      int			 y,
 				      int			 width,
 				      int			 height,
 				      uint8_t			*buffer,
@@ -198,20 +277,28 @@ void
     iter->buffer = (uint32_t *)buffer;
     iter->x = x;
     iter->y = y;
     iter->width = width;
     iter->height = height;
     iter->iter_flags = iter_flags;
     iter->image_flags = image_flags;
 
-    (*imp->src_iter_init) (imp, iter);
+    while (imp)
+    {
+	if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter))
+	    return TRUE;
+
+	imp = imp->fallback;
+    }
+
+    return FALSE;
 }
 
-void
+pixman_bool_t
 _pixman_implementation_dest_iter_init (pixman_implementation_t	*imp,
 				       pixman_iter_t            *iter,
 				       pixman_image_t		*image,
 				       int			 x,
 				       int			 y,
 				       int			 width,
 				       int			 height,
 				       uint8_t			*buffer,
@@ -222,17 +309,25 @@ void
     iter->buffer = (uint32_t *)buffer;
     iter->x = x;
     iter->y = y;
     iter->width = width;
     iter->height = height;
     iter->iter_flags = iter_flags;
     iter->image_flags = image_flags;
 
-    (*imp->dest_iter_init) (imp, iter);
+    while (imp)
+    {
+	if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter))
+	    return TRUE;
+
+	imp = imp->fallback;
+    }
+
+    return FALSE;
 }
 
 pixman_bool_t
 _pixman_disabled (const char *name)
 {
     const char *env;
 
     if ((env = getenv ("PIXMAN_DISABLE")))
--- a/gfx/cairo/libpixman/src/pixman-linear-gradient.c
+++ b/gfx/cairo/libpixman/src/pixman-linear-gradient.c
@@ -381,17 +381,18 @@ linear_get_scanline_16 (pixman_iter_t  *
     return iter->buffer;
 }
 
 static uint32_t *
 linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 {
     uint32_t *buffer = linear_get_scanline_narrow (iter, NULL);
 
-    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
+    pixman_expand_to_float (
+	(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
 
     return buffer;
 }
 
 void
 _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t  *iter)
 {
     // XXX: we can't use this optimization when dithering
@@ -414,18 +415,18 @@ void
 	else if (iter->iter_flags & ITER_NARROW)
 	    iter->get_scanline = linear_get_scanline_narrow;
 	else
 	    iter->get_scanline = linear_get_scanline_wide;
     }
 }
 
 PIXMAN_EXPORT pixman_image_t *
-pixman_image_create_linear_gradient (pixman_point_fixed_t *        p1,
-                                     pixman_point_fixed_t *        p2,
+pixman_image_create_linear_gradient (const pixman_point_fixed_t *  p1,
+                                     const pixman_point_fixed_t *  p2,
                                      const pixman_gradient_stop_t *stops,
                                      int                           n_stops)
 {
     pixman_image_t *image;
     linear_gradient_t *linear;
 
     image = _pixman_image_allocate ();
 
--- a/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S
+++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S
@@ -744,16 +744,1100 @@ 31:
     sh       t2, 0(a0)
 4:
     RESTORE_REGS_FROM_STACK  24, v0, s0, s1, s2, s3, s4, s5, s6, s7, s8
     j        ra
      nop
 
 END(pixman_composite_over_n_8_0565_asm_mips)
 
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_n_8888_asm_mips)
+/*
+ * a0 - dst  (a8r8g8b8)
+ * a1 - src  (a8r8g8b8)
+ * a2 - mask (32bit constant)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, s0
+    li       t4, 0x00ff00ff
+    beqz     a3, 3f
+     nop
+    addiu    t1, a3, -1
+    srl      a2, a2, 24
+    beqz     t1, 2f
+     nop
+
+1:
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw       t1, 4(a1) /* t1 = source      (a8r8g8b8) */
+                       /* a2 = mask        (32bit constant) */
+    lw       t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+    lw       t3, 4(a0) /* t3 = destination (a8r8g8b8) */
+    addiu    a1, a1, 8
+
+    OVER_2x8888_2x8_2x8888 t0, t1, a2, a2, t2, t3, \
+                           t5, t6, t4, t7, t8, t9, t0, t1, s0
+
+    sw       t5, 0(a0)
+    sw       t6, 4(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 8
+2:
+    beqz     a3, 3f
+     nop
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+                       /* a2 = mask        (32bit constant) */
+    lw       t1, 0(a0) /* t1 = destination (a8r8g8b8) */
+
+    OVER_8888_8_8888 t0, a2, t1, t3, t4, t5, t6, t7, t8
+
+    sw       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 0, s0
+    j        ra
+     nop
+
+END(pixman_composite_over_8888_n_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_n_0565_asm_mips)
+/*
+ * a0 - dst  (r5g6b5)
+ * a1 - src  (a8r8g8b8)
+ * a2 - mask (32bit constant)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, s0, s1, s2, s3
+    li       t6, 0x00ff00ff
+    li       t7, 0xf800f800
+    li       t8, 0x07e007e0
+    li       t9, 0x001F001F
+    beqz     a3, 3f
+     nop
+    srl      a2, a2, 24
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw       t1, 4(a1) /* t1 = source      (a8r8g8b8) */
+                       /* a2 = mask        (32bit constant) */
+    lhu      t2, 0(a0) /* t2 = destination (r5g6b5) */
+    lhu      t3, 2(a0) /* t2 = destination (r5g6b5) */
+    addiu    a1, a1, 8
+
+    CONVERT_2x0565_TO_2x8888 t2, t3, t4, t5, t8, t9, s0, s1, t2, t3
+    OVER_2x8888_2x8_2x8888   t0, t1, a2, a2, t4, t5, \
+                             t2, t3, t6, t0, t1, s0, s1, s2, s3
+    CONVERT_2x8888_TO_2x0565 t2, t3, t4, t5, t7, t8, t9, s0, s1
+
+    sh       t4, 0(a0)
+    sh       t5, 2(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 4
+2:
+    beqz     a3, 3f
+     nop
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+                       /* a2 = mask        (32bit constant) */
+    lhu      t1, 0(a0) /* t1 = destination (r5g6b5) */
+
+    CONVERT_1x0565_TO_1x8888 t1, t2, t4, t5
+    OVER_8888_8_8888         t0, a2, t2, t1, t6, t3, t4, t5, t7
+    CONVERT_1x8888_TO_1x0565 t1, t3, t4, t5
+
+    sh       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
+    j                 ra
+     nop
+
+END(pixman_composite_over_8888_n_0565_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_0565_n_0565_asm_mips)
+/*
+ * a0 - dst  (r5g6b5)
+ * a1 - src  (r5g6b5)
+ * a2 - mask (32bit constant)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 20, s0, s1, s2, s3, s4, s5
+    li       t6, 0x00ff00ff
+    li       t7, 0xf800f800
+    li       t8, 0x07e007e0
+    li       t9, 0x001F001F
+    beqz     a3, 3f
+     nop
+    srl      a2, a2, 24
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+    lhu      t0, 0(a1) /* t0 = source      (r5g6b5) */
+    lhu      t1, 2(a1) /* t1 = source      (r5g6b5) */
+                       /* a2 = mask        (32bit constant) */
+    lhu      t2, 0(a0) /* t2 = destination (r5g6b5) */
+    lhu      t3, 2(a0) /* t3 = destination (r5g6b5) */
+    addiu    a1, a1, 4
+
+    CONVERT_2x0565_TO_2x8888 t0, t1, t4, t5, t8, t9, s0, s1, s2, s3
+    CONVERT_2x0565_TO_2x8888 t2, t3, s0, s1, t8, t9, s2, s3, s4, s5
+    OVER_2x8888_2x8_2x8888   t4, t5, a2, a2, s0, s1, \
+                             t0, t1, t6, s2, s3, s4, s5, t4, t5
+    CONVERT_2x8888_TO_2x0565 t0, t1, s0, s1, t7, t8, t9, s2, s3
+
+    sh       s0, 0(a0)
+    sh       s1, 2(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 4
+2:
+    beqz     a3, 3f
+     nop
+    lhu      t0, 0(a1) /* t0 = source      (r5g6b5) */
+                       /* a2 = mask        (32bit constant) */
+    lhu      t1, 0(a0) /* t1 = destination (r5g6b5) */
+
+    CONVERT_1x0565_TO_1x8888 t0, t2, t4, t5
+    CONVERT_1x0565_TO_1x8888 t1, t3, t4, t5
+    OVER_8888_8_8888         t2, a2, t3, t0, t6, t1, t4, t5, t7
+    CONVERT_1x8888_TO_1x0565 t0, t3, t4, t5
+
+    sh       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 20, s0, s1, s2, s3, s4, s5
+    j        ra
+     nop
+
+END(pixman_composite_over_0565_n_0565_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_8_8888_asm_mips)
+/*
+ * a0 - dst  (a8r8g8b8)
+ * a1 - src  (a8r8g8b8)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, s0, s1
+    li       t4, 0x00ff00ff
+    beqz     a3, 3f
+     nop
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw       t1, 4(a1) /* t1 = source      (a8r8g8b8) */
+    lbu      t2, 0(a2) /* t2 = mask        (a8) */
+    lbu      t3, 1(a2) /* t3 = mask        (a8) */
+    lw       t5, 0(a0) /* t5 = destination (a8r8g8b8) */
+    lw       t6, 4(a0) /* t6 = destination (a8r8g8b8) */
+    addiu    a1, a1, 8
+    addiu    a2, a2, 2
+
+    OVER_2x8888_2x8_2x8888 t0, t1, t2, t3, t5, t6, \
+                           t7, t8, t4, t9, s0, s1, t0, t1, t2
+
+    sw       t7, 0(a0)
+    sw       t8, 4(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 8
+2:
+    beqz     a3, 3f
+     nop
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lbu      t1, 0(a2) /* t1 = mask        (a8) */
+    lw       t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+
+    OVER_8888_8_8888 t0, t1, t2, t3, t4, t5, t6, t7, t8
+
+    sw       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 0, s0, s1
+    j        ra
+     nop
+
+END(pixman_composite_over_8888_8_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_8_0565_asm_mips)
+/*
+ * a0 - dst  (r5g6b5)
+ * a1 - src  (a8r8g8b8)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 20, s0, s1, s2, s3, s4, s5
+    li       t6, 0x00ff00ff
+    li       t7, 0xf800f800
+    li       t8, 0x07e007e0
+    li       t9, 0x001F001F
+    beqz     a3, 3f
+     nop
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw       t1, 4(a1) /* t1 = source      (a8r8g8b8) */
+    lbu      t2, 0(a2) /* t2 = mask        (a8) */
+    lbu      t3, 1(a2) /* t3 = mask        (a8) */
+    lhu      t4, 0(a0) /* t4 = destination (r5g6b5) */
+    lhu      t5, 2(a0) /* t5 = destination (r5g6b5) */
+    addiu    a1, a1, 8
+    addiu    a2, a2, 2
+
+    CONVERT_2x0565_TO_2x8888 t4, t5, s0, s1, t8, t9, s2, s3, s4, s5
+    OVER_2x8888_2x8_2x8888   t0, t1, t2, t3, s0, s1, \
+                             t4, t5, t6, s2, s3, s4, s5, t0, t1
+    CONVERT_2x8888_TO_2x0565 t4, t5, s0, s1, t7, t8, t9, s2, s3
+
+    sh       s0, 0(a0)
+    sh       s1, 2(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 4
+2:
+    beqz     a3, 3f
+     nop
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lbu      t1, 0(a2) /* t1 = mask        (a8) */
+    lhu      t2, 0(a0) /* t2 = destination (r5g6b5) */
+
+    CONVERT_1x0565_TO_1x8888 t2, t3, t4, t5
+    OVER_8888_8_8888         t0, t1, t3, t2, t6, t4, t5, t7, t8
+    CONVERT_1x8888_TO_1x0565 t2, t3, t4, t5
+
+    sh       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 20, s0, s1, s2, s3, s4, s5
+    j        ra
+     nop
+
+END(pixman_composite_over_8888_8_0565_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_0565_8_0565_asm_mips)
+/*
+ * a0 - dst  (r5g6b5)
+ * a1 - src  (r5g6b5)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 20, s0, s1, s2, s3, s4, s5
+    li       t4, 0xf800f800
+    li       t5, 0x07e007e0
+    li       t6, 0x001F001F
+    li       t7, 0x00ff00ff
+    beqz     a3, 3f
+     nop
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+    lhu      t0, 0(a1) /* t0 = source      (r5g6b5) */
+    lhu      t1, 2(a1) /* t1 = source      (r5g6b5) */
+    lbu      t2, 0(a2) /* t2 = mask        (a8) */
+    lbu      t3, 1(a2) /* t3 = mask        (a8) */
+    lhu      t8, 0(a0) /* t8 = destination (r5g6b5) */
+    lhu      t9, 2(a0) /* t9 = destination (r5g6b5) */
+    addiu    a1, a1, 4
+    addiu    a2, a2, 2
+
+    CONVERT_2x0565_TO_2x8888 t0, t1, s0, s1, t5, t6, s2, s3, s4, s5
+    CONVERT_2x0565_TO_2x8888 t8, t9, s2, s3, t5, t6, s4, s5, t0, t1
+    OVER_2x8888_2x8_2x8888   s0, s1, t2, t3, s2, s3, \
+                             t0, t1, t7, s4, s5, t8, t9, s0, s1
+    CONVERT_2x8888_TO_2x0565 t0, t1, s0, s1, t4, t5, t6, s2, s3
+
+    sh       s0, 0(a0)
+    sh       s1, 2(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 4
+2:
+    beqz     a3, 3f
+     nop
+    lhu      t0, 0(a1) /* t0 = source      (r5g6b5) */
+    lbu      t1, 0(a2) /* t1 = mask        (a8) */
+    lhu      t2, 0(a0) /* t2 = destination (r5g6b5) */
+
+    CONVERT_1x0565_TO_1x8888 t0, t3, t4, t5
+    CONVERT_1x0565_TO_1x8888 t2, t4, t5, t6
+    OVER_8888_8_8888         t3, t1, t4, t0, t7, t2, t5, t6, t8
+    CONVERT_1x8888_TO_1x0565 t0, t3, t4, t5
+
+    sh       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 20, s0, s1, s2, s3, s4, s5
+    j        ra
+     nop
+
+END(pixman_composite_over_0565_8_0565_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_8888_8888_asm_mips)
+/*
+ * a0 - dst  (a8r8g8b8)
+ * a1 - src  (a8r8g8b8)
+ * a2 - mask (a8r8g8b8)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, s0, s1, s2
+    li       t4, 0x00ff00ff
+    beqz     a3, 3f
+     nop
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw       t1, 4(a1) /* t1 = source      (a8r8g8b8) */
+    lw       t2, 0(a2) /* t2 = mask        (a8r8g8b8) */
+    lw       t3, 4(a2) /* t3 = mask        (a8r8g8b8) */
+    lw       t5, 0(a0) /* t5 = destination (a8r8g8b8) */
+    lw       t6, 4(a0) /* t6 = destination (a8r8g8b8) */
+    addiu    a1, a1, 8
+    addiu    a2, a2, 8
+    srl      t2, t2, 24
+    srl      t3, t3, 24
+
+    OVER_2x8888_2x8_2x8888 t0, t1, t2, t3, t5, t6, t7, t8, t4, t9, s0, s1, s2, t0, t1
+
+    sw       t7, 0(a0)
+    sw       t8, 4(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 8
+2:
+    beqz     a3, 3f
+     nop
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw       t1, 0(a2) /* t1 = mask        (a8r8g8b8) */
+    lw       t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+    srl      t1, t1, 24
+
+    OVER_8888_8_8888 t0, t1, t2, t3, t4, t5, t6, t7, t8
+
+    sw       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 0, s0, s1, s2
+    j        ra
+     nop
+
+END(pixman_composite_over_8888_8888_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_over_8888_8888_asm_mips)
+/*
+ * a0 - dst  (a8r8g8b8)
+ * a1 - src  (a8r8g8b8)
+ * a2 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, s0, s1, s2
+    li           t4, 0x00ff00ff
+    beqz         a2, 3f
+     nop
+    addiu        t1, a2, -1
+    beqz         t1, 2f
+     nop
+1:
+    lw           t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw           t1, 4(a1) /* t1 = source      (a8r8g8b8) */
+    lw           t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+    lw           t3, 4(a0) /* t3 = destination (a8r8g8b8) */
+    addiu        a1, a1, 8
+
+    not          t5, t0
+    srl          t5, t5, 24
+    not          t6, t1
+    srl          t6, t6, 24
+
+    or           t7, t5, t6
+    beqz         t7, 11f
+     or          t8, t0, t1
+    beqz         t8, 12f
+
+    MIPS_2xUN8x4_MUL_2xUN8 t2, t3, t5, t6, t7, t8, t4, t9, s0, s1, s2, t2, t3
+
+    addu_s.qb    t0, t7, t0
+    addu_s.qb    t1, t8, t1
+11:
+    sw           t0, 0(a0)
+    sw           t1, 4(a0)
+12:
+    addiu        a2, a2, -2
+    addiu        t1, a2, -1
+    bgtz         t1, 1b
+     addiu       a0, a0, 8
+2:
+    beqz         a2, 3f
+     nop
+
+    lw           t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw           t1, 0(a0) /* t1 = destination (a8r8g8b8) */
+    addiu        a1, a1, 4
+
+    not          t2, t0
+    srl          t2, t2, 24
+
+    beqz         t2, 21f
+     nop
+    beqz         t0, 3f
+
+    MIPS_UN8x4_MUL_UN8 t1, t2, t3, t4, t5, t6, t7
+
+    addu_s.qb    t0, t3, t0
+21:
+    sw           t0, 0(a0)
+
+3:
+    RESTORE_REGS_FROM_STACK 0, s0, s1, s2
+    j            ra
+     nop
+
+END(pixman_composite_over_8888_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_add_8_8_8_asm_mips)
+/*
+ * a0 - dst  (a8)
+ * a1 - src  (a8)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, v0, v1
+    li                t9, 0x00ff00ff
+    beqz              a3, 3f
+     nop
+
+    srl               v0, a3, 2   /* v0 = how many multiples of 4 dst pixels */
+    beqz              v0, 1f      /* branch if less than 4 src pixels */
+     nop
+
+0:
+    beqz              v0, 1f
+     addiu            v0, v0, -1
+    lbu               t0, 0(a2)
+    lbu               t1, 1(a2)
+    lbu               t2, 2(a2)
+    lbu               t3, 3(a2)
+    lbu               t4, 0(a0)
+    lbu               t5, 1(a0)
+    lbu               t6, 2(a0)
+    lbu               t7, 3(a0)
+
+    addiu             a2, a2, 4
+
+    precr_sra.ph.w    t1, t0, 0
+    precr_sra.ph.w    t3, t2, 0
+    precr_sra.ph.w    t5, t4, 0
+    precr_sra.ph.w    t7, t6, 0
+
+    precr.qb.ph       t0, t3, t1
+    precr.qb.ph       t1, t7, t5
+
+    lbu               t4, 0(a1)
+    lbu               v1, 1(a1)
+    lbu               t7, 2(a1)
+    lbu               t8, 3(a1)
+
+    addiu             a1, a1, 4
+
+    precr_sra.ph.w    v1, t4, 0
+    precr_sra.ph.w    t8, t7, 0
+
+    muleu_s.ph.qbl    t2, t0, t8
+    muleu_s.ph.qbr    t3, t0, v1
+    shra_r.ph         t4, t2, 8
+    shra_r.ph         t5, t3, 8
+    and               t4, t4, t9
+    and               t5, t5, t9
+    addq.ph           t2, t2, t4
+    addq.ph           t3, t3, t5
+    shra_r.ph         t2, t2, 8
+    shra_r.ph         t3, t3, 8
+    precr.qb.ph       t0, t2, t3
+
+    addu_s.qb         t2, t0, t1
+
+    sb                t2, 0(a0)
+    srl               t2, t2, 8
+    sb                t2, 1(a0)
+    srl               t2, t2, 8
+    sb                t2, 2(a0)
+    srl               t2, t2, 8
+    sb                t2, 3(a0)
+    addiu             a3, a3, -4
+    b                 0b
+     addiu            a0, a0, 4
+
+1:
+    beqz              a3, 3f
+     nop
+2:
+    lbu               t8, 0(a1)
+    lbu               t0, 0(a2)
+    lbu               t1, 0(a0)
+    addiu             a1, a1, 1
+    addiu             a2, a2, 1
+
+    mul               t2, t0, t8
+    shra_r.ph         t3, t2, 8
+    andi              t3, t3, 0xff
+    addq.ph           t2, t2, t3
+    shra_r.ph         t2, t2, 8
+    andi              t2, t2, 0xff
+
+    addu_s.qb         t2, t2, t1
+    sb                t2, 0(a0)
+    addiu             a3, a3, -1
+    bnez              a3, 2b
+     addiu            a0, a0, 1
+
+3:
+    RESTORE_REGS_FROM_STACK 0, v0, v1
+    j                 ra
+     nop
+
+END(pixman_composite_add_8_8_8_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_add_n_8_8_asm_mips)
+/*
+ * a0 - dst  (a8)
+ * a1 - src  (32bit constant)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, v0
+    li                t9, 0x00ff00ff
+    beqz              a3, 3f
+     nop
+
+    srl               v0, a3, 2   /* v0 = how many multiples of 4 dst pixels */
+    beqz              v0, 1f      /* branch if less than 4 src pixels */
+     nop
+
+    srl               t8, a1, 24
+    replv.ph          t8, t8
+
+0:
+    beqz              v0, 1f
+     addiu            v0, v0, -1
+    lbu               t0, 0(a2)
+    lbu               t1, 1(a2)
+    lbu               t2, 2(a2)
+    lbu               t3, 3(a2)
+    lbu               t4, 0(a0)
+    lbu               t5, 1(a0)
+    lbu               t6, 2(a0)
+    lbu               t7, 3(a0)
+
+    addiu             a2, a2, 4
+
+    precr_sra.ph.w    t1, t0, 0
+    precr_sra.ph.w    t3, t2, 0
+    precr_sra.ph.w    t5, t4, 0
+    precr_sra.ph.w    t7, t6, 0
+
+    precr.qb.ph       t0, t3, t1
+    precr.qb.ph       t1, t7, t5
+
+    muleu_s.ph.qbl    t2, t0, t8
+    muleu_s.ph.qbr    t3, t0, t8
+    shra_r.ph         t4, t2, 8
+    shra_r.ph         t5, t3, 8
+    and               t4, t4, t9
+    and               t5, t5, t9
+    addq.ph           t2, t2, t4
+    addq.ph           t3, t3, t5
+    shra_r.ph         t2, t2, 8
+    shra_r.ph         t3, t3, 8
+    precr.qb.ph       t0, t2, t3
+
+    addu_s.qb         t2, t0, t1
+
+    sb                t2, 0(a0)
+    srl               t2, t2, 8
+    sb                t2, 1(a0)
+    srl               t2, t2, 8
+    sb                t2, 2(a0)
+    srl               t2, t2, 8
+    sb                t2, 3(a0)
+    addiu             a3, a3, -4
+    b                 0b
+     addiu            a0, a0, 4
+
+1:
+    beqz              a3, 3f
+     nop
+    srl               t8, a1, 24
+2:
+    lbu               t0, 0(a2)
+    lbu               t1, 0(a0)
+    addiu             a2, a2, 1
+
+    mul               t2, t0, t8
+    shra_r.ph         t3, t2, 8
+    andi              t3, t3, 0xff
+    addq.ph           t2, t2, t3
+    shra_r.ph         t2, t2, 8
+    andi              t2, t2, 0xff
+
+    addu_s.qb         t2, t2, t1
+    sb                t2, 0(a0)
+    addiu             a3, a3, -1
+    bnez              a3, 2b
+     addiu            a0, a0, 1
+
+3:
+    RESTORE_REGS_FROM_STACK 0, v0
+    j                 ra
+     nop
+
+END(pixman_composite_add_n_8_8_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_add_n_8_8888_asm_mips)
+/*
+ * a0 - dst  (a8r8g8b8)
+ * a1 - src  (32bit constant)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, s0, s1, s2
+    li       t4, 0x00ff00ff
+    beqz     a3, 3f
+     nop
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+                       /* a1 = source      (32bit constant) */
+    lbu      t0, 0(a2) /* t0 = mask        (a8) */
+    lbu      t1, 1(a2) /* t1 = mask        (a8) */
+    lw       t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+    lw       t3, 4(a0) /* t3 = destination (a8r8g8b8) */
+    addiu    a2, a2, 2
+
+    MIPS_2xUN8x4_MUL_2xUN8_ADD_2xUN8x4 a1, a1, \
+                                       t0, t1, \
+                                       t2, t3, \
+                                       t5, t6, \
+                                       t4, t7, t8, t9, s0, s1, s2
+
+    sw       t5, 0(a0)
+    sw       t6, 4(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 8
+2:
+    beqz     a3, 3f
+     nop
+                       /* a1 = source      (32bit constant) */
+    lbu      t0, 0(a2) /* t0 = mask        (a8) */
+    lw       t1, 0(a0) /* t1 = destination (a8r8g8b8) */
+
+    MIPS_UN8x4_MUL_UN8_ADD_UN8x4 a1, t0, t1, t2, t4, t3, t5, t6
+
+    sw       t2, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 0, s0, s1, s2
+    j        ra
+     nop
+
+END(pixman_composite_add_n_8_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_add_0565_8_0565_asm_mips)
+/*
+ * a0 - dst  (r5g6b5)
+ * a1 - src  (r5g6b5)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 20, s0, s1, s2, s3, s4, s5, s6, s7
+    li       t4, 0xf800f800
+    li       t5, 0x07e007e0
+    li       t6, 0x001F001F
+    li       t7, 0x00ff00ff
+    beqz     a3, 3f
+     nop
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+    lhu      t0, 0(a1) /* t0 = source      (r5g6b5) */
+    lhu      t1, 2(a1) /* t1 = source      (r5g6b5) */
+    lbu      t2, 0(a2) /* t2 = mask        (a8) */
+    lbu      t3, 1(a2) /* t3 = mask        (a8) */
+    lhu      t8, 0(a0) /* t8 = destination (r5g6b5) */
+    lhu      t9, 2(a0) /* t9 = destination (r5g6b5) */
+    addiu    a1, a1, 4
+    addiu    a2, a2, 2
+
+    CONVERT_2x0565_TO_2x8888  t0, t1, s0, s1, t5, t6, s2, s3, s4, s5
+    CONVERT_2x0565_TO_2x8888  t8, t9, s2, s3, t5, t6, s4, s5, s6, s7
+    MIPS_2xUN8x4_MUL_2xUN8_ADD_2xUN8x4  s0, s1, \
+                                        t2, t3, \
+                                        s2, s3, \
+                                        t0, t1, \
+                                        t7, s4, s5, s6, s7, t8, t9
+    CONVERT_2x8888_TO_2x0565  t0, t1, s0, s1, t4, t5, t6, s2, s3
+
+    sh       s0, 0(a0)
+    sh       s1, 2(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 4
+2:
+    beqz     a3, 3f
+     nop
+    lhu      t0, 0(a1) /* t0 = source      (r5g6b5) */
+    lbu      t1, 0(a2) /* t1 = mask        (a8) */
+    lhu      t2, 0(a0) /* t2 = destination (r5g6b5) */
+
+    CONVERT_1x0565_TO_1x8888  t0, t3, t4, t5
+    CONVERT_1x0565_TO_1x8888  t2, t4, t5, t6
+    MIPS_UN8x4_MUL_UN8_ADD_UN8x4  t3, t1, t4, t0, t7, t2, t5, t6
+    CONVERT_1x8888_TO_1x0565  t0, t3, t4, t5
+
+    sh       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 20, s0, s1, s2, s3, s4, s5, s6, s7
+    j        ra
+     nop
+
+END(pixman_composite_add_0565_8_0565_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_add_8888_8_8888_asm_mips)
+/*
+ * a0 - dst  (a8r8g8b8)
+ * a1 - src  (a8r8g8b8)
+ * a2 - mask (a8)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, s0, s1, s2
+    li       t4, 0x00ff00ff
+    beqz     a3, 3f
+     nop
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw       t1, 4(a1) /* t1 = source      (a8r8g8b8) */
+    lbu      t2, 0(a2) /* t2 = mask        (a8) */
+    lbu      t3, 1(a2) /* t3 = mask        (a8) */
+    lw       t5, 0(a0) /* t5 = destination (a8r8g8b8) */
+    lw       t6, 4(a0) /* t6 = destination (a8r8g8b8) */
+    addiu    a1, a1, 8
+    addiu    a2, a2, 2
+
+    MIPS_2xUN8x4_MUL_2xUN8_ADD_2xUN8x4 t0, t1, \
+                                       t2, t3, \
+                                       t5, t6, \
+                                       t7, t8, \
+                                       t4, t9, s0, s1, s2, t0, t1
+
+    sw       t7, 0(a0)
+    sw       t8, 4(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 8
+2:
+    beqz     a3, 3f
+     nop
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lbu      t1, 0(a2) /* t1 = mask        (a8) */
+    lw       t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+
+    MIPS_UN8x4_MUL_UN8_ADD_UN8x4 t0, t1, t2, t3, t4, t5, t6, t7
+
+    sw       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 0, s0, s1, s2
+    j        ra
+     nop
+
+END(pixman_composite_add_8888_8_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_add_8888_n_8888_asm_mips)
+/*
+ * a0 - dst  (a8r8g8b8)
+ * a1 - src  (a8r8g8b8)
+ * a2 - mask (32bit constant)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, s0, s1, s2
+    li       t4, 0x00ff00ff
+    beqz     a3, 3f
+     nop
+    srl      a2, a2, 24
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw       t1, 4(a1) /* t1 = source      (a8r8g8b8) */
+                       /* a2 = mask        (32bit constant) */
+    lw       t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+    lw       t3, 4(a0) /* t3 = destination (a8r8g8b8) */
+    addiu    a1, a1, 8
+
+    MIPS_2xUN8x4_MUL_2xUN8_ADD_2xUN8x4 t0, t1, \
+                                       a2, a2, \
+                                       t2, t3, \
+                                       t5, t6, \
+                                       t4, t7, t8, t9, s0, s1, s2
+
+    sw       t5, 0(a0)
+    sw       t6, 4(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 8
+2:
+    beqz     a3, 3f
+     nop
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+                       /* a2 = mask        (32bit constant) */
+    lw       t1, 0(a0) /* t1 = destination (a8r8g8b8) */
+
+    MIPS_UN8x4_MUL_UN8_ADD_UN8x4 t0, a2, t1, t3, t4, t5, t6, t7
+
+    sw       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 0, s0, s1, s2
+    j        ra
+     nop
+
+END(pixman_composite_add_8888_n_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_add_8888_8888_8888_asm_mips)
+/*
+ * a0 - dst  (a8r8g8b8)
+ * a1 - src  (a8r8g8b8)
+ * a2 - mask (a8r8g8b8)
+ * a3 - w
+ */
+
+    SAVE_REGS_ON_STACK 0, s0, s1, s2
+    li       t4, 0x00ff00ff
+    beqz     a3, 3f
+     nop
+    addiu    t1, a3, -1
+    beqz     t1, 2f
+     nop
+1:
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw       t1, 4(a1) /* t1 = source      (a8r8g8b8) */
+    lw       t2, 0(a2) /* t2 = mask        (a8r8g8b8) */
+    lw       t3, 4(a2) /* t3 = mask        (a8r8g8b8) */
+    lw       t5, 0(a0) /* t5 = destination (a8r8g8b8) */
+    lw       t6, 4(a0) /* t6 = destination (a8r8g8b8) */
+    addiu    a1, a1, 8
+    addiu    a2, a2, 8
+    srl      t2, t2, 24
+    srl      t3, t3, 24
+
+    MIPS_2xUN8x4_MUL_2xUN8_ADD_2xUN8x4 t0, t1, \
+                                       t2, t3, \
+                                       t5, t6, \
+                                       t7, t8, \
+                                       t4, t9, s0, s1, s2, t0, t1
+
+    sw       t7, 0(a0)
+    sw       t8, 4(a0)
+    addiu    a3, a3, -2
+    addiu    t1, a3, -1
+    bgtz     t1, 1b
+     addiu   a0, a0, 8
+2:
+    beqz     a3, 3f
+     nop
+    lw       t0, 0(a1) /* t0 = source      (a8r8g8b8) */
+    lw       t1, 0(a2) /* t1 = mask        (a8r8g8b8) */
+    lw       t2, 0(a0) /* t2 = destination (a8r8g8b8) */
+    srl      t1, t1, 24
+
+    MIPS_UN8x4_MUL_UN8_ADD_UN8x4 t0, t1, t2, t3, t4, t5, t6, t7
+
+    sw       t3, 0(a0)
+3:
+    RESTORE_REGS_FROM_STACK 0, s0, s1, s2
+    j        ra
+     nop
+
+END(pixman_composite_add_8888_8888_8888_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_add_8_8_asm_mips)
+/*
+ * a0 - dst  (a8)
+ * a1 - src  (a8)
+ * a2 - w
+ */
+
+    beqz              a2, 3f
+     nop
+    srl               t9, a2, 2   /* t9 = how many multiples of 4 dst pixels */
+    beqz              t9, 1f      /* branch if less than 4 src pixels */
+     nop
+
+0:
+    beqz              t9, 1f
+     addiu            t9, t9, -1
+    lbu               t0, 0(a1)
+    lbu               t1, 1(a1)
+    lbu               t2, 2(a1)
+    lbu               t3, 3(a1)
+    lbu               t4, 0(a0)
+    lbu               t5, 1(a0)
+    lbu               t6, 2(a0)
+    lbu               t7, 3(a0)
+
+    addiu             a1, a1, 4
+
+    precr_sra.ph.w    t1, t0, 0
+    precr_sra.ph.w    t3, t2, 0
+    precr_sra.ph.w    t5, t4, 0
+    precr_sra.ph.w    t7, t6, 0
+
+    precr.qb.ph       t0, t3, t1
+    precr.qb.ph       t1, t7, t5
+
+    addu_s.qb         t2, t0, t1
+
+    sb                t2, 0(a0)
+    srl               t2, t2, 8
+    sb                t2, 1(a0)
+    srl               t2, t2, 8
+    sb                t2, 2(a0)
+    srl               t2, t2, 8
+    sb                t2, 3(a0)
+    addiu             a2, a2, -4
+    b                 0b
+     addiu            a0, a0, 4
+
+1:
+    beqz              a2, 3f
+     nop
+2:
+    lbu               t0, 0(a1)
+    lbu               t1, 0(a0)
+    addiu             a1, a1, 1
+
+    addu_s.qb         t2, t0, t1
+    sb                t2, 0(a0)
+    addiu             a2, a2, -1
+    bnez              a2, 2b
+     addiu            a0, a0, 1
+
+3:
+    j                 ra
+     nop
+
+END(pixman_composite_add_8_8_asm_mips)
+
+LEAF_MIPS_DSPR2(pixman_composite_add_8888_8888_asm_mips)
+/*
+ * a0 - dst (a8r8g8b8)
+ * a1 - src (a8r8g8b8)
+ * a2 - w
+ */
+
+    beqz         a2, 4f
+     nop
+
+    srl          t9, a2, 2      /* t1 = how many multiples of 4 src pixels */
+    beqz         t9, 3f         /* branch if less than 4 src pixels */
+     nop
+1:
+    addiu        t9, t9, -1
+    beqz         t9, 2f
+     addiu       a2, a2, -4
+
+    lw           t0, 0(a1)
+    lw           t1, 4(a1)
+    lw           t2, 8(a1)
+    lw           t3, 12(a1)
+    lw           t4, 0(a0)
+    lw           t5, 4(a0)
+    lw           t6, 8(a0)
+    lw           t7, 12(a0)
+    addiu        a1, a1, 16
+
+    addu_s.qb    t4, t4, t0
+    addu_s.qb    t5, t5, t1
+    addu_s.qb    t6, t6, t2
+    addu_s.qb    t7, t7, t3
+
+    sw           t4, 0(a0)
+    sw           t5, 4(a0)
+    sw           t6, 8(a0)
+    sw           t7, 12(a0)
+    b            1b
+     addiu       a0, a0, 16
+2:
+    lw           t0, 0(a1)
+    lw           t1, 4(a1)
+    lw           t2, 8(a1)
+    lw           t3, 12(a1)
+    lw           t4, 0(a0)
+    lw           t5, 4(a0)
+    lw           t6, 8(a0)
+    lw           t7, 12(a0)
+    addiu        a1, a1, 16
+
+    addu_s.qb    t4, t4, t0
+    addu_s.qb    t5, t5, t1
+    addu_s.qb    t6, t6, t2
+    addu_s.qb    t7, t7, t3
+
+    sw           t4, 0(a0)
+    sw           t5, 4(a0)
+    sw           t6, 8(a0)
+    sw           t7, 12(a0)
+
+    beqz         a2, 4f
+     addiu       a0, a0, 16
+3:
+    lw           t0, 0(a1)
+    lw           t1, 0(a0)
+    addiu        a1, a1, 4
+    addiu        a2, a2, -1
+    addu_s.qb    t1, t1, t0
+    sw           t1, 0(a0)
+    bnez         a2, 3b
+     addiu       a0, a0, 4
+4:
+    jr           ra
+     nop
+
+END(pixman_composite_add_8888_8888_asm_mips)
+
 LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_mips)
 /*
  * a0     - *dst
  * a1     - *src_top
  * a2     - *src_bottom
  * a3     - w
  * 16(sp) - wt
  * 20(sp) - wb
--- a/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h
+++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h
@@ -595,16 +595,38 @@ LEAF_MIPS32R2(symbol)                   
                                     scratch1, scratch2, scratch3
     MIPS_UN8x4_MUL_UN8 \s_8888, \m_8, \
                        \out_8888, \maskLSR, \
                        \scratch1, \scratch2, \scratch3
 
     addu_s.qb          \out_8888, \out_8888, \d_8888
 .endm
 
+.macro MIPS_2xUN8x4_MUL_2xUN8_ADD_2xUN8x4 s1_8888,   \
+                             s2_8888,   \
+                             m1_8,      \
+                             m2_8,      \
+                             d1_8888,   \
+                             d2_8888,   \
+                             out1_8888, \
+                             out2_8888, \
+                             maskLSR,   \
+                             scratch1,  scratch2, scratch3, \
+                             scratch4, scratch5, scratch6
+    MIPS_2xUN8x4_MUL_2xUN8 \s1_8888,   \s2_8888, \
+                           \m1_8,      \m2_8, \
+                           \out1_8888, \out2_8888, \
+                           \maskLSR, \
+                           \scratch1,  \scratch2, \scratch3, \
+                           \scratch4,  \scratch5, \scratch6
+
+    addu_s.qb             \out1_8888, \out1_8888, \d1_8888
+    addu_s.qb             \out2_8888, \out2_8888, \d2_8888
+.endm
+
 .macro BILINEAR_INTERPOLATE_SINGLE_PIXEL tl, tr, bl, br,         \
                                          scratch1, scratch2,     \
                                          alpha, red, green, blue \
                                          wt1, wt2, wb1, wb2
     andi            \scratch1, \tl,  0xff
     andi            \scratch2, \tr,  0xff
     andi            \alpha,    \bl,  0xff
     andi            \red,      \br,  0xff
--- a/gfx/cairo/libpixman/src/pixman-mips-dspr2.c
+++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2.c
@@ -43,25 +43,61 @@ PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, s
 PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_0565_8888,
                                     uint16_t, 1, uint32_t, 1)
 PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0565_0565,
                                     uint16_t, 1, uint16_t, 1)
 PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_8888_8888,
                                     uint32_t, 1, uint32_t, 1)
 PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0888_0888,
                                     uint8_t, 3, uint8_t, 3)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, over_8888_8888,
+                                    uint32_t, 1, uint32_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, add_8_8,
+                                    uint8_t, 1, uint8_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, add_8888_8888,
+                                    uint32_t, 1, uint32_t, 1)
 
 PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_8888_ca,
                                        uint32_t, 1, uint32_t, 1)
 PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_0565_ca,
                                        uint32_t, 1, uint16_t, 1)
 PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_8888,
                                        uint8_t, 1, uint32_t, 1)
 PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_0565,
                                        uint8_t, 1, uint16_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, add_n_8_8,
+                                       uint8_t, 1, uint8_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, add_n_8_8888,
+                                       uint8_t, 1, uint32_t, 1)
+
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_8888_n_8888,
+                                      uint32_t, 1, uint32_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_8888_n_0565,
+                                      uint32_t, 1, uint16_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_0565_n_0565,
+                                      uint16_t, 1, uint16_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, add_8888_n_8888,
+                                      uint32_t, 1, uint32_t, 1)
+
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_8_8_8, uint8_t,  1,
+                                         uint8_t,  1, uint8_t,  1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_8888_8_8888, uint32_t, 1,
+                                         uint8_t, 1, uint32_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_8888_8888_8888, uint32_t, 1,
+                                         uint32_t, 1, uint32_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_0565_8_0565, uint16_t, 1,
+                                         uint8_t,  1, uint16_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8_8888, uint32_t, 1,
+                                         uint8_t, 1, uint32_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8_0565, uint32_t, 1,
+                                         uint8_t, 1, uint16_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_0565_8_0565, uint16_t, 1,
+                                         uint8_t, 1, uint16_t, 1)
+PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8888_8888, uint32_t, 1,
+                                         uint32_t, 1, uint32_t, 1)
 
 PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_8888, SRC,
                                           uint32_t, uint32_t)
 PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_0565, SRC,
                                           uint32_t, uint16_t)
 PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 0565_8888, SRC,
                                           uint16_t, uint32_t)
 PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 0565_0565, SRC,
@@ -80,24 +116,25 @@ PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_
 PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 0565_8_0565, SRC,
                                              uint16_t, uint16_t)
 PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, OVER,
                                              uint32_t, uint32_t)
 PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, ADD,
                                              uint32_t, uint32_t)
 
 static pixman_bool_t
-pixman_fill_mips (uint32_t *bits,
-                  int       stride,
-                  int       bpp,
-                  int       x,
-                  int       y,
-                  int       width,
-                  int       height,
-                  uint32_t  _xor)
+mips_dspr2_fill (pixman_implementation_t *imp,
+                 uint32_t *               bits,
+                 int                      stride,
+                 int                      bpp,
+                 int                      x,
+                 int                      y,
+                 int                      width,
+                 int                      height,
+                 uint32_t                 _xor)
 {
     uint8_t *byte_line;
     uint32_t byte_width;
     switch (bpp)
     {
     case 16:
         stride = stride * (int) sizeof (uint32_t) / 2;
         byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x);
@@ -125,28 +162,29 @@ pixman_fill_mips (uint32_t *bits,
         }
         return TRUE;
     default:
         return FALSE;
     }
 }
 
 static pixman_bool_t
-pixman_blt_mips (uint32_t *src_bits,
-                 uint32_t *dst_bits,
-                 int       src_stride,
-                 int       dst_stride,
-                 int       src_bpp,
-                 int       dst_bpp,
-                 int       src_x,
-                 int       src_y,
-                 int       dest_x,
-                 int       dest_y,
-                 int       width,
-                 int       height)
+mips_dspr2_blt (pixman_implementation_t *imp,
+                uint32_t *               src_bits,
+                uint32_t *               dst_bits,
+                int                      src_stride,
+                int                      dst_stride,
+                int                      src_bpp,
+                int                      dst_bpp,
+                int                      src_x,
+                int                      src_y,
+                int                      dest_x,
+                int                      dest_y,
+                int                      width,
+                int                      height)
 {
     if (src_bpp != dst_bpp)
         return FALSE;
 
     uint8_t *src_bytes;
     uint8_t *dst_bytes;
     uint32_t byte_width;
 
@@ -227,16 +265,50 @@ static const pixman_fast_path_t mips_dsp
     PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5,   mips_composite_over_n_8888_0565_ca),
     PIXMAN_STD_FAST_PATH (OVER, solid,    a8,       a8r8g8b8, mips_composite_over_n_8_8888),
     PIXMAN_STD_FAST_PATH (OVER, solid,    a8,       x8r8g8b8, mips_composite_over_n_8_8888),
     PIXMAN_STD_FAST_PATH (OVER, solid,    a8,       a8b8g8r8, mips_composite_over_n_8_8888),
     PIXMAN_STD_FAST_PATH (OVER, solid,    a8,       x8b8g8r8, mips_composite_over_n_8_8888),
     PIXMAN_STD_FAST_PATH (OVER, solid,    a8,       r5g6b5,   mips_composite_over_n_8_0565),
     PIXMAN_STD_FAST_PATH (OVER, solid,    a8,       b5g6r5,   mips_composite_over_n_8_0565),
 
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid,    a8r8g8b8, mips_composite_over_8888_n_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid,    x8r8g8b8, mips_composite_over_8888_n_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid,    r5g6b5,   mips_composite_over_8888_n_0565),
+    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid,    b5g6r5,   mips_composite_over_8888_n_0565),
+    PIXMAN_STD_FAST_PATH (OVER, r5g6b5,   solid,    r5g6b5,   mips_composite_over_0565_n_0565),
+    PIXMAN_STD_FAST_PATH (OVER, b5g6r5,   solid,    b5g6r5,   mips_composite_over_0565_n_0565),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8,       a8r8g8b8, mips_composite_over_8888_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8,       x8r8g8b8, mips_composite_over_8888_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8,       a8b8g8r8, mips_composite_over_8888_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8,       x8b8g8r8, mips_composite_over_8888_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8,       r5g6b5,   mips_composite_over_8888_8_0565),
+    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8,       b5g6r5,   mips_composite_over_8888_8_0565),
+    PIXMAN_STD_FAST_PATH (OVER, r5g6b5,   a8,       r5g6b5,   mips_composite_over_0565_8_0565),
+    PIXMAN_STD_FAST_PATH (OVER, b5g6r5,   a8,       b5g6r5,   mips_composite_over_0565_8_0565),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, a8r8g8b8, mips_composite_over_8888_8888_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null,     a8r8g8b8, mips_composite_over_8888_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null,     x8r8g8b8, mips_composite_over_8888_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null,     a8b8g8r8, mips_composite_over_8888_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null,     x8b8g8r8, mips_composite_over_8888_8888),
+    PIXMAN_STD_FAST_PATH (ADD,  solid,    a8,       a8,       mips_composite_add_n_8_8),
+    PIXMAN_STD_FAST_PATH (ADD,  solid,    a8,       a8r8g8b8, mips_composite_add_n_8_8888),
+    PIXMAN_STD_FAST_PATH (ADD,  solid,    a8,       a8b8g8r8, mips_composite_add_n_8_8888),
+    PIXMAN_STD_FAST_PATH (ADD,  a8,       a8,       a8,       mips_composite_add_8_8_8),
+    PIXMAN_STD_FAST_PATH (ADD,  r5g6b5,   a8,       r5g6b5,   mips_composite_add_0565_8_0565),
+    PIXMAN_STD_FAST_PATH (ADD,  b5g6r5,   a8,       b5g6r5,   mips_composite_add_0565_8_0565),
+    PIXMAN_STD_FAST_PATH (ADD,  a8r8g8b8, a8,       a8r8g8b8, mips_composite_add_8888_8_8888),
+    PIXMAN_STD_FAST_PATH (ADD,  a8b8g8r8, a8,       a8b8g8r8, mips_composite_add_8888_8_8888),
+    PIXMAN_STD_FAST_PATH (ADD,  a8r8g8b8, a8r8g8b8, a8r8g8b8, mips_composite_add_8888_8888_8888),
+    PIXMAN_STD_FAST_PATH (ADD,  a8r8g8b8, solid,    a8r8g8b8, mips_composite_add_8888_n_8888),
+    PIXMAN_STD_FAST_PATH (ADD,  a8b8g8r8, solid,    a8b8g8r8, mips_composite_add_8888_n_8888),
+    PIXMAN_STD_FAST_PATH (ADD,  a8,       null,     a8,       mips_composite_add_8_8),
+    PIXMAN_STD_FAST_PATH (ADD,  a8r8g8b8, null,     a8r8g8b8, mips_composite_add_8888_8888),
+    PIXMAN_STD_FAST_PATH (ADD,  a8b8g8r8, null,     a8b8g8r8, mips_composite_add_8888_8888),
+
     SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8888),
     SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8888),
     SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mips_8888_8888),
 
     SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, r5g6b5, mips_8888_0565),
     SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, r5g6b5, mips_8888_0565),
 
     SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8888),
@@ -261,66 +333,37 @@ static const pixman_fast_path_t mips_dsp
     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8_8888),
     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8_8888),
 
     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, mips_8888_8_8888),
     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, mips_8888_8_8888),
     { PIXMAN_OP_NONE },
 };
 
-static pixman_bool_t
-mips_dspr2_blt (pixman_implementation_t *imp,
-                uint32_t *               src_bits,
-                uint32_t *               dst_bits,
-                int                      src_stride,
-                int                      dst_stride,
-                int                      src_bpp,
-                int                      dst_bpp,
-                int                      src_x,
-                int                      src_y,
-                int                      dest_x,
-                int                      dest_y,
-                int                      width,
-                int                      height)
+static void
+mips_dspr2_combine_over_u (pixman_implementation_t *imp,
+                           pixman_op_t              op,
+                           uint32_t *               dest,
+                           const uint32_t *         src,
+                           const uint32_t *         mask,
+                           int                      width)
 {
-    if (!pixman_blt_mips (
-            src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
-            src_x, src_y, dest_x, dest_y, width, height))
-
-    {
-        return _pixman_implementation_blt (
-            imp->delegate,
-            src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
-            src_x, src_y, dest_x, dest_y, width, height);
-    }
-
-    return TRUE;
-}
-
-static pixman_bool_t
-mips_dspr2_fill (pixman_implementation_t *imp,
-                 uint32_t *               bits,
-                 int                      stride,
-                 int                      bpp,
-                 int                      x,
-                 int                      y,
-                 int                      width,
-                 int                      height,
-                 uint32_t xor)
-{
-    if (pixman_fill_mips (bits, stride, bpp, x, y, width, height, xor))
-        return TRUE;
-
-    return _pixman_implementation_fill (
-        imp->delegate, bits, stride, bpp, x, y, width, height, xor);
+    if (mask)
+        pixman_composite_over_8888_8888_8888_asm_mips (
+            dest, (uint32_t *)src, (uint32_t *)mask, width);
+    else
+        pixman_composite_over_8888_8888_asm_mips (
+		    dest, (uint32_t *)src, width);
 }
 
 pixman_implementation_t *
 _pixman_implementation_create_mips_dspr2 (pixman_implementation_t *fallback)
 {
     pixman_implementation_t *imp =
         _pixman_implementation_create (fallback, mips_dspr2_fast_paths);
 
+    imp->combine_32[PIXMAN_OP_OVER] = mips_dspr2_combine_over_u;
+
     imp->blt = mips_dspr2_blt;
     imp->fill = mips_dspr2_fill;
 
     return imp;
 }
--- a/gfx/cairo/libpixman/src/pixman-mips-dspr2.h
+++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2.h
@@ -122,16 +122,99 @@ mips_composite_##name (pixman_implementa
         dst = dst_line;                                             \
         dst_line += dst_stride;                                     \
         mask = mask_line;                                           \
         mask_line += mask_stride;                                   \
         pixman_composite_##name##_asm_mips (dst, src, mask, width); \
     }                                                               \
 }
 
+/*******************************************************************/
+
+#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST(flags, name,           \
+                                            src_type, src_cnt,      \
+                                            dst_type, dst_cnt)      \
+void                                                                \
+pixman_composite_##name##_asm_mips (dst_type  *dst,                 \
+                                    src_type  *src,                 \
+                                    uint32_t   mask,                \
+                                    int32_t    w);                  \
+                                                                    \
+static void                                                         \
+mips_composite_##name (pixman_implementation_t *imp,                \
+                       pixman_composite_info_t *info)               \
+{                                                                   \
+    PIXMAN_COMPOSITE_ARGS (info);                                   \
+    dst_type  *dst_line, *dst;                                      \
+    src_type  *src_line, *src;                                      \
+    int32_t    dst_stride, src_stride;                              \
+    uint32_t   mask;                                                \
+                                                                    \
+    mask = _pixman_image_get_solid (                                \
+        imp, mask_image, dest_image->bits.format);                  \
+                                                                    \
+    if ((flags & SKIP_ZERO_MASK) && mask == 0)                      \
+        return;                                                     \
+                                                                    \
+    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type,    \
+                           dst_stride, dst_line, dst_cnt);          \
+    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type,       \
+                           src_stride, src_line, src_cnt);          \
+                                                                    \
+    while (height--)                                                \
+    {                                                               \
+        dst = dst_line;                                             \
+        dst_line += dst_stride;                                     \
+        src = src_line;                                             \
+        src_line += src_stride;                                     \
+                                                                    \
+        pixman_composite_##name##_asm_mips (dst, src, mask, width); \
+    }                                                               \
+}
+
+/************************************************************************/
+
+#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST(name, src_type, src_cnt, \
+                                                mask_type, mask_cnt,     \
+                                                dst_type, dst_cnt)       \
+void                                                                     \
+pixman_composite_##name##_asm_mips (dst_type  *dst,                      \
+                                    src_type  *src,                      \
+                                    mask_type *mask,                     \
+                                    int32_t   w);                        \
+                                                                         \
+static void                                                              \
+mips_composite_##name (pixman_implementation_t *imp,                     \
+                       pixman_composite_info_t *info)                    \
+{                                                                        \
+    PIXMAN_COMPOSITE_ARGS (info);                                        \
+    dst_type  *dst_line, *dst;                                           \
+    src_type  *src_line, *src;                                           \
+    mask_type *mask_line, *mask;                                         \
+    int32_t    dst_stride, src_stride, mask_stride;                      \
+                                                                         \
+    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type,         \
+                           dst_stride, dst_line, dst_cnt);               \
+    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type,            \
+                           src_stride, src_line, src_cnt);               \
+    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type,        \
+                           mask_stride, mask_line, mask_cnt);            \
+                                                                         \
+    while (height--)                                                     \
+    {                                                                    \
+        dst = dst_line;                                                  \
+        dst_line += dst_stride;                                          \
+        mask = mask_line;                                                \
+        mask_line += mask_stride;                                        \
+        src = src_line;                                                  \
+        src_line += src_stride;                                          \
+        pixman_composite_##name##_asm_mips (dst, src, mask, width);      \
+    }                                                                    \
+}
+
 /****************************************************************************/
 
 #define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST(flags, name, op,            \
                                                  src_type, dst_type)         \
 void                                                                         \
 pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips(                    \
                                              dst_type *       dst,           \
                                              const src_type * src_top,       \
--- a/gfx/cairo/libpixman/src/pixman-mips.c
+++ b/gfx/cairo/libpixman/src/pixman-mips.c
@@ -70,15 +70,25 @@ pixman_implementation_t *
 {
 #ifdef USE_LOONGSON_MMI
     /* I really don't know if some Loongson CPUs don't have MMI. */
     if (!_pixman_disabled ("loongson-mmi") && have_feature ("Loongson"))
 	imp = _pixman_implementation_create_mmx (imp);
 #endif
 
 #ifdef USE_MIPS_DSPR2
-    /* Only currently available MIPS core that supports DSPr2 is 74K. */
-    if (!_pixman_disabled ("mips-dspr2") && have_feature ("MIPS 74K"))
-	imp = _pixman_implementation_create_mips_dspr2 (imp);
+    if (!_pixman_disabled ("mips-dspr2"))
+    {
+	int already_compiling_everything_for_dspr2 = 0;
+#if defined(__mips_dsp) && (__mips_dsp_rev >= 2)
+	already_compiling_everything_for_dspr2 = 1;
+#endif
+	if (already_compiling_everything_for_dspr2 ||
+	    /* Only currently available MIPS core that supports DSPr2 is 74K. */
+	    have_feature ("MIPS 74K"))
+	{
+	    imp = _pixman_implementation_create_mips_dspr2 (imp);
+	}
+    }
 #endif
 
     return imp;
 }
--- a/gfx/cairo/libpixman/src/pixman-mmx.c
+++ b/gfx/cairo/libpixman/src/pixman-mmx.c
@@ -47,17 +47,17 @@
 #define no_vERBOSE
 
 #ifdef VERBOSE
 #define CHECKPOINT() error_f ("at %s %d\n", __FUNCTION__, __LINE__)
 #else
 #define CHECKPOINT()
 #endif
 
-#ifdef USE_ARM_IWMMXT
+#if defined USE_ARM_IWMMXT && __GNUC__ == 4 && __GNUC_MINOR__ < 8
 /* Empty the multimedia state. For some reason, ARM's mmintrin.h doesn't provide this.  */
 extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
 _mm_empty (void)
 {
 
 }
 #endif
 
@@ -536,17 +536,17 @@ expand565 (__m64 pixel, int pos)
 
 /* Expand 4 16 bit pixels in an mmx register into two mmx registers of
  *
  *    AARRGGBBRRGGBB
  */
 static force_inline void
 expand_4xpacked565 (__m64 vin, __m64 *vout0, __m64 *vout1, int full_alpha)
 {
-    __m64 t0, t1, alpha = _mm_setzero_si64 ();;
+    __m64 t0, t1, alpha = _mm_setzero_si64 ();
     __m64 r = _mm_and_si64 (vin, MC (expand_565_r));
     __m64 g = _mm_and_si64 (vin, MC (expand_565_g));
     __m64 b = _mm_and_si64 (vin, MC (expand_565_b));
     if (full_alpha)
 	alpha = _mm_cmpeq_pi32 (alpha, alpha);
 
     /* Replicate high bits into empty low bits. */
     r = _mm_or_si64 (_mm_srli_pi16 (r, 8), _mm_srli_pi16 (r, 13));
@@ -1898,23 +1898,24 @@ mmx_composite_over_8888_0565 (pixman_imp
 	}
 
 	CHECKPOINT ();
 
 	while (w >= 4)
 	{
 	    __m64 vdest = *(__m64 *)dst;
 	    __m64 v0, v1, v2, v3;
+	    __m64 vsrc0, vsrc1, vsrc2, vsrc3;
 
 	    expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0);
 
-	    __m64 vsrc0 = load8888 ((src + 0));
-	    __m64 vsrc1 = load8888 ((src + 1));
-	    __m64 vsrc2 = load8888 ((src + 2));
-	    __m64 vsrc3 = load8888 ((src + 3));
+	    vsrc0 = load8888 ((src + 0));
+	    vsrc1 = load8888 ((src + 1));
+	    vsrc2 = load8888 ((src + 2));
+	    vsrc3 = load8888 ((src + 3));
 
 	    v0 = over (vsrc0, expand_alpha (vsrc0), v0);
 	    v1 = over (vsrc1, expand_alpha (vsrc1), v1);
 	    v2 = over (vsrc2, expand_alpha (vsrc2), v2);
 	    v3 = over (vsrc3, expand_alpha (vsrc3), v3);
 
 	    *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3);
 
@@ -2049,25 +2050,26 @@ mmx_composite_over_n_8_8888 (pixman_impl
 		store8888 (dst, vdest);
 	    }
 	}
     }
 
     _mm_empty ();
 }
 
-pixman_bool_t
-pixman_fill_mmx (uint32_t *bits,
-                 int       stride,
-                 int       bpp,
-                 int       x,
-                 int       y,
-                 int       width,
-                 int       height,
-                 uint32_t xor)
+static pixman_bool_t
+mmx_fill (pixman_implementation_t *imp,
+          uint32_t *               bits,
+          int                      stride,
+          int                      bpp,
+          int                      x,
+          int                      y,
+          int                      width,
+          int                      height,
+          uint32_t		   xor)
 {
     uint64_t fill;
     __m64 vfill;
     uint32_t byte_width;
     uint8_t     *byte_line;
 
 #if defined __GNUC__ && defined USE_X86_MMX
     __m64 v1, v2, v3, v4, v5, v6, v7;
@@ -2275,19 +2277,19 @@ mmx_composite_src_n_8_8888 (pixman_imple
 
     CHECKPOINT ();
 
     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
     {
-	pixman_fill_mmx (dest_image->bits.bits, dest_image->bits.rowstride,
-			 PIXMAN_FORMAT_BPP (dest_image->bits.format),
-	                 dest_x, dest_y, width, height, 0);
+	mmx_fill (imp, dest_image->bits.bits, dest_image->bits.rowstride,
+		  PIXMAN_FORMAT_BPP (dest_image->bits.format),
+		  dest_x, dest_y, width, height, 0);
 	return;
     }
 
     srcsrc = (uint64_t)src << 32 | src;
 
     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
 
@@ -2450,29 +2452,30 @@ mmx_composite_over_n_8_0565 (pixman_impl
 	    if (srca == 0xff && (m0 & m1 & m2 & m3) == 0xff)
 	    {
 		*(__m64 *)dst = srcsrcsrcsrc;
 	    }
 	    else if (m0 | m1 | m2 | m3)
 	    {
 		__m64 vdest = *(__m64 *)dst;
 		__m64 v0, v1, v2, v3;
+		__m64 vm0, vm1, vm2, vm3;
 
 		expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0);
 
-		__m64 vm0 = to_m64 (m0);
+		vm0 = to_m64 (m0);
 		v0 = in_over (vsrc, vsrca, expand_alpha_rev (vm0), v0);
 
-		__m64 vm1 = to_m64 (m1);
+		vm1 = to_m64 (m1);
 		v1 = in_over (vsrc, vsrca, expand_alpha_rev (vm1), v1);
 
-		__m64 vm2 = to_m64 (m2);
+		vm2 = to_m64 (m2);
 		v2 = in_over (vsrc, vsrca, expand_alpha_rev (vm2), v2);
 
-		__m64 vm3 = to_m64 (m3);
+		vm3 = to_m64 (m3);
 		v3 = in_over (vsrc, vsrca, expand_alpha_rev (vm3), v3);
 
 		*(__m64 *)dst = pack_4x565 (v0, v1, v2, v3);;
 	    }
 
 	    w -= 4;
 	    mask += 4;
 	    dst += 4;
@@ -3233,28 +3236,29 @@ mmx_composite_add_8888_8888 (pixman_impl
 
 	}
     }
 
     _mm_empty ();
 }
 
 static pixman_bool_t
-pixman_blt_mmx (uint32_t *src_bits,
-                uint32_t *dst_bits,
-                int       src_stride,
-                int       dst_stride,
-                int       src_bpp,
-                int       dst_bpp,
-                int       src_x,
-                int       src_y,
-                int       dest_x,
-                int       dest_y,
-                int       width,
-                int       height)
+mmx_blt (pixman_implementation_t *imp,
+         uint32_t *               src_bits,
+         uint32_t *               dst_bits,
+         int                      src_stride,
+         int                      dst_stride,
+         int                      src_bpp,
+         int                      dst_bpp,
+         int                      src_x,
+         int                      src_y,
+         int                      dest_x,
+         int                      dest_y,
+         int                      width,
+         int                      height)
 {
     uint8_t *   src_bytes;
     uint8_t *   dst_bytes;
     int byte_width;
 
     if (src_bpp != dst_bpp)
 	return FALSE;
 
@@ -3389,23 +3393,23 @@ pixman_blt_mmx (uint32_t *src_bits,
 }
 
 static void
 mmx_composite_copy_area (pixman_implementation_t *imp,
                          pixman_composite_info_t *info)
 {
     PIXMAN_COMPOSITE_ARGS (info);
 
-    pixman_blt_mmx (src_image->bits.bits,
-                    dest_image->bits.bits,
-                    src_image->bits.rowstride,
-                    dest_image->bits.rowstride,
-                    PIXMAN_FORMAT_BPP (src_image->bits.format),
-                    PIXMAN_FORMAT_BPP (dest_image->bits.format),
-                    src_x, src_y, dest_x, dest_y, width, height);
+    mmx_blt (imp, src_image->bits.bits,
+	     dest_image->bits.bits,
+	     src_image->bits.rowstride,
+	     dest_image->bits.rowstride,
+	     PIXMAN_FORMAT_BPP (src_image->bits.format),
+	     PIXMAN_FORMAT_BPP (dest_image->bits.format),
+	     src_x, src_y, dest_x, dest_y, width, height);
 }
 
 static void
 mmx_composite_over_x888_8_8888 (pixman_implementation_t *imp,
                                 pixman_composite_info_t *info)
 {
     PIXMAN_COMPOSITE_ARGS (info);
     uint32_t  *src, *src_line;
@@ -3543,55 +3547,54 @@ mmx_composite_over_reverse_n_8888 (pixma
     const __m64 mm_zero = _mm_setzero_si64 ();					\
     __m64 mm_x = _mm_set_pi16 (vx, vx, vx, vx)
 
 #define BILINEAR_INTERPOLATE_ONE_PIXEL(pix)					\
 do {										\
     /* fetch 2x2 pixel block into 2 mmx registers */				\
     __m64 t = ldq_u ((__m64 *)&src_top [pixman_fixed_to_int (vx)]);		\
     __m64 b = ldq_u ((__m64 *)&src_bottom [pixman_fixed_to_int (vx)]);		\
-    vx += unit_x;								\
     /* vertical interpolation */						\
     __m64 t_hi = _mm_mullo_pi16 (_mm_unpackhi_pi8 (t, mm_zero), mm_wt);		\
     __m64 t_lo = _mm_mullo_pi16 (_mm_unpacklo_pi8 (t, mm_zero), mm_wt);		\
     __m64 b_hi = _mm_mullo_pi16 (_mm_unpackhi_pi8 (b, mm_zero), mm_wb);		\
     __m64 b_lo = _mm_mullo_pi16 (_mm_unpacklo_pi8 (b, mm_zero), mm_wb);		\
     __m64 hi = _mm_add_pi16 (t_hi, b_hi);					\
     __m64 lo = _mm_add_pi16 (t_lo, b_lo);					\
+    vx += unit_x;								\
     if (BILINEAR_INTERPOLATION_BITS < 8)					\
     {										\
 	/* calculate horizontal weights */					\
 	__m64 mm_wh = _mm_add_pi16 (mm_addc7, _mm_xor_si64 (mm_xorc7,		\
 			  _mm_srli_pi16 (mm_x,					\
 					 16 - BILINEAR_INTERPOLATION_BITS)));	\
-	mm_x = _mm_add_pi16 (mm_x, mm_ux);					\
 	/* horizontal interpolation */						\
 	__m64 p = _mm_unpacklo_pi16 (lo, hi);					\
 	__m64 q = _mm_unpackhi_pi16 (lo, hi);					\
 	lo = _mm_madd_pi16 (p, mm_wh);						\
 	hi = _mm_madd_pi16 (q, mm_wh);						\
     }										\
     else									\
     {										\
 	/* calculate horizontal weights */					\
 	__m64 mm_wh_lo = _mm_sub_pi16 (mm_BSHIFT, _mm_srli_pi16 (mm_x,		\
 					16 - BILINEAR_INTERPOLATION_BITS));	\
 	__m64 mm_wh_hi = _mm_srli_pi16 (mm_x,					\
 					16 - BILINEAR_INTERPOLATION_BITS);	\
-	mm_x = _mm_add_pi16 (mm_x, mm_ux);					\
 	/* horizontal interpolation */						\
 	__m64 mm_lo_lo = _mm_mullo_pi16 (lo, mm_wh_lo);				\
 	__m64 mm_lo_hi = _mm_mullo_pi16 (hi, mm_wh_hi);				\
 	__m64 mm_hi_lo = _mm_mulhi_pu16 (lo, mm_wh_lo);				\
 	__m64 mm_hi_hi = _mm_mulhi_pu16 (hi, mm_wh_hi);				\
 	lo = _mm_add_pi32 (_mm_unpacklo_pi16 (mm_lo_lo, mm_hi_lo),		\
 			   _mm_unpacklo_pi16 (mm_lo_hi, mm_hi_hi));		\
 	hi = _mm_add_pi32 (_mm_unpackhi_pi16 (mm_lo_lo, mm_hi_lo),		\
 			   _mm_unpackhi_pi16 (mm_lo_hi, mm_hi_hi));		\
     }										\
+    mm_x = _mm_add_pi16 (mm_x, mm_ux);						\
     /* shift and pack the result */						\
     hi = _mm_srli_pi32 (hi, BILINEAR_INTERPOLATION_BITS * 2);			\
     lo = _mm_srli_pi32 (lo, BILINEAR_INTERPOLATION_BITS * 2);			\
     lo = _mm_packs_pi32 (lo, hi);						\
     lo = _mm_packs_pu16 (lo, lo);						\
     pix = lo;									\
 } while (0)
 
@@ -3907,17 +3910,17 @@ typedef struct
 static const fetcher_info_t fetchers[] =
 {
     { PIXMAN_x8r8g8b8,		mmx_fetch_x8r8g8b8 },
     { PIXMAN_r5g6b5,		mmx_fetch_r5g6b5 },
     { PIXMAN_a8,		mmx_fetch_a8 },
     { PIXMAN_null }
 };
 
-static void
+static pixman_bool_t
 mmx_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
 {
     pixman_image_t *image = iter->image;
 
 #define FLAGS								\
     (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM |		\
      FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
 
@@ -3932,22 +3935,22 @@ mmx_src_iter_init (pixman_implementation
 	    {
 		uint8_t *b = (uint8_t *)image->bits.bits;
 		int s = image->bits.rowstride * 4;
 
 		iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (f->format) / 8;
 		iter->stride = s;
 
 		iter->get_scanline = f->get_scanline;
-		return;
+		return TRUE;
 	    }
 	}
     }
 
-    imp->delegate->src_iter_init (imp->delegate, iter);
+    return FALSE;
 }
 
 static const pixman_fast_path_t mmx_fast_paths[] =
 {
     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       r5g6b5,   mmx_composite_over_n_8_0565       ),
     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       b5g6r5,   mmx_composite_over_n_8_0565       ),
     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       a8r8g8b8, mmx_composite_over_n_8_8888       ),
     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       x8r8g8b8, mmx_composite_over_n_8_8888       ),
@@ -4036,65 +4039,16 @@ static const pixman_fast_path_t mmx_fast
     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mmx_8888_8_8888                   ),
     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mmx_8888_8_8888                   ),
     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mmx_8888_8_8888                   ),
     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mmx_8888_8_8888                   ),
 
     { PIXMAN_OP_NONE },
 };
 
-static pixman_bool_t
-mmx_blt (pixman_implementation_t *imp,
-         uint32_t *               src_bits,
-         uint32_t *               dst_bits,
-         int                      src_stride,
-         int                      dst_stride,
-         int                      src_bpp,
-         int                      dst_bpp,
-         int                      src_x,
-         int                      src_y,
-         int                      dest_x,
-         int                      dest_y,
-         int                      width,
-         int                      height)
-{
-    if (!pixman_blt_mmx (
-            src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
-            src_x, src_y, dest_x, dest_y, width, height))
-
-    {
-	return _pixman_implementation_blt (
-	    imp->delegate,
-	    src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
-	    src_x, src_y, dest_x, dest_y, width, height);
-    }
-
-    return TRUE;
-}
-
-static pixman_bool_t
-mmx_fill (pixman_implementation_t *imp,
-          uint32_t *               bits,
-          int                      stride,
-          int                      bpp,
-          int                      x,
-          int                      y,
-          int                      width,
-          int                      height,
-          uint32_t xor)
-{
-    if (!pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor))
-    {
-	return _pixman_implementation_fill (
-	    imp->delegate, bits, stride, bpp, x, y, width, height, xor);
-    }
-
-    return TRUE;
-}
-
 pixman_implementation_t *
 _pixman_implementation_create_mmx (pixman_implementation_t *fallback)
 {
     pixman_implementation_t *imp = _pixman_implementation_create (fallback, mmx_fast_paths);
 
     imp->combine_32[PIXMAN_OP_OVER] = mmx_combine_over_u;
     imp->combine_32[PIXMAN_OP_OVER_REVERSE] = mmx_combine_over_reverse_u;
     imp->combine_32[PIXMAN_OP_IN] = mmx_combine_in_u;
--- a/gfx/cairo/libpixman/src/pixman-noop.c
+++ b/gfx/cairo/libpixman/src/pixman-noop.c
@@ -54,17 +54,17 @@ noop_get_scanline (pixman_iter_t *iter, 
 }
 
 static uint32_t *
 get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
 {
     return NULL;
 }
 
-static void
+static pixman_bool_t
 noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
 {
     pixman_image_t *image = iter->image;
 
 #define FLAGS						\
     (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM)
 
     if (!image)
@@ -88,19 +88,19 @@ noop_src_iter_init (pixman_implementatio
 	    uint32_t *buffer = iter->buffer;
 	    uint32_t *end = buffer + iter->width;
 
 	    while (buffer < end)
 		*(buffer++) = color;
 	}
 	else
 	{
-	    uint64_t color = bits->fetch_pixel_64 (bits, 0, 0);
-	    uint64_t *buffer = (uint64_t *)iter->buffer;
-	    uint64_t *end = buffer + iter->width;
+	    argb_t color = bits->fetch_pixel_float (bits, 0, 0);
+	    argb_t *buffer = (argb_t *)iter->buffer;
+	    argb_t *end = buffer + iter->width;
 
 	    while (buffer < end)
 		*(buffer++) = color;
 	}
 
 	iter->get_scanline = _pixman_iter_get_scanline_noop;
     }
     else if (image->common.extended_format_code == PIXMAN_a8r8g8b8	&&
@@ -112,53 +112,57 @@ noop_src_iter_init (pixman_implementatio
     {
 	iter->buffer =
 	    image->bits.bits + iter->y * image->bits.rowstride + iter->x;
 
 	iter->get_scanline = noop_get_scanline;
     }
     else
     {
-	(* imp->delegate->src_iter_init) (imp->delegate, iter);
+	return FALSE;
     }
+
+    return TRUE;
 }
 
-static void
+static pixman_bool_t
 noop_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
 {
     pixman_image_t *image = iter->image;
     uint32_t image_flags = iter->image_flags;
     uint32_t iter_flags = iter->iter_flags;
     
     if ((image_flags & FAST_PATH_STD_DEST_FLAGS) == FAST_PATH_STD_DEST_FLAGS	&&
 	(iter_flags & ITER_NARROW) == ITER_NARROW				&&
 	((image->common.extended_format_code == PIXMAN_a8r8g8b8)	||
 	 (image->common.extended_format_code == PIXMAN_x8r8g8b8 &&
 	  (iter_flags & (ITER_LOCALIZED_ALPHA)))))
     {
 	iter->buffer = image->bits.bits + iter->y * image->bits.rowstride + iter->x;
 
 	iter->get_scanline = _pixman_iter_get_scanline_noop;
 	iter->write_back = dest_write_back_direct;
+
+	return TRUE;
     }
     else
     {
-	(* imp->delegate->dest_iter_init) (imp->delegate, iter);
+	return FALSE;
     }
 }
 
 static const pixman_fast_path_t noop_fast_paths[] =
 {
     { PIXMAN_OP_DST, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, noop_composite },
     { PIXMAN_OP_NONE },
 };
 
 pixman_implementation_t *
 _pixman_implementation_create_noop (pixman_implementation_t *fallback)
 {
     pixman_implementation_t *imp =
 	_pixman_implementation_create (fallback, noop_fast_paths);
-
+ 
     imp->src_iter_init = noop_src_iter_init;
     imp->dest_iter_init = noop_dest_iter_init;
 
     return imp;
 }
--- a/gfx/cairo/libpixman/src/pixman-private.h
+++ b/gfx/cairo/libpixman/src/pixman-private.h
@@ -49,30 +49,40 @@ typedef struct gradient gradient_t;
 typedef struct linear_gradient linear_gradient_t;
 typedef struct horizontal_gradient horizontal_gradient_t;
 typedef struct vertical_gradient vertical_gradient_t;
 typedef struct conical_gradient conical_gradient_t;
 typedef struct radial_gradient radial_gradient_t;
 typedef struct bits_image bits_image_t;
 typedef struct circle circle_t;
 
+typedef struct argb_t argb_t;
+
+struct argb_t
+{
+    float a;
+    float r;
+    float g;
+    float b;
+};
+
 typedef void (*fetch_scanline_t) (pixman_image_t *image,
 				  int             x,
 				  int             y,
 				  int             width,
 				  uint32_t       *buffer,
 				  const uint32_t *mask);
 
 typedef uint32_t (*fetch_pixel_32_t) (bits_image_t *image,
 				      int           x,
 				      int           y);
 
-typedef uint64_t (*fetch_pixel_64_t) (bits_image_t *image,
-				      int           x,
-				      int           y);
+typedef argb_t (*fetch_pixel_float_t) (bits_image_t *image,
+				       int           x,
+				       int           y);
 
 typedef void (*store_scanline_t) (bits_image_t *  image,
 				  int             x,
 				  int             y,
 				  int             width,
 				  const uint32_t *values);
 
 typedef enum
@@ -116,19 +126,19 @@ struct image_common
     uint32_t			flags;
     pixman_format_code_t	extended_format_code;
 };
 
 struct solid_fill
 {
     image_common_t common;
     pixman_color_t color;
-    
+
     uint32_t	   color_32;
-    uint64_t	   color_64;
+    argb_t	   color_float;
 };
 
 struct gradient
 {
     image_common_t	    common;
     int                     n_stops;
     pixman_gradient_stop_t *stops;
 };
@@ -179,19 +189,19 @@ struct bits_image
     int                        rowstride;  /* in number of uint32_t's */
 
     fetch_scanline_t           fetch_scanline_16;
 
     fetch_scanline_t           fetch_scanline_32;
     fetch_pixel_32_t	       fetch_pixel_32;
     store_scanline_t           store_scanline_32;
 
-    fetch_scanline_t           fetch_scanline_64;
-    fetch_pixel_64_t	       fetch_pixel_64;
-    store_scanline_t           store_scanline_64;
+    fetch_scanline_t	       fetch_scanline_float;
+    fetch_pixel_float_t	       fetch_pixel_float;
+    store_scanline_t           store_scanline_float;
 
     store_scanline_t           store_scanline_16;
 
     /* Used for indirect access to the bits */
     pixman_read_memory_func_t  read_func;
     pixman_write_memory_func_t write_func;
 };
 
@@ -288,17 +298,18 @@ void
 _pixman_image_init (pixman_image_t *image);
 
 pixman_bool_t
 _pixman_bits_image_init (pixman_image_t *     image,
                          pixman_format_code_t format,
                          int                  width,
                          int                  height,
                          uint32_t *           bits,
-                         int                  rowstride);
+                         int                  rowstride,
+			 pixman_bool_t	      clear);
 pixman_bool_t
 _pixman_image_fini (pixman_image_t *image);
 
 pixman_image_t *
 _pixman_image_allocate (void);
 
 pixman_bool_t
 _pixman_init_gradient (gradient_t *                  gradient,
@@ -429,22 +440,22 @@ typedef struct
 
 typedef void (*pixman_combine_32_func_t) (pixman_implementation_t *imp,
 					  pixman_op_t              op,
 					  uint32_t *               dest,
 					  const uint32_t *         src,
 					  const uint32_t *         mask,
 					  int                      width);
 
-typedef void (*pixman_combine_64_func_t) (pixman_implementation_t *imp,
-					  pixman_op_t              op,
-					  uint64_t *               dest,
-					  const uint64_t *         src,
-					  const uint64_t *         mask,
-					  int                      width);
+typedef void (*pixman_combine_float_func_t) (pixman_implementation_t *imp,
+					     pixman_op_t	      op,
+					     float *		      dest,
+					     const float *	      src,
+					     const float *	      mask,
+					     int		      n_pixels);
 
 typedef void (*pixman_composite_func_t) (pixman_implementation_t *imp,
 					 pixman_composite_info_t *info);
 typedef pixman_bool_t (*pixman_blt_func_t) (pixman_implementation_t *imp,
 					    uint32_t *               src_bits,
 					    uint32_t *               dst_bits,
 					    int                      src_stride,
 					    int                      dst_stride,
@@ -460,62 +471,74 @@ typedef pixman_bool_t (*pixman_fill_func
 					     uint32_t *               bits,
 					     int                      stride,
 					     int                      bpp,
 					     int                      x,
 					     int                      y,
 					     int                      width,
 					     int                      height,
 					     uint32_t                 xor);
-typedef void (*pixman_iter_init_func_t) (pixman_implementation_t *imp,
-                                         pixman_iter_t           *iter);
+typedef pixman_bool_t (*pixman_iter_init_func_t) (pixman_implementation_t *imp,
+						  pixman_iter_t           *iter);
 
 void _pixman_setup_combiner_functions_16 (pixman_implementation_t *imp);
 void _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp);
-void _pixman_setup_combiner_functions_64 (pixman_implementation_t *imp);
+void _pixman_setup_combiner_functions_float (pixman_implementation_t *imp);
 
 typedef struct
 {
     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_composite_func_t func;
 } pixman_fast_path_t;
 
 struct pixman_implementation_t
 {
     pixman_implementation_t *	toplevel;
-    pixman_implementation_t *	delegate;
+    pixman_implementation_t *	fallback;
     const pixman_fast_path_t *	fast_paths;
 
     pixman_blt_func_t		blt;
     pixman_fill_func_t		fill;
     pixman_iter_init_func_t     src_iter_init;
     pixman_iter_init_func_t     dest_iter_init;
 
     pixman_combine_32_func_t	combine_32[PIXMAN_N_OPERATORS];
     pixman_combine_32_func_t	combine_32_ca[PIXMAN_N_OPERATORS];
-    pixman_combine_64_func_t	combine_64[PIXMAN_N_OPERATORS];
-    pixman_combine_64_func_t	combine_64_ca[PIXMAN_N_OPERATORS];
-    pixman_combine_64_func_t	combine_16[PIXMAN_N_OPERATORS];
+    pixman_combine_float_func_t	combine_float[PIXMAN_N_OPERATORS];
+    pixman_combine_float_func_t	combine_float_ca[PIXMAN_N_OPERATORS];
+    pixman_combine_32_func_t    combine_16[PIXMAN_N_OPERATORS];
 };
 
 uint32_t
 _pixman_image_get_solid (pixman_implementation_t *imp,
 			 pixman_image_t *         image,
                          pixman_format_code_t     format);
 
 pixman_implementation_t *
-_pixman_implementation_create (pixman_implementation_t *delegate,
+_pixman_implementation_create (pixman_implementation_t *fallback,
 			       const pixman_fast_path_t *fast_paths);
 
+pixman_bool_t
+_pixman_implementation_lookup_composite (pixman_implementation_t  *toplevel,
+					 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_combine_32_func_t
 _pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
 					pixman_op_t		 op,
 					pixman_bool_t		 component_alpha,
 					pixman_bool_t		 wide,
 					pixman_bool_t		 rgb16);
 
 pixman_bool_t
@@ -539,29 +562,29 @@ pixman_bool_t
                              int                      stride,
                              int                      bpp,
                              int                      x,
                              int                      y,
                              int                      width,
                              int                      height,
                              uint32_t                 xor);
 
-void
+pixman_bool_t
 _pixman_implementation_src_iter_init (pixman_implementation_t       *imp,
 				      pixman_iter_t                 *iter,
 				      pixman_image_t                *image,
 				      int                            x,
 				      int                            y,
 				      int                            width,
 				      int                            height,
 				      uint8_t                       *buffer,
 				      iter_flags_t                   flags,
 				      uint32_t                       image_flags);
 
-void
+pixman_bool_t
 _pixman_implementation_dest_iter_init (pixman_implementation_t       *imp,
 				       pixman_iter_t                 *iter,
 				       pixman_image_t                *image,
 				       int                            x,
 				       int                            y,
 				       int                            width,
 				       int                            height,
 				       uint8_t                       *buffer,
@@ -761,16 +784,22 @@ get_implementation (void)
 {
 #ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
     if (!global_implementation)
 	global_implementation = _pixman_choose_implementation ();
 #endif
     return global_implementation;
 }
 
+/* This function is exported for the sake of the test suite and not part
+ * of the ABI.
+ */
+PIXMAN_EXPORT pixman_implementation_t *
+_pixman_internal_only_get_implementation (void);
+
 /* Memory allocation helpers */
 void *
 pixman_malloc_ab (unsigned int n, unsigned int b);
 
 void *
 pixman_malloc_abc (unsigned int a, unsigned int b, unsigned int c);
 
 pixman_bool_t
@@ -779,37 +808,25 @@ pixman_bool_t
 pixman_bool_t
 _pixman_multiply_overflows_int (unsigned int a, unsigned int b);
 
 pixman_bool_t
 _pixman_addition_overflows_int (unsigned int a, unsigned int b);
 
 /* Compositing utilities */
 void
-pixman_expand (uint64_t *           dst,
-               const uint32_t *     src,
-               pixman_format_code_t format,
-               int                  width);
+pixman_expand_to_float (argb_t               *dst,
+			const uint32_t       *src,
+			pixman_format_code_t  format,
+			int                   width);
 
 void
-pixman_contract (uint32_t *      dst,
-                 const uint64_t *src,
-                 int             width);
-
-pixman_bool_t
-_pixman_lookup_composite_function (pixman_implementation_t     *toplevel,
-				   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_contract_from_float (uint32_t     *dst,
+			    const argb_t *src,
+			    int           width);
 
 /* Region Helpers */
 pixman_bool_t
 pixman_region32_copy_from_region16 (pixman_region32_t *dst,
                                     pixman_region16_t *src);
 
 pixman_bool_t
 pixman_region16_copy_from_region32 (pixman_region16_t *dst,
@@ -960,16 +977,19 @@ unorm_to_unorm (uint32_t val, int from_b
     REPLICATE();
     REPLICATE();
     REPLICATE();
     REPLICATE();
 
     return result;
 }
 
+uint16_t pixman_float_to_unorm (float f, int n_bits);
+float pixman_unorm_to_float (uint16_t u, int n_bits);
+
 /*
  * Various debugging code
  */
 
 #undef DEBUG
 
 #define COMPILE_TIME_ASSERT(x)						\
     do { typedef int compile_time_assertion [(x)?1:-1]; } while (0)
@@ -1101,25 +1121,18 @@ void pixman_timer_register (pixman_timer
 									\
 	timer ## tname.n_times++;					\
 	begin ## tname = OIL_STAMP ();
 
 #define TIMER_END(tname)                                                \
     timer ## tname.total += OIL_STAMP () - begin ## tname;		\
     }
 
-#endif /* PIXMAN_TIMERS */
+#else
 
-/* sRGB<->linear conversion tables. Linear color space is the same
- * as sRGB but the components are in linear light (gamma 1.0).
- *
- * linear_to_srgb maps linear value from 0 to 4095 ([0.0, 1.0])
- * and returns 8-bit sRGB value.
- *
- * srgb_to_linear maps 8-bit sRGB value to 16-bit linear value
- * with range 0 to 65535 ([0.0, 1.0]).
- */
-extern const uint8_t linear_to_srgb[4096];
-extern const uint16_t srgb_to_linear[256];
+#define TIMER_BEGIN(tname)
+#define TIMER_END(tname)
+
+#endif /* PIXMAN_TIMERS */
 
 #endif /* __ASSEMBLER__ */
 
 #endif /* PIXMAN_PRIVATE_H */
--- a/gfx/cairo/libpixman/src/pixman-radial-gradient.c
+++ b/gfx/cairo/libpixman/src/pixman-radial-gradient.c
@@ -658,17 +658,18 @@ radial_get_scanline_16 (pixman_iter_t *i
     iter->y++;
     return iter->buffer;
 }
 static uint32_t *
 radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 {
     uint32_t *buffer = radial_get_scanline_narrow (iter, NULL);
 
-    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
+    pixman_expand_to_float (
+	(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
 
     return buffer;
 }
 
 void
 _pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
 {
     if (iter->iter_flags & ITER_16)
@@ -676,18 +677,18 @@ void
     else if (iter->iter_flags & ITER_NARROW)
 	iter->get_scanline = radial_get_scanline_narrow;
     else
 	iter->get_scanline = radial_get_scanline_wide;
 }
 
 
 PIXMAN_EXPORT pixman_image_t *
-pixman_image_create_radial_gradient (pixman_point_fixed_t *        inner,
-                                     pixman_point_fixed_t *        outer,
+pixman_image_create_radial_gradient (const pixman_point_fixed_t *  inner,
+                                     const pixman_point_fixed_t *  outer,
                                      pixman_fixed_t                inner_radius,
                                      pixman_fixed_t                outer_radius,
                                      const pixman_gradient_stop_t *stops,
                                      int                           n_stops)
 {
     pixman_image_t *image;
     radial_gradient_t *radial;
 
--- a/gfx/cairo/libpixman/src/pixman-region.c
+++ b/gfx/cairo/libpixman/src/pixman-region.c
@@ -737,32 +737,31 @@ pixman_region_append_non_o (region_type_
  */
 
 typedef pixman_bool_t (*overlap_proc_ptr) (region_type_t *region,
 					   box_type_t *   r1,
 					   box_type_t *   r1_end,
 					   box_type_t *   r2,
 					   box_type_t *   r2_end,
 					   int            y1,
-					   int            y2,
-					   int *          overlap);
+					   int            y2);
 
 static pixman_bool_t
 pixman_op (region_type_t *  new_reg,               /* Place to store result	    */
 	   region_type_t *  reg1,                  /* First region in operation     */
 	   region_type_t *  reg2,                  /* 2d region in operation        */
 	   overlap_proc_ptr overlap_func,          /* Function to call for over-
 						    * lapping bands		    */
 	   int              append_non1,           /* Append non-overlapping bands  
 						    * in region 1 ?
 						    */
-	   int              append_non2,           /* Append non-overlapping bands
+	   int              append_non2            /* Append non-overlapping bands
 						    * in region 2 ?
 						    */
-	   int *            overlap)
+    )
 {
     box_type_t *r1;                 /* Pointer into first region     */
     box_type_t *r2;                 /* Pointer into 2d region	     */
     box_type_t *r1_end;             /* End of 1st region	     */
     box_type_t *r2_end;             /* End of 2d region		     */
     int ybot;                       /* Bottom of intersection	     */
     int ytop;                       /* Top of intersection	     */
     region_data_type_t *old_data;   /* Old data for new_reg	     */
@@ -930,18 +929,17 @@ pixman_op (region_type_t *  new_reg,    
         ybot = MIN (r1->y2, r2->y2);
         if (ybot > ytop)
         {
             cur_band = new_reg->data->numRects;
 
             if (!(*overlap_func)(new_reg,
                                  r1, r1_band_end,
                                  r2, r2_band_end,
-                                 ytop, ybot,
-                                 overlap))
+                                 ytop, ybot))
 	    {
 		goto bail;
 	    }
 	    
             COALESCE (new_reg, prev_band, cur_band);
 	}
 
         /*
@@ -1108,18 +1106,17 @@ pixman_set_extents (region_type_t *regio
 /*ARGSUSED*/
 static pixman_bool_t
 pixman_region_intersect_o (region_type_t *region,
                            box_type_t *   r1,
                            box_type_t *   r1_end,
                            box_type_t *   r2,
                            box_type_t *   r2_end,
                            int            y1,
-                           int            y2,
-                           int *          overlap)
+                           int            y2)
 {
     int x1;
     int x2;
     box_type_t *        next_rect;
 
     next_rect = PIXREGION_TOP (region);
 
     critical_if_fail (y1 < y2);
@@ -1205,40 +1202,33 @@ PREFIX (_intersect) (region_type_t *    
     }
     else if (reg1 == reg2)
     {
         return PREFIX (_copy) (new_reg, reg1);
     }
     else
     {
         /* General purpose intersection */
-        int overlap; /* result ignored */
 
-        if (!pixman_op (new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, FALSE,
-                        &overlap))
-	{
+        if (!pixman_op (new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, FALSE))
 	    return FALSE;
-	}
 	
         pixman_set_extents (new_reg);
     }
 
     GOOD (new_reg);
     return(TRUE);
 }
 
 #define MERGERECT(r)							\
     do									\
     {									\
         if (r->x1 <= x2)						\
 	{								\
             /* Merge with current rectangle */				\
-            if (r->x1 < x2)						\
-		*overlap = TRUE;					\
-									\
             if (x2 < r->x2)						\
 		x2 = r->x2;						\
 	}								\
 	else								\
 	{								\
             /* Add current rectangle, start new one */			\
             NEWRECT (region, next_rect, x1, y1, x2, y2);		\
             x1 = r->x1;							\
@@ -1268,18 +1258,17 @@ PREFIX (_intersect) (region_type_t *    
  */
 static pixman_bool_t
 pixman_region_union_o (region_type_t *region,
 		       box_type_t *   r1,
 		       box_type_t *   r1_end,
 		       box_type_t *   r2,
 		       box_type_t *   r2_end,
 		       int            y1,
-		       int            y2,
-		       int *          overlap)
+		       int            y2)
 {
     box_type_t *next_rect;
     int x1;            /* left and right side of current union */
     int x2;
 
     critical_if_fail (y1 < y2);
     critical_if_fail (r1 != r1_end && r2 != r2_end);
 
@@ -1378,18 +1367,16 @@ PREFIX (_union_rect) (region_type_t *des
     return PREFIX (_union) (dest, source, &region);
 }
 
 PIXMAN_EXPORT pixman_bool_t
 PREFIX (_union) (region_type_t *new_reg,
                  region_type_t *reg1,
                  region_type_t *reg2)
 {
-    int overlap; /* result ignored */
-
     /* Return TRUE if some overlap
      * between reg1, reg2
      */
     GOOD (reg1);
     GOOD (reg2);
     GOOD (new_reg);
 
     /*  checks all the simple cases */
@@ -1445,17 +1432,17 @@ PREFIX (_union) (region_type_t *new_reg,
     if (!reg2->data && SUBSUMES (&reg2->extents, &reg1->extents))
     {
         if (new_reg != reg2)
 	    return PREFIX (_copy) (new_reg, reg2);
 
 	return TRUE;
     }
 
-    if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE, &overlap))
+    if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE))
 	return FALSE;
 
     new_reg->extents.x1 = MIN (reg1->extents.x1, reg2->extents.x1);
     new_reg->extents.y1 = MIN (reg1->extents.y1, reg2->extents.y1);
     new_reg->extents.x2 = MAX (reg1->extents.x2, reg2->extents.x2);
     new_reg->extents.y2 = MAX (reg1->extents.y2, reg2->extents.y2);
     
     GOOD (new_reg);
@@ -1512,19 +1499,17 @@ quick_sort_rects (
         do
         {
             r = &(rects[i]);
             do
             {
                 r++;
                 i++;
 	    }
-
-            while (i != numRects && (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)))
-		;
+	    while (i != numRects && (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
 
 	    r = &(rects[j]);
             do
             {
                 r--;
                 j--;
 	    }
             while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
@@ -1575,18 +1560,17 @@ quick_sort_rects (
  *	Step 3. Merge the separate regions down to a single region by calling
  *		pixman_region_union.  Maximize the work each pixman_region_union call does by using
  *		a binary merge.
  *
  *-----------------------------------------------------------------------
  */
 
 static pixman_bool_t
-validate (region_type_t * badreg,
-          int *           overlap)
+validate (region_type_t * badreg)
 {
     /* Descriptor for regions under construction  in Step 2. */
     typedef struct
     {
         region_type_t reg;
         int prev_band;
         int cur_band;
     } region_info_t;
@@ -1601,17 +1585,16 @@ validate (region_type_t * badreg,
     int j;                          /* Index into ri			    */
     region_info_t *rit;             /* &ri[j]				    */
     region_type_t *reg;             /* ri[j].reg			    */
     box_type_t *box;                /* Current box in rects		    */
     box_type_t *ri_box;             /* Last box in ri[j].reg		    */
     region_type_t *hreg;            /* ri[j_half].reg			    */
     pixman_bool_t ret = TRUE;
 
-    *overlap = FALSE;
     if (!badreg->data)
     {
         GOOD (badreg);
         return TRUE;
     }
     
     numRects = badreg->data->numRects;
     if (!numRects)
@@ -1675,19 +1658,16 @@ validate (region_type_t * badreg,
             ri_box = PIXREGION_END (reg);
 
             if (box->y1 == ri_box->y1 && box->y2 == ri_box->y2)
             {
                 /* box is in same band as ri_box.  Merge or append it */
                 if (box->x1 <= ri_box->x2)
                 {
                     /* Merge it with ri_box */
-                    if (box->x1 < ri_box->x2)
-			*overlap = TRUE;
-
                     if (box->x2 > ri_box->x2)
 			ri_box->x2 = box->x2;
 		}
                 else
                 {
                     RECTALLOC_BAIL (reg, 1, bail);
                     *PIXREGION_TOP (reg) = *box;
                     reg->data->numRects++;
@@ -1781,17 +1761,17 @@ validate (region_type_t * badreg,
     while (num_ri > 1)
     {
         int half = num_ri / 2;
         for (j = num_ri & 1; j < (half + (num_ri & 1)); j++)
         {
             reg = &ri[j].reg;
             hreg = &ri[j + half].reg;
 
-            if (!pixman_op (reg, reg, hreg, pixman_region_union_o, TRUE, TRUE, overlap))
+            if (!pixman_op (reg, reg, hreg, pixman_region_union_o, TRUE, TRUE))
 		ret = FALSE;
 
             if (hreg->extents.x1 < reg->extents.x1)
 		reg->extents.x1 = hreg->extents.x1;
 
             if (hreg->extents.y1 < reg->extents.y1)
 		reg->extents.y1 = hreg->extents.y1;
 
@@ -1849,18 +1829,17 @@ bail:
 /*ARGSUSED*/
 static pixman_bool_t
 pixman_region_subtract_o (region_type_t * region,
 			  box_type_t *    r1,
 			  box_type_t *    r1_end,
 			  box_type_t *    r2,
 			  box_type_t *    r2_end,
 			  int             y1,
-			  int             y2,
-			  int *           overlap)
+			  int             y2)
 {
     box_type_t *        next_rect;
     int x1;
 
     x1 = r1->x1;
 
     critical_if_fail (y1 < y2);
     critical_if_fail (r1 != r1_end && r2 != r2_end);
@@ -1974,18 +1953,16 @@ pixman_region_subtract_o (region_type_t 
  *
  *-----------------------------------------------------------------------
  */
 PIXMAN_EXPORT pixman_bool_t
 PREFIX (_subtract) (region_type_t *reg_d,
                     region_type_t *reg_m,
                     region_type_t *reg_s)
 {
-    int overlap; /* result ignored */
-
     GOOD (reg_m);
     GOOD (reg_s);
     GOOD (reg_d);
     
     /* check for trivial rejects */
     if (PIXREGION_NIL (reg_m) || PIXREGION_NIL (reg_s) ||
         !EXTENTCHECK (&reg_m->extents, &reg_s->extents))
     {
@@ -2002,17 +1979,17 @@ PREFIX (_subtract) (region_type_t *reg_d
         reg_d->data = pixman_region_empty_data;
 
         return TRUE;
     }
 
     /* Add those rectangles in region 1 that aren't in region 2,
        do yucky substraction for overlaps, and
        just throw away rectangles in region 2 that aren't in region 1 */
-    if (!pixman_op (reg_d, reg_m, reg_s, pixman_region_subtract_o, TRUE, FALSE, &overlap))
+    if (!pixman_op (reg_d, reg_m, reg_s, pixman_region_subtract_o, TRUE, FALSE))
 	return FALSE;
 
     /*
      * Can't alter reg_d's extents before we call pixman_op because
      * it might be one of the source regions and pixman_op depends
      * on the extents of those regions being unaltered. Besides, this
      * way there's no checking against rectangles that will be nuked
      * due to coalescing, so we have to examine fewer rectangles.
@@ -2043,18 +2020,16 @@ PREFIX (_subtract) (region_type_t *reg_d
  */
 PIXMAN_EXPORT pixman_bool_t
 PREFIX (_inverse) (region_type_t *new_reg,  /* Destination region */
 		   region_type_t *reg1,     /* Region to invert */
 		   box_type_t *   inv_rect) /* Bounding box for inversion */
 {
     region_type_t inv_reg; /* Quick and dirty region made from the
 			    * bounding box */
-    int overlap;           /* result ignored */
-
     GOOD (reg1);
     GOOD (new_reg);
     
     /* check for trivial rejects */
     if (PIXREGION_NIL (reg1) || !EXTENTCHECK (inv_rect, &reg1->extents))
     {
         if (PIXREGION_NAR (reg1))
 	    return pixman_break (new_reg);
@@ -2067,17 +2042,17 @@ PREFIX (_inverse) (region_type_t *new_re
     }
 
     /* Add those rectangles in region 1 that aren't in region 2,
      * do yucky substraction for overlaps, and
      * just throw away rectangles in region 2 that aren't in region 1
      */
     inv_reg.extents = *inv_rect;
     inv_reg.data = (region_data_type_t *)NULL;
-    if (!pixman_op (new_reg, &inv_reg, reg1, pixman_region_subtract_o, TRUE, FALSE, &overlap))
+    if (!pixman_op (new_reg, &inv_reg, reg1, pixman_region_subtract_o, TRUE, FALSE))
 	return FALSE;
 
     /*
      * Can't alter new_reg's extents before we call pixman_op because
      * it might be one of the source regions and pixman_op depends
      * on the extents of those regions being unaltered. Besides, this
      * way there's no checking against rectangles that will be nuked
      * due to coalescing, so we have to examine fewer rectangles.
@@ -2570,17 +2545,17 @@ PREFIX (_init_rects) (region_type_t *reg
         GOOD (region);
 
         return TRUE;
     }
 
     /* Validate */
     region->extents.x1 = region->extents.x2 = 0;
 
-    return validate (region, &i);
+    return validate (region);
 }
 
 #define READ(_ptr) (*(_ptr))
 
 static inline box_type_t *
 bitmap_addrect (region_type_t *reg,
                 box_type_t *r,
                 box_type_t **first_rect,
--- a/gfx/cairo/libpixman/src/pixman-solid-fill.c
+++ b/gfx/cairo/libpixman/src/pixman-solid-fill.c
@@ -35,19 +35,19 @@ void
 	uint32_t *e = b + iter->width;
 	uint32_t color = iter->image->solid.color_32;
 
 	while (b < e)
 	    *(b++) = color;
     }
     else
     {
-	uint64_t *b = (uint64_t *)iter->buffer;
-	uint64_t *e = b + iter->width;
-	uint64_t color = image->solid.color_64;
+	argb_t *b = (argb_t *)iter->buffer;
+	argb_t *e = b + iter->width;
+	argb_t color = image->solid.color_float;
 
 	while (b < e)
 	    *(b++) = color;
     }
 
     iter->get_scanline = _pixman_iter_get_scanline_noop;
 }
 
@@ -56,34 +56,37 @@ color_to_uint32 (const pixman_color_t *c
 {
     return
         (color->alpha >> 8 << 24) |
         (color->red >> 8 << 16) |
         (color->green & 0xff00) |
         (color->blue >> 8);
 }
 
-static uint64_t
-color_to_uint64 (const pixman_color_t *color)
+static argb_t
+color_to_float (const pixman_color_t *color)
 {
-    return
-        ((uint64_t)color->alpha << 48) |
-        ((uint64_t)color->red << 32) |
-        ((uint64_t)color->green << 16) |
-        ((uint64_t)color->blue);
+    argb_t result;
+
+    result.a = pixman_unorm_to_float (color->alpha, 16);
+    result.r = pixman_unorm_to_float (color->red, 16);
+    result.g = pixman_unorm_to_float (color->green, 16);
+    result.b = pixman_unorm_to_float (color->blue, 16);
+
+    return result;
 }
 
 PIXMAN_EXPORT pixman_image_t *
-pixman_image_create_solid_fill (pixman_color_t *color)
+pixman_image_create_solid_fill (const pixman_color_t *color)
 {
     pixman_image_t *img = _pixman_image_allocate ();
 
     if (!img)
 	return NULL;
 
     img->type = SOLID;
     img->solid.color = *color;
     img->solid.color_32 = color_to_uint32 (color);
-    img->solid.color_64 = color_to_uint64 (color);
+    img->solid.color_float = color_to_float (color);
 
     return img;
 }
 
deleted file mode 100644
--- a/gfx/cairo/libpixman/src/pixman-srgb.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/* WARNING: This file is generated by make-srgb.pl.
- * Please edit that file instead of this one.
- */
-
-#include <stdint.h>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "pixman-private.h"
-
-const uint8_t linear_to_srgb[4096] =
-{
-	0, 1, 2, 2, 3, 4, 5, 6, 6, 7, 
-	8, 9, 10, 10, 11, 12, 13, 13, 14, 15, 
-	15, 16, 16, 17, 18, 18, 19, 19, 20, 20, 
-	21, 21, 22, 22, 23, 23, 23, 24, 24, 25, 
-	25, 25, 26, 26, 27, 27, 27, 28, 28, 29, 
-	29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 
-	32, 33, 33, 33, 34, 34, 34, 34, 35, 35, 
-	35, 36, 36, 36, 37, 37, 37, 37, 38, 38, 
-	38, 38, 39, 39, 39, 40, 40, 40, 40, 41, 
-	41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 
-	43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 
-	46, 46, 46, 46, 46, 47, 47, 47, 47, 48, 
-	48, 48, 48, 48, 49, 49, 49, 49, 49, 50, 
-	50, 50, 50, 50, 51, 51, 51, 51, 51, 52, 
-	52, 52, 52, 52, 53, 53, 53, 53, 53, 54, 
-	54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 
-	56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 
-	57, 58, 58, 58, 58, 58, 58, 59, 59, 59, 
-	59, 59, 59, 60, 60, 60, 60, 60, 60, 61, 
-	61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 
-	62, 63, 63, 63, 63, 63, 63, 64, 64, 64, 
-	64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 
-	66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 
-	67, 67, 67, 67, 68, 68, 68, 68, 68, 68, 
-	68, 69, 69, 69, 69, 69, 69, 69, 70, 70, 
-	70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 
-	71, 71, 72, 72, 72, 72, 72, 72, 72, 72, 
-	73, 73, 73, 73, 73, 73, 73, 74, 74, 74, 
-	74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 
-	75, 75, 75, 76, 76, 76, 76, 76, 76, 76, 
-	77, 77, 77, 77, 77, 77, 77, 77, 78, 78, 
-	78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 
-	79, 79, 79, 79, 79, 80, 80, 80, 80, 80, 
-	80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 
-	81, 81, 82, 82, 82, 82, 82, 82, 82, 82, 
-	83, 83, 83, 83, 83, 83, 83, 83, 83, 84, 
-	84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 
-	85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 
-	86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 
-	87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 
-	88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 
-	89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 
-	90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 
-	91, 91, 91, 91, 92, 92, 92, 92, 92, 92, 
-	92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 
-	93, 93, 93, 93, 94, 94, 94, 94, 94, 94, 
-	94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 
-	95, 95, 95, 95, 96, 96, 96, 96, 96, 96, 
-	96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 
-	97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 
-	98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 
-	99, 99, 99, 99, 99, 99, 99, 100, 100, 100, 
-	100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 
-	101, 101, 101, 101, 101, 101, 101, 101, 101, 102, 
-	102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 
-	103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 
-	103, 103, 104, 104, 104, 104, 104, 104, 104, 104, 
-	104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 
-	105, 105, 105, 105, 105, 106, 106, 106, 106, 106, 
-	106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 
-	107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 
-	108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-	108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 
-	109, 109, 109, 110, 110, 110, 110, 110, 110, 110, 
-	110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 
-	111, 111, 111, 111, 111, 111, 111, 111, 112, 112, 
-	112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 
-	113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 
-	113, 113, 113, 114, 114, 114, 114, 114, 114, 114, 
-	114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 
-	115, 115, 115, 115, 115, 115, 115, 115, 115, 116, 
-	116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 
-	116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 
-	117, 117, 117, 117, 117, 117, 118, 118, 118, 118, 
-	118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 
-	119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-	119, 119, 119, 120, 120, 120, 120, 120, 120, 120, 
-	120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 
-	121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 
-	122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 
-	122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 
-	123, 123, 123, 123, 123, 123, 123, 123, 123, 124, 
-	124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 
-	124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 
-	125, 125, 125, 125, 125, 125, 125, 125, 126, 126, 
-	126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 
-	126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 
-	127, 127, 127, 127, 127, 127, 127, 128, 128, 128, 
-	128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 
-	128, 128, 129, 129, 129, 129, 129, 129, 129, 129, 
-	129, 129, 129, 129, 129, 129, 129, 130, 130, 130, 
-	130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 
-	130, 130, 131, 131, 131, 131, 131, 131, 131, 131, 
-	131, 131, 131, 131, 131, 131, 131, 131, 132, 132, 
-	132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 
-	132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 
-	133, 133, 133, 133, 133, 133, 133, 133, 133, 134, 
-	134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 
-	134, 134, 134, 134, 134, 135, 135, 135, 135, 135, 
-	135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 
-	135, 136, 136, 136, 136, 136, 136, 136, 136, 136, 
-	136, 136, 136, 136, 136, 136, 136, 137, 137, 137, 
-	137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 
-	137, 137, 137, 138, 138, 138, 138, 138, 138, 138, 
-	138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 
-	139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 
-	139, 139, 139, 139, 139, 139, 140, 140, 140, 140, 
-	140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 
-	140, 140, 140, 141, 141, 141, 141, 141, 141, 141, 
-	141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 
-	142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 
-	142, 142, 142, 142, 142, 142, 142, 143, 143, 143, 
-	143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 
-	143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 
-	144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 
-	144, 145, 145, 145, 145, 145, 145, 145, 145, 145, 
-	145, 145, 145, 145, 145, 145, 145, 145, 145, 146, 
-	146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 
-	146, 146, 146, 146, 146, 146, 147, 147, 147, 147, 
-	147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 
-	147, 147, 147, 147, 148, 148, 148, 148, 148, 148, 
-	148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 
-	148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 
-	149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 
-	150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 
-	150, 150, 150, 150, 150, 150, 150, 150, 150, 151, 
-	151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 
-	151, 151, 151, 151, 151, 151, 151, 152, 152, 152, 
-	152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 
-	152, 152, 152, 152, 152, 152, 153, 153, 153, 153, 
-	153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 
-	153, 153, 153, 153, 154, 154, 154, 154, 154, 154, 
-	154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 
-	154, 154, 154, 155, 155, 155, 155, 155, 155, 155, 
-	155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 
-	155, 155, 156, 156, 156, 156, 156, 156, 156, 156, 
-	156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 
-	156, 156, 157, 157, 157, 157, 157, 157, 157, 157, 
-	157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 
-	157, 158, 158, 158, 158, 158, 158, 158, 158, 158, 
-	158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 
-	159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 
-	159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 
-	160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 
-	160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 
-	161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 
-	161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 
-	162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 
-	162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 
-	163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 
-	163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 
-	164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 
-	164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 
-	164, 165, 165, 165, 165, 165, 165, 165, 165, 165, 
-	165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 
-	165, 165, 166, 166, 166, 166, 166, 166, 166, 166, 
-	166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 
-	166, 166, 167, 167, 167, 167, 167, 167, 167, 167, 
-	167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 
-	167, 167, 167, 168, 168, 168, 168, 168, 168, 168, 
-	168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 
-	168, 168, 168, 168, 168, 169, 169, 169, 169, 169, 
-	169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 
-	169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 
-	170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 
-	170, 170, 170, 170, 170, 170, 170, 171, 171, 171, 
-	171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 
-	171, 171, 171, 171, 171, 171, 171, 171, 171, 172, 
-	172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-	172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-	172, 173, 173, 173, 173, 173, 173, 173, 173, 173, 
-	173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 
-	173, 173, 173, 174, 174, 174, 174, 174, 174, 174, 
-	174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 
-	174, 174, 174, 174, 174, 175, 175, 175, 175, 175, 
-	175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 
-	175, 175, 175, 175, 175, 175, 175, 176, 176, 176, 
-	176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 
-	176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 
-	177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 
-	177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 
-	177, 177, 178, 178, 178, 178, 178, 178, 178, 178, 
-	178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 
-	178, 178, 178, 178, 178, 179, 179, 179, 179, 179, 
-	179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 
-	179, 179, 179, 179, 179, 179, 179, 179, 180, 180, 
-	180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 
-	180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 
-	180, 181, 181, 181, 181, 181, 181, 181, 181, 181, 
-	181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 
-	181, 181, 181, 181, 182, 182, 182, 182, 182, 182, 
-	182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 
-	182, 182, 182, 182, 182, 182, 182, 182, 183, 183, 
-	183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 
-	183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 
-	183, 184, 184, 184, 184, 184, 184, 184, 184, 184, 
-	184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 
-	184, 184, 184, 184, 184, 185, 185, 185, 185, 185, 
-	185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 
-	185, 185, 185, 185, 185, 185, 185, 185, 185, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 
-	186, 186, 186, 187, 187, 187, 187, 187, 187, 187, 
-	187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 
-	187, 187, 187, 187, 187, 187, 187, 187, 188, 188, 
-	188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 
-	188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 
-	188, 188, 189, 189, 189, 189, 189, 189, 189, 189, 
-	189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 
-	189, 189, 189, 189, 189, 189, 189, 190, 190, 190, 
-	190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 
-	190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 
-	190, 190, 191, 191, 191, 191, 191, 191, 191, 191, 
-	191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 
-	191, 191, 191, 191, 191, 191, 192, 192, 192, 192, 
-	192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 
-	192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 
-	192, 192, 193, 193, 193, 193, 193, 193, 193, 193, 
-	193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 
-	193, 193, 193, 193, 193, 193, 193, 194, 194, 194, 
-	194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 
-	194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 
-	194, 194, 195, 195, 195, 195, 195, 195, 195, 195, 
-	195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 
-	195, 195, 195, 195, 195, 195, 195, 195, 196, 196, 
-	196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 
-	196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 
-	196, 196, 196, 196, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 
-	197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 
-	198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 
-	198, 198, 198, 198, 198, 198, 199, 199, 199, 199, 
-	199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 
-	199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 
-	199, 199, 200, 200, 200, 200, 200, 200, 200, 200, 
-	200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 
-	200, 200, 200, 200, 200, 200, 200, 200, 200, 201, 
-	201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 
-	201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 
-	201, 201, 201, 201, 201, 201, 202, 202, 202, 202, 
-	202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 
-	202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 
-	202, 202, 202, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 
-	204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 
-	204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 
-	204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 
-	205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 
-	205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 
-	205, 205, 205, 205, 206, 206, 206, 206, 206, 206, 
-	206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 
-	206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 
-	206, 206, 207, 207, 207, 207, 207, 207, 207, 207, 
-	207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
-	207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 
-	208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 
-	208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 
-	208, 208, 208, 208, 208, 208, 208, 209, 209, 209, 
-	209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 
-	209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 
-	209, 209, 209, 209, 209, 209, 210, 210, 210, 210, 
-	210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 
-	210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 
-	210, 210, 210, 210, 211, 211, 211, 211, 211, 211, 
-	211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 
-	211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 
-	211, 211, 212, 212, 212, 212, 212, 212, 212, 212, 
-	212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 
-	212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 
-	212, 213, 213, 213, 213, 213, 213, 213, 213, 213, 
-	213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 
-	213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 
-	214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 
-	214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 
-	214, 214, 214, 214, 214, 214, 214, 214, 214, 215, 
-	215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 
-	215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 
-	215, 215, 215, 215, 215, 215, 215, 215, 216, 216, 
-	216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 
-	216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 
-	216, 216, 216, 216, 216, 216, 216, 217, 217, 217, 
-	217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 
-	217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 
-	217, 217, 217, 217, 217, 217, 217, 218, 218, 218, 
-	218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 
-	218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 
-	218, 218, 218, 218, 218, 218, 219, 219, 219, 219, 
-	219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 
-	219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 
-	219, 219, 219, 219, 219, 219, 220, 220, 220, 220, 
-	220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 
-	220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 
-	220, 220, 220, 220, 220, 220, 221, 221, 221, 221, 
-	221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 
-	221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 
-	221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 
-	222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 
-	222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 
-	222, 222, 222, 222, 222, 222, 222, 223, 223, 223, 
-	223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 
-	223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 
-	223, 223, 223, 223, 223, 223, 223, 223, 224, 224, 
-	224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 
-	224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 
-	224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 
-	225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 
-	225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 
-	225, 225, 225, 225, 225, 225, 225, 225, 225, 226, 
-	226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 
-	226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 
-	226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 
-	227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 
-	227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 
-	227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 
-	227, 227, 228, 228, 228, 228, 228, 228, 228, 228, 
-	228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 
-	228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 
-	228, 228, 228, 229, 229, 229, 229, 229, 229, 229, 
-	229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 
-	229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 
-	229, 229, 229, 229, 229, 230, 230, 230, 230, 230, 
-	230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 
-	230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 
-	230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 
-	231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 
-	231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 
-	231, 231, 231, 231, 231, 231, 231, 231, 231, 232, 
-	232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 
-	232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 
-	232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 
-	232, 233, 233, 233, 233, 233, 233, 233, 233, 233, 
-	233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 
-	233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 
-	233, 233, 233, 233, 234, 234, 234, 234, 234, 234, 
-	234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 
-	234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 
-	234, 234, 234, 234, 234, 234, 235, 235, 235, 235, 
-	235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 
-	235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 
-	235, 235, 235, 235, 235, 235, 235, 235, 235, 236, 
-	236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 
-	236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 
-	236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 
-	236, 236, 237, 237, 237, 237, 237, 237, 237, 237, 
-	237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 
-	237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 
-	237, 237, 237, 237, 237, 238, 238, 238, 238, 238, 
-	238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 
-	238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 
-	238, 238, 238, 238, 238, 238, 238, 238, 239, 239, 
-	239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 
-	239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 
-	239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 
-	239, 239, 240, 240, 240, 240, 240, 240, 240, 240, 
-	240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 
-	240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 
-	240, 240, 240, 240, 240, 240, 241, 241, 241, 241, 
-	241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 
-	241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 
-	241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 
-	242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 
-	242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 
-	242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 
-	242, 242, 242, 242, 243, 243, 243, 243, 243, 243, 
-	243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 
-	243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 
-	243, 243, 243, 243, 243, 243, 243, 243, 244, 244, 
-	244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 
-	244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 
-	244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 
-	244, 244, 245, 245, 245, 245, 245, 245, 245, 245, 
-	245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 
-	245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 
-	245, 245, 245, 245, 245, 245, 245, 246, 246, 246, 
-	246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 
-	246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 
-	246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 
-	246, 246, 247, 247, 247, 247, 247, 247, 247, 247, 
-	247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 
-	247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 
-	247, 247, 247, 247, 247, 247, 247, 248, 248, 248, 
-	248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 
-	248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 
-	248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 
-	248, 248, 249, 249, 249, 249, 249, 249, 249, 249, 
-	249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 
-	249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 
-	249, 249, 249, 249, 249, 249, 249, 250, 250, 250, 
-	250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 
-	250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 
-	250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 
-	250, 250, 250, 251, 251, 251, 251, 251, 251, 251, 
-	251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 
-	251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 
-	251, 251, 251, 251, 251, 251, 251, 251, 251, 252, 
-	252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 
-	252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 
-	252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 
-	252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 
-	253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 
-	253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 
-	253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 
-	253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 
-	254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 
-	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 
-	255, 255, 255, 255, 255, 255, 
-};
-
-const uint16_t srgb_to_linear[256] =
-{
-	0, 20, 40, 64, 80, 99, 119, 144, 160, 179, 
-	199, 224, 241, 264, 288, 313, 340, 368, 396, 427, 
-	458, 491, 526, 562, 599, 637, 677, 718, 761, 805, 
-	851, 898, 947, 997, 1048, 1101, 1156, 1212, 1270, 1330, 
-	1391, 1453, 1517, 1583, 1651, 1720, 1790, 1863, 1937, 2013, 
-	2090, 2170, 2250, 2333, 2418, 2504, 2592, 2681, 2773, 2866, 
-	2961, 3058, 3157, 3258, 3360, 3464, 3570, 3678, 3788, 3900, 
-	4014, 4129, 4247, 4366, 4488, 4611, 4736, 4864, 4993, 5124, 
-	5257, 5392, 5530, 5669, 5810, 5953, 6099, 6246, 6395, 6547, 
-	6700, 6856, 7014, 7174, 7335, 7500, 7666, 7834, 8004, 8177, 
-	8352, 8528, 8708, 8889, 9072, 9258, 9445, 9635, 9828, 10022, 
-	10219, 10417, 10619, 10822, 11028, 11235, 11446, 11658, 11873, 12090, 
-	12309, 12530, 12754, 12980, 13209, 13440, 13673, 13909, 14146, 14387, 
-	14629, 14874, 15122, 15371, 15623, 15878, 16135, 16394, 16656, 16920, 
-	17187, 17456, 17727, 18001, 18277, 18556, 18837, 19121, 19407, 19696, 
-	19987, 20281, 20577, 20876, 21177, 21481, 21787, 22096, 22407, 22721, 
-	23038, 23357, 23678, 24002, 24329, 24658, 24990, 25325, 25662, 26001, 
-	26344, 26688, 27036, 27386, 27739, 28094, 28452, 28813, 29176, 29542, 
-	29911, 30282, 30656, 31033, 31412, 31794, 32179, 32567, 32957, 33350, 
-	33745, 34143, 34544, 34948, 35355, 35764, 36176, 36591, 37008, 37429, 
-	37852, 38278, 38706, 39138, 39572, 40009, 40449, 40891, 41337, 41785, 
-	42236, 42690, 43147, 43606, 44069, 44534, 45002, 45473, 45947, 46423, 
-	46903, 47385, 47871, 48359, 48850, 49344, 49841, 50341, 50844, 51349, 
-	51858, 52369, 52884, 53401, 53921, 54445, 54971, 55500, 56032, 56567, 
-	57105, 57646, 58190, 58737, 59287, 59840, 60396, 60955, 61517, 62082, 
-	62650, 63221, 63795, 64372, 64952, 65535, 
-};
--- a/gfx/cairo/libpixman/src/pixman-sse2.c
+++ b/gfx/cairo/libpixman/src/pixman-sse2.c
@@ -141,17 +141,17 @@ pack_565_2packedx128_128 (__m128i lo, __
     /* Simulates _mm_packus_epi32 */
     t0 = _mm_slli_epi32 (t0, 16 - 5);
     t1 = _mm_slli_epi32 (t1, 16 - 5);
     t0 = _mm_srai_epi32 (t0, 16);
     t1 = _mm_srai_epi32 (t1, 16);
     return _mm_packs_epi32 (t0, t1);
 }
 
-__m128i
+static force_inline __m128i
 pack_565_2x128_128 (__m128i lo, __m128i hi)
 {
     __m128i data;
     __m128i r, g1, g2, b;
 
     data = pack_2x128_128 (lo, hi);
 
     r  = _mm_and_si128 (data, mask_565_r);
@@ -3304,92 +3304,96 @@ sse2_composite_over_n_8_8888 (pixman_imp
 
 	    w--;
 	    dst++;
 	}
     }
 
 }
 
+#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
+__attribute__((__force_align_arg_pointer__))
+#endif
 static pixman_bool_t
-pixman_fill_sse2 (uint32_t *bits,
-                  int       stride,
-                  int       bpp,
-                  int       x,
-                  int       y,
-                  int       width,
-                  int       height,
-                  uint32_t  data)
+sse2_fill (pixman_implementation_t *imp,
+           uint32_t *               bits,
+           int                      stride,
+           int                      bpp,
+           int                      x,
+           int                      y,
+           int                      width,
+           int                      height,
+           uint32_t		    xor)
 {
     uint32_t byte_width;
-    uint8_t         *byte_line;
+    uint8_t *byte_line;
 
     __m128i xmm_def;
 
     if (bpp == 8)
     {
 	uint8_t b;
 	uint16_t w;
 
 	stride = stride * (int) sizeof (uint32_t) / 1;
 	byte_line = (uint8_t *)(((uint8_t *)bits) + stride * y + x);
 	byte_width = width;
 	stride *= 1;
 
-	b = data & 0xff;
+	b = xor & 0xff;
 	w = (b << 8) | b;
-	data = (w << 16) | w;
+	xor = (w << 16) | w;
     }
     else if (bpp == 16)
     {
 	stride = stride * (int) sizeof (uint32_t) / 2;
 	byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x);
 	byte_width = 2 * width;
 	stride *= 2;
 
-        data = (data & 0xffff) * 0x00010001;
+        xor = (xor & 0xffff) * 0x00010001;
     }
     else if (bpp == 32)
     {
 	stride = stride * (int) sizeof (uint32_t) / 4;
 	byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x);
 	byte_width = 4 * width;
 	stride *= 4;
     }
     else
     {
 	return FALSE;
     }
 
-    xmm_def = create_mask_2x32_128 (data, data);
+    xmm_def = create_mask_2x32_128 (xor, xor);
 
     while (height--)
     {
 	int w;
 	uint8_t *d = byte_line;
 	byte_line += stride;
 	w = byte_width;
 
 	if (w >= 1 && ((unsigned long)d & 1))
 	{
-	    *(uint8_t *)d = data;
+	    *(uint8_t *)d = xor;
 	    w -= 1;
 	    d += 1;
 	}
 
 	while (w >= 2 && ((unsigned long)d & 3))
 	{
-	    *(uint16_t *)d = data;
+	    *(uint16_t *)d = xor;
 	    w -= 2;
 	    d += 2;
 	}
 
 	while (w >= 4 && ((unsigned long)d & 15))
 	{
-	    *(uint32_t *)d = data;
+	    *(uint32_t *)d = xor;
 
 	    w -= 4;
 	    d += 4;
 	}
 
 	while (w >= 128)
 	{
 	    save_128_aligned ((__m128i*)(d),     xmm_def);
@@ -3430,32 +3434,32 @@ pixman_fill_sse2 (uint32_t *bits,
 	    save_128_aligned ((__m128i*)(d),     xmm_def);
 
 	    d += 16;
 	    w -= 16;
 	}
 
 	while (w >= 4)
 	{
-	    *(uint32_t *)d = data;
+	    *(uint32_t *)d = xor;
 
 	    w -= 4;
 	    d += 4;
 	}
 
 	if (w >= 2)
 	{
-	    *(uint16_t *)d = data;
+	    *(uint16_t *)d = xor;
 	    w -= 2;
 	    d += 2;
 	}
 
 	if (w >= 1)
 	{
-	    *(uint8_t *)d = data;
+	    *(uint8_t *)d = xor;
 	    w -= 1;
 	    d += 1;
 	}
     }
 
     return TRUE;
 }
 
@@ -3474,19 +3478,19 @@ sse2_composite_src_n_8_8888 (pixman_impl
     __m128i xmm_src, xmm_def;
     __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi;
 
     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
     {
-	pixman_fill_sse2 (dest_image->bits.bits, dest_image->bits.rowstride,
-	                  PIXMAN_FORMAT_BPP (dest_image->bits.format),
-	                  dest_x, dest_y, width, height, 0);
+	sse2_fill (imp, dest_image->bits.bits, dest_image->bits.rowstride,
+		   PIXMAN_FORMAT_BPP (dest_image->bits.format),
+		   dest_x, dest_y, width, height, 0);
 	return;
     }
 
     PIXMAN_IMAGE_GET_LINE (
 	dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
     PIXMAN_IMAGE_GET_LINE (
 	mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
 
@@ -4518,28 +4522,29 @@ sse2_composite_add_8888_8888 (pixman_imp
 	src_line += src_stride;
 
 	sse2_combine_add_u (imp, op, dst, src, NULL, width);
     }
 
 }
 
 static pixman_bool_t
-pixman_blt_sse2 (uint32_t *src_bits,
-                 uint32_t *dst_bits,
-                 int       src_stride,
-                 int       dst_stride,
-                 int       src_bpp,
-                 int       dst_bpp,
-                 int       src_x,
-                 int       src_y,
-                 int       dest_x,
-                 int       dest_y,
-                 int       width,
-                 int       height)
+sse2_blt (pixman_implementation_t *imp,
+          uint32_t *               src_bits,
+          uint32_t *               dst_bits,
+          int                      src_stride,
+          int                      dst_stride,
+          int                      src_bpp,
+          int                      dst_bpp,
+          int                      src_x,
+          int                      src_y,
+          int                      dest_x,
+          int                      dest_y,
+          int                      width,
+          int                      height)
 {
     uint8_t *   src_bytes;
     uint8_t *   dst_bytes;
     int byte_width;
 
     if (src_bpp != dst_bpp)
 	return FALSE;
 
@@ -4635,32 +4640,31 @@ pixman_blt_sse2 (uint32_t *src_bits,
 	{
 	    *(uint16_t *)d = *(uint16_t *)s;
 	    w -= 2;
 	    s += 2;
 	    d += 2;
 	}
     }
 
-
     return TRUE;
 }
 
 static void
 sse2_composite_copy_area (pixman_implementation_t *imp,
                           pixman_composite_info_t *info)
 {
     PIXMAN_COMPOSITE_ARGS (info);
-    pixman_blt_sse2 (src_image->bits.bits,
-                     dest_image->bits.bits,
-                     src_image->bits.rowstride,
-                     dest_image->bits.rowstride,
-                     PIXMAN_FORMAT_BPP (src_image->bits.format),
-                     PIXMAN_FORMAT_BPP (dest_image->bits.format),
-                     src_x, src_y, dest_x, dest_y, width, height);
+    sse2_blt (imp, src_image->bits.bits,
+	      dest_image->bits.bits,
+	      src_image->bits.rowstride,
+	      dest_image->bits.rowstride,
+	      PIXMAN_FORMAT_BPP (src_image->bits.format),
+	      PIXMAN_FORMAT_BPP (dest_image->bits.format),
+	      src_x, src_y, dest_x, dest_y, width, height);
 }
 
 static void
 sse2_composite_over_x888_8_8888 (pixman_implementation_t *imp,
                                  pixman_composite_info_t *info)
 {
     PIXMAN_COMPOSITE_ARGS (info);
     uint32_t    *src, *src_line, s;
@@ -5953,68 +5957,16 @@ static const pixman_fast_path_t sse2_fas
     /* and here the needed entries are added to the fast path table */
 
     SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, r5g6b5, sse2_8888_0565),
     SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8, b5g6r5, sse2_8888_0565),
 
     { PIXMAN_OP_NONE },
 };
 
-static pixman_bool_t
-sse2_blt (pixman_implementation_t *imp,
-          uint32_t *               src_bits,
-          uint32_t *               dst_bits,
-          int                      src_stride,
-          int                      dst_stride,
-          int                      src_bpp,
-          int                      dst_bpp,
-          int                      src_x,
-          int                      src_y,
-          int                      dest_x,
-          int                      dest_y,
-          int                      width,
-          int                      height)
-{
-    if (!pixman_blt_sse2 (
-            src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
-            src_x, src_y, dest_x, dest_y, width, height))
-
-    {
-	return _pixman_implementation_blt (
-	    imp->delegate,
-	    src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
-	    src_x, src_y, dest_x, dest_y, width, height);
-    }
-
-    return TRUE;
-}
-
-#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
-__attribute__((__force_align_arg_pointer__))
-#endif
-static pixman_bool_t
-sse2_fill (pixman_implementation_t *imp,
-           uint32_t *               bits,
-           int                      stride,
-           int                      bpp,
-           int                      x,
-           int                      y,
-           int                      width,
-           int                      height,
-           uint32_t xor)
-{
-    if (!pixman_fill_sse2 (bits, stride, bpp, x, y, width, height, xor))
-    {
-	return _pixman_implementation_fill (
-	    imp->delegate, bits, stride, bpp, x, y, width, height, xor);
-    }
-
-    return TRUE;
-}
-
 static uint32_t *
 sse2_fetch_x8r8g8b8 (pixman_iter_t *iter, const uint32_t *mask)
 {
     int w = iter->width;
     __m128i ff000000 = mask_ff000000;
     uint32_t *dst = iter->buffer;
     uint32_t *src = (uint32_t *)iter->bits;
 
@@ -6147,17 +6099,17 @@ typedef struct
 static const fetcher_info_t fetchers[] =
 {
     { PIXMAN_x8r8g8b8,		sse2_fetch_x8r8g8b8 },
     { PIXMAN_r5g6b5,		sse2_fetch_r5g6b5 },
     { PIXMAN_a8,		sse2_fetch_a8 },
     { PIXMAN_null }
 };
 
-static void
+static pixman_bool_t
 sse2_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
 {
     pixman_image_t *image = iter->image;
 
 #define FLAGS								\
     (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM |		\
      FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
 
@@ -6172,22 +6124,22 @@ sse2_src_iter_init (pixman_implementatio
 	    {
 		uint8_t *b = (uint8_t *)image->bits.bits;
 		int s = image->bits.rowstride * 4;
 
 		iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (f->format) / 8;
 		iter->stride = s;
 
 		iter->get_scanline = f->get_scanline;
-		return;
+		return TRUE;
 	    }
 	}
     }
 
-    imp->delegate->src_iter_init (imp->delegate, iter);
+    return FALSE;
 }
 
 #if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
 __attribute__((__force_align_arg_pointer__))
 #endif
 pixman_implementation_t *
 _pixman_implementation_create_sse2 (pixman_implementation_t *fallback)
 {
--- a/gfx/cairo/libpixman/src/pixman-trap.c
+++ b/gfx/cairo/libpixman/src/pixman-trap.c
@@ -225,21 +225,21 @@ pixman_line_fixed_edge_init (pixman_edge
     pixman_edge_init (e, n, y,
                       top->x + x_off_fixed,
                       top->y + y_off_fixed,
                       bot->x + x_off_fixed,
                       bot->y + y_off_fixed);
 }
 
 PIXMAN_EXPORT void
-pixman_add_traps (pixman_image_t * image,
-                  int16_t          x_off,
-                  int16_t          y_off,
-                  int              ntrap,
-                  pixman_trap_t *  traps)
+pixman_add_traps (pixman_image_t *     image,
+                  int16_t              x_off,
+                  int16_t              y_off,
+                  int                  ntrap,
+                  const pixman_trap_t *traps)
 {
     int bpp;
     int height;
 
     pixman_fixed_t x_off_fixed;
     pixman_fixed_t y_off_fixed;
     pixman_edge_t l, r;
     pixman_fixed_t t, b;
@@ -382,28 +382,105 @@ pixman_rasterize_trapezoid (pixman_image
 	/* initialize edge walkers */
 	pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off);
 	pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off);
 
 	pixman_rasterize_edges (image, &l, &r, t, b);
     }
 }
 
+static const pixman_bool_t zero_src_has_no_effect[PIXMAN_N_OPERATORS] =
+{
+    FALSE,	/* Clear		0			0    */
+    FALSE,	/* Src			1			0    */
+    TRUE,	/* Dst			0			1    */
+    TRUE,	/* Over			1			1-Aa */
+    TRUE,	/* OverReverse		1-Ab			1    */
+    FALSE,	/* In			Ab			0    */
+    FALSE,	/* InReverse		0			Aa   */
+    FALSE,	/* Out			1-Ab			0    */
+    TRUE,	/* OutReverse		0			1-Aa */
+    TRUE,	/* Atop			Ab			1-Aa */
+    FALSE,	/* AtopReverse		1-Ab			Aa   */
+    TRUE,	/* Xor			1-Ab			1-Aa */
+    TRUE,	/* Add			1			1    */
+};
+
+static pixman_bool_t
+get_trap_extents (pixman_op_t op, pixman_image_t *dest,
+		  const pixman_trapezoid_t *traps, int n_traps,
+		  pixman_box32_t *box)
+{
+    int i;
+
+    /* When the operator is such that a zero source has an
+     * effect on the underlying image, we have to
+     * composite across the entire destination
+     */
+    if (!zero_src_has_no_effect [op])
+    {
+	box->x1 = 0;
+	box->y1 = 0;
+	box->x2 = dest->bits.width;
+	box->y2 = dest->bits.height;
+	return TRUE;
+    }
+    
+    box->x1 = INT32_MAX;
+    box->y1 = INT32_MAX;
+    box->x2 = INT32_MIN;
+    box->y2 = INT32_MIN;
+	
+    for (i = 0; i < n_traps; ++i)
+    {
+	const pixman_trapezoid_t *trap = &(traps[i]);
+	int y1, y2;
+	    
+	if (!pixman_trapezoid_valid (trap))
+	    continue;
+	    
+	y1 = pixman_fixed_to_int (trap->top);
+	if (y1 < box->y1)
+	    box->y1 = y1;
+	    
+	y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom));
+	if (y2 > box->y2)
+	    box->y2 = y2;
+	    
+#define EXTEND_MIN(x)							\
+	if (pixman_fixed_to_int ((x)) < box->x1)			\
+	    box->x1 = pixman_fixed_to_int ((x));
+#define EXTEND_MAX(x)							\
+	if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box->x2)	\
+	    box->x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x)));
+	    
+#define EXTEND(x)							\
+	EXTEND_MIN(x);							\
+	EXTEND_MAX(x);
+	    
+	EXTEND(trap->left.p1.x);
+	EXTEND(trap->left.p2.x);
+	EXTEND(trap->right.p1.x);
+	EXTEND(trap->right.p2.x);
+    }
+	
+    if (box->x1 >= box->x2 || box->y1 >= box->y2)
+	return FALSE;
+
+    return TRUE;
+}
+
 /*
  * pixman_composite_trapezoids()
  *
  * All the trapezoids are conceptually rendered to an infinitely big image.
  * The (0, 0) coordinates of this image are then aligned with the (x, y)
  * coordinates of the source image, and then both images are aligned with
- * the (x, y) coordinates of the destination. Then, in principle, compositing
- * of these three images takes place across the entire destination.
- *
- * FIXME: However, there is currently a bug, where we restrict this compositing
- * to the bounding box of the trapezoids. This is incorrect for operators such
- * as SRC and IN where blank source pixels do have an effect on the destination.
+ * the (x, y) coordinates of the destination. Then these three images are
+ * composited across the entire destination.
  */
 PIXMAN_EXPORT void
 pixman_composite_trapezoids (pixman_op_t		op,
 			     pixman_image_t *		src,
 			     pixman_image_t *		dst,
 			     pixman_format_code_t	mask_format,
 			     int			x_src,
 			     int			y_src,
@@ -434,56 +511,19 @@ pixman_composite_trapezoids (pixman_op_t
 	    
 	    pixman_rasterize_trapezoid (dst, trap, x_dst, y_dst);
 	}
     }
     else
     {
 	pixman_image_t *tmp;
 	pixman_box32_t box;
-	
-	box.x1 = INT32_MAX;
-	box.y1 = INT32_MAX;
-	box.x2 = INT32_MIN;
-	box.y2 = INT32_MIN;
-	
-	for (i = 0; i < n_traps; ++i)
-	{
-	    const pixman_trapezoid_t *trap = &(traps[i]);
-	    int y1, y2;
-	    
-	    if (!pixman_trapezoid_valid (trap))
-		continue;
-	    
-	    y1 = pixman_fixed_to_int (trap->top);
-	    if (y1 < box.y1)
-		box.y1 = y1;
-	    
-	    y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom));
-	    if (y2 > box.y2)
-		box.y2 = y2;
-	    
-#define EXTEND_MIN(x)							\
-	    if (pixman_fixed_to_int ((x)) < box.x1)			\
-		box.x1 = pixman_fixed_to_int ((x));
-#define EXTEND_MAX(x)							\
-	    if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box.x2)	\
-		box.x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x)));
-	    
-#define EXTEND(x)							\
-	    EXTEND_MIN(x);						\
-	    EXTEND_MAX(x);
-	    
-	    EXTEND(trap->left.p1.x);
-	    EXTEND(trap->left.p2.x);
-	    EXTEND(trap->right.p1.x);
-	    EXTEND(trap->right.p2.x);
-	}
-	
-	if (box.x1 >= box.x2 || box.y1 >= box.y2)
+	int i;
+
+	if (!get_trap_extents (op, dst, traps, n_traps, &box))
 	    return;
 	
 	tmp = pixman_image_create_bits (
 	    mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1);
 	
 	for (i = 0; i < n_traps; ++i)
 	{
 	    const pixman_trapezoid_t *trap = &(traps[i]);
--- a/gfx/cairo/libpixman/src/pixman-utils.c
+++ b/gfx/cairo/libpixman/src/pixman-utils.c
@@ -26,128 +26,16 @@
 #include <config.h>
 #endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <limits.h>
 
 #include "pixman-private.h"
 
-#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);
-
-pixman_bool_t
-_pixman_lookup_composite_function (pixman_implementation_t     *toplevel,
-				   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 = toplevel; 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_bool_t
 _pixman_multiply_overflows_size (size_t a, size_t b)
 {
     return a >= SIZE_MAX / b;
 }
 
 pixman_bool_t
 _pixman_multiply_overflows_int (unsigned int a, unsigned int b)
@@ -179,129 +67,150 @@ pixman_malloc_abc (unsigned int a,
     if (a >= INT32_MAX / b)
 	return NULL;
     else if (a * b >= INT32_MAX / c)
 	return NULL;
     else
 	return malloc (a * b * c);
 }
 
-static void
-unorm_to_unorm_params (int in_width, int out_width, uint32_t *factor, int *shift)
+static force_inline uint16_t
+float_to_unorm (float f, int n_bits)
 {
-    int w = 0;
+    uint32_t u;
+
+    if (f > 1.0)
+	f = 1.0;
+    if (f < 0.0)
+	f = 0.0;
 
-    *factor = 0;
-    while (in_width != 0 && w < out_width)
-    {
-	*factor |= 1 << w;
-	w += in_width;
-    }
+    u = f * (1 << n_bits);
+    u -= (u >> n_bits);
+
+    return u;
+}
 
-    /* Did we generate too many bits? */
-    *shift = w - out_width;
+static force_inline float
+unorm_to_float (uint16_t u, int n_bits)
+{
+    uint32_t m = ((1 << n_bits) - 1);
+
+    return (u & m) * (1.f / (float)m);
 }
 
 /*
- * This function expands images from ARGB8 format to ARGB16.  To preserve
- * precision, it needs to know the original source format.  For example, if the
- * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
- * the expanded value is 12345123.  To correctly expand this to 16 bits, it
- * should be 1234512345123451 and not 1234512312345123.
+ * This function expands images from a8r8g8b8 to argb_t.  To preserve
+ * precision, it needs to know from which source format the a8r8g8b8 pixels
+ * originally came.
+ *
+ * For example, if the source was PIXMAN_x1r5g5b5 and the red component
+ * contained bits 12345, then the 8-bit value is 12345123.  To correctly
+ * expand this to floating point, it should be 12345 / 31.0 and not
+ * 12345123 / 255.0.
  */
 void
-pixman_expand (uint64_t *           dst,
-               const uint32_t *     src,
-               pixman_format_code_t format,
-               int                  width)
+pixman_expand_to_float (argb_t               *dst,
+			const uint32_t       *src,
+			pixman_format_code_t  format,
+			int                   width)
 {
+    static const float multipliers[16] = {
+	0.0f,
+	1.0f / ((1 <<  1) - 1),
+	1.0f / ((1 <<  2) - 1),
+	1.0f / ((1 <<  3) - 1),
+	1.0f / ((1 <<  4) - 1),
+	1.0f / ((1 <<  5) - 1),
+	1.0f / ((1 <<  6) - 1),
+	1.0f / ((1 <<  7) - 1),
+	1.0f / ((1 <<  8) - 1),
+	1.0f / ((1 <<  9) - 1),
+	1.0f / ((1 << 10) - 1),
+	1.0f / ((1 << 11) - 1),
+	1.0f / ((1 << 12) - 1),
+	1.0f / ((1 << 13) - 1),
+	1.0f / ((1 << 14) - 1),
+	1.0f / ((1 << 15) - 1),
+    };
+    int a_size, r_size, g_size, b_size;
+    int a_shift, r_shift, g_shift, b_shift;
+    float a_mul, r_mul, g_mul, b_mul;
+    uint32_t a_mask, r_mask, g_mask, b_mask;
+    int i;
+
+    if (!PIXMAN_FORMAT_VIS (format))
+	format = PIXMAN_a8r8g8b8;
+
     /*
      * Determine the sizes of each component and the masks and shifts
      * required to extract them from the source pixel.
      */
-    const int a_size = PIXMAN_FORMAT_A (format),
-              r_size = PIXMAN_FORMAT_R (format),
-              g_size = PIXMAN_FORMAT_G (format),
-              b_size = PIXMAN_FORMAT_B (format);
-    const int a_shift = 32 - a_size,
-              r_shift = 24 - r_size,
-              g_shift = 16 - g_size,
-              b_shift =  8 - b_size;
-    const uint8_t a_mask = ~(~0 << a_size),
-                  r_mask = ~(~0 << r_size),
-                  g_mask = ~(~0 << g_size),
-                  b_mask = ~(~0 << b_size);
-    uint32_t au_factor, ru_factor, gu_factor, bu_factor;
-    int au_shift, ru_shift, gu_shift, bu_shift;
-    int i;
+    a_size = PIXMAN_FORMAT_A (format);
+    r_size = PIXMAN_FORMAT_R (format);
+    g_size = PIXMAN_FORMAT_G (format);
+    b_size = PIXMAN_FORMAT_B (format);
+
+    a_shift = 32 - a_size;
+    r_shift = 24 - r_size;
+    g_shift = 16 - g_size;
+    b_shift =  8 - b_size;
 
-    unorm_to_unorm_params (a_size, 16, &au_factor, &au_shift);
-    unorm_to_unorm_params (r_size, 16, &ru_factor, &ru_shift);
-    unorm_to_unorm_params (g_size, 16, &gu_factor, &gu_shift);
-    unorm_to_unorm_params (b_size, 16, &bu_factor, &bu_shift);
+    a_mask = ((1 << a_size) - 1);
+    r_mask = ((1 << r_size) - 1);
+    g_mask = ((1 << g_size) - 1);
+    b_mask = ((1 << b_size) - 1);
+
+    a_mul = multipliers[a_size];
+    r_mul = multipliers[r_size];
+    g_mul = multipliers[g_size];
+    b_mul = multipliers[b_size];
 
     /* Start at the end so that we can do the expansion in place
      * when src == dst
      */
     for (i = width - 1; i >= 0; i--)
     {
 	const uint32_t pixel = src[i];
-	uint8_t a, r, g, b;
-	uint64_t a16, r16, g16, b16;
 
-	if (a_size)
-	{
-	    a = (pixel >> a_shift) & a_mask;
-            a16 = a * au_factor >> au_shift;
-	}
-	else
-	{
-	    a16 = 0xffff;
-	}
-
-	if (r_size)
-	{
-	    r = (pixel >> r_shift) & r_mask;
-	    g = (pixel >> g_shift) & g_mask;
-	    b = (pixel >> b_shift) & b_mask;
-            r16 = r * ru_factor >> ru_shift;
-            g16 = g * gu_factor >> gu_shift;
-            b16 = b * bu_factor >> bu_shift;
-	}
-	else
-	{
-	    r16 = g16 = b16 = 0;
-	}
-	
-	dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
+	dst[i].a = a_mask? ((pixel >> a_shift) & a_mask) * a_mul : 1.0f;
+	dst[i].r = ((pixel >> r_shift) & r_mask) * r_mul;
+	dst[i].g = ((pixel >> g_shift) & g_mask) * g_mul;
+	dst[i].b = ((pixel >> b_shift) & b_mask) * b_mul;
     }
 }
 
-/*
- * Contracting is easier than expanding.  We just need to truncate the
- * components.
- */
+uint16_t
+pixman_float_to_unorm (float f, int n_bits)
+{
+    return float_to_unorm (f, n_bits);
+}
+
+float
+pixman_unorm_to_float (uint16_t u, int n_bits)
+{
+    return unorm_to_float (u, n_bits);
+}
+
 void
-pixman_contract (uint32_t *      dst,
-                 const uint64_t *src,
-                 int             width)
+pixman_contract_from_float (uint32_t     *dst,
+			    const argb_t *src,
+			    int           width)
 {
     int i;
 
-    /* Start at the beginning so that we can do the contraction in
-     * place when src == dst
-     */
-    for (i = 0; i < width; i++)
+    for (i = 0; i < width; ++i)
     {
-	const uint8_t a = src[i] >> 56,
-	              r = src[i] >> 40,
-	              g = src[i] >> 24,
-	              b = src[i] >> 8;
+	uint8_t a, r, g, b;
 
-	dst[i] = a << 24 | r << 16 | g << 8 | b;
+	a = float_to_unorm (src[i].a, 8);
+	r = float_to_unorm (src[i].r, 8);
+	g = float_to_unorm (src[i].g, 8);
+	b = float_to_unorm (src[i].b, 8);
+
+	dst[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0);
     }
 }
 
 uint32_t *
 _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask)
 {
     return iter->buffer;
 }
@@ -370,16 +279,25 @@ pixman_region32_copy_from_region16 (pixm
     retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
 
     if (boxes32 != tmp_boxes)
 	free (boxes32);
 
     return retval;
 }
 
+/* This function is exported for the sake of the test suite and not part
+ * of the ABI.
+ */
+PIXMAN_EXPORT pixman_implementation_t *
+_pixman_internal_only_get_implementation (void)
+{
+    return get_implementation ();
+}
+
 #ifdef DEBUG
 
 void
 _pixman_log_error (const char *function, const char *message)
 {
     static int n_messages = 0;
 
     if (n_messages < 10)
--- a/gfx/cairo/libpixman/src/pixman.c
+++ b/gfx/cairo/libpixman/src/pixman.c
@@ -600,16 +600,17 @@ pixman_image_composite32 (pixman_op_t   
 
     dest_format = dest->common.extended_format_code;
     dest_flags = dest->common.flags;
 
     /* Check for pixbufs */
     if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
 	(src->type == BITS && src->bits.bits == mask->bits.bits)	   &&
 	(src->common.repeat == mask->common.repeat)			   &&
+	(src_flags & mask_flags & FAST_PATH_ID_TRANSFORM)		   &&
 	(src_x == mask_x && src_y == mask_y))
     {
 	if (src_format == PIXMAN_x8b8g8r8)
 	    src_format = mask_format = PIXMAN_pixbuf;
 	else if (src_format == PIXMAN_x8r8g8b8)
 	    src_format = mask_format = PIXMAN_rpixbuf;
     }
 
@@ -664,17 +665,17 @@ pixman_image_composite32 (pixman_op_t   
 
     /*
      * 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 (_pixman_lookup_composite_function (
+    if (_pixman_implementation_lookup_composite (
 	    get_implementation (), op,
 	    src_format, src_flags, mask_format, mask_flags, dest_format, dest_flags,
 	    &imp, &func))
     {
 	pixman_composite_info_t info;
 	const pixman_box32_t *pbox;
 	int n;
 
@@ -769,19 +770,19 @@ color_to_uint32 (const pixman_color_t *c
     return
         (color->alpha >> 8 << 24) |
         (color->red >> 8 << 16) |
         (color->green & 0xff00) |
         (color->blue >> 8);
 }
 
 static pixman_bool_t
-color_to_pixel (pixman_color_t *     color,
-                uint32_t *           pixel,
-                pixman_format_code_t format)
+color_to_pixel (const pixman_color_t *color,
+                uint32_t *            pixel,
+                pixman_format_code_t  format)
 {
     uint32_t c = color_to_uint32 (color);
 
     if (!(format == PIXMAN_a8r8g8b8     ||
           format == PIXMAN_x8r8g8b8     ||
           format == PIXMAN_a8b8g8r8     ||
           format == PIXMAN_x8b8g8r8     ||
           format == PIXMAN_b8g8r8a8     ||
@@ -828,17 +829,17 @@ color_to_pixel (pixman_color_t *     col
 
     *pixel = c;
     return TRUE;
 }
 
 PIXMAN_EXPORT pixman_bool_t
 pixman_image_fill_rectangles (pixman_op_t                 op,
                               pixman_image_t *            dest,
-                              pixman_color_t *            color,
+			      const pixman_color_t *      color,
                               int                         n_rects,
                               const pixman_rectangle16_t *rects)
 {
     pixman_box32_t stack_boxes[6];
     pixman_box32_t *boxes;
     pixman_bool_t result;
     int i;
 
@@ -867,17 +868,17 @@ pixman_image_fill_rectangles (pixman_op_
         free (boxes);
     
     return result;
 }
 
 PIXMAN_EXPORT pixman_bool_t
 pixman_image_fill_boxes (pixman_op_t           op,
                          pixman_image_t *      dest,
-                         pixman_color_t *      color,
+                         const pixman_color_t *color,
                          int                   n_boxes,
                          const pixman_box32_t *boxes)
 {
     pixman_image_t *solid;
     pixman_color_t c;
     int i;
 
     _pixman_image_validate (dest);
--- a/gfx/cairo/libpixman/src/pixman.h
+++ b/gfx/cairo/libpixman/src/pixman.h
@@ -734,36 +734,41 @@ typedef enum {
     PIXMAN_yv12 =	 PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0)
 } pixman_format_code_t;
 
 /* Querying supported format values. */
 pixman_bool_t pixman_format_supported_destination (pixman_format_code_t format);
 pixman_bool_t pixman_format_supported_source      (pixman_format_code_t format);
 
 /* Constructors */
-pixman_image_t *pixman_image_create_solid_fill       (pixman_color_t               *color);
-pixman_image_t *pixman_image_create_linear_gradient  (pixman_point_fixed_t         *p1,
-						      pixman_point_fixed_t         *p2,
+pixman_image_t *pixman_image_create_solid_fill       (const pixman_color_t         *color);
+pixman_image_t *pixman_image_create_linear_gradient  (const pixman_point_fixed_t   *p1,
+						      const pixman_point_fixed_t   *p2,
 						      const pixman_gradient_stop_t *stops,
 						      int                           n_stops);
-pixman_image_t *pixman_image_create_radial_gradient  (pixman_point_fixed_t         *inner,
-						      pixman_point_fixed_t         *outer,
+pixman_image_t *pixman_image_create_radial_gradient  (const pixman_point_fixed_t   *inner,
+						      const pixman_point_fixed_t   *outer,
 						      pixman_fixed_t                inner_radius,
 						      pixman_fixed_t                outer_radius,
 						      const pixman_gradient_stop_t *stops,
 						      int                           n_stops);
-pixman_image_t *pixman_image_create_conical_gradient (pixman_point_fixed_t         *center,
+pixman_image_t *pixman_image_create_conical_gradient (const pixman_point_fixed_t   *center,
 						      pixman_fixed_t                angle,
 						      const pixman_gradient_stop_t *stops,
 						      int                           n_stops);
 pixman_image_t *pixman_image_create_bits             (pixman_format_code_t          format,
 						      int                           width,
 						      int                           height,
 						      uint32_t                     *bits,
 						      int                           rowstride_bytes);
+pixman_image_t *pixman_image_create_bits_no_clear    (pixman_format_code_t format,
+						      int                  width,
+						      int                  height,
+						      uint32_t *           bits,
+						      int                  rowstride_bytes);
 
 /* Destructor */
 pixman_image_t *pixman_image_ref                     (pixman_image_t               *image);
 pixman_bool_t   pixman_image_unref                   (pixman_image_t               *image);
 
 void		pixman_image_set_destroy_function    (pixman_image_t		   *image,
 						      pixman_image_destroy_func_t   function,
 						      void			   *data);
@@ -801,22 +806,22 @@ void		pixman_image_set_indexed	     (pix
 uint32_t       *pixman_image_get_data                (pixman_image_t               *image);
 int		pixman_image_get_width               (pixman_image_t               *image);
 int             pixman_image_get_height              (pixman_image_t               *image);
 int		pixman_image_get_stride              (pixman_image_t               *image); /* in bytes */
 int		pixman_image_get_depth               (pixman_image_t		   *image);
 pixman_format_code_t pixman_image_get_format	     (pixman_image_t		   *image);
 pixman_bool_t	pixman_image_fill_rectangles	     (pixman_op_t		    op,
 						      pixman_image_t		   *image,
-						      pixman_color_t		   *color,
+						      const pixman_color_t	   *color,
 						      int			    n_rects,
 						      const pixman_rectangle16_t   *rects);
 pixman_bool_t   pixman_image_fill_boxes              (pixman_op_t                   op,
                                                       pixman_image_t               *dest,
-                                                      pixman_color_t               *color,
+                                                      const pixman_color_t         *color,
                                                       int                           n_boxes,
                                                       const pixman_box32_t         *boxes);
 
 /* Composite */
 pixman_bool_t pixman_compute_composite_region (pixman_region16_t *region,
 					       pixman_image_t    *src_image,
 					       pixman_image_t    *mask_image,
 					       pixman_image_t    *dest_image,
@@ -900,42 +905,42 @@ void                  pixman_glyph_cache
 						       void                 *font_key,
 						       void                 *glyph_key);
 void                  pixman_glyph_get_extents        (pixman_glyph_cache_t *cache,
 						       int                   n_glyphs,
 						       pixman_glyph_t       *glyphs,
 						       pixman_box32_t       *extents);
 pixman_format_code_t  pixman_glyph_get_mask_format    (pixman_glyph_cache_t *cache,
 						       int		     n_glyphs,
-						       pixman_glyph_t *      glyphs);
+						       const pixman_glyph_t *glyphs);
 void                  pixman_composite_glyphs         (pixman_op_t           op,
 						       pixman_image_t       *src,
 						       pixman_image_t       *dest,
 						       pixman_format_code_t  mask_format,
 						       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_glyph_cache_t *cache,
 						       int		     n_glyphs,
-						       pixman_glyph_t       *glyphs);
+						       const pixman_glyph_t *glyphs);
 void                  pixman_composite_glyphs_no_mask (pixman_op_t           op,
 						       pixman_image_t       *src,
 						       pixman_image_t       *dest,
 						       int32_t               src_x,
 						       int32_t               src_y,
 						       int32_t               dest_x,
 						       int32_t               dest_y,
 						       pixman_glyph_cache_t *cache,
 						       int		     n_glyphs,
-						       pixman_glyph_t       *glyphs);
+						       const pixman_glyph_t *glyphs);
 
 /*
  * Trapezoids
  */
 typedef struct pixman_edge pixman_edge_t;
 typedef struct pixman_trapezoid pixman_trapezoid_t;
 typedef struct pixman_trap pixman_trap_t;
 typedef struct pixman_span_fix pixman_span_fix_t;
@@ -1011,17 +1016,17 @@ void           pixman_rasterize_edges   
 					    pixman_edge_t             *l,
 					    pixman_edge_t             *r,
 					    pixman_fixed_t             t,
 					    pixman_fixed_t             b);
 void           pixman_add_traps            (pixman_image_t            *image,
 					    int16_t                    x_off,
 					    int16_t                    y_off,
 					    int                        ntrap,
-					    pixman_trap_t             *traps);
+					    const pixman_trap_t       *traps);
 void           pixman_add_trapezoids       (pixman_image_t            *image,
 					    int16_t                    x_off,
 					    int                        y_off,
 					    int                        ntraps,
 					    const pixman_trapezoid_t  *traps);
 void           pixman_rasterize_trapezoid  (pixman_image_t            *image,
 					    const pixman_trapezoid_t  *trap,
 					    int                        x_off,