[cairo-commit] 6 commits - acinclude.m4 configure.in perf/cairo-perf.c perf/cairo-perf-diff src/cairo-fixed.c

Carl Worth cworth at kemper.freedesktop.org
Mon Nov 6 10:16:37 PST 2006


 acinclude.m4         |   65 +++++++++++++++++++++++++++++++++++++++++++++++++++
 configure.in         |    1 
 perf/cairo-perf-diff |   26 ++++++++++++++++++--
 perf/cairo-perf.c    |    2 +
 src/cairo-fixed.c    |   48 ++++++++++++++++++++++++++++++++++++-
 5 files changed, 138 insertions(+), 4 deletions(-)

New commits:
diff-tree 52eb7134bd22c648a10e2b9b8c5d1409de309887 (from e760d0927ee5b732392284fc19fda225f137f909)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Nov 3 15:32:57 2006 -0800

    cairo-perf-diff: Use two-part hash to avoid stale data when perf suite changes.
    
    The perf tree's sha1 is now in the cache file name, so that
    if the performance suite itself ever changes then new data
    will be generated rather than using stale stuff from the cache.
    
    Also, we now use the src tree's sha1 rather than the commit's
    so that commits that don't change the src directory are also
    treated as identical, (which they really should be as far as
    performance of the library itself is concerned).

diff --git a/perf/cairo-perf-diff b/perf/cairo-perf-diff
index f261c7e..b1e5458 100755
--- a/perf/cairo-perf-diff
+++ b/perf/cairo-perf-diff
@@ -46,13 +46,25 @@ git_setup() {
 
 rev2sha() {
     rev=$1
-    git rev-parse --verify $rev || ( echo "Cannot resolve $rev to a revision" && exit 1 )
+    git rev-parse --verify $rev || ( echo "Cannot resolve $rev as a git object" && exit 1 )
 }
 
+# We cache performance output based on a two-part name capturing the
+# current performance test suite and the library being tested. We
+# capture these as the tree object of the perf directory in HEAD and
+# the tree object of the src directory of the revision being tested.
+#
+# This way, whenever the performance suite is updated, cached output
+# from old versions of the suite are automatically invalidated. Also,
+# if a commit just changes things outside of the src tree, (say it
+# changes the "test" test suite, or README or configure.in, or
+# whatever), cairo-perf-diff will be smart enough to still use cached
+# results from a run with an equivalent src tree.
 rev2perf() {
     rev=$1
-    sha=$(rev2sha $rev)
-    echo "$CAIRO_PERF_DIR/$sha.perf"
+    src_tree_sha=$(rev2sha $rev:src)
+    perf_tree_sha=$(rev2sha HEAD:perf)
+    echo "$CAIRO_PERF_DIR/${perf_tree_sha}-${src_tree_sha}.perf"
 }
 
 # Usage: run_cairo_perf_if_not_cached <rev>
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 0bee719..2212676 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -68,7 +68,7 @@ target_is_measurable (cairo_boilerplate_
     case CAIRO_SURFACE_TYPE_WIN32:
     case CAIRO_SURFACE_TYPE_BEOS:
     case CAIRO_SURFACE_TYPE_DIRECTFB:
-#if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR = 1 && CAIRO_VERSION_MINOR > 2)
+#if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR > 2)
     case CAIRO_SURFACE_TYPE_NQUARTZ:
     case CAIRO_SURFACE_TYPE_OS2:
 #endif
diff-tree e760d0927ee5b732392284fc19fda225f137f909 (from 4cd50965a1935bf934f39f9e35b7d1a055ae7e16)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Nov 3 14:58:30 2006 -0800

    Don't rely on NQUARTZ or OS2 surface types unless they exist.
    
    This allows the cairo-perf stuff to build on older checkouts,
    (such as 1.2.4), so that we can usefully do things like:
    
    	cairo-perf-diff 1.2.4 HEAD

diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 91f8e68..0bee719 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -68,8 +68,10 @@ target_is_measurable (cairo_boilerplate_
     case CAIRO_SURFACE_TYPE_WIN32:
     case CAIRO_SURFACE_TYPE_BEOS:
     case CAIRO_SURFACE_TYPE_DIRECTFB:
+#if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR = 1 && CAIRO_VERSION_MINOR > 2)
     case CAIRO_SURFACE_TYPE_NQUARTZ:
     case CAIRO_SURFACE_TYPE_OS2:
+#endif
 	return TRUE;
     case CAIRO_SURFACE_TYPE_PDF:
     case CAIRO_SURFACE_TYPE_PS:
diff-tree 4cd50965a1935bf934f39f9e35b7d1a055ae7e16 (from 5376e474255b80d084dd250cab6ea5c14220a3f3)
Author: Dan Amelang <dan at amelang.net>
Date:   Sun Oct 29 21:31:23 2006 -0800

    Change _cairo_fixed_from_double to use the "magic number" technique
    
    See long thread here:
    http://lists.freedesktop.org/archives/cairo/2006-October/008285.html
    
    This patch provides a 3x performance improvement (on x86) for the
    conversion of floating-point to fixed-point values as measured by
    the recent pattern_create_radial performance test:
    
    image-rgba      pattern_create_radial-16     8.98 3.36% ->   2.97 1.03%:  3.38x speedup
    ██▍
    image-rgb       pattern_create_radial-16     8.94 3.21% ->   2.97 0.18%:  3.36x speedup
    ██▍
     xlib-rgb       pattern_create_radial-16     9.55 3.17% ->   3.64 0.51%:  2.93x speedup
    █▉
     xlib-rgba      pattern_create_radial-16     9.63 3.53% ->   3.69 0.66%:  2.91x speedup
    █▉

diff --git a/src/cairo-fixed.c b/src/cairo-fixed.c
index 604c9e7..fe6c2dc 100644
--- a/src/cairo-fixed.c
+++ b/src/cairo-fixed.c
@@ -42,10 +42,56 @@ _cairo_fixed_from_int (int i)
     return i << 16;
 }
 
+/* This is the "magic number" approach to converting a double into fixed
+ * point as described here:
+ *
+ * http://www.stereopsis.com/sree/fpu2006.html (an overview)
+ * http://www.d6.com/users/checker/pdfs/gdmfp.pdf (in detail)
+ *
+ * The basic idea is to add a large enough number to the double that the
+ * literal floating point is moved up to the extent that it forces the
+ * double's value to be shifted down to the bottom of the mantissa (to make
+ * room for the large number being added in). Since the mantissa is, at a
+ * given moment in time, a fixed point integer itself, one can convert a
+ * float to various fixed point representations by moving around the point
+ * of a floating point number through arithmetic operations. This behavior
+ * is reliable on most modern platforms as it is mandated by the IEEE-754
+ * standard for floating point arithmetic.
+ *
+ * For our purposes, a "magic number" must be carefully selected that is
+ * both large enough to produce the desired point-shifting effect, and also
+ * has no lower bits in its representation that would interfere with our
+ * value at the bottom of the mantissa. The magic number is calculated as
+ * follows:
+ *
+ *          (2 ^ (MANTISSA_SIZE - FRACTIONAL_SIZE)) * 1.5
+ *
+ * where in our case:
+ *  - MANTISSA_SIZE for 64-bit doubles is 52
+ *  - FRACTIONAL_SIZE for 16.16 fixed point is 16
+ *
+ * Although this approach provides a very large speedup of this function
+ * on a wide-array of systems, it does come with two caveats:
+ *
+ * 1) It uses banker's rounding as opposed to arithmetic rounding.
+ * 2) It doesn't function properly if the FPU is in single-precision
+ *    mode.
+ */
+#define CAIRO_MAGIC_NUMBER_FIXED_16_16 (103079215104.0)
 cairo_fixed_t
 _cairo_fixed_from_double (double d)
 {
-    return (cairo_fixed_t) floor (d * 65536 + 0.5);
+    union {
+        double d;
+        int32_t i[2];
+    } u;
+
+    u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16;
+#ifdef FLOAT_WORDS_BIGENDIAN
+    return u.i[1];
+#else
+    return u.i[0];
+#endif
 }
 
 cairo_fixed_t
diff-tree 5376e474255b80d084dd250cab6ea5c14220a3f3 (from 941b517024c79dfd157337565477b0a440924702)
Author: Dan Amelang <dan at amelang.net>
Date:   Sun Oct 29 21:30:08 2006 -0800

    Add autoconf macro AX_C_FLOAT_WORDS_BIGENDIAN
    
    The symbol that this macro defines (FLOAT_WORDS_BIGENDIAN) can be used
    to make double arithmetic tricks portable.

diff --git a/acinclude.m4 b/acinclude.m4
index af73800..a0eb13a 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -51,3 +51,68 @@ ifelse([$1],[],,
   AM_CONDITIONAL(ENABLE_GTK_DOC, test x$enable_gtk_doc = xyes)
   AM_CONDITIONAL(GTK_DOC_USE_LIBTOOL, test -n "$LIBTOOL")
 ])
+
+# AX_C_FLOAT_WORDS_BIGENDIAN ([ACTION-IF-TRUE], [ACTION-IF-FALSE],
+#                             [ACTION-IF-UNKNOWN])
+#
+# Checks the ordering of words within a multi-word float. This check
+# is necessary because on some systems (e.g. certain ARM systems), the
+# float word ordering can be different from the byte ordering. In a
+# multi-word float context, "big-endian" implies that the word containing
+# the sign bit is found in the memory location with the lowest address.
+# This implemenation was inspired by the AC_C_BIGENDIAN macro in autoconf.
+# -------------------------------------------------------------------------
+AC_DEFUN([AX_C_FLOAT_WORDS_BIGENDIAN],
+  [AC_CACHE_CHECK(whether float word ordering is bigendian,
+                  ax_cv_c_float_words_bigendian, [
+
+# The endianess is detected by first compiling C code that contains a special
+# double float value, then grepping the resulting object file for certain
+# strings of ascii values. The double is specially crafted to have a
+# binary representation that corresponds with a simple string. In this
+# implementation, the string "noonsees" was selected because the individual
+# word values ("noon" and "sees") are palindromes, thus making this test
+# byte-order agnostic. If grep finds the string "noonsees" in the object
+# file, the target platform stores float words in big-endian order. If grep
+# finds "seesnoon", float words are in little-endian order. If neither value
+# is found, the user is instructed to specify the ordering.
+
+ax_cv_c_float_words_bigendian=unknown
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+
+double d = 90904234967036810337470478905505011476211692735615632014797120844053488865816695273723469097858056257517020191247487429516932130503560650002327564517570778480236724525140520121371739201496540132640109977779420565776568942592.0;
+
+]])], [
+
+if grep noonsees conftest.$ac_objext >/dev/null ; then
+  ax_cv_c_float_words_bigendian=yes
+fi
+if grep seesnoon conftest.$ac_objext >/dev/null ; then
+  if test "$ax_cv_c_float_words_bigendian" = unknown; then
+    ax_cv_c_float_words_bigendian=no
+  else
+    ax_cv_c_float_words_bigendian=unknown
+  fi
+fi
+
+])])
+
+case $ax_cv_c_float_words_bigendian in
+  yes)
+    m4_default([$1],
+      [AC_DEFINE([FLOAT_WORDS_BIGENDIAN], 1,
+                 [Define to 1 if your system stores words within floats
+                  with the most significant word first])]) ;;
+  no)
+    $2 ;;
+  *)
+    m4_default([$3],
+      [AC_MSG_ERROR([
+
+Unknown float word ordering. You need to manually preset
+ax_cv_c_float_words_bigendian=no (or yes) according to your system.
+
+    ])]) ;;
+esac
+
+])# AX_C_FLOAT_WORDS_BIGENDIAN
diff --git a/configure.in b/configure.in
index c45258b..ade9df6 100644
--- a/configure.in
+++ b/configure.in
@@ -55,6 +55,7 @@ AC_PROG_CPP
 AC_PROG_LIBTOOL dnl required version (1.4) DON'T REMOVE!
 AC_STDC_HEADERS
 AC_C_BIGENDIAN
+AX_C_FLOAT_WORDS_BIGENDIAN
 
 dnl ===========================================================================
 dnl === Local macros
diff-tree 941b517024c79dfd157337565477b0a440924702 (from e2ede57fbb8d729f066bc592e33bae23a11fa4d9)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Nov 3 13:26:48 2006 -0800

    cairo-perf-diff: Build and run latest cairo-perf program rather than whatever was in the old checkout

diff --git a/perf/cairo-perf-diff b/perf/cairo-perf-diff
index a751256..f261c7e 100755
--- a/perf/cairo-perf-diff
+++ b/perf/cairo-perf-diff
@@ -80,6 +80,11 @@ run_cairo_perf_if_not_cached() {
     git checkout tmp-cairo-perf-diff
     git reset --hard $sha
     make CFLAGS="-O2" || (rm config.cache && make CFLAGS="-O2")
+    cp -a $CAIRO_DIR/boilerplate .
+    (cd boilerplate; make)
+    cp -a $CAIRO_DIR/perf .
+    cd perf;
+    make || exit 1
     (make perf || echo "*** Performance test crashed") > $perf
     cd $owd
 }
diff-tree e2ede57fbb8d729f066bc592e33bae23a11fa4d9 (from 8e74f9f945f4a498ec64930ddd46cc89129812bc)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Nov 3 12:40:09 2006 -0800

    cairo-perf-diff: Fix to still function if run from the top-level directory containing .git

diff --git a/perf/cairo-perf-diff b/perf/cairo-perf-diff
index 9864a31..a751256 100755
--- a/perf/cairo-perf-diff
+++ b/perf/cairo-perf-diff
@@ -38,6 +38,9 @@ git_setup() {
     SUBDIRECTORY_OK='Yes'
     . git-sh-setup
     CAIRO_DIR=$(dirname $GIT_DIR)
+    if [ "$CAIRO_DIR" = "." ]; then
+	CAIRO_DIR=$(pwd)
+    fi
     CAIRO_PERF_DIR=$CAIRO_DIR/.perf
 }
 


More information about the cairo-commit mailing list