am afd5bbd8: Merge remote-tracking branch \'origin/kitkat-dev\'

* commit 'afd5bbd8074cedec8544d07920fa06786d5a4f08':
  Initial empty repository
diff --git a/pixman/Android.mk b/pixman/Android.mk
index 777aaf3..eb9436a 100644
--- a/pixman/Android.mk
+++ b/pixman/Android.mk
@@ -6,48 +6,21 @@
 
 LOCAL_MODULE := libpixman
 
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
+LOCAL_CFLAGS := -DHAVE_CONFIG_H -fvisibility=hidden
 
 # Core files
 LOCAL_SRC_FILES := \
-	pixman.c \
-	pixman-access.c \
-	pixman-access-accessors.c \
-	pixman-bits-image.c \
-	pixman-combine32.c \
-	pixman-combine-float.c \
-	pixman-conical-gradient.c \
-	pixman-filter.c \
-	pixman-x86.c \
-	pixman-mips.c \
-	pixman-arm.c \
-	pixman-ppc.c \
-	pixman-edge.c \
-	pixman-edge-accessors.c \
-	pixman-fast-path.c \
-	pixman-glyph.c \
-	pixman-general.c \
-	pixman-gradient-walker.c \
-	pixman-image.c \
-	pixman-implementation.c \
-	pixman-linear-gradient.c \
-	pixman-matrix.c \
-	pixman-noop.c \
-	pixman-radial-gradient.c \
-	pixman-region16.c \
-	pixman-region32.c \
-	pixman-solid-fill.c \
-	pixman-timer.c \
-	pixman-trap.c \
-	pixman-utils.c
+	pixman-matrix.c
+
+# Android additions
+LOCAL_SRC_FILES += \
+	pixman-android.c
 
 ifeq ($(strip $(TARGET_ARCH)),arm)
 	# Will only be used if runtime detection reports NEON capabilities
 	LOCAL_CFLAGS += -DUSE_ARM_NEON
 	LOCAL_SRC_FILES += \
-		pixman-arm-neon.c \
-		pixman-arm-neon-asm.S \
-		pixman-arm-neon-asm-bilinear.S
+		pixman-android-neon.S
 endif
 
 LOCAL_STATIC_LIBRARIES := cpufeatures
diff --git a/pixman/pixman-android-neon.S b/pixman/pixman-android-neon.S
new file mode 100644
index 0000000..46f5e9b
--- /dev/null
+++ b/pixman/pixman-android-neon.S
@@ -0,0 +1,353 @@
+/*
+ * Copyright © 2013 The Android Open Source Project
+ *
+ * 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.
+ */
+/*
+ * Copyright © 2009 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author:  Siarhei Siamashka (siarhei.siamashka@nokia.com)
+ */
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+    .text
+    .fpu neon
+    .arch armv7a
+    .object_arch armv4
+    .eabi_attribute 10, 0 /* suppress Tag_FP_arch */
+    .eabi_attribute 12, 0 /* suppress Tag_Advanced_SIMD_arch */
+    .arm
+    .altmacro
+    .p2align 2
+
+#include "pixman-private.h"
+#include "pixman-arm-neon-asm.h"
+
+.set RESPECT_STRICT_ALIGNMENT, 1
+.set PREFETCH_TYPE_DEFAULT, PREFETCH_TYPE_ADVANCED
+.set PREFETCH_DISTANCE_SIMPLE, 64
+
+.set BILINEAR_FLAG_UNROLL_4,          0
+.set BILINEAR_FLAG_UNROLL_8,          1
+.set BILINEAR_FLAG_USE_ALL_NEON_REGS, 2
+
+/* Supplementary macro for setting function attributes */
+.macro pixman_asm_function fname
+    .func fname
+    .global fname
+#ifdef __ELF__
+    .hidden fname
+    .type fname, %function
+#endif
+fname:
+.endm
+
+.macro bilinear_load_8888 reg1, reg2, tmp
+    mov       TMP1, X, asr #16
+    add       X, X, UX
+    add       TMP1, TOP, TMP1, asl #2
+    vld1.32   {reg1}, [TMP1], STRIDE
+    vld1.32   {reg2}, [TMP1]
+.endm
+
+.macro bilinear_load_and_vertical_interpolate_two_8888 \
+                    acc1, acc2, reg1, reg2, reg3, reg4, tmp1, tmp2
+
+    bilinear_load_8888 reg1, reg2, tmp1
+    vmull.u8  acc1, reg1, d28
+    vmlal.u8  acc1, reg2, d29
+    bilinear_load_8888 reg3, reg4, tmp2
+    vmull.u8  acc2, reg3, d28
+    vmlal.u8  acc2, reg4, d29
+.endm
+
+.macro bilinear_store_8888 numpix, tmp1, tmp2
+.if numpix == 4
+    vst1.32   {d0, d1}, [OUT, :128]!
+.elseif numpix == 2
+    vst1.32   {d0}, [OUT, :64]!
+.elseif numpix == 1
+    vst1.32   {d0[0]}, [OUT, :32]!
+.else
+    .error bilinear_store_8888 numpix is unsupported
+.endif
+.endm
+
+.macro bilinear_interpolate_last_pixel src_fmt, dst_fmt
+    bilinear_load_&src_fmt d0, d1, d2
+    vmull.u8  q1, d0, d28
+    vmlal.u8  q1, d1, d29
+    /* 5 cycles bubble */
+    vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS
+    vmlsl.u16 q0, d2, d30
+    vmlal.u16 q0, d3, d30
+    /* 5 cycles bubble */
+    vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS)
+    /* 3 cycles bubble */
+    vmovn.u16 d0, q0
+    /* 1 cycle bubble */
+    bilinear_store_&dst_fmt 1, q2, q3
+.endm
+
+.macro bilinear_interpolate_two_pixels src_fmt, dst_fmt
+    bilinear_load_and_vertical_interpolate_two_&src_fmt \
+                q1, q11, d0, d1, d20, d21, d22, d23
+    vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS
+    vmlsl.u16 q0, d2, d30
+    vmlal.u16 q0, d3, d30
+    vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS
+    vmlsl.u16 q10, d22, d31
+    vmlal.u16 q10, d23, d31
+    vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS)
+    vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS)
+    vshr.u16  q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS)
+    vadd.u16  q12, q12, q13
+    vmovn.u16 d0, q0
+    bilinear_store_&dst_fmt 2, q2, q3
+.endm
+
+.macro bilinear_interpolate_four_pixels src_fmt, dst_fmt
+    bilinear_load_and_vertical_interpolate_four_&src_fmt \
+                q1, q11, d0, d1, d20, d21, d22, d23 \
+                q3, q9,  d4, d5, d16, d17, d18, d19
+    pld       [TMP1, PF_OFFS]
+    sub       TMP1, TMP1, STRIDE
+    vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS
+    vmlsl.u16 q0, d2, d30
+    vmlal.u16 q0, d3, d30
+    vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS
+    vmlsl.u16 q10, d22, d31
+    vmlal.u16 q10, d23, d31
+    vshr.u16  q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS)
+    vshll.u16 q2, d6, #BILINEAR_INTERPOLATION_BITS
+    vmlsl.u16 q2, d6, d30
+    vmlal.u16 q2, d7, d30
+    vshll.u16 q8, d18, #BILINEAR_INTERPOLATION_BITS
+    pld       [TMP2, PF_OFFS]
+    vmlsl.u16 q8, d18, d31
+    vmlal.u16 q8, d19, d31
+    vadd.u16  q12, q12, q13
+    vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS)
+    vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS)
+    vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS)
+    vshrn.u32 d5, q8, #(2 * BILINEAR_INTERPOLATION_BITS)
+    vshr.u16  q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS)
+    vmovn.u16 d0, q0
+    vmovn.u16 d1, q2
+    vadd.u16  q12, q12, q13
+    bilinear_store_&dst_fmt 4, q2, q3
+.endm
+
+.macro bilinear_interpolate_four_pixels_head src_fmt, dst_fmt
+.ifdef have_bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt
+    bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt&_head
+.else
+    bilinear_interpolate_four_pixels src_fmt, dst_fmt
+.endif
+.endm
+
+.macro bilinear_interpolate_four_pixels_tail src_fmt, dst_fmt
+.ifdef have_bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt
+    bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt&_tail
+.endif
+.endm
+
+.macro bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt
+.ifdef have_bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt
+    bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt&_tail_head
+.else
+    bilinear_interpolate_four_pixels src_fmt, dst_fmt
+.endif
+.endm
+
+.macro bilinear_load_and_vertical_interpolate_four_8888 \
+                xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \
+                yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi
+
+    bilinear_load_and_vertical_interpolate_two_8888 \
+                xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi
+    bilinear_load_and_vertical_interpolate_two_8888 \
+                yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi
+.endm
+
+.macro generate_bilinear_scanline_func fname, src_fmt, dst_fmt, \
+                                       src_bpp_shift, dst_bpp_shift, \
+                                       prefetch_distance, flags
+
+pixman_asm_function fname
+    OUT       .req      r0
+    TOP       .req      r1
+    BOTTOM    .req      r2
+    WT        .req      r3
+    WB        .req      r4
+    X         .req      r5
+    UX        .req      r6
+    WIDTH     .req      ip
+    TMP1      .req      r3
+    TMP2      .req      r4
+    PF_OFFS   .req      r7
+    TMP3      .req      r8
+    TMP4      .req      r9
+    STRIDE    .req      r2
+
+    mov       ip, sp
+    push      {r4, r5, r6, r7, r8, r9}
+    mov       PF_OFFS, #prefetch_distance
+    ldmia     ip, {WB, X, UX, WIDTH}
+    mul       PF_OFFS, PF_OFFS, UX
+
+.if ((flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0
+    vpush     {d8-d15}
+.endif
+
+    sub       STRIDE, BOTTOM, TOP
+    .unreq    BOTTOM
+
+    cmp       WIDTH, #0
+    ble       3f
+
+    vdup.u16  q12, X
+    vdup.u16  q13, UX
+    vdup.u8   d28, WT
+    vdup.u8   d29, WB
+    vadd.u16  d25, d25, d26
+
+    /* ensure good destination alignment  */
+    cmp       WIDTH, #1
+    blt       0f
+    tst       OUT, #(1 << dst_bpp_shift)
+    beq       0f
+    vshr.u16  q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS)
+    vadd.u16  q12, q12, q13
+    bilinear_interpolate_last_pixel src_fmt, dst_fmt
+    sub       WIDTH, WIDTH, #1
+0:
+    vadd.u16  q13, q13, q13
+    vshr.u16  q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS)
+    vadd.u16  q12, q12, q13
+
+    cmp       WIDTH, #2
+    blt       0f
+    tst       OUT, #(1 << (dst_bpp_shift + 1))
+    beq       0f
+    bilinear_interpolate_two_pixels src_fmt, dst_fmt
+    sub       WIDTH, WIDTH, #2
+0:
+.if ((flags) & BILINEAR_FLAG_UNROLL_8) != 0
+/*********** 8 pixels per iteration *****************/
+    cmp       WIDTH, #4
+    blt       0f
+    tst       OUT, #(1 << (dst_bpp_shift + 2))
+    beq       0f
+    bilinear_interpolate_four_pixels src_fmt, dst_fmt
+    sub       WIDTH, WIDTH, #4
+0:
+    subs      WIDTH, WIDTH, #8
+    blt       1f
+    mov       PF_OFFS, PF_OFFS, asr #(16 - src_bpp_shift)
+    bilinear_interpolate_eight_pixels_head src_fmt, dst_fmt
+    subs      WIDTH, WIDTH, #8
+    blt       5f
+0:
+    bilinear_interpolate_eight_pixels_tail_head src_fmt, dst_fmt
+    subs      WIDTH, WIDTH, #8
+    bge       0b
+5:
+    bilinear_interpolate_eight_pixels_tail src_fmt, dst_fmt
+1:
+    tst       WIDTH, #4
+    beq       2f
+    bilinear_interpolate_four_pixels src_fmt, dst_fmt
+2:
+.else
+/*********** 4 pixels per iteration *****************/
+    subs      WIDTH, WIDTH, #4
+    blt       1f
+    mov       PF_OFFS, PF_OFFS, asr #(16 - src_bpp_shift)
+    bilinear_interpolate_four_pixels_head src_fmt, dst_fmt
+    subs      WIDTH, WIDTH, #4
+    blt       5f
+0:
+    bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt
+    subs      WIDTH, WIDTH, #4
+    bge       0b
+5:
+    bilinear_interpolate_four_pixels_tail src_fmt, dst_fmt
+1:
+/****************************************************/
+.endif
+    /* handle the remaining trailing pixels */
+    tst       WIDTH, #2
+    beq       2f
+    bilinear_interpolate_two_pixels src_fmt, dst_fmt
+2:
+    tst       WIDTH, #1
+    beq       3f
+    bilinear_interpolate_last_pixel src_fmt, dst_fmt
+3:
+.if ((flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0
+    vpop      {d8-d15}
+.endif
+    pop       {r4, r5, r6, r7, r8, r9}
+    bx        lr
+
+    .unreq    OUT
+    .unreq    TOP
+    .unreq    WT
+    .unreq    WB
+    .unreq    X
+    .unreq    UX
+    .unreq    WIDTH
+    .unreq    TMP1
+    .unreq    TMP2
+    .unreq    PF_OFFS
+    .unreq    TMP3
+    .unreq    TMP4
+    .unreq    STRIDE
+.endfunc
+
+.endm
+
+generate_bilinear_scanline_func \
+    pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon, 8888, 8888, \
+    2, 2, 28, BILINEAR_FLAG_UNROLL_4
+
diff --git a/pixman/pixman-android.c b/pixman/pixman-android.c
new file mode 100644
index 0000000..261c01b
--- /dev/null
+++ b/pixman/pixman-android.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright © 2013 The Android Open Source Project
+ *
+ * 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.
+ */
+/*
+ * Copyright © 2000 SuSE, Inc.
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  SuSE makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author:  Keith Packard, SuSE, Inc.
+ */
+/*
+ * Copyright © 2009 ARM Ltd, Movial Creative Technologies Oy
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of ARM Ltd not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  ARM Ltd makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Author:  Ian Rickards (ian.rickards@arm.com)
+ * Author:  Jonathan Morton (jonathan.morton@movial.com)
+ * Author:  Markku Vire (markku.vire@movial.com)
+ *
+ */
+
+#include "config.h"
+#include "pixman-android.h"
+#include "pixman-private.h"
+#include <cpu-features.h>
+
+static force_inline void scaled_nearest_scanline_8888_8888_none_SRC(
+        uint32_t *dst, const uint32_t *src, int32_t w, pixman_fixed_t vx,
+        pixman_fixed_t unit_x, pixman_fixed_t src_width_fixed) {
+    uint32_t d;
+    uint32_t s1, s2;
+    uint8_t a1, a2;
+    int x1, x2;
+
+    while ((w -= 2) >= 0) {
+        x1 = pixman_fixed_to_int(vx);
+        vx += unit_x;
+        s1 = *(src + x1);
+        x2 = pixman_fixed_to_int(vx);
+        vx += unit_x;
+        s2 = *(src + x2);
+        *dst++ = s1;
+        *dst++ = s2;
+    }
+    if (w & 1) {
+        x1 = pixman_fixed_to_int(vx);
+        s1 = *(src + x1);
+        *dst++ = s1;
+    }
+}
+
+static force_inline int pixman_fixed_to_bilinear_weight(pixman_fixed_t x) {
+    return (x >> (16 - BILINEAR_INTERPOLATION_BITS))
+            & ((1 << BILINEAR_INTERPOLATION_BITS) - 1);
+}
+
+/*
+ * For each scanline fetched from source image with PAD repeat:
+ * - calculate how many pixels need to be padded on the left side
+ * - calculate how many pixels need to be padded on the right side
+ * - update width to only count pixels which are fetched from the image
+ * All this information is returned via 'width', 'left_pad', 'right_pad'
+ * arguments. The code is assuming that 'unit_x' is positive.
+ *
+ * Note: 64-bit math is used in order to avoid potential overflows, which
+ *       is probably excessive in many cases. This particular function
+ *       may need its own correctness test and performance tuning.
+ */
+static force_inline void pad_repeat_get_scanline_bounds(
+        int32_t source_image_width, pixman_fixed_t vx, pixman_fixed_t unit_x,
+        int32_t * width, int32_t * left_pad, int32_t * right_pad) {
+    int64_t max_vx = (int64_t) source_image_width << 16;
+    int64_t tmp;
+    if (vx < 0) {
+        tmp = ((int64_t) unit_x - 1 - vx) / unit_x;
+        if (tmp > *width) {
+            *left_pad = *width;
+            *width = 0;
+        } else {
+            *left_pad = (int32_t) tmp;
+            *width -= (int32_t) tmp;
+        }
+    } else {
+        *left_pad = 0;
+    }
+    tmp = ((int64_t) unit_x - 1 - vx + max_vx) / unit_x - *left_pad;
+    if (tmp < 0) {
+        *right_pad = *width;
+        *width = 0;
+    } else if (tmp >= *width) {
+        *right_pad = 0;
+    } else {
+        *right_pad = *width - (int32_t) tmp;
+        *width = (int32_t) tmp;
+    }
+}
+
+static force_inline void bilinear_pad_repeat_get_scanline_bounds(
+        int32_t source_image_width, pixman_fixed_t vx, pixman_fixed_t unit_x,
+        int32_t * left_pad, int32_t * left_tz, int32_t * width,
+        int32_t * right_tz, int32_t * right_pad) {
+    int width1 = *width, left_pad1, right_pad1;
+    int width2 = *width, left_pad2, right_pad2;
+
+    pad_repeat_get_scanline_bounds(source_image_width, vx, unit_x, &width1,
+            &left_pad1, &right_pad1);
+    pad_repeat_get_scanline_bounds(source_image_width, vx + pixman_fixed_1,
+            unit_x, &width2, &left_pad2, &right_pad2);
+
+    *left_pad = left_pad2;
+    *left_tz = left_pad1 - left_pad2;
+    *right_tz = right_pad2 - right_pad1;
+    *right_pad = right_pad1;
+    *width -= *left_pad + *left_tz + *right_tz + *right_pad;
+}
+
+#ifdef USE_ARM_NEON
+void pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(uint32_t *dst,
+        const uint32_t *top, const uint32_t *bottom, int wt, int wb,
+        pixman_fixed_t x, pixman_fixed_t ux, int width);
+
+static void android_bilinear_filter_neon(android_simple_image* src_image,
+        android_simple_image* dst_image, float scale, int src_x, int src_y) {
+    int32_t src_width = src_image->width;
+    int32_t src_height = src_image->height;
+    pixman_vector_t v;
+    int32_t left_pad, left_tz, right_tz, right_pad;
+    pixman_fixed_t unit_x, unit_y;
+    int32_t width = dst_image->width;
+    int32_t height = dst_image->height;
+    uint32_t dst_line = 0;
+    uint32_t* dst;
+    int y1, y2;
+    pixman_fixed_t vx, vy;
+    /* reference point is the center of the pixel */
+    v.vector[0] = pixman_double_to_fixed((src_x + 0.5f) * scale);
+    v.vector[1] = pixman_double_to_fixed((src_y + 0.5f) * scale);
+    v.vector[2] = pixman_fixed_1;
+    unit_x = unit_y = pixman_double_to_fixed(scale);
+    vy = v.vector[1];
+    bilinear_pad_repeat_get_scanline_bounds(src_width, v.vector[0], unit_x,
+            &left_pad, &left_tz, &width, &right_tz, &right_pad);
+    v.vector[0] += left_pad * unit_x;
+    while (--height >= 0) {
+        int weight1, weight2;
+        dst_image->get_scanline(dst_image, (void**)(&dst), dst_line);
+        dst_line++;
+        vx = v.vector[0];
+        y1 = pixman_fixed_to_int(vy);
+        weight2 = pixman_fixed_to_bilinear_weight(vy);
+        if (weight2) {
+            /* both weight1 and weight2 are smaller than BILINEAR_INTERPOLATION_RANGE */
+            y2 = y1 + 1;
+            weight1 = BILINEAR_INTERPOLATION_RANGE - weight2;
+        } else {
+            /* set both top and bottom row to the same scanline and tweak weights */
+            y2 = y1;
+            weight1 = weight2 = BILINEAR_INTERPOLATION_RANGE / 2;
+        }
+        vy += unit_y;
+        uint32_t buf1[2];
+        uint32_t buf2[2];
+        uint32_t* src1;
+        uint32_t* src2;
+        /* handle top/bottom zero padding by just setting weights to 0 if needed */
+        if (y1 < 0) {
+            weight1 = 0;
+            y1 = 0;
+        }
+        if (y1 >= src_height) {
+            weight1 = 0;
+            y1 = src_height - 1;
+        }
+        if (y2 < 0) {
+            weight2 = 0;
+            y2 = 0;
+        }
+        if (y2 >= src_height) {
+            weight2 = 0;
+            y2 = src_height - 1;
+        }
+        src_image->get_scanline(src_image, (void**)(&src1), y1);
+        src_image->get_scanline(src_image, (void**)(&src2), y2);
+        if (left_pad > 0) {
+            buf1[0] = buf1[1] = 0;
+            buf2[0] = buf2[1] = 0;
+            pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(
+                    dst, buf1, buf2, weight1, weight2, 0, 0, left_pad);
+            dst += left_pad;
+        }
+        if (left_tz > 0) {
+            buf1[0] = 0;
+            buf1[1] = src1[0];
+            buf2[0] = 0;
+            buf2[1] = src2[0];
+            pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(
+                    dst, buf1, buf2, weight1, weight2,
+                    pixman_fixed_frac(vx), unit_x, left_tz);
+            dst += left_tz;
+            vx += left_tz * unit_x;
+        }
+        if (width > 0) {
+            pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(
+                    dst, src1, src2, weight1, weight2, vx, unit_x, width);
+            dst += width;
+            vx += width * unit_x;
+        }
+        if (right_tz > 0) {
+            buf1[0] = src1[src_width - 1];
+            buf1[1] = 0;
+            buf2[0] = src2[src_width - 1];
+            buf2[1] = 0;
+            pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(
+                    dst, buf1, buf2, weight1, weight2,
+                    pixman_fixed_frac(vx), unit_x, right_tz);
+            dst += right_tz;
+        }
+        if (right_pad > 0) {
+            buf1[0] = buf1[1] = 0;
+            buf2[0] = buf2[1] = 0;
+            pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(
+                    dst, buf1, buf2, weight1, weight2, 0, 0, right_pad);
+        }
+    }
+}
+#endif // ARM_USE_NEON
+
+static void android_nearest_filter(android_simple_image* src_image,
+        android_simple_image* dst_image, float scale, int src_x, int src_y) {
+    int32_t src_width = src_image->width;
+    int32_t src_height = src_image->height;
+    int32_t width = dst_image->width;
+    int32_t height = dst_image->height;
+    uint32_t dst_line = 0;
+    int y;
+    pixman_fixed_t src_width_fixed = pixman_int_to_fixed(src_width);
+    pixman_fixed_t max_vy;
+    pixman_vector_t v;
+    pixman_fixed_t vx, vy;
+    pixman_fixed_t unit_x, unit_y;
+    int32_t left_pad, right_pad;
+    uint32_t *src;
+    uint32_t *dst;
+    /* reference point is the center of the pixel */
+    v.vector[0] = pixman_double_to_fixed((src_x + 0.5f) * scale);
+    v.vector[1] = pixman_double_to_fixed((src_y + 0.5f) * scale);
+    v.vector[2] = pixman_fixed_1;
+    unit_x = unit_y = pixman_double_to_fixed(scale);
+    vx = v.vector[0];
+    vy = v.vector[1];
+    pad_repeat_get_scanline_bounds(src_width, vx, unit_x,
+            &width, &left_pad, &right_pad);
+    vx += left_pad * unit_x;
+    while (--height >= 0) {
+        dst_image->get_scanline(dst_image, (void**)(&dst), dst_line);
+        dst_line++;
+        y = ((int) ((vy) >> 16));
+        vy += unit_y;
+        static const uint32_t zero[1] = { 0 };
+        if (y < 0 || y >= src_height) {
+            scaled_nearest_scanline_8888_8888_none_SRC(
+                    dst, zero + 1, left_pad + width + right_pad,
+                    -((pixman_fixed_t) 1), 0, src_width_fixed);
+            continue;
+        }
+        src_image->get_scanline(src_image, (void**)(&src), y);
+        if (left_pad > 0) {
+            scaled_nearest_scanline_8888_8888_none_SRC(
+                    dst, zero + 1, left_pad, -((pixman_fixed_t) 1), 0,
+                    src_width_fixed);
+        }
+        if (width > 0) {
+            scaled_nearest_scanline_8888_8888_none_SRC(
+                    dst + left_pad, src + src_width, width,
+                    vx - src_width_fixed, unit_x, src_width_fixed);
+        }
+        if (right_pad > 0) {
+            scaled_nearest_scanline_8888_8888_none_SRC(
+                    dst + left_pad + width, zero + 1, right_pad,
+                    -((pixman_fixed_t) 1), 0, src_width_fixed);
+        }
+    }
+}
+
+PIXMAN_EXPORT void android_simple_scale(android_simple_image* src_image,
+        android_simple_image* dst_image, float scale, int src_x, int src_y) {
+#ifdef USE_ARM_NEON
+    if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM
+            && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON)) {
+        android_bilinear_filter_neon(src_image, dst_image, scale, src_x, src_y);
+        return;
+    }
+#endif
+    android_nearest_filter(src_image, dst_image, scale, src_x, src_y);
+}
diff --git a/pixman/pixman-android.h b/pixman/pixman-android.h
new file mode 100644
index 0000000..96ac19c
--- /dev/null
+++ b/pixman/pixman-android.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PIXMAN_ANDROID_H_
+#define PIXMAN_ANDROID_H_
+
+typedef struct _android_simple_image android_simple_image;
+
+struct _android_simple_image {
+    int width;
+    int height;
+    int bpp;
+    void* user_object;
+    void (*get_scanline)(android_simple_image* self, void** buffer, int line);
+};
+
+void android_simple_scale(android_simple_image* src_image,
+        android_simple_image* dst_image, float scale, int src_x, int src_y);
+
+#endif /* PIXMAN_ANDROID_H_ */