pixman: Branch 'master' - 31 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Tue Sep 21 05:54:49 PDT 2010


 configure.ac               |   29 +
 pixman/pixman-bits-image.c |  253 +++++++++++++++
 pixman/pixman-compiler.h   |    7 
 pixman/pixman-fast-path.h  |    2 
 pixman/pixman-general.c    |   54 +--
 pixman/pixman-image.c      |   44 ++
 pixman/pixman-private.h    |    9 
 pixman/pixman.c            |  103 +++---
 test/Makefile.am           |   17 -
 test/affine-test.c         |  261 ++++++++++++++++
 test/alphamap.c            |  243 +++++++++++++--
 test/blitters-test.c       |   15 
 test/composite-test.c      |    5 
 test/lowlevel-blt-bench.c  |  712 +++++++++++++++++++++++++++++++++++++++++++++
 test/utils.c               |  143 ++++++++-
 test/utils.h               |   19 +
 16 files changed, 1772 insertions(+), 144 deletions(-)

New commits:
commit 7cd4f2fa201c4dc846153c022423e3dced2cfb13
Author: Jonathan Morton <jonathan.morton at movial.com>
Date:   Fri Sep 17 17:52:23 2010 +0300

    Add a lowlevel blitter benchmark
    
    This test is a modified version of Siarhei's compositor throughput
    benchmark.  It's expanded with explicit reporting of memory bandwidth
    consumption for the M-test, and with an additional 8x8-random test
    intended to determine peak ops/sec capability.  There are also quite a
    lot more operations tested for.

diff --git a/test/Makefile.am b/test/Makefile.am
index ff851c9..119ba15 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -94,7 +94,14 @@ convolution_test_SOURCES = convolution-test.c $(GTK_UTILS)
 
 endif
 
-noinst_PROGRAMS = $(TESTPROGRAMS) $(TESTPROGRAMS_GTK)
+# Benchmarks
 
-TESTS = $(TESTPROGRAMS)
+BENCHMARKS =			\
+	lowlevel-blt-bench
+
+lowlevel_blt_bench_SOURCES = lowlevel-blt-bench.c utils.c utils.h
+lowlevel_blt_bench_LDADD = $(TEST_LDADD)
 
+noinst_PROGRAMS = $(TESTPROGRAMS) $(TESTPROGRAMS_GTK) $(BENCHMARKS)
+
+TESTS = $(TESTPROGRAMS)
diff --git a/test/lowlevel-blt-bench.c b/test/lowlevel-blt-bench.c
new file mode 100644
index 0000000..a313a0d
--- /dev/null
+++ b/test/lowlevel-blt-bench.c
@@ -0,0 +1,712 @@
+/*
+ * Copyright © 2009 Nokia Corporation
+ * Copyright © 2010 Movial Creative Technologies Oy
+ *
+ * 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.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pixman-private.h"
+#include "utils.h"
+
+#define SOLID_FLAG 1
+#define CA_FLAG    2
+
+#define L1CACHE_SIZE (8 * 1024)
+#define L2CACHE_SIZE (128 * 1024)
+
+#define WIDTH  1920
+#define HEIGHT 1080
+#define BUFSIZE (WIDTH * HEIGHT * 4)
+#define XWIDTH 256
+#define XHEIGHT 256
+#define TILEWIDTH 32
+#define TINYWIDTH 8
+
+#define EXCLUDE_OVERHEAD 1
+
+uint32_t *dst;
+uint32_t *src;
+uint32_t *mask;
+
+double bandwidth = 0;
+
+double
+bench_memcpy ()
+{
+    int64_t n = 0, total;
+    double  t1, t2;
+    int     x = 0;
+
+    t1 = gettime ();
+    while (1)
+    {
+	memcpy (dst, src, BUFSIZE - 64);
+	memcpy (src, dst, BUFSIZE - 64);
+	n += 4 * (BUFSIZE - 64);
+	t2 = gettime ();
+	if (t2 - t1 > 0.5)
+	    break;
+    }
+    n = total = n * 5;
+    t1 = gettime ();
+    while (n > 0)
+    {
+	if (++x >= 64)
+	    x = 0;
+	memcpy ((char *)dst + 1, (char *)src + x, BUFSIZE - 64);
+	memcpy ((char *)src + 1, (char *)dst + x, BUFSIZE - 64);
+	n -= 4 * (BUFSIZE - 64);
+    }
+    t2 = gettime ();
+    return (double)total / (t2 - t1);
+}
+
+static void
+pixman_image_composite_wrapper (pixman_implementation_t *impl,
+                                pixman_op_t              op,
+                                pixman_image_t *         src_image,
+                                pixman_image_t *         mask_image,
+                                pixman_image_t *         dst_image,
+                                int32_t                  src_x,
+                                int32_t                  src_y,
+                                int32_t                  mask_x,
+                                int32_t                  mask_y,
+                                int32_t                  dest_x,
+                                int32_t                  dest_y,
+                                int32_t                  width,
+                                int32_t                  height)
+{
+    pixman_image_composite (op, src_image, mask_image, dst_image, src_x,
+                            src_y, mask_x, mask_y, dest_x, dest_y, width, height);
+}
+
+static void
+pixman_image_composite_empty (pixman_implementation_t *impl,
+                              pixman_op_t              op,
+                              pixman_image_t *         src_image,
+                              pixman_image_t *         mask_image,
+                              pixman_image_t *         dst_image,
+                              int32_t                  src_x,
+                              int32_t                  src_y,
+                              int32_t                  mask_x,
+                              int32_t                  mask_y,
+                              int32_t                  dest_x,
+                              int32_t                  dest_y,
+                              int32_t                  width,
+                              int32_t                  height)
+{
+    pixman_image_composite (op, src_image, mask_image, dst_image, 0,
+                            0, 0, 0, 0, 0, 1, 1);
+}
+
+void
+noinline
+bench_L  (pixman_op_t              op,
+          pixman_image_t *         src_img,
+          pixman_image_t *         mask_img,
+          pixman_image_t *         dst_img,
+          int64_t                  n,
+          pixman_composite_func_t  func,
+          int                      width,
+          int                      lines_count)
+{
+    int64_t      i, j;
+    int          x = 0;
+    int          q = 0;
+    volatile int qx;
+
+    for (i = 0; i < n; i++)
+    {
+	/* touch destination buffer to fetch it into L1 cache */
+	for (j = 0; j < width + 64; j += 16) {
+	    q += dst[j];
+	    q += src[j];
+	}
+	if (++x >= 64)
+	    x = 0;
+	func (0, op, src_img, mask_img, dst_img, x, 0, x, 0, 63 - x, 0, width, lines_count);
+    }
+    qx = q;
+}
+
+void
+noinline
+bench_M (pixman_op_t              op,
+         pixman_image_t *         src_img,
+         pixman_image_t *         mask_img,
+         pixman_image_t *         dst_img,
+         int64_t                  n,
+         pixman_composite_func_t  func)
+{
+    int64_t i;
+    int     x = 0;
+
+    for (i = 0; i < n; i++)
+    {
+	if (++x >= 64)
+	    x = 0;
+	func (0, op, src_img, mask_img, dst_img, x, 0, x, 0, 1, 0, WIDTH - 64, HEIGHT);
+    }
+}
+
+double
+noinline
+bench_HT (pixman_op_t              op,
+          pixman_image_t *         src_img,
+          pixman_image_t *         mask_img,
+          pixman_image_t *         dst_img,
+          int64_t                  n,
+          pixman_composite_func_t  func)
+{
+    double  pix_cnt = 0;
+    int     x = 0;
+    int     y = 0;
+    int64_t i;
+
+    srand (0);
+    for (i = 0; i < n; i++)
+    {
+	int w = (rand () % (TILEWIDTH * 2)) + 1;
+	int h = (rand () % (TILEWIDTH * 2)) + 1;
+	if (x + w > WIDTH)
+	{
+	    x = 0;
+	    y += TILEWIDTH * 2;
+	}
+	if (y + h > HEIGHT)
+	{
+	    y = 0;
+	}
+	func (0, op, src_img, mask_img, dst_img, x, y, x, y, x, y, w, h);
+	x += w;
+	pix_cnt += w * h;
+    }
+    return pix_cnt;
+}
+
+double
+noinline
+bench_VT (pixman_op_t              op,
+          pixman_image_t *         src_img,
+          pixman_image_t *         mask_img,
+          pixman_image_t *         dst_img,
+          int64_t                  n,
+          pixman_composite_func_t  func)
+{
+    double  pix_cnt = 0;
+    int     x = 0;
+    int     y = 0;
+    int64_t i;
+
+    srand (0);
+    for (i = 0; i < n; i++)
+    {
+	int w = (rand () % (TILEWIDTH * 2)) + 1;
+	int h = (rand () % (TILEWIDTH * 2)) + 1;
+	if (y + h > HEIGHT)
+	{
+	    y = 0;
+	    x += TILEWIDTH * 2;
+	}
+	if (x + w > WIDTH)
+	{
+	    x = 0;
+	}
+	func (0, op, src_img, mask_img, dst_img, x, y, x, y, x, y, w, h);
+	y += h;
+	pix_cnt += w * h;
+    }
+    return pix_cnt;
+}
+
+double
+noinline
+bench_R (pixman_op_t              op,
+         pixman_image_t *         src_img,
+         pixman_image_t *         mask_img,
+         pixman_image_t *         dst_img,
+         int64_t                  n,
+         pixman_composite_func_t  func,
+         int                      maxw,
+         int                      maxh)
+{
+    double  pix_cnt = 0;
+    int64_t i;
+
+    if (maxw <= TILEWIDTH * 2 || maxh <= TILEWIDTH * 2)
+    {
+	printf("error: maxw <= TILEWIDTH * 2 || maxh <= TILEWIDTH * 2\n");
+        return 0;
+    }
+
+    srand (0);
+    for (i = 0; i < n; i++)
+    {
+	int w = (rand () % (TILEWIDTH * 2)) + 1;
+	int h = (rand () % (TILEWIDTH * 2)) + 1;
+	int sx = rand () % (maxw - TILEWIDTH * 2);
+	int sy = rand () % (maxh - TILEWIDTH * 2);
+	int dx = rand () % (maxw - TILEWIDTH * 2);
+	int dy = rand () % (maxh - TILEWIDTH * 2);
+	func (0, op, src_img, mask_img, dst_img, sx, sy, sx, sy, dx, dy, w, h);
+	pix_cnt += w * h;
+    }
+    return pix_cnt;
+}
+
+double
+noinline
+bench_RT (pixman_op_t              op,
+          pixman_image_t *         src_img,
+          pixman_image_t *         mask_img,
+          pixman_image_t *         dst_img,
+          int64_t                  n,
+          pixman_composite_func_t  func,
+          int                      maxw,
+          int                      maxh)
+{
+    double  pix_cnt = 0;
+    int64_t i;
+
+    if (maxw <= TINYWIDTH * 2 || maxh <= TINYWIDTH * 2)
+    {
+	printf("error: maxw <= TINYWIDTH * 2 || maxh <= TINYWIDTH * 2\n");
+        return 0;
+    }
+
+    srand (0);
+    for (i = 0; i < n; i++)
+    {
+	int w = (rand () % (TINYWIDTH * 2)) + 1;
+	int h = (rand () % (TINYWIDTH * 2)) + 1;
+	int sx = rand () % (maxw - TINYWIDTH * 2);
+	int sy = rand () % (maxh - TINYWIDTH * 2);
+	int dx = rand () % (maxw - TINYWIDTH * 2);
+	int dy = rand () % (maxh - TINYWIDTH * 2);
+	func (0, op, src_img, mask_img, dst_img, sx, sy, sx, sy, dx, dy, w, h);
+	pix_cnt += w * h;
+    }
+    return pix_cnt;
+}
+
+void
+bench_composite (char * testname,
+                 int    src_fmt,
+                 int    src_flags,
+                 int    op,
+                 int    mask_fmt,
+                 int    mask_flags,
+                 int    dst_fmt,
+                 double npix)
+{
+    pixman_image_t *                src_img;
+    pixman_image_t *                dst_img;
+    pixman_image_t *                mask_img;
+    pixman_image_t *                xsrc_img;
+    pixman_image_t *                xdst_img;
+    pixman_image_t *                xmask_img;
+    double                          t1, t2, t3, pix_cnt;
+    int64_t                         n, l1test_width, nlines;
+    double                             bytes_per_pix = 0;
+
+    pixman_composite_func_t func = pixman_image_composite_wrapper;
+
+    if (!(src_flags & SOLID_FLAG))
+    {
+        bytes_per_pix += (src_fmt >> 24) / 8.0;
+        src_img = pixman_image_create_bits (src_fmt,
+                                            WIDTH, HEIGHT,
+                                            src,
+                                            WIDTH * 4);
+        xsrc_img = pixman_image_create_bits (src_fmt,
+                                             XWIDTH, XHEIGHT,
+                                             src,
+                                             XWIDTH * 4);
+    }
+    else
+    {
+        src_img = pixman_image_create_bits (src_fmt,
+                                            1, 1,
+                                            src,
+                                            4);
+        xsrc_img = pixman_image_create_bits (src_fmt,
+                                             1, 1,
+                                             src,
+                                             4);
+        pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
+        pixman_image_set_repeat (xsrc_img, PIXMAN_REPEAT_NORMAL);
+    }
+
+    bytes_per_pix += (dst_fmt >> 24) / 8.0;
+    dst_img = pixman_image_create_bits (dst_fmt,
+                                        WIDTH, HEIGHT,
+                                        dst,
+                                        WIDTH * 4);
+
+    mask_img = NULL;
+    xmask_img = NULL;
+    if (!(mask_flags & SOLID_FLAG) && mask_fmt != PIXMAN_null)
+    {
+        bytes_per_pix += (mask_fmt >> 24) / ((op == PIXMAN_OP_SRC) ? 8.0 : 4.0);
+        mask_img = pixman_image_create_bits (mask_fmt,
+                                             WIDTH, HEIGHT,
+                                             mask,
+                                             WIDTH * 4);
+        xmask_img = pixman_image_create_bits (mask_fmt,
+                                             XWIDTH, XHEIGHT,
+                                             mask,
+                                             XWIDTH * 4);
+    }
+    else if (mask_fmt != PIXMAN_null)
+    {
+        mask_img = pixman_image_create_bits (mask_fmt,
+                                             1, 1,
+                                             mask,
+                                             4);
+        xmask_img = pixman_image_create_bits (mask_fmt,
+                                             1, 1,
+                                             mask,
+                                             4 * 4);
+       pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
+       pixman_image_set_repeat (xmask_img, PIXMAN_REPEAT_NORMAL);
+    }
+    if ((mask_flags & CA_FLAG) && mask_fmt != PIXMAN_null)
+    {
+       pixman_image_set_component_alpha (mask_img, 1);
+    }
+    xdst_img = pixman_image_create_bits (dst_fmt,
+                                         XWIDTH, XHEIGHT,
+                                         dst,
+                                         XWIDTH * 4);
+
+
+    printf ("%24s %c", testname, func != pixman_image_composite_wrapper ?
+            '-' : '=');
+
+    memcpy (src, dst, BUFSIZE);
+    memcpy (dst, src, BUFSIZE);
+
+    l1test_width = L1CACHE_SIZE / 8 - 64;
+    if (l1test_width < 1)
+	l1test_width = 1;
+    if (l1test_width > WIDTH - 64)
+	l1test_width = WIDTH - 64;
+    n = 1 + npix / (l1test_width * 8);
+    t1 = gettime ();
+#if EXCLUDE_OVERHEAD
+    bench_L (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, l1test_width, 1);
+#endif
+    t2 = gettime ();
+    bench_L (op, src_img, mask_img, dst_img, n, func, l1test_width, 1);
+    t3 = gettime ();
+    printf ("  L1:%7.2f", (double)n * l1test_width * 1 /
+            ((t3 - t2) - (t2 - t1)) / 1000000.);
+    fflush (stdout);
+
+    memcpy (src, dst, BUFSIZE);
+    memcpy (dst, src, BUFSIZE);
+
+    nlines = (L2CACHE_SIZE / l1test_width) /
+	((PIXMAN_FORMAT_BPP(src_fmt) + PIXMAN_FORMAT_BPP(dst_fmt)) / 8);
+    if (nlines < 1)
+	nlines = 1;
+    n = 1 + npix / (l1test_width * nlines);
+    t1 = gettime ();
+#if EXCLUDE_OVERHEAD
+    bench_L (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, l1test_width, nlines);
+#endif
+    t2 = gettime ();
+    bench_L (op, src_img, mask_img, dst_img, n, func, l1test_width, nlines);
+    t3 = gettime ();
+    printf ("  L2:%7.2f", (double)n * l1test_width * nlines /
+            ((t3 - t2) - (t2 - t1)) / 1000000.);
+    fflush (stdout);
+
+    memcpy (src, dst, BUFSIZE);
+    memcpy (dst, src, BUFSIZE);
+
+    n = 1 + npix / (WIDTH * HEIGHT);
+    t1 = gettime ();
+#if EXCLUDE_OVERHEAD
+    bench_M (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty);
+#endif
+    t2 = gettime ();
+    bench_M (op, src_img, mask_img, dst_img, n, func);
+    t3 = gettime ();
+    printf ("  M:%6.2f (%6.2f%%)",
+        ((double)n * (WIDTH - 64) * HEIGHT / ((t3 - t2) - (t2 - t1))) / 1000000.,
+        ((double)n * (WIDTH - 64) * HEIGHT / ((t3 - t2) - (t2 - t1)) * bytes_per_pix) * (100.0 / bandwidth) );
+    fflush (stdout);
+
+    memcpy (src, dst, BUFSIZE);
+    memcpy (dst, src, BUFSIZE);
+
+    n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
+    t1 = gettime ();
+#if EXCLUDE_OVERHEAD
+    pix_cnt = bench_HT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty);
+#endif
+    t2 = gettime ();
+    pix_cnt = bench_HT (op, src_img, mask_img, dst_img, n, func);
+    t3 = gettime ();
+    printf ("  HT:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.);
+    fflush (stdout);
+
+    memcpy (src, dst, BUFSIZE);
+    memcpy (dst, src, BUFSIZE);
+
+    n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
+    t1 = gettime ();
+#if EXCLUDE_OVERHEAD
+    pix_cnt = bench_VT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty);
+#endif
+    t2 = gettime ();
+    pix_cnt = bench_VT (op, src_img, mask_img, dst_img, n, func);
+    t3 = gettime ();
+    printf ("  VT:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.);
+    fflush (stdout);
+
+    memcpy (src, dst, BUFSIZE);
+    memcpy (dst, src, BUFSIZE);
+
+    n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
+    t1 = gettime ();
+#if EXCLUDE_OVERHEAD
+    pix_cnt = bench_R (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, WIDTH, HEIGHT);
+#endif
+    t2 = gettime ();
+    pix_cnt = bench_R (op, src_img, mask_img, dst_img, n, func, WIDTH, HEIGHT);
+    t3 = gettime ();
+    printf ("  R:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.);
+    fflush (stdout);
+
+    memcpy (src, dst, BUFSIZE);
+    memcpy (dst, src, BUFSIZE);
+
+    n = 1 + npix / (16 * TINYWIDTH * TINYWIDTH);
+    t1 = gettime ();
+#if EXCLUDE_OVERHEAD
+    pix_cnt = bench_RT (op, src_img, mask_img, dst_img, n, pixman_image_composite_empty, WIDTH, HEIGHT);
+#endif
+    t2 = gettime ();
+    pix_cnt = bench_RT (op, src_img, mask_img, dst_img, n, func, WIDTH, HEIGHT);
+    t3 = gettime ();
+    printf ("  RT:%6.2f (%4.0fKops/s)\n", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000., (double) n / ((t3 - t2) * 1000));
+
+    if (mask_img) {
+	pixman_image_unref (mask_img);
+	pixman_image_unref (xmask_img);
+    }
+    pixman_image_unref (src_img);
+    pixman_image_unref (dst_img);
+    pixman_image_unref (xsrc_img);
+    pixman_image_unref (xdst_img);
+}
+
+#define PIXMAN_OP_OUT_REV (PIXMAN_OP_OUT_REVERSE)
+
+struct
+{
+    char *testname;
+    int   src_fmt;
+    int   src_flags;
+    int   op;
+    int   mask_fmt;
+    int   mask_flags;
+    int   dst_fmt;
+}
+tests_tbl[] =
+{
+    { "add_8_8_8",             PIXMAN_a8,          0, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a8 },
+    { "add_n_8_8000",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a8 },
+    { "add_n_8_8888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
+    { "add_n_8_x888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
+    { "add_n_8_0565",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
+    { "add_n_8_1555",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
+    { "add_n_8_4444",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a4r4g4b4 },
+    { "add_n_8_2222",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a2r2g2b2 },
+    { "add_n_8_2x10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_x2r10g10b10 },
+    { "add_n_8_2a10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_a8,       0, PIXMAN_a2r10g10b10 },
+    { "add_n_8000",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8 },
+    { "add_n_8888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
+    { "add_n_x888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
+    { "add_n_0565",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
+    { "add_n_1555",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
+    { "add_n_4444",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
+    { "add_n_2222",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
+    { "add_n_2x10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
+    { "add_n_2a10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
+    { "add_8000_8000",         PIXMAN_a8,          0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8 },
+    { "add_x888_x888",         PIXMAN_x8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
+    { "add_8888_8888",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
+    { "add_8888_0565",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
+    { "add_8888_1555",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
+    { "add_8888_4444",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
+    { "add_8888_2222",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
+    { "add_0565_0565",         PIXMAN_r5g6b5,      0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
+    { "add_1555_1555",         PIXMAN_a1r5g5b5,    0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
+    { "add_0565_2x10",         PIXMAN_r5g6b5,      0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
+    { "add_2a10_2a10",         PIXMAN_a2r10g10b10, 0, PIXMAN_OP_ADD,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
+    { "src_n_2222",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
+    { "src_n_0565",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
+    { "src_n_1555",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
+    { "src_n_4444",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
+    { "src_n_x888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
+    { "src_n_8888",            PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
+    { "src_n_2x10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
+    { "src_n_2a10",            PIXMAN_a2r10g10b10, 1, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
+    { "src_8888_0565",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
+    { "src_8888_4444",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a4r4g4b4 },
+    { "src_8888_2222",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r2g2b2 },
+    { "src_8888_2x10",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x2r10g10b10 },
+    { "src_8888_2a10",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a2r10g10b10 },
+    { "src_0888_0565",         PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
+    { "src_0888_8888",         PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
+    { "src_0888_x888",         PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
+    { "src_x888_x888",         PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
+    { "src_x888_8888",         PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
+    { "src_8888_8888",         PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
+    { "src_0565_0565",         PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
+    { "src_1555_0565",         PIXMAN_a1r5g5b5,    0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_r5g6b5 },
+    { "src_0565_1555",         PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
+    { "src_n_8_0565",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
+    { "src_n_8_1555",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
+    { "src_n_8_4444",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a4r4g4b4 },
+    { "src_n_8_2222",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a2r2g2b2 },
+    { "src_n_8_x888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
+    { "src_n_8_8888",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
+    { "src_n_8_2x10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x2r10g10b10 },
+    { "src_n_8_2a10",          PIXMAN_a8r8g8b8,    1, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a2r10g10b10 },
+    { "src_8888_8_0565",       PIXMAN_a8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
+    { "src_0888_8_0565",       PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
+    { "src_0888_8_8888",       PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
+    { "src_0888_8_x888",       PIXMAN_r8g8b8,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
+    { "src_x888_8_x888",       PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
+    { "src_x888_8_8888",       PIXMAN_x8r8g8b8,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
+    { "src_0565_8_0565",       PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
+    { "src_1555_8_0565",       PIXMAN_a1r5g5b5,    0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_r5g6b5 },
+    { "src_0565_8_1555",       PIXMAN_r5g6b5,      0, PIXMAN_OP_SRC,     PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
+    { "over_n_x888",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
+    { "over_n_8888",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_a8r8g8b8 },
+    { "over_n_0565",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_r5g6b5 },
+    { "over_n_1555",           PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_a1r5g5b5 },
+    { "over_8888_0565",        PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_r5g6b5 },
+    { "over_8888_x888",        PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_null,     0, PIXMAN_x8r8g8b8 },
+    { "over_n_8_0565",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_r5g6b5 },
+    { "over_n_8_1555",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
+    { "over_n_8_4444",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a4r4g4b4 },
+    { "over_n_8_2222",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a2r2g2b2 },
+    { "over_n_8_x888",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
+    { "over_n_8_8888",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
+    { "over_n_8_2x10",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_x2r10g10b10 },
+    { "over_n_8_2a10",         PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8,       0, PIXMAN_a2r10g10b10 },
+    { "over_n_8888_8888_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a8r8g8b8 },
+    { "over_n_8888_x888_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_x8r8g8b8 },
+    { "over_n_8888_0565_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_r5g6b5 },
+    { "over_n_8888_1555_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a1r5g5b5 },
+    { "over_n_8888_4444_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a4r4g4b4 },
+    { "over_n_8888_2222_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a2r2g2b2 },
+    { "over_n_8888_2x10_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_x2r10g10b10 },
+    { "over_n_8888_2a10_ca",   PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OVER,    PIXMAN_a8r8g8b8, 2, PIXMAN_a2r10g10b10 },
+    { "over_8888_n_8888",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_a8r8g8b8 },
+    { "over_8888_n_x888",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_x8r8g8b8 },
+    { "over_8888_n_0565",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_r5g6b5 },
+    { "over_8888_n_1555",      PIXMAN_a8r8g8b8,    0, PIXMAN_OP_OVER,    PIXMAN_a8,       1, PIXMAN_a1r5g5b5 },
+    { "outrev_n_8_0565",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_r5g6b5 },
+    { "outrev_n_8_1555",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_a1r5g5b5 },
+    { "outrev_n_8_x888",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_x8r8g8b8 },
+    { "outrev_n_8_8888",       PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8,       0, PIXMAN_a8r8g8b8 },
+    { "outrev_n_8888_0565_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_r5g6b5 },
+    { "outrev_n_8888_1555_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_a1r5g5b5 },
+    { "outrev_n_8888_x888_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_x8r8g8b8 },
+    { "outrev_n_8888_8888_ca", PIXMAN_a8r8g8b8,    1, PIXMAN_OP_OUT_REV, PIXMAN_a8r8g8b8, 2, PIXMAN_a8r8g8b8 },
+};
+
+int
+main (int argc, char *argv[])
+{
+    double x;
+    int i;
+    char *pattern = argc > 1 ? argv[1] : "all";
+
+    src = aligned_malloc (4096, BUFSIZE * 3);
+    memset (src, 0xCC, BUFSIZE * 3);
+    dst = src + (BUFSIZE / 4);
+    mask = dst + (BUFSIZE / 4);
+
+    printf ("Benchmark for a set of most commonly used functions\n");
+    printf ("---\n");
+    printf ("All results are presented in millions of pixels per second\n");
+    printf ("L1  - small Xx1 rectangle (fitting L1 cache), always blitted at the same\n");
+    printf ("      memory location with small drift in horizontal direction\n");
+    printf ("L2  - small XxY rectangle (fitting L2 cache), always blitted at the same\n");
+    printf ("      memory location with small drift in horizontal direction\n");
+    printf ("M   - large %dx%d rectangle, always blitted at the same\n",
+            WIDTH - 64, HEIGHT);
+    printf ("      memory location with small drift in horizontal direction\n");
+    printf ("HT  - random rectangles with %dx%d average size are copied from\n",
+            TILEWIDTH, TILEWIDTH);
+    printf ("      one %dx%d buffer to another, traversing from left to right\n",
+            WIDTH, HEIGHT);
+    printf ("      and from top to bottom\n");
+    printf ("VT  - random rectangles with %dx%d average size are copied from\n",
+            TILEWIDTH, TILEWIDTH);
+    printf ("      one %dx%d buffer to another, traversing from top to bottom\n",
+            WIDTH, HEIGHT);
+    printf ("      and from left to right\n");
+    printf ("R   - random rectangles with %dx%d average size are copied from\n",
+            TILEWIDTH, TILEWIDTH);
+    printf ("      random locations of one %dx%d buffer to another\n",
+            WIDTH, HEIGHT);
+    printf ("RT  - as R, but %dx%d average sized rectangles are copied\n",
+            TINYWIDTH, TINYWIDTH);
+    printf ("---\n");
+    bandwidth = x = bench_memcpy ();
+    printf ("reference memcpy speed = %.1fMB/s (%.1fMP/s for 32bpp fills)\n",
+            x / 1000000., x / 4000000);
+    printf ("---\n");
+
+    for (i = 0; i < sizeof(tests_tbl) / sizeof(tests_tbl[0]); i++)
+    {
+	if (strcmp (pattern, "all") == 0 || strstr (tests_tbl[i].testname, pattern))
+	{
+	    bench_composite (tests_tbl[i].testname,
+			     tests_tbl[i].src_fmt,
+			     tests_tbl[i].src_flags,
+			     tests_tbl[i].op,
+			     tests_tbl[i].mask_fmt,
+			     tests_tbl[i].mask_flags,
+			     tests_tbl[i].dst_fmt,
+			     bandwidth/8);
+	}
+    }
+
+    free (src);
+    return 0;
+}
commit eab3a77877b0e850c46f95dacffb31994e6a7e41
Author: Dmitri Vorobiev <dmitri.vorobiev at movial.com>
Date:   Fri Sep 17 17:52:22 2010 +0300

    Add noinline macro
    
    This patch adds a noinline macro, which expands to compiler-dependent
    keywords that tell the compiler to never inline a function.

diff --git a/pixman/pixman-compiler.h b/pixman/pixman-compiler.h
index 22b9fe7..8f6c787 100644
--- a/pixman/pixman-compiler.h
+++ b/pixman/pixman-compiler.h
@@ -50,13 +50,18 @@
 /* 'inline' is available only in C++ in MSVC */
 #   define inline __inline
 #   define force_inline __forceinline
+#   define noinline __declspec(noinline)
 #elif defined __GNUC__ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
 #   define inline __inline__
 #   define force_inline __inline__ __attribute__ ((__always_inline__))
+#   define noinline __attribute__((noinline))
 #else
 #   ifndef force_inline
 #      define force_inline inline
 #   endif
+#   ifndef noinline
+#      define noinline
+#   endif
 #endif
 
 /* GCC visibility */
commit cab3261c0da6e833d803a7f3ccab600adca7abe1
Author: Dmitri Vorobiev <dmitri.vorobiev at movial.com>
Date:   Fri Sep 17 17:52:21 2010 +0300

    Add gettime() routine to test utils
    
    Impending benchmark code will need a function to get current time
    in seconds, and this patch introduces such routine. We try to use
    the POSIX gettimeofday() function when available, and fall back to
    clock() when not.

diff --git a/configure.ac b/configure.ac
index 47213a0..4b38abd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -609,7 +609,7 @@ AC_SUBST(DEP_CFLAGS)
 AC_SUBST(DEP_LIBS)
 
 dnl =====================================
-dnl posix_memalign, sigaction, alarm
+dnl posix_memalign, sigaction, alarm, gettimeofday
 
 AC_CHECK_FUNC(posix_memalign, have_posix_memalign=yes, have_posix_memalign=no)
 if test x$have_posix_memalign = xyes; then
@@ -639,6 +639,12 @@ if test x$have_getpagesize = xyes; then
    AC_DEFINE(HAVE_GETPAGESIZE, 1, [Whether we have getpagesize()])
 fi
 
+AC_CHECK_FUNC(gettimeofday, have_gettimeofday=yes, have_gettimeofday=no)
+AC_CHECK_HEADER(sys/time.h, have_sys_time_h=yes, have_sys_time_h=no)
+if test x$have_gettimeofday = xyes && test x$have_sys_time_h = xyes; then
+   AC_DEFINE(HAVE_GETTIMEOFDAY, 1, [Whether we have gettimeofday()])
+fi
+
 dnl =====================================
 dnl Thread local storage
 
diff --git a/test/utils.c b/test/utils.c
index ccc637e..2cd763d 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -1,6 +1,12 @@
 #include "utils.h"
 #include <signal.h>
 
+#ifdef HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -431,6 +437,20 @@ fuzzer_test_main (const char *test_name,
     return 0;
 }
 
+/* Try to obtain current time in seconds */
+double
+gettime (void)
+{
+#ifdef HAVE_GETTIMEOFDAY
+    struct timeval tv;
+
+    gettimeofday (&tv, NULL);
+    return (double)((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.;
+#else
+    return (double)clock() / (double)CLOCKS_PER_SEC;
+#endif
+}
+
 static const char *global_msg;
 
 static void
diff --git a/test/utils.h b/test/utils.h
index 06cd857..e7920f0 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -64,6 +64,10 @@ fence_free (void *data);
 uint8_t *
 make_random_bytes (int n_bytes);
 
+/* Return current time in seconds */
+double
+gettime (void);
+
 /* main body of the fuzzer test */
 int
 fuzzer_test_main (const char *test_name,
commit fd3c87d460a6d1803880d17af416cce344a086c4
Author: Dmitri Vorobiev <dmitri.vorobiev at movial.com>
Date:   Fri Sep 17 17:52:20 2010 +0300

    Move aligned_malloc() to utils
    
    The aligned_malloc() routine will be used in more than one test utility.
    At least, a low-level blitter benchmark needs it. Therefore, let's make
    this function a part of common test utilities code.

diff --git a/test/blitters-test.c b/test/blitters-test.c
index 9dd9163..7ba80eb 100644
--- a/test/blitters-test.c
+++ b/test/blitters-test.c
@@ -14,21 +14,6 @@
 static pixman_indexed_t rgb_palette[9];
 static pixman_indexed_t y_palette[9];
 
-static void *
-aligned_malloc (size_t align, size_t size)
-{
-    void *result;
-
-#ifdef HAVE_POSIX_MEMALIGN
-    if (posix_memalign (&result, align, size) != 0)
-      result = NULL;
-#else
-    result = malloc (size);
-#endif
-
-    return result;
-}
-
 /* Create random image for testing purposes */
 static pixman_image_t *
 create_random_image (pixman_format_code_t *allowed_formats,
diff --git a/test/utils.c b/test/utils.c
index 580a51d..ccc637e 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -458,3 +458,18 @@ fail_after (int seconds, const char *msg)
 #endif
 #endif
 }
+
+void *
+aligned_malloc (size_t align, size_t size)
+{
+    void *result;
+
+#ifdef HAVE_POSIX_MEMALIGN
+    if (posix_memalign (&result, align, size) != 0)
+      result = NULL;
+#else
+    result = malloc (size);
+#endif
+
+    return result;
+}
diff --git a/test/utils.h b/test/utils.h
index 14e3c8b..06cd857 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -110,3 +110,7 @@ fail_after (int seconds, const char *msg);
     assert (frcd_canary_variable6 == frcd_volatile_constant6); \
     assert (frcd_canary_variable7 == frcd_volatile_constant7); \
     assert (frcd_canary_variable8 == frcd_volatile_constant8);
+
+/* Try to get an aligned memory chunk */
+void *
+aligned_malloc (size_t align, size_t size);
commit f474783607e51183d31814972d0f055907876079
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Sep 16 10:33:23 2010 -0400

    Enable bits_image_fetch_bilinear_affine_normal_r5g6b5

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 2094c2a..c878250 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -961,9 +961,7 @@ MAKE_BILINEAR_FETCHER (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT);
-#if 0
 MAKE_BILINEAR_FETCHER (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL);
-#endif
 
 static void
 bits_image_fetch_solid_32 (pixman_image_t * image,
@@ -1199,9 +1197,7 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (pad_r5g6b5, r5g6b5, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_r5g6b5, r5g6b5, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_r5g6b5, r5g6b5, REFLECT)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (normal_r5g6b5, r5g6b5, NORMAL)
-#endif
 
     /* Affine, no alpha */
     { PIXMAN_any,
commit 91521d30ab9b033a35fb7797e4566d575ad1c1dc
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Sep 16 10:33:10 2010 -0400

    Enable bits_image_fetch_bilinear_affine_reflect_r5g6b5

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 19f2274..2094c2a 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -960,8 +960,8 @@ MAKE_BILINEAR_FETCHER (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE);
-#if 0
 MAKE_BILINEAR_FETCHER (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT);
+#if 0
 MAKE_BILINEAR_FETCHER (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL);
 #endif
 
@@ -1198,8 +1198,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (normal_a8, a8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_r5g6b5, r5g6b5, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_r5g6b5, r5g6b5, NONE)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (reflect_r5g6b5, r5g6b5, REFLECT)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (normal_r5g6b5, r5g6b5, NORMAL)
 #endif
 
commit 372d7b954aee4f3a2ad94ed8484a2b4084db0c7c
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Sep 16 10:33:00 2010 -0400

    Enable bits_image_fetch_bilinear_affine_none_r5g6b5

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index cf94484..19f2274 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -959,8 +959,8 @@ MAKE_BILINEAR_FETCHER (none_a8,          a8,       PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD);
-#if 0
 MAKE_BILINEAR_FETCHER (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE);
+#if 0
 MAKE_BILINEAR_FETCHER (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL);
 #endif
@@ -1197,8 +1197,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (reflect_a8, a8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_a8, a8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_r5g6b5, r5g6b5, PAD)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (none_r5g6b5, r5g6b5, NONE)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (reflect_r5g6b5, r5g6b5, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_r5g6b5, r5g6b5, NORMAL)
 #endif
commit a826ae0e3a0279557e892856ef1333971b105d01
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Sep 16 10:32:44 2010 -0400

    Enable bits_image_fetch_bilinear_affine_pad_r5g6b5

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 5a45c1a..cf94484 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -958,8 +958,8 @@ MAKE_BILINEAR_FETCHER (pad_a8,           a8,       PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_a8,          a8,       PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL);
-#if 0
 MAKE_BILINEAR_FETCHER (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD);
+#if 0
 MAKE_BILINEAR_FETCHER (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL);
@@ -1196,8 +1196,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (none_a8, a8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_a8, a8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_a8, a8, NORMAL)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (pad_r5g6b5, r5g6b5, PAD)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (none_r5g6b5, r5g6b5, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_r5g6b5, r5g6b5, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_r5g6b5, r5g6b5, NORMAL)
commit c5238bd1809433af5b0efc3add23c1ccb4da884c
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Sep 16 10:32:27 2010 -0400

    Enable bits_image_fetch_bilinear_affine_normal_a8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 42677f7..5a45c1a 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -957,8 +957,8 @@ MAKE_BILINEAR_FETCHER (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_a8,           a8,       PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_a8,          a8,       PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT);
-#if 0
 MAKE_BILINEAR_FETCHER (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL);
+#if 0
 MAKE_BILINEAR_FETCHER (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT);
@@ -1195,8 +1195,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (pad_a8, a8, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_a8, a8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_a8, a8, REFLECT)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (normal_a8, a8, NORMAL)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (pad_r5g6b5, r5g6b5, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_r5g6b5, r5g6b5, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_r5g6b5, r5g6b5, REFLECT)
commit d12daefcdb8845e539309df46b08916829a86d9c
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Sep 16 10:32:12 2010 -0400

    Enable bits_image_fetch_bilinear_affine_reflect_a8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 12b683b..42677f7 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -956,8 +956,8 @@ MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_a8,           a8,       PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_a8,          a8,       PIXMAN_REPEAT_NONE);
-#if 0
 MAKE_BILINEAR_FETCHER (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT);
+#if 0
 MAKE_BILINEAR_FETCHER (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE);
@@ -1194,8 +1194,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (normal_x8r8g8b8, x8r8g8b8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_a8, a8, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_a8, a8, NONE)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (reflect_a8, a8, REFLECT)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (normal_a8, a8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_r5g6b5, r5g6b5, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_r5g6b5, r5g6b5, NONE)
commit 9388be32932898ed424c8916a57a6201f995416b
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Sep 16 10:31:57 2010 -0400

    Enable bits_image_fetch_bilinear_affine_none_a8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 90cab34..12b683b 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -955,8 +955,8 @@ MAKE_BILINEAR_FETCHER (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_a8,           a8,       PIXMAN_REPEAT_PAD);
-#if 0
 MAKE_BILINEAR_FETCHER (none_a8,          a8,       PIXMAN_REPEAT_NONE);
+#if 0
 MAKE_BILINEAR_FETCHER (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD);
@@ -1193,8 +1193,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_x8r8g8b8, x8r8g8b8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_a8, a8, PAD)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (none_a8, a8, NONE)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (reflect_a8, a8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_a8, a8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_r5g6b5, r5g6b5, PAD)
commit 8e4d4e8d110c379cb85f53752660c6b2fab33d5e
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Sep 16 10:31:45 2010 -0400

    Enable bits_image_fetch_bilinear_affine_pad_a8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 47e16df..90cab34 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -954,8 +954,8 @@ MAKE_BILINEAR_FETCHER (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL);
-#if 0
 MAKE_BILINEAR_FETCHER (pad_a8,           a8,       PIXMAN_REPEAT_PAD);
+#if 0
 MAKE_BILINEAR_FETCHER (none_a8,          a8,       PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL);
@@ -1192,8 +1192,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (none_x8r8g8b8, x8r8g8b8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_x8r8g8b8, x8r8g8b8, NORMAL)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (pad_a8, a8, PAD)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (none_a8, a8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_a8, a8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_a8, a8, NORMAL)
commit ce1f6c50b4ddf8f7c48a3b272c19d281beca4b34
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Aug 28 02:41:20 2010 -0400

    Enable bits_image_fetch_bilinear_affine_normal_x8r8g8b8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 619726e..47e16df 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -953,8 +953,8 @@ MAKE_BILINEAR_FETCHER (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
-#if 0
 MAKE_BILINEAR_FETCHER (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL);
+#if 0
 MAKE_BILINEAR_FETCHER (pad_a8,           a8,       PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_a8,          a8,       PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT);
@@ -1191,8 +1191,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (pad_x8r8g8b8, x8r8g8b8, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_x8r8g8b8, x8r8g8b8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (normal_x8r8g8b8, x8r8g8b8, NORMAL)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (pad_a8, a8, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_a8, a8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_a8, a8, REFLECT)
commit 83f2ee3e958a02fc85a2dc6eddc048b63d74cd5c
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Aug 28 02:41:08 2010 -0400

    Enable bits_image_fetch_bilinear_affine_reflect_x8r8g8b8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 4d32dea..619726e 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -952,8 +952,8 @@ MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE);
-#if 0
 MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
+#if 0
 MAKE_BILINEAR_FETCHER (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_a8,           a8,       PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_a8,          a8,       PIXMAN_REPEAT_NONE);
@@ -1190,8 +1190,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (normal_a8r8g8b8, a8r8g8b8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_x8r8g8b8, x8r8g8b8, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_x8r8g8b8, x8r8g8b8, NONE)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (normal_x8r8g8b8, x8r8g8b8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_a8, a8, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_a8, a8, NONE)
commit be37ae331c6e5e9539b0c1eac6e196366532df29
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Aug 28 02:40:56 2010 -0400

    Enable bits_image_fetch_bilinear_affine_none_x8r8g8b8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 3953b1e..4d32dea 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -951,8 +951,8 @@ MAKE_BILINEAR_FETCHER (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD);
-#if 0
 MAKE_BILINEAR_FETCHER (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE);
+#if 0
 MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_a8,           a8,       PIXMAN_REPEAT_PAD);
@@ -1189,8 +1189,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_a8r8g8b8, a8r8g8b8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_x8r8g8b8, x8r8g8b8, PAD)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (none_x8r8g8b8, x8r8g8b8, NONE)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_x8r8g8b8, x8r8g8b8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_a8, a8, PAD)
commit 5f8a9bebc04deb55de79e7443578779a93b8cfa6
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Aug 28 02:40:46 2010 -0400

    Enable bits_image_fetch_bilinear_affine_pad_x8r8g8b8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 0f33421..3953b1e 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -950,8 +950,8 @@ MAKE_BILINEAR_FETCHER (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL);
-#if 0
 MAKE_BILINEAR_FETCHER (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD);
+#if 0
 MAKE_BILINEAR_FETCHER (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL);
@@ -1188,8 +1188,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (none_a8r8g8b8, a8r8g8b8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_a8r8g8b8, a8r8g8b8, NORMAL)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (pad_x8r8g8b8, x8r8g8b8, PAD)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (none_x8r8g8b8, x8r8g8b8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_x8r8g8b8, x8r8g8b8, NORMAL)
commit c59584cb862ef8774a2ef1eabb87fef18506d10f
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Aug 28 02:40:16 2010 -0400

    Enable bits_image_fetch_bilinear_affine_normal_a8r8g8b8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 1b6b84d..0f33421 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -949,8 +949,8 @@ convert_r5g6b5 (const uint8_t *row, int x)
 MAKE_BILINEAR_FETCHER (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT);
-#if 0
 MAKE_BILINEAR_FETCHER (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL);
+#if 0
 MAKE_BILINEAR_FETCHER (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
@@ -1187,8 +1187,8 @@ static const fetcher_info_t fetcher_info[] =
     BILINEAR_AFFINE_FAST_PATH (pad_a8r8g8b8, a8r8g8b8, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_a8r8g8b8, a8r8g8b8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (normal_a8r8g8b8, a8r8g8b8, NORMAL)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (pad_x8r8g8b8, x8r8g8b8, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_x8r8g8b8, x8r8g8b8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
commit 2292cff304fd5aad6dbcc86342a57ea523136de6
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Aug 28 02:40:03 2010 -0400

    Enable bits_image_fetch_bilinear_affine_reflect_a8r8g8b8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 6e4e894..1b6b84d 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -948,8 +948,8 @@ convert_r5g6b5 (const uint8_t *row, int x)
 
 MAKE_BILINEAR_FETCHER (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE);
-#if 0
 MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT);
+#if 0
 MAKE_BILINEAR_FETCHER (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD);
 MAKE_BILINEAR_FETCHER (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE);
@@ -1186,8 +1186,8 @@ static const fetcher_info_t fetcher_info[] =
 
     BILINEAR_AFFINE_FAST_PATH (pad_a8r8g8b8, a8r8g8b8, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_a8r8g8b8, a8r8g8b8, NONE)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (normal_a8r8g8b8, a8r8g8b8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_x8r8g8b8, x8r8g8b8, PAD)
     BILINEAR_AFFINE_FAST_PATH (none_x8r8g8b8, x8r8g8b8, NONE)
commit 8b29162693adc30dbb5c0f60098d2853c3942c36
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Aug 28 02:39:51 2010 -0400

    Enable bits_image_fetch_bilinear_affine_none_a8r8g8b8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 0490856..6e4e894 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -947,8 +947,8 @@ convert_r5g6b5 (const uint8_t *row, int x)
     }
 
 MAKE_BILINEAR_FETCHER (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD);
-#if 0
 MAKE_BILINEAR_FETCHER (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE);
+#if 0
 MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL);
 MAKE_BILINEAR_FETCHER (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD);
@@ -1185,8 +1185,8 @@ static const fetcher_info_t fetcher_info[] =
     },
 
     BILINEAR_AFFINE_FAST_PATH (pad_a8r8g8b8, a8r8g8b8, PAD)
-#if 0
     BILINEAR_AFFINE_FAST_PATH (none_a8r8g8b8, a8r8g8b8, NONE)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_a8r8g8b8, a8r8g8b8, NORMAL)
     BILINEAR_AFFINE_FAST_PATH (pad_x8r8g8b8, x8r8g8b8, PAD)
commit e8555874e122f6e113f85e37059932457ee509cb
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Aug 28 02:39:37 2010 -0400

    Enable bits_image_fetch_bilinear_affine_pad_a8r8g8b8

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 98dc28a..0490856 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -946,8 +946,8 @@ convert_r5g6b5 (const uint8_t *row, int x)
 					  repeat_mode);			\
     }
 
-#if 0
 MAKE_BILINEAR_FETCHER (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD);
+#if 0
 MAKE_BILINEAR_FETCHER (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE);
 MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT);
 MAKE_BILINEAR_FETCHER (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL);
@@ -1184,8 +1184,8 @@ static const fetcher_info_t fetcher_info[] =
       _pixman_image_get_scanline_generic_64				\
     },
 
-#if 0
     BILINEAR_AFFINE_FAST_PATH (pad_a8r8g8b8, a8r8g8b8, PAD)
+#if 0
     BILINEAR_AFFINE_FAST_PATH (none_a8r8g8b8, a8r8g8b8, NONE)
     BILINEAR_AFFINE_FAST_PATH (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
     BILINEAR_AFFINE_FAST_PATH (normal_a8r8g8b8, a8r8g8b8, NORMAL)
commit f9778c15e9c01c02e0002edfc4d4a1d517d14d87
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sun May 23 04:44:33 2010 -0400

    Use a macro to generate some {a,x}8r8g8b8, a8, and r5g6b5 bilinear fetchers.
    
    There are versions for all combinations of x8r8g8b8/a8r8g8b8 and
    pad/repeat/none/normal repeat modes. The bulk of each scaler is an
    inline function that takes a format and a repeat mode as parameters.
    
    The new scalers are all commented out, but the next commits will
    enable them one at a time to facilitate bisecting.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index a32ebcc..98dc28a 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -637,7 +637,7 @@ bits_image_fetch_affine_no_alpha (pixman_image_t * image,
 	    buffer[i] = bits_image_fetch_pixel_filtered (
 		&image->bits, x, y, fetch_pixel_no_alpha);
 	}
-	
+
 	x += ux;
 	y += uy;
     }
@@ -749,6 +749,222 @@ bits_image_fetch_general (pixman_image_t * image,
     }
 }
 
+static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
+
+static force_inline void
+bits_image_fetch_bilinear_affine (pixman_image_t * image,
+				  int              offset,
+				  int              line,
+				  int              width,
+				  uint32_t *       buffer,
+				  const uint32_t * mask,
+
+				  convert_pixel_t	convert_pixel,
+				  pixman_format_code_t	format,
+				  pixman_repeat_t	repeat_mode)
+{
+    pixman_fixed_t x, y;
+    pixman_fixed_t ux, uy;
+    pixman_vector_t v;
+    bits_image_t *bits = &image->bits;
+    int i;
+
+    /* reference point is the center of the pixel */
+    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
+    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
+    v.vector[2] = pixman_fixed_1;
+
+    if (!pixman_transform_point_3d (image->common.transform, &v))
+	return;
+
+    ux = image->common.transform->matrix[0][0];
+    uy = image->common.transform->matrix[1][0];
+
+    x = v.vector[0];
+    y = v.vector[1];
+
+    for (i = 0; i < width; ++i)
+    {
+	int x1, y1, x2, y2;
+	uint32_t tl, tr, bl, br;
+	int32_t distx, disty;
+	int width = image->bits.width;
+	int height = image->bits.height;
+	const uint8_t *row1;
+	const uint8_t *row2;
+
+	if (mask && !mask[i])
+	    goto next;
+
+	x1 = x - pixman_fixed_1 / 2;
+	y1 = y - pixman_fixed_1 / 2;
+
+	distx = (x1 >> 8) & 0xff;
+	disty = (y1 >> 8) & 0xff;
+
+	y1 = pixman_fixed_to_int (y1);
+	y2 = y1 + 1;
+	x1 = pixman_fixed_to_int (x1);
+	x2 = x1 + 1;
+
+	if (repeat_mode != PIXMAN_REPEAT_NONE)
+	{
+	    uint32_t mask;
+
+	    mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
+
+	    repeat (repeat_mode, width, &x1);
+	    repeat (repeat_mode, height, &y1);
+	    repeat (repeat_mode, width, &x2);
+	    repeat (repeat_mode, height, &y2);
+
+	    row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
+	    row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
+
+	    tl = convert_pixel (row1, x1) | mask;
+	    tr = convert_pixel (row1, x2) | mask;
+	    bl = convert_pixel (row2, x1) | mask;
+	    br = convert_pixel (row2, x2) | mask;
+	}
+	else
+	{
+	    uint32_t mask1, mask2;
+	    int bpp;
+
+	    /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
+	     * which means if you use it in expressions, those
+	     * expressions become unsigned themselves. Since
+	     * the variables below can be negative in some cases,
+	     * that will lead to crashes on 64 bit architectures.
+	     *
+	     * So this line makes sure bpp is signed
+	     */
+	    bpp = PIXMAN_FORMAT_BPP (format);
+
+	    if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
+	    {
+		buffer[i] = 0;
+		goto next;
+	    }
+
+	    if (y2 == 0)
+	    {
+		row1 = zero;
+		mask1 = 0;
+	    }
+	    else
+	    {
+		row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
+		row1 += bpp / 8 * x1;
+
+		mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
+	    }
+
+	    if (y1 == height - 1)
+	    {
+		row2 = zero;
+		mask2 = 0;
+	    }
+	    else
+	    {
+		row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
+		row2 += bpp / 8 * x1;
+
+		mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
+	    }
+
+	    if (x2 == 0)
+	    {
+		tl = 0;
+		bl = 0;
+	    }
+	    else
+	    {
+		tl = convert_pixel (row1, 0) | mask1;
+		bl = convert_pixel (row2, 0) | mask2;
+	    }
+
+	    if (x1 == width - 1)
+	    {
+		tr = 0;
+		br = 0;
+	    }
+	    else
+	    {
+		tr = convert_pixel (row1, 1) | mask1;
+		br = convert_pixel (row2, 1) | mask2;
+	    }
+	}
+
+	buffer[i] = bilinear_interpolation (
+	    tl, tr, bl, br, distx, disty);
+
+    next:
+	x += ux;
+	y += uy;
+    }
+}
+
+static force_inline uint32_t
+convert_a8r8g8b8 (const uint8_t *row, int x)
+{
+    return *(((uint32_t *)row) + x);
+}
+
+static force_inline uint32_t
+convert_x8r8g8b8 (const uint8_t *row, int x)
+{
+    return *(((uint32_t *)row) + x);
+}
+
+static force_inline uint32_t
+convert_a8 (const uint8_t *row, int x)
+{
+    return *(row + x) << 24;
+}
+
+static force_inline uint32_t
+convert_r5g6b5 (const uint8_t *row, int x)
+{
+    return CONVERT_0565_TO_0888 (*((uint16_t *)row + x));
+}
+
+#define MAKE_BILINEAR_FETCHER(name, format, repeat_mode)		\
+    static void								\
+    bits_image_fetch_bilinear_affine_ ## name (pixman_image_t *image,	\
+					       int              offset,	\
+					       int              line,	\
+					       int              width,	\
+					       uint32_t *       buffer,	\
+					       const uint32_t * mask)	\
+    {									\
+	bits_image_fetch_bilinear_affine (image, offset, line, width, buffer, mask, \
+					  convert_ ## format,		\
+					  PIXMAN_ ## format,		\
+					  repeat_mode);			\
+    }
+
+#if 0
+MAKE_BILINEAR_FETCHER (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD);
+MAKE_BILINEAR_FETCHER (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE);
+MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT);
+MAKE_BILINEAR_FETCHER (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL);
+MAKE_BILINEAR_FETCHER (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD);
+MAKE_BILINEAR_FETCHER (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE);
+MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
+MAKE_BILINEAR_FETCHER (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL);
+MAKE_BILINEAR_FETCHER (pad_a8,           a8,       PIXMAN_REPEAT_PAD);
+MAKE_BILINEAR_FETCHER (none_a8,          a8,       PIXMAN_REPEAT_NONE);
+MAKE_BILINEAR_FETCHER (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT);
+MAKE_BILINEAR_FETCHER (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL);
+MAKE_BILINEAR_FETCHER (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD);
+MAKE_BILINEAR_FETCHER (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE);
+MAKE_BILINEAR_FETCHER (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT);
+MAKE_BILINEAR_FETCHER (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL);
+#endif
+
 static void
 bits_image_fetch_solid_32 (pixman_image_t * image,
                            int              x,
@@ -954,14 +1170,47 @@ static const fetcher_info_t fetcher_info[] =
       _pixman_image_get_scanline_generic_64
     },
 
+#define GENERAL_BILINEAR_FLAGS						\
+    (FAST_PATH_NO_ALPHA_MAP		|				\
+     FAST_PATH_NO_ACCESSORS		|				\
+     FAST_PATH_HAS_TRANSFORM		|				\
+     FAST_PATH_AFFINE_TRANSFORM		|				\
+     FAST_PATH_BILINEAR_FILTER)
+
+#define 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				\
+    },
+
+#if 0
+    BILINEAR_AFFINE_FAST_PATH (pad_a8r8g8b8, a8r8g8b8, PAD)
+    BILINEAR_AFFINE_FAST_PATH (none_a8r8g8b8, a8r8g8b8, NONE)
+    BILINEAR_AFFINE_FAST_PATH (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
+    BILINEAR_AFFINE_FAST_PATH (normal_a8r8g8b8, a8r8g8b8, NORMAL)
+    BILINEAR_AFFINE_FAST_PATH (pad_x8r8g8b8, x8r8g8b8, PAD)
+    BILINEAR_AFFINE_FAST_PATH (none_x8r8g8b8, x8r8g8b8, NONE)
+    BILINEAR_AFFINE_FAST_PATH (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
+    BILINEAR_AFFINE_FAST_PATH (normal_x8r8g8b8, x8r8g8b8, NORMAL)
+    BILINEAR_AFFINE_FAST_PATH (pad_a8, a8, PAD)
+    BILINEAR_AFFINE_FAST_PATH (none_a8, a8, NONE)
+    BILINEAR_AFFINE_FAST_PATH (reflect_a8, a8, REFLECT)
+    BILINEAR_AFFINE_FAST_PATH (normal_a8, a8, NORMAL)
+    BILINEAR_AFFINE_FAST_PATH (pad_r5g6b5, r5g6b5, PAD)
+    BILINEAR_AFFINE_FAST_PATH (none_r5g6b5, r5g6b5, NONE)
+    BILINEAR_AFFINE_FAST_PATH (reflect_r5g6b5, r5g6b5, REFLECT)
+    BILINEAR_AFFINE_FAST_PATH (normal_r5g6b5, r5g6b5, NORMAL)
+#endif
+
+    /* Affine, no alpha */
     { PIXMAN_any,
-      (FAST_PATH_NO_ALPHA_MAP |
-       FAST_PATH_HAS_TRANSFORM |
-       FAST_PATH_AFFINE_TRANSFORM),
+      (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
     },
 
+    /* General */
     { PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 },
 
     { PIXMAN_null },
diff --git a/test/composite-test.c b/test/composite-test.c
index 5401abf..f5f352f 100644
--- a/test/composite-test.c
+++ b/test/composite-test.c
@@ -104,12 +104,11 @@ main (int argc, char **argv)
 	{ d2f (0.0), { full, low, low, alpha } },
 	{ d2f (0.25), { full, full, low, alpha } },
 	{ d2f (0.4), { low, full, low, alpha } },
-	{ d2f (0.5), { low, full, full, alpha } },
+	{ d2f (0.6), { low, full, full, alpha } },
 	{ d2f (0.8), { low, low, full, alpha } },
 	{ d2f (1.0), { full, low, full, alpha } },
     };
-	
-	    
+
     int i;
 
     gtk_init (&argc, &argv);
commit 6d1e10a8b5c456ee501a309f5cf2f801efcf63b0
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Wed Jul 14 16:27:27 2010 -0400

    test: Add affine-test
    
    This test tests compositing with various affine transformations. It is
    almost identical to scaling-test, except that it also applies a random
    rotation in addition to the random scaling and translation.

diff --git a/test/Makefile.am b/test/Makefile.am
index f3b2b58..ff851c9 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -18,6 +18,7 @@ TESTPROGRAMS =			\
 	alphamap		\
 	blitters-test		\
 	scaling-test		\
+	affine-test		\
 	composite
 
 a1_trap_test_LDADD = $(TEST_LDADD)
@@ -39,6 +40,9 @@ blitters_test_SOURCES = blitters-test.c utils.c utils.h
 scaling_test_LDADD = $(TEST_LDADD)
 scaling_test_SOURCES = scaling-test.c utils.c utils.h
 
+affine_test_LDADD = $(TEST_LDADD)
+affine_test_SOURCES = affine-test.c utils.c utils.h
+
 alphamap_LDADD = $(TEST_LDADD)
 alphamap_SOURCES = alphamap.c utils.c utils.h
 
diff --git a/test/affine-test.c b/test/affine-test.c
new file mode 100644
index 0000000..27f2567
--- /dev/null
+++ b/test/affine-test.c
@@ -0,0 +1,261 @@
+/*
+ * Test program, which can detect some problems with affine transformations
+ * in pixman. Testing is done by running lots of random SRC and OVER
+ * compositing operations a8r8g8b8, x8a8r8g8b8, r5g6b5 and a8 color formats
+ * with random scaled, rotated and translated transforms.
+ *
+ * Script 'fuzzer-find-diff.pl' can be used to narrow down the problem in
+ * the case of test failure.
+ */
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "utils.h"
+
+#define MAX_SRC_WIDTH  16
+#define MAX_SRC_HEIGHT 16
+#define MAX_DST_WIDTH  16
+#define MAX_DST_HEIGHT 16
+#define MAX_STRIDE     4
+
+/*
+ * Composite operation with pseudorandom images
+ */
+uint32_t
+test_composite (int      testnum,
+		int      verbose)
+{
+    int                i;
+    pixman_image_t *   src_img;
+    pixman_image_t *   dst_img;
+    pixman_transform_t transform;
+    pixman_region16_t  clip;
+    int                src_width, src_height;
+    int                dst_width, dst_height;
+    int                src_stride, dst_stride;
+    int                src_x, src_y;
+    int                dst_x, dst_y;
+    int                src_bpp;
+    int                dst_bpp;
+    int                w, h;
+    pixman_fixed_t     scale_x = 65536, scale_y = 65536;
+    pixman_fixed_t     translate_x = 0, translate_y = 0;
+    int                op;
+    int                repeat = 0;
+    int                src_fmt, dst_fmt;
+    uint32_t *         srcbuf;
+    uint32_t *         dstbuf;
+    uint32_t           crc32;
+    FLOAT_REGS_CORRUPTION_DETECTOR_START ();
+
+    lcg_srand (testnum);
+
+    src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4;
+    dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4;
+    op = (lcg_rand_n (2) == 0) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER;
+
+    src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1;
+    src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1;
+    dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1;
+    dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1;
+    src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp;
+    dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp;
+
+    if (src_stride & 3)
+	src_stride += 2;
+
+    if (dst_stride & 3)
+	dst_stride += 2;
+
+    src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2);
+    src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2);
+    dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2);
+    dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2);
+    w = lcg_rand_n (dst_width * 3 / 2 - dst_x);
+    h = lcg_rand_n (dst_height * 3 / 2 - dst_y);
+
+    srcbuf = (uint32_t *)malloc (src_stride * src_height);
+    dstbuf = (uint32_t *)malloc (dst_stride * dst_height);
+
+    for (i = 0; i < src_stride * src_height; i++)
+	*((uint8_t *)srcbuf + i) = lcg_rand_n (256);
+
+    for (i = 0; i < dst_stride * dst_height; i++)
+	*((uint8_t *)dstbuf + i) = lcg_rand_n (256);
+
+    src_fmt = src_bpp == 4 ? (lcg_rand_n (2) == 0 ?
+                              PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5;
+
+    dst_fmt = dst_bpp == 4 ? (lcg_rand_n (2) == 0 ?
+                              PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5;
+
+    src_img = pixman_image_create_bits (
+        src_fmt, src_width, src_height, srcbuf, src_stride);
+
+    dst_img = pixman_image_create_bits (
+        dst_fmt, dst_width, dst_height, dstbuf, dst_stride);
+
+    image_endian_swap (src_img, src_bpp * 8);
+    image_endian_swap (dst_img, dst_bpp * 8);
+
+    pixman_transform_init_identity (&transform);
+    
+    if (lcg_rand_n (8) > 0)
+    {
+	scale_x = -32768 * 3 + lcg_rand_N (65536 * 5);
+	scale_y = -32768 * 3 + lcg_rand_N (65536 * 5);
+	translate_x = lcg_rand_N (65536);
+	translate_y = lcg_rand_N (65536);
+	pixman_transform_init_scale (&transform, scale_x, scale_y);
+	pixman_transform_translate (&transform, NULL, translate_x, translate_y);
+    }
+
+    if (lcg_rand_n (4) > 0)
+    {
+	int c = lcg_rand_N (2 * 65536) - 65536;
+	int s = lcg_rand_N (2 * 65536) - 65536;
+	
+	pixman_transform_rotate (&transform, NULL, c, s);
+    }
+
+    pixman_image_set_transform (src_img, &transform);
+    
+    switch (lcg_rand_n (4))
+    {
+    case 0:
+	repeat = PIXMAN_REPEAT_NONE;
+	break;
+
+    case 1:
+	repeat = PIXMAN_REPEAT_NORMAL;
+	break;
+
+    case 2:
+	repeat = PIXMAN_REPEAT_PAD;
+	break;
+
+    case 3:
+	repeat = PIXMAN_REPEAT_REFLECT;
+	break;
+
+    default:
+        break;
+    }
+    pixman_image_set_repeat (src_img, repeat);
+
+    if (lcg_rand_n (2))
+	pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0);
+    else
+	pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0);
+
+    if (verbose)
+    {
+	printf ("src_fmt=%08X, dst_fmt=%08X\n", src_fmt, dst_fmt);
+	printf ("op=%d, scale_x=%d, scale_y=%d, repeat=%d\n",
+	        op, scale_x, scale_y, repeat);
+	printf ("translate_x=%d, translate_y=%d\n",
+	        translate_x, translate_y);
+	printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
+	        src_width, src_height, dst_width, dst_height);
+	printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
+	        src_x, src_y, dst_x, dst_y);
+	printf ("w=%d, h=%d\n", w, h);
+    }
+
+    if (lcg_rand_n (8) == 0)
+    {
+	pixman_box16_t clip_boxes[2];
+	int            n = lcg_rand_n (2) + 1;
+
+	for (i = 0; i < n; i++)
+	{
+	    clip_boxes[i].x1 = lcg_rand_n (src_width);
+	    clip_boxes[i].y1 = lcg_rand_n (src_height);
+	    clip_boxes[i].x2 =
+		clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1);
+	    clip_boxes[i].y2 =
+		clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1);
+
+	    if (verbose)
+	    {
+		printf ("source clip box: [%d,%d-%d,%d]\n",
+		        clip_boxes[i].x1, clip_boxes[i].y1,
+		        clip_boxes[i].x2, clip_boxes[i].y2);
+	    }
+	}
+
+	pixman_region_init_rects (&clip, clip_boxes, n);
+	pixman_image_set_clip_region (src_img, &clip);
+	pixman_image_set_source_clipping (src_img, 1);
+	pixman_region_fini (&clip);
+    }
+
+    if (lcg_rand_n (8) == 0)
+    {
+	pixman_box16_t clip_boxes[2];
+	int            n = lcg_rand_n (2) + 1;
+	for (i = 0; i < n; i++)
+	{
+	    clip_boxes[i].x1 = lcg_rand_n (dst_width);
+	    clip_boxes[i].y1 = lcg_rand_n (dst_height);
+	    clip_boxes[i].x2 =
+		clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1);
+	    clip_boxes[i].y2 =
+		clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1);
+
+	    if (verbose)
+	    {
+		printf ("destination clip box: [%d,%d-%d,%d]\n",
+		        clip_boxes[i].x1, clip_boxes[i].y1,
+		        clip_boxes[i].x2, clip_boxes[i].y2);
+	    }
+	}
+	pixman_region_init_rects (&clip, clip_boxes, n);
+	pixman_image_set_clip_region (dst_img, &clip);
+	pixman_region_fini (&clip);
+    }
+
+    pixman_image_composite (op, src_img, NULL, dst_img,
+                            src_x, src_y, 0, 0, dst_x, dst_y, w, h);
+
+    if (dst_fmt == PIXMAN_x8r8g8b8)
+    {
+	/* ignore unused part */
+	for (i = 0; i < dst_stride * dst_height / 4; i++)
+	    dstbuf[i] &= 0xFFFFFF;
+    }
+
+    image_endian_swap (dst_img, dst_bpp * 8);
+
+    if (verbose)
+    {
+	int j;
+
+	for (i = 0; i < dst_height; i++)
+	{
+	    for (j = 0; j < dst_stride; j++)
+		printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j));
+
+	    printf ("\n");
+	}
+    }
+
+    pixman_image_unref (src_img);
+    pixman_image_unref (dst_img);
+
+    crc32 = compute_crc32 (0, dstbuf, dst_stride * dst_height);
+    free (srcbuf);
+    free (dstbuf);
+
+    FLOAT_REGS_CORRUPTION_DETECTOR_FINISH ();
+    return crc32;
+}
+
+int
+main (int argc, const char *argv[])
+{
+    pixman_disable_out_of_bounds_workaround ();
+
+    return fuzzer_test_main ("affine", 8000000, 0x46EC3C6A,
+			     test_composite, argc, argv);
+}
commit 4fa33537d7093ac759b7ded1718a628dacd2aff4
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sun Sep 12 06:07:41 2010 -0400

    analyze_extents: Fast path for non-transformed BITS images
    
    Profiling various cairo traces showed that we were spending a lot of
    time in analyze_extents and compute_sample_extents(). This was
    especially bad for glyphs where all this computation was completely
    unnecessary.
    
    This patch adds a fast path for the case of non-transformed BITS
    images. The result is approximately a 6% improvement on the
    firefox-talos-gfx benchmark:
    
    Before:
    
    [ # ]  backend                         test   min(s) median(s) stddev. count
    [  0]    image            firefox-talos-gfx   13.797   13.848   0.20%    6/6
    
    After:
    
    [ # ]  backend                         test   min(s) median(s) stddev. count
    [  0]    image            firefox-talos-gfx   12.946   13.018   0.39%    6/6

diff --git a/pixman/pixman.c b/pixman/pixman.c
index 72779c8..2296325 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -724,6 +724,7 @@ analyze_extent (pixman_image_t *image, int x, int y,
 	return FALSE;
     }
 
+    transform = image->common.transform;
     if (image->common.type == BITS)
     {
 	/* During repeat mode calculations we might convert the
@@ -733,6 +734,18 @@ analyze_extent (pixman_image_t *image, int x, int y,
 	if (image->bits.width >= 0x7fff	|| image->bits.height >= 0x7fff)
 	    return FALSE;
 
+#define ID_AND_NEAREST (FAST_PATH_ID_TRANSFORM | FAST_PATH_NEAREST_FILTER)
+	
+	if ((image->common.flags & ID_AND_NEAREST) == ID_AND_NEAREST &&
+	    extents->x1 - x >= 0 &&
+	    extents->y1 - y >= 0 &&
+	    extents->x2 - x <= image->bits.width &&
+	    extents->y2 - y <= image->bits.height)
+	{
+	    *flags |= (FAST_PATH_SAMPLES_COVER_CLIP | FAST_PATH_COVERS_CLIP);
+	    return TRUE;
+	}
+    
 	switch (image->common.filter)
 	{
 	case PIXMAN_FILTER_CONVOLUTION:
@@ -763,6 +776,17 @@ analyze_extent (pixman_image_t *image, int x, int y,
 	default:
 	    return FALSE;
 	}
+
+	/* Check whether the non-expanded, transformed extent is entirely within
+	 * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
+	 */
+	ex = *extents;
+	if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height) &&
+	    ex.x1 >= 0 && ex.y1 >= 0 &&
+	    ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
+	{
+	    *flags |= (FAST_PATH_SAMPLES_COVER_CLIP | FAST_PATH_COVERS_CLIP);
+	}
     }
     else
     {
@@ -781,24 +805,9 @@ analyze_extent (pixman_image_t *image, int x, int y,
     ex.x2 = extents->x2 + 1;
     ex.y2 = extents->y2 + 1;
 
-    transform = image->common.transform;
-
     if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
 	return FALSE;
 
-    if (image->type == BITS)
-    {
-	/* Check whether the non-expanded, transformed extent is entirely within
-	 * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
-	 */
-	ex = *extents;
-	if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
-	{
-	    if (ex.x1 >= 0 && ex.y1 >= 0 && ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
-		*flags |= (FAST_PATH_SAMPLES_COVER_CLIP | FAST_PATH_COVERS_CLIP);
-	}
-    }
-
     return TRUE;
 }
 
commit c97881fe3c3a0af78cf5953d2c135654440b0269
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Sep 16 08:35:05 2010 -0400

    Move some of the FAST_PATH_COVERS_CLIP computation to pixman-image.c
    
    When an image is solid or repeating, the FAST_PATH_COVERS_CLIP flag
    can be set in compute_image_info().
    
    Also the code that turned this flag off in pixman.c was not correct;
    it didn't take transformations into account. With this patch, pixman.c
    doesn't set the flag by default, but instead relies on the call to
    compute_samples_extents() to set it when possible.

diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 029a1df..8397f6a 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -353,19 +353,34 @@ compute_image_info (pixman_image_t *image)
     switch (image->common.repeat)
     {
     case PIXMAN_REPEAT_NONE:
-	flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NORMAL_REPEAT;
+	flags |=
+	    FAST_PATH_NO_REFLECT_REPEAT		|
+	    FAST_PATH_NO_PAD_REPEAT		|
+	    FAST_PATH_NO_NORMAL_REPEAT;
 	break;
 
     case PIXMAN_REPEAT_REFLECT:
-	flags |= FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NONE_REPEAT | FAST_PATH_NO_NORMAL_REPEAT;
+	flags |=
+	    FAST_PATH_NO_PAD_REPEAT		|
+	    FAST_PATH_NO_NONE_REPEAT		|
+	    FAST_PATH_NO_NORMAL_REPEAT		|
+	    FAST_PATH_COVERS_CLIP;
 	break;
 
     case PIXMAN_REPEAT_PAD:
-	flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_NONE_REPEAT | FAST_PATH_NO_NORMAL_REPEAT;
+	flags |=
+	    FAST_PATH_NO_REFLECT_REPEAT		|
+	    FAST_PATH_NO_NONE_REPEAT		|
+	    FAST_PATH_NO_NORMAL_REPEAT		|
+	    FAST_PATH_COVERS_CLIP;
 	break;
 
     default:
-	flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NONE_REPEAT;
+	flags |=
+	    FAST_PATH_NO_REFLECT_REPEAT		|
+	    FAST_PATH_NO_PAD_REPEAT		|
+	    FAST_PATH_NO_NONE_REPEAT		|
+	    FAST_PATH_COVERS_CLIP;
 	break;
     }
 
@@ -385,6 +400,8 @@ compute_image_info (pixman_image_t *image)
 
 	if (image->solid.color.alpha == 0xffff)
 	    flags |= FAST_PATH_IS_OPAQUE;
+
+	flags |= FAST_PATH_COVERS_CLIP;
 	break;
 
     case BITS:
diff --git a/pixman/pixman.c b/pixman/pixman.c
index 285bbfc..72779c8 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -708,29 +708,9 @@ analyze_extent (pixman_image_t *image, int x, int y,
     pixman_fixed_t width, height;
     pixman_box32_t ex;
 
-    *flags |= FAST_PATH_COVERS_CLIP;
     if (!image)
 	return TRUE;
 
-    transform = image->common.transform;
-    if (image->common.type == BITS)
-    {
-	/* During repeat mode calculations we might convert the
-	 * width/height of an image to fixed 16.16, so we need
-	 * them to be smaller than 16 bits.
-	 */
-	if (image->bits.width >= 0x7fff	|| image->bits.height >= 0x7fff)
-	    return FALSE;
-
-	if (image->common.repeat == PIXMAN_REPEAT_NONE &&
-	    (x > extents->x1 || y > extents->y1 ||
-	     x + image->bits.width < extents->x2 ||
-	     y + image->bits.height < extents->y2))
-	{
-	    (*flags) &= ~FAST_PATH_COVERS_CLIP;
-	}
-    }
-
     /* Some compositing functions walk one step
      * outside the destination rectangle, so we
      * check here that the expanded-by-one source
@@ -746,6 +726,13 @@ analyze_extent (pixman_image_t *image, int x, int y,
 
     if (image->common.type == BITS)
     {
+	/* During repeat mode calculations we might convert the
+	 * width/height of an image to fixed 16.16, so we need
+	 * them to be smaller than 16 bits.
+	 */
+	if (image->bits.width >= 0x7fff	|| image->bits.height >= 0x7fff)
+	    return FALSE;
+
 	switch (image->common.filter)
 	{
 	case PIXMAN_FILTER_CONVOLUTION:
@@ -786,14 +773,16 @@ analyze_extent (pixman_image_t *image, int x, int y,
     }
 
     /* Check that the extents expanded by one don't overflow. This ensures that
-     * compositing functions can simply walk the source space using 16.16 variables
-     * without worrying about overflow.
+     * compositing functions can simply walk the source space using 16.16
+     * variables without worrying about overflow.
      */
     ex.x1 = extents->x1 - 1;
     ex.y1 = extents->y1 - 1;
     ex.x2 = extents->x2 + 1;
     ex.y2 = extents->y2 + 1;
 
+    transform = image->common.transform;
+
     if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
 	return FALSE;
 
@@ -806,7 +795,7 @@ analyze_extent (pixman_image_t *image, int x, int y,
 	if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
 	{
 	    if (ex.x1 >= 0 && ex.y1 >= 0 && ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
-		*flags |= FAST_PATH_SAMPLES_COVER_CLIP;
+		*flags |= (FAST_PATH_SAMPLES_COVER_CLIP | FAST_PATH_COVERS_CLIP);
 	}
     }
 
commit 3411f9399c3ab6d642f350ea8e4c355f719d01d9
Author: Tor Lillqvist <tml at iki.fi>
Date:   Wed Sep 15 11:53:47 2010 -0400

    Support __thread on MINGW 4.5
    
    By the way, it seems that with gcc 4.5.0 from mingw.org, __thread, sse
    and mmx work fine.
    
    I added the below to pixman 0.18 and as far as I can see, it works.
    make check reports no problems. (Earlier I had to use --disable-mmx
    and --disable-sse2.) Also gtk-demo and gimp run fine.
    
    (Also a change to get rid of the warnings about -fvisibility being ignored.)

diff --git a/configure.ac b/configure.ac
index d3b71fa..47213a0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -248,6 +248,9 @@ dnl -fvisibility stuff
 
 PIXMAN_CHECK_CFLAG([-fvisibility=hidden], [dnl
 #if defined(__GNUC__) && (__GNUC__ >= 4)
+#ifdef _WIN32
+#error Have -fvisibility but it is ignored and generates a warning
+#endif
 #else
 error Need GCC 4.0 for visibility
 #endif
@@ -643,8 +646,9 @@ support_for__thread=no
 
 AC_MSG_CHECKING(for __thread)
 AC_LINK_IFELSE([
-#ifdef __MINGW32__
-#error MinGW has broken __thread support
+#ifdef defined __MINGW32__ && !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#error This MinGW version has broken __thread support
+#endif
 #endif
 #ifdef __OpenBSD__
 #error OpenBSD has broken __thread support
diff --git a/pixman/pixman-compiler.h b/pixman/pixman-compiler.h
index 5501396..22b9fe7 100644
--- a/pixman/pixman-compiler.h
+++ b/pixman/pixman-compiler.h
@@ -60,7 +60,7 @@
 #endif
 
 /* GCC visibility */
-#if defined(__GNUC__) && __GNUC__ >= 4
+#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32)
 #   define PIXMAN_EXPORT __attribute__ ((visibility("default")))
 /* Sun Studio 8 visibility */
 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
commit add0fd1bac84a5b6dddf7632b4100d6b3f2ebc18
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sun Aug 29 22:46:09 2010 -0400

    Clip composite region against the destination alpha map extents.
    
    Otherwise we can end up writing outside the alpha map.

diff --git a/pixman/pixman.c b/pixman/pixman.c
index cdf4b75..285bbfc 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -315,14 +315,27 @@ pixman_compute_composite_region32 (pixman_region32_t * region,
 	    return FALSE;
     }
 
-    if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
+    if (dst_image->common.alpha_map)
     {
-	if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
-	                         -dst_image->common.alpha_origin_x,
-	                         -dst_image->common.alpha_origin_y))
+	if (!pixman_region32_intersect_rect (region, region,
+					     dst_image->common.alpha_origin_x,
+					     dst_image->common.alpha_origin_y,
+					     dst_image->common.alpha_map->width,
+					     dst_image->common.alpha_map->height))
 	{
 	    return FALSE;
 	}
+	if (!pixman_region32_not_empty (region))
+	    return FALSE;
+	if (dst_image->common.alpha_map->common.have_clip_region)
+	{
+	    if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
+				     -dst_image->common.alpha_origin_x,
+				     -dst_image->common.alpha_origin_y))
+	    {
+		return FALSE;
+	    }
+	}
     }
 
     /* clip against src */
commit af2f0080feada1abe569e2031acacf51be7f8f68
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sun Aug 29 17:07:40 2010 -0400

    Remove FAST_PATH_NARROW_FORMAT flag if there is a wide alpha map
    
    If an image has an alpha map that has wide components, then we need to
    use 64 bit processing for that image. We detect this situation in
    pixman-image.c and remove the FAST_PATH_NARROW_FORMAT flag.
    
    In pixman-general, the wide/narrow decision is now based on the flags
    instead of on the formats.

diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index fc276bd..4d234a0 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -57,17 +57,6 @@ general_composite_rect  (pixman_implementation_t *imp,
                          int32_t                  height)
 {
     uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3];
-    const pixman_format_code_t src_format =
-	src->type == BITS ? src->bits.format : 0;
-    const pixman_format_code_t mask_format =
-	mask && mask->type == BITS ? mask->bits.format : 0;
-    const pixman_format_code_t dest_format =
-	dest->type == BITS ? dest->bits.format : 0;
-    const int src_narrow = !PIXMAN_FORMAT_IS_WIDE (src_format);
-    const int mask_narrow = !mask || !PIXMAN_FORMAT_IS_WIDE (mask_format);
-    const int dest_narrow = !PIXMAN_FORMAT_IS_WIDE (dest_format);
-    const int narrow = src_narrow && mask_narrow && dest_narrow;
-    const int Bpp = narrow ? 4 : 8;
     uint8_t *scanline_buffer = stack_scanline_buffer;
     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
     fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL;
@@ -77,8 +66,15 @@ general_composite_rect  (pixman_implementation_t *imp,
     pixman_bool_t component_alpha;
     uint32_t *bits;
     int32_t stride;
+    int narrow, Bpp;
     int i;
 
+    narrow =
+	(src->common.flags & FAST_PATH_NARROW_FORMAT)		&&
+	(!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT)	&&
+	(dest->common.flags & FAST_PATH_NARROW_FORMAT);
+    Bpp = narrow ? 4 : 8;
+
     if (width * Bpp > SCANLINE_BUFFER_LENGTH)
     {
 	scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 102df6c..029a1df 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -327,10 +327,6 @@ compute_image_info (pixman_image_t *image)
 	    flags |= FAST_PATH_Y_UNIT_ZERO;
     }
 
-    /* Alpha map */
-    if (!image->common.alpha_map)
-	flags |= FAST_PATH_NO_ALPHA_MAP;
-
     /* Filter */
     switch (image->common.filter)
     {
@@ -454,6 +450,17 @@ compute_image_info (pixman_image_t *image)
 	break;
     }
 
+    /* Alpha map */
+    if (!image->common.alpha_map)
+    {
+	flags |= FAST_PATH_NO_ALPHA_MAP;
+    }
+    else
+    {
+	if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
+	    flags &= ~FAST_PATH_NARROW_FORMAT;
+    }
+
     /* Both alpha maps and convolution filters can introduce
      * non-opaqueness in otherwise opaque images. Also
      * an image with component alpha turned on is only opaque
commit 0afc61341526887c59d6dd9e43073f73451a74c6
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sun Aug 29 17:03:01 2010 -0400

    Rename FAST_PATH_NO_WIDE_FORMAT to FAST_PATH_NARROW_FORMAT
    
    This avoids a negative in the name. Also, by renaming the "wide"
    variable in pixman-general.c to "narrow" and fixing up the logic
    correspondingly, the code there reads a lot more straightforwardly.

diff --git a/pixman/pixman-fast-path.h b/pixman/pixman-fast-path.h
index a6b5414..ed09ba5 100644
--- a/pixman/pixman-fast-path.h
+++ b/pixman/pixman-fast-path.h
@@ -389,7 +389,7 @@ fast_composite_scaled_nearest_ ## scale_func_name (pixman_implementation_t *imp,
      FAST_PATH_NO_ALPHA_MAP	|					\
      FAST_PATH_NEAREST_FILTER	|					\
      FAST_PATH_NO_ACCESSORS	|					\
-     FAST_PATH_NO_WIDE_FORMAT)
+     FAST_PATH_NARROW_FORMAT)
 
 #define SIMPLE_NEAREST_FAST_PATH_NORMAL(op,s,d,func)			\
     {   PIXMAN_OP_ ## op,						\
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index fc742c0..fc276bd 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -63,11 +63,11 @@ general_composite_rect  (pixman_implementation_t *imp,
 	mask && mask->type == BITS ? mask->bits.format : 0;
     const pixman_format_code_t dest_format =
 	dest->type == BITS ? dest->bits.format : 0;
-    const int src_wide = PIXMAN_FORMAT_IS_WIDE (src_format);
-    const int mask_wide = mask && PIXMAN_FORMAT_IS_WIDE (mask_format);
-    const int dest_wide = PIXMAN_FORMAT_IS_WIDE (dest_format);
-    const int wide = src_wide || mask_wide || dest_wide;
-    const int Bpp = wide ? 8 : 4;
+    const int src_narrow = !PIXMAN_FORMAT_IS_WIDE (src_format);
+    const int mask_narrow = !mask || !PIXMAN_FORMAT_IS_WIDE (mask_format);
+    const int dest_narrow = !PIXMAN_FORMAT_IS_WIDE (dest_format);
+    const int narrow = src_narrow && mask_narrow && dest_narrow;
+    const int Bpp = narrow ? 4 : 8;
     uint8_t *scanline_buffer = stack_scanline_buffer;
     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
     fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL;
@@ -106,29 +106,29 @@ general_composite_rect  (pixman_implementation_t *imp,
 
     if (op == PIXMAN_OP_CLEAR)
 	fetch_src = NULL;
-    else if (wide)
-	fetch_src = _pixman_image_get_scanline_64;
-    else
+    else if (narrow)
 	fetch_src = _pixman_image_get_scanline_32;
+    else
+	fetch_src = _pixman_image_get_scanline_64;
 
     if (!mask || op == PIXMAN_OP_CLEAR)
 	fetch_mask = NULL;
-    else if (wide)
-	fetch_mask = _pixman_image_get_scanline_64;
-    else
+    else if (narrow)
 	fetch_mask = _pixman_image_get_scanline_32;
+    else
+	fetch_mask = _pixman_image_get_scanline_64;
 
     if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC)
 	fetch_dest = NULL;
-    else if (wide)
-	fetch_dest = _pixman_image_get_scanline_64;
-    else
+    else if (narrow)
 	fetch_dest = _pixman_image_get_scanline_32;
-
-    if (wide)
-	store = _pixman_image_store_scanline_64;
     else
+	fetch_dest = _pixman_image_get_scanline_64;
+
+    if (narrow)
 	store = _pixman_image_store_scanline_32;
+    else
+	store = _pixman_image_store_scanline_64;
 
     /* Skip the store step and composite directly into the
      * destination if the output format of the compose func matches
@@ -148,7 +148,7 @@ general_composite_rect  (pixman_implementation_t *imp,
 	  op == PIXMAN_OP_OUT_REVERSE	||
 	  op == PIXMAN_OP_DST)))
     {
-	if (!wide &&
+	if (narrow &&
 	    !dest->common.alpha_map &&
 	    !dest->bits.write_func)
 	{
@@ -175,19 +175,19 @@ general_composite_rect  (pixman_implementation_t *imp,
         mask->common.component_alpha    &&
         PIXMAN_FORMAT_RGB (mask->bits.format);
 
-    if (wide)
+    if (narrow)
     {
 	if (component_alpha)
-	    compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
+	    compose = _pixman_implementation_combine_32_ca;
 	else
-	    compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
+	    compose = _pixman_implementation_combine_32;
     }
     else
     {
 	if (component_alpha)
-	    compose = _pixman_implementation_combine_32_ca;
+	    compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
 	else
-	    compose = _pixman_implementation_combine_32;
+	    compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
     }
 
     if (!compose)
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index cfee865..102df6c 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -379,7 +379,7 @@ compute_image_info (pixman_image_t *image)
     else
 	flags |= FAST_PATH_UNIFIED_ALPHA;
 
-    flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NO_WIDE_FORMAT);
+    flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
 
     /* Type specific checks */
     switch (image->type)
@@ -426,7 +426,7 @@ compute_image_info (pixman_image_t *image)
 	    flags &= ~FAST_PATH_NO_ACCESSORS;
 
 	if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
-	    flags &= ~FAST_PATH_NO_WIDE_FORMAT;
+	    flags &= ~FAST_PATH_NARROW_FORMAT;
 	break;
 
     case LINEAR:
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 36b9d91..d85868f 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -554,7 +554,7 @@ _pixman_choose_implementation (void);
 #define FAST_PATH_NO_PAD_REPEAT			(1 <<  3)
 #define FAST_PATH_NO_REFLECT_REPEAT		(1 <<  4)
 #define FAST_PATH_NO_ACCESSORS			(1 <<  5)
-#define FAST_PATH_NO_WIDE_FORMAT		(1 <<  6)
+#define FAST_PATH_NARROW_FORMAT		(1 <<  6)
 #define FAST_PATH_COVERS_CLIP			(1 <<  7)
 #define FAST_PATH_COMPONENT_ALPHA		(1 <<  8)
 #define FAST_PATH_UNIFIED_ALPHA			(1 <<  9)
@@ -600,7 +600,7 @@ _pixman_choose_implementation (void);
      FAST_PATH_NO_PAD_REPEAT		|				\
      FAST_PATH_NO_REFLECT_REPEAT	|				\
      FAST_PATH_NO_ACCESSORS		|				\
-     FAST_PATH_NO_WIDE_FORMAT		|				\
+     FAST_PATH_NARROW_FORMAT		|				\
      FAST_PATH_COVERS_CLIP)
 
 #define FAST_PATH_STD_SRC_FLAGS						\
@@ -614,7 +614,7 @@ _pixman_choose_implementation (void);
 #define FAST_PATH_STD_DEST_FLAGS					\
     (FAST_PATH_NO_ACCESSORS		|				\
      FAST_PATH_NO_ALPHA_MAP		|				\
-     FAST_PATH_NO_WIDE_FORMAT)
+     FAST_PATH_NARROW_FORMAT)
 
 #define FAST_PATH(op, src, src_flags, mask, mask_flags, dest, dest_flags, func) \
     PIXMAN_OP_ ## op,							\
commit ae77548f0d9ca95a86a466fc4ff099e000716067
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sun Aug 29 16:59:02 2010 -0400

    Update and extend the alphamap test
    
    - Test many more combinations of formats
    
    - Test destination alpha maps
    
    - Test various different alpha origins
    
    Also add a transformation to the destination, but comment it out
    because it is actually broken at the moment (and pretty difficult to
    fix).

diff --git a/test/Makefile.am b/test/Makefile.am
index 3d98e17..f3b2b58 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -13,9 +13,9 @@ TESTPROGRAMS =			\
 	window-test		\
 	gradient-crash-test	\
 	trap-crasher		\
-	alphamap		\
 	alpha-loop		\
 	scaling-crash-test	\
+	alphamap		\
 	blitters-test		\
 	scaling-test		\
 	composite
diff --git a/test/alphamap.c b/test/alphamap.c
index e6a25ef..09de387 100644
--- a/test/alphamap.c
+++ b/test/alphamap.c
@@ -2,47 +2,238 @@
 #include <stdlib.h>
 #include "utils.h"
 
-#define WIDTH 400
-#define HEIGHT 200
+#define WIDTH 100
+#define HEIGHT 100
 
-int
-main (int argc, char **argv)
+static const pixman_format_code_t formats[] =
+{
+    PIXMAN_a8r8g8b8,
+    PIXMAN_a2r10g10b10,
+    PIXMAN_a4r4g4b4,
+    PIXMAN_a8
+};
+
+static const pixman_format_code_t alpha_formats[] =
+{
+    PIXMAN_null,
+    PIXMAN_a8,
+    PIXMAN_a2r10g10b10,
+    PIXMAN_a4r4g4b4
+};
+
+static const int origins[] =
 {
-    uint8_t *alpha = make_random_bytes (WIDTH * HEIGHT);
-    uint32_t *src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4);
-    uint32_t *dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4);
-    int i;
+    0, 10, -100
+};
 
-    pixman_image_t *a = pixman_image_create_bits (PIXMAN_a8, WIDTH, HEIGHT, (uint32_t *)alpha, WIDTH);
-    pixman_image_t *d = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4);
+static const char *
+format_name (pixman_format_code_t format)
+{
+    if (format == PIXMAN_a8)
+	return "a8";
+    else if (format == PIXMAN_a2r10g10b10)
+	return "a2r10g10b10";
+    else if (format == PIXMAN_a8r8g8b8)
+	return "a8r8g8b8";
+    else if (format == PIXMAN_a4r4g4b4)
+	return "a4r4g4b4";
+    else if (format == PIXMAN_null)
+	return "none";
+    else
+	assert (0);
 
-    for (i = 0; i < 2; ++i)
+    return "<unknown - bug in alphamap.c>";
+}
+
+static pixman_image_t *
+make_image (pixman_format_code_t format)
+{
+    uint32_t *bits;
+    uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8;
+
+    bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp);
+
+    return pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp);
+}
+
+static pixman_image_t *
+create_image (pixman_format_code_t format, pixman_format_code_t alpha_format,
+	      int alpha_origin_x, int alpha_origin_y)
+{
+    pixman_image_t *image = make_image (format);
+
+    if (alpha_format != PIXMAN_null)
     {
-	pixman_format_code_t sformat = (i == 0)? PIXMAN_a8r8g8b8 : PIXMAN_a2r10g10b10;
-	pixman_image_t *s = pixman_image_create_bits (sformat, WIDTH, HEIGHT, src, WIDTH * 4);
-	int j, k;
+	pixman_image_t *alpha = make_image (alpha_format);
 
-	pixman_image_set_alpha_map (s, a, 0, 0);
+	pixman_image_set_alpha_map (image, alpha,
+				    alpha_origin_x, alpha_origin_y);
+    }
 
-	pixman_image_composite (PIXMAN_OP_SRC, s, NULL, d, 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
+    return image;
+}
 
-	for (j = 0; j < HEIGHT; ++j)
+static uint8_t
+get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
+{
+    uint8_t *bits;
+    uint8_t r;
+
+    if (image->common.alpha_map)
+    {
+	if (x - orig_x >= 0 && x - orig_x < WIDTH &&
+	    y - orig_y >= 0 && y - orig_y < HEIGHT)
+	{
+	    image = (pixman_image_t *)image->common.alpha_map;
+
+	    x -= orig_x;
+	    y -= orig_y;
+	}
+	else
 	{
-	    for (k = 0; k < WIDTH; ++k)
+	    return 0;
+	}
+    }
+
+    bits = (uint8_t *)image->bits.bits;
+
+    if (image->bits.format == PIXMAN_a8)
+    {
+	r = bits[y * WIDTH + x];
+    }
+    else if (image->bits.format == PIXMAN_a2r10g10b10)
+    {
+	r = ((uint32_t *)bits)[y * WIDTH + x] >> 30;
+	r |= r << 2;
+	r |= r << 4;
+    }
+    else if (image->bits.format == PIXMAN_a8r8g8b8)
+    {
+	r = ((uint32_t *)bits)[y * WIDTH + x] >> 24;
+    }
+    else if (image->bits.format == PIXMAN_a4r4g4b4)
+    {
+	r = ((uint16_t *)bits)[y * WIDTH + x] >> 12;
+	r |= r << 4;
+    }
+    else
+    {
+	assert (0);
+    }
+
+    return r;
+}
+
+#define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0])))
+
+static int
+run_test (int s, int d, int sa, int da, int soff, int doff)
+{
+    pixman_format_code_t sf = formats[s];
+    pixman_format_code_t df = formats[d];
+    pixman_format_code_t saf = alpha_formats[sa];
+    pixman_format_code_t daf = alpha_formats[da];
+    pixman_image_t *src, *dst, *orig_dst;
+    pixman_transform_t t1;
+    int j, k;
+    int n_alpha_bits;
+
+    soff = origins[soff];
+    doff = origins[doff];
+
+    n_alpha_bits = PIXMAN_FORMAT_A (df);
+    if (daf != PIXMAN_null)
+	n_alpha_bits = PIXMAN_FORMAT_A (daf);
+
+
+    src = create_image (sf, saf, soff, soff);
+    orig_dst = create_image (df, daf, doff, doff);
+    dst = create_image (df, daf, doff, doff);
+
+    /* Transformations on destinations should be ignored, so just set some
+     * random one.
+     */
+    pixman_transform_init_identity (&t1);
+    pixman_transform_scale (&t1, NULL, pixman_int_to_fixed (100), pixman_int_to_fixed (11));
+    pixman_transform_rotate (&t1, NULL, pixman_double_to_fixed (0.5), pixman_double_to_fixed (0.11));
+    pixman_transform_translate (&t1, NULL, pixman_int_to_fixed (11), pixman_int_to_fixed (17));
+
+#if 0
+    /* Unfortunately, this is actually broken at the moment, so we can't
+     * actually turn it on
+     */
+    pixman_image_set_transform (dst, &t1);
+#endif
+
+    pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst,
+			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
+
+    pixman_image_composite (PIXMAN_OP_ADD, src, NULL, dst,
+			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
+
+    for (j = MAX (doff, 0); j < MIN (HEIGHT, HEIGHT + doff); ++j)
+    {
+	for (k = MAX (doff, 0); k < MIN (WIDTH, WIDTH + doff); ++k)
+	{
+	    uint8_t sa, da, oda, ref;
+
+	    sa = get_alpha (src, k, j, soff, soff);
+	    da = get_alpha (dst, k, j, doff, doff);
+	    oda = get_alpha (orig_dst, k, j, doff, doff);
+
+	    if (sa + oda > 255)
+		ref = 255;
+	    else
+		ref = sa + oda;
+
+	    if (da >> (8 - n_alpha_bits) != ref >> (8 - n_alpha_bits))
 	    {
-		uint8_t ap = ((uint8_t *)alpha)[j * WIDTH + k];
-		uint32_t dap = (dest[j * WIDTH + k] >> 24);
-		uint32_t sap = (src[j * WIDTH + k] >> 24);
+		printf ("\nWrong alpha value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
+			k, j, ref, da, sa, oda);
+
+		printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
+			format_name (sf),
+			format_name (saf),
+			soff, soff,
+			format_name (df),
+			format_name (daf),
+			doff, doff);
+		return 1;
+	    }
+	}
+    }
+
+    pixman_image_unref (src);
+    pixman_image_unref (dst);
+    pixman_image_unref (orig_dst);
+
+    return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+    int i, j, a, b, x, y;
 
-		if (ap != dap)
+    for (i = 0; i < ARRAY_LENGTH (formats); ++i)
+    {
+	for (j = 0; j < ARRAY_LENGTH (formats); ++j)
+	{
+	    for (a = 0; a < ARRAY_LENGTH (alpha_formats); ++a)
+	    {
+		for (b = 0; b < ARRAY_LENGTH (alpha_formats); ++b)
 		{
-		    printf ("Wrong alpha value at (%d, %d). Should be %d; got %d (src was %d)\n", k, j, ap, dap, sap);
-		    return 1;
+		    for (x = 0; x < ARRAY_LENGTH (origins); ++x)
+		    {
+			for (y = 0; y < ARRAY_LENGTH (origins); ++y)
+			{
+			    if (run_test (i, j, a, b, x, y) != 0)
+				return 1;
+			}
+		    }
 		}
 	    }
 	}
-
-	pixman_image_unref (s);
     }
 
     return 0;
commit dc9fe269ea2a1a0b8334d0936e2541af48b81bc7
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Mon Sep 13 14:34:34 2010 -0400

    Add fence_malloc() and fence_free().
    
    These variants of malloc() and free() try to surround the allocated
    memory with protected pages so that out-of-bounds accessess will cause
    a segmentation fault.
    
    If mprotect() and getpagesize() are not available, these functions are
    simply equivalent to malloc() and free().

diff --git a/configure.ac b/configure.ac
index dbff2a6..d3b71fa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -623,6 +623,19 @@ if test x$have_alarm = xyes; then
    AC_DEFINE(HAVE_ALARM, 1, [Whether we have alarm()])
 fi
 
+AC_CHECK_HEADER([sys/mman.h],
+   [AC_DEFINE(HAVE_SYS_MMAN_H, [1], [Define to 1 if we have <sys/mman.h>])])
+
+AC_CHECK_FUNC(mprotect, have_mprotect=yes, have_mprotect=no)
+if test x$have_mprotect = xyes; then
+   AC_DEFINE(HAVE_MPROTECT, 1, [Whether we have mprotect()])
+fi
+
+AC_CHECK_FUNC(getpagesize, have_getpagesize=yes, have_getpagesize=no)
+if test x$have_getpagesize = xyes; then
+   AC_DEFINE(HAVE_GETPAGESIZE, 1, [Whether we have getpagesize()])
+fi
+
 dnl =====================================
 dnl Thread local storage
 
diff --git a/test/utils.c b/test/utils.c
index d95cbc2..580a51d 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -5,6 +5,10 @@
 #include <unistd.h>
 #endif
 
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
 /* Random number seed
  */
 
@@ -197,10 +201,112 @@ image_endian_swap (pixman_image_t *img, int bpp)
     }
 }
 
+#define N_LEADING_PROTECTED	10
+#define N_TRAILING_PROTECTED	10
+
+typedef struct
+{
+    void *addr;
+    uint32_t len;
+    uint8_t *trailing;
+    int n_bytes;
+} info_t;
+
+#if defined(HAVE_MPROTECT) && defined(HAVE_GETPAGESIZE)
+
+void *
+fence_malloc (uint32_t len)
+{
+    unsigned long page_size = getpagesize();
+    unsigned long page_mask = page_size - 1;
+    uint32_t n_payload_bytes = (len + page_mask) & ~page_mask;
+    uint32_t n_bytes =
+	(page_size * (N_LEADING_PROTECTED + N_TRAILING_PROTECTED + 2) +
+	 n_payload_bytes) & ~page_mask;
+    uint8_t *initial_page;
+    uint8_t *leading_protected;
+    uint8_t *trailing_protected;
+    uint8_t *payload;
+    uint8_t *addr;
+
+    addr = mmap (NULL, n_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
+		 -1, 0);
+
+    if (addr == (void *)MAP_FAILED)
+    {
+	printf ("mmap failed on %u %u\n", len, n_bytes);
+	return NULL;
+    }
+
+    initial_page = (uint8_t *)(((unsigned long)addr + page_mask) & ~page_mask);
+    leading_protected = initial_page + page_size;
+    payload = leading_protected + N_LEADING_PROTECTED * page_size;
+    trailing_protected = payload + n_payload_bytes;
+
+    ((info_t *)initial_page)->addr = addr;
+    ((info_t *)initial_page)->len = len;
+    ((info_t *)initial_page)->trailing = trailing_protected;
+    ((info_t *)initial_page)->n_bytes = n_bytes;
+
+    if (mprotect (leading_protected, N_LEADING_PROTECTED * page_size,
+		  PROT_NONE) == -1)
+    {
+	free (addr);
+	return NULL;
+    }
+
+    if (mprotect (trailing_protected, N_TRAILING_PROTECTED * page_size,
+		  PROT_NONE) == -1)
+    {
+	mprotect (leading_protected, N_LEADING_PROTECTED * page_size,
+		  PROT_READ | PROT_WRITE);
+
+	free (addr);
+	return NULL;
+    }
+
+    return payload;
+}
+
+void
+fence_free (void *data)
+{
+    uint32_t page_size = getpagesize();
+    uint8_t *payload = data;
+    uint8_t *leading_protected = payload - N_LEADING_PROTECTED * page_size;
+    uint8_t *initial_page = leading_protected - page_size;
+    info_t *info = (info_t *)initial_page;
+    uint8_t *trailing_protected = info->trailing;
+
+    mprotect (leading_protected, N_LEADING_PROTECTED * page_size,
+	      PROT_READ | PROT_WRITE);
+
+    mprotect (trailing_protected, N_LEADING_PROTECTED * page_size,
+	      PROT_READ | PROT_WRITE);
+
+    munmap (info->addr, info->n_bytes);
+}
+
+#else
+
+void *
+fence_malloc (uint32_t len)
+{
+    return malloc (len);
+}
+
+void
+fence_free (void *data)
+{
+    free (data);
+}
+
+#endif
+
 uint8_t *
 make_random_bytes (int n_bytes)
 {
-    uint8_t *bytes = malloc (n_bytes);
+    uint8_t *bytes = fence_malloc (n_bytes);
     int i;
 
     if (!bytes)
diff --git a/test/utils.h b/test/utils.h
index a39af02..14e3c8b 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -51,7 +51,16 @@ compute_crc32 (uint32_t    in_crc32,
 void
 image_endian_swap (pixman_image_t *img, int bpp);
 
-/* Generate n_bytes random bytes in malloced memory */
+/* Allocate memory that is bounded by protected pages,
+ * so that out-of-bounds access will cause segfaults
+ */
+void *
+fence_malloc (uint32_t len);
+
+void
+fence_free (void *data);
+
+/* Generate n_bytes random bytes in fence_malloced memory */
 uint8_t *
 make_random_bytes (int n_bytes);
 
commit f4dc73bad4f662bdc3c94cb1e224f9a1989beba5
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sun Sep 12 04:35:08 2010 -0400

    Do opacity computation with shifts instead of comparing with 0
    
    Also add a COMPILE_TIME_ASSERT() macro and use it to assert that the
    shift is correct.

diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 3557fb2..36b9d91 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -744,6 +744,9 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst,
 
 #undef DEBUG
 
+#define COMPILE_TIME_ASSERT(x)						\
+    do { typedef int compile_time_assertion [(x)?1:-1]; } while (0)
+
 /* Turn on debugging depending on what type of release this is
  */
 #if (((PIXMAN_VERSION_MICRO % 2) == 0) && ((PIXMAN_VERSION_MINOR % 2) == 1))
diff --git a/pixman/pixman.c b/pixman/pixman.c
index 47ffdd6..cdf4b75 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -139,14 +139,18 @@ optimize_operator (pixman_op_t     op,
 		   uint32_t        dst_flags)
 {
     pixman_bool_t is_source_opaque, is_dest_opaque;
-    int opaqueness;
 
-    is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE) != 0;
-    is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE) != 0;
+#define OPAQUE_SHIFT 13
+    
+    COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
+    
+    is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
+    is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
 
-    opaqueness = ((is_dest_opaque << 1) | is_source_opaque);
+    is_dest_opaque >>= OPAQUE_SHIFT - 1;
+    is_source_opaque >>= OPAQUE_SHIFT;
 
-    return operator_table[op].opaque_info[opaqueness];
+    return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
 }
 
 static void


More information about the xorg-commit mailing list