13c5ee0fc482e93912b9b090d0df1af496288a702John Reck/* 23c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Copyright © 2013 The Android Open Source Project 33c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 43c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Permission is hereby granted, free of charge, to any person obtaining a 53c5ee0fc482e93912b9b090d0df1af496288a702John Reck * copy of this software and associated documentation files (the "Software"), 63c5ee0fc482e93912b9b090d0df1af496288a702John Reck * to deal in the Software without restriction, including without limitation 73c5ee0fc482e93912b9b090d0df1af496288a702John Reck * the rights to use, copy, modify, merge, publish, distribute, sublicense, 83c5ee0fc482e93912b9b090d0df1af496288a702John Reck * and/or sell copies of the Software, and to permit persons to whom the 93c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Software is furnished to do so, subject to the following conditions: 103c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 113c5ee0fc482e93912b9b090d0df1af496288a702John Reck * The above copyright notice and this permission notice (including the next 123c5ee0fc482e93912b9b090d0df1af496288a702John Reck * paragraph) shall be included in all copies or substantial portions of the 133c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Software. 143c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 153c5ee0fc482e93912b9b090d0df1af496288a702John Reck * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 163c5ee0fc482e93912b9b090d0df1af496288a702John Reck * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 173c5ee0fc482e93912b9b090d0df1af496288a702John Reck * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 183c5ee0fc482e93912b9b090d0df1af496288a702John Reck * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 193c5ee0fc482e93912b9b090d0df1af496288a702John Reck * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 203c5ee0fc482e93912b9b090d0df1af496288a702John Reck * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 213c5ee0fc482e93912b9b090d0df1af496288a702John Reck * DEALINGS IN THE SOFTWARE. 223c5ee0fc482e93912b9b090d0df1af496288a702John Reck */ 233c5ee0fc482e93912b9b090d0df1af496288a702John Reck/* 243c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Copyright © 2000 SuSE, Inc. 253c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Copyright © 2007 Red Hat, Inc. 263c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 273c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Permission to use, copy, modify, distribute, and sell this software and its 283c5ee0fc482e93912b9b090d0df1af496288a702John Reck * documentation for any purpose is hereby granted without fee, provided that 293c5ee0fc482e93912b9b090d0df1af496288a702John Reck * the above copyright notice appear in all copies and that both that 303c5ee0fc482e93912b9b090d0df1af496288a702John Reck * copyright notice and this permission notice appear in supporting 313c5ee0fc482e93912b9b090d0df1af496288a702John Reck * documentation, and that the name of SuSE not be used in advertising or 323c5ee0fc482e93912b9b090d0df1af496288a702John Reck * publicity pertaining to distribution of the software without specific, 333c5ee0fc482e93912b9b090d0df1af496288a702John Reck * written prior permission. SuSE makes no representations about the 343c5ee0fc482e93912b9b090d0df1af496288a702John Reck * suitability of this software for any purpose. It is provided "as is" 353c5ee0fc482e93912b9b090d0df1af496288a702John Reck * without express or implied warranty. 363c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 373c5ee0fc482e93912b9b090d0df1af496288a702John Reck * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 383c5ee0fc482e93912b9b090d0df1af496288a702John Reck * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 393c5ee0fc482e93912b9b090d0df1af496288a702John Reck * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 403c5ee0fc482e93912b9b090d0df1af496288a702John Reck * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 413c5ee0fc482e93912b9b090d0df1af496288a702John Reck * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 423c5ee0fc482e93912b9b090d0df1af496288a702John Reck * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 433c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 443c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Author: Keith Packard, SuSE, Inc. 453c5ee0fc482e93912b9b090d0df1af496288a702John Reck */ 463c5ee0fc482e93912b9b090d0df1af496288a702John Reck/* 473c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Copyright © 2009 ARM Ltd, Movial Creative Technologies Oy 483c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 493c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Permission to use, copy, modify, distribute, and sell this software and its 503c5ee0fc482e93912b9b090d0df1af496288a702John Reck * documentation for any purpose is hereby granted without fee, provided that 513c5ee0fc482e93912b9b090d0df1af496288a702John Reck * the above copyright notice appear in all copies and that both that 523c5ee0fc482e93912b9b090d0df1af496288a702John Reck * copyright notice and this permission notice appear in supporting 533c5ee0fc482e93912b9b090d0df1af496288a702John Reck * documentation, and that the name of ARM Ltd not be used in 543c5ee0fc482e93912b9b090d0df1af496288a702John Reck * advertising or publicity pertaining to distribution of the software without 553c5ee0fc482e93912b9b090d0df1af496288a702John Reck * specific, written prior permission. ARM Ltd makes no 563c5ee0fc482e93912b9b090d0df1af496288a702John Reck * representations about the suitability of this software for any purpose. It 573c5ee0fc482e93912b9b090d0df1af496288a702John Reck * is provided "as is" without express or implied warranty. 583c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 593c5ee0fc482e93912b9b090d0df1af496288a702John Reck * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 603c5ee0fc482e93912b9b090d0df1af496288a702John Reck * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 613c5ee0fc482e93912b9b090d0df1af496288a702John Reck * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 623c5ee0fc482e93912b9b090d0df1af496288a702John Reck * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 633c5ee0fc482e93912b9b090d0df1af496288a702John Reck * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 643c5ee0fc482e93912b9b090d0df1af496288a702John Reck * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 653c5ee0fc482e93912b9b090d0df1af496288a702John Reck * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 663c5ee0fc482e93912b9b090d0df1af496288a702John Reck * SOFTWARE. 673c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 683c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Author: Ian Rickards (ian.rickards@arm.com) 693c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Author: Jonathan Morton (jonathan.morton@movial.com) 703c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Author: Markku Vire (markku.vire@movial.com) 713c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 723c5ee0fc482e93912b9b090d0df1af496288a702John Reck */ 733c5ee0fc482e93912b9b090d0df1af496288a702John Reck 743c5ee0fc482e93912b9b090d0df1af496288a702John Reck#include "config.h" 753c5ee0fc482e93912b9b090d0df1af496288a702John Reck#include "pixman-android.h" 763c5ee0fc482e93912b9b090d0df1af496288a702John Reck#include "pixman-private.h" 775e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck#include <cpu-features.h> 783c5ee0fc482e93912b9b090d0df1af496288a702John Reck 795e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reckstatic force_inline void scaled_nearest_scanline_8888_8888_none_SRC( 805e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck uint32_t *dst, const uint32_t *src, int32_t w, pixman_fixed_t vx, 815e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_fixed_t unit_x, pixman_fixed_t src_width_fixed) { 825e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck uint32_t d; 835e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck uint32_t s1, s2; 845e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck uint8_t a1, a2; 855e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck int x1, x2; 863c5ee0fc482e93912b9b090d0df1af496288a702John Reck 875e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck while ((w -= 2) >= 0) { 885e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck x1 = pixman_fixed_to_int(vx); 895e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck vx += unit_x; 905e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck s1 = *(src + x1); 915e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck x2 = pixman_fixed_to_int(vx); 925e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck vx += unit_x; 935e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck s2 = *(src + x2); 945e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck *dst++ = s1; 955e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck *dst++ = s2; 965e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck } 975e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck if (w & 1) { 985e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck x1 = pixman_fixed_to_int(vx); 995e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck s1 = *(src + x1); 1005e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck *dst++ = s1; 1015e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck } 1023c5ee0fc482e93912b9b090d0df1af496288a702John Reck} 1033c5ee0fc482e93912b9b090d0df1af496288a702John Reck 1045e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reckstatic force_inline int pixman_fixed_to_bilinear_weight(pixman_fixed_t x) { 1053c5ee0fc482e93912b9b090d0df1af496288a702John Reck return (x >> (16 - BILINEAR_INTERPOLATION_BITS)) 1063c5ee0fc482e93912b9b090d0df1af496288a702John Reck & ((1 << BILINEAR_INTERPOLATION_BITS) - 1); 1073c5ee0fc482e93912b9b090d0df1af496288a702John Reck} 1083c5ee0fc482e93912b9b090d0df1af496288a702John Reck 1093c5ee0fc482e93912b9b090d0df1af496288a702John Reck/* 1103c5ee0fc482e93912b9b090d0df1af496288a702John Reck * For each scanline fetched from source image with PAD repeat: 1113c5ee0fc482e93912b9b090d0df1af496288a702John Reck * - calculate how many pixels need to be padded on the left side 1123c5ee0fc482e93912b9b090d0df1af496288a702John Reck * - calculate how many pixels need to be padded on the right side 1133c5ee0fc482e93912b9b090d0df1af496288a702John Reck * - update width to only count pixels which are fetched from the image 1143c5ee0fc482e93912b9b090d0df1af496288a702John Reck * All this information is returned via 'width', 'left_pad', 'right_pad' 1153c5ee0fc482e93912b9b090d0df1af496288a702John Reck * arguments. The code is assuming that 'unit_x' is positive. 1163c5ee0fc482e93912b9b090d0df1af496288a702John Reck * 1173c5ee0fc482e93912b9b090d0df1af496288a702John Reck * Note: 64-bit math is used in order to avoid potential overflows, which 1183c5ee0fc482e93912b9b090d0df1af496288a702John Reck * is probably excessive in many cases. This particular function 1193c5ee0fc482e93912b9b090d0df1af496288a702John Reck * may need its own correctness test and performance tuning. 1203c5ee0fc482e93912b9b090d0df1af496288a702John Reck */ 1213c5ee0fc482e93912b9b090d0df1af496288a702John Reckstatic force_inline void pad_repeat_get_scanline_bounds( 1223c5ee0fc482e93912b9b090d0df1af496288a702John Reck int32_t source_image_width, pixman_fixed_t vx, pixman_fixed_t unit_x, 1233c5ee0fc482e93912b9b090d0df1af496288a702John Reck int32_t * width, int32_t * left_pad, int32_t * right_pad) { 1243c5ee0fc482e93912b9b090d0df1af496288a702John Reck int64_t max_vx = (int64_t) source_image_width << 16; 1253c5ee0fc482e93912b9b090d0df1af496288a702John Reck int64_t tmp; 1263c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (vx < 0) { 1273c5ee0fc482e93912b9b090d0df1af496288a702John Reck tmp = ((int64_t) unit_x - 1 - vx) / unit_x; 1283c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (tmp > *width) { 1293c5ee0fc482e93912b9b090d0df1af496288a702John Reck *left_pad = *width; 1303c5ee0fc482e93912b9b090d0df1af496288a702John Reck *width = 0; 1313c5ee0fc482e93912b9b090d0df1af496288a702John Reck } else { 1323c5ee0fc482e93912b9b090d0df1af496288a702John Reck *left_pad = (int32_t) tmp; 1333c5ee0fc482e93912b9b090d0df1af496288a702John Reck *width -= (int32_t) tmp; 1343c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 1353c5ee0fc482e93912b9b090d0df1af496288a702John Reck } else { 1363c5ee0fc482e93912b9b090d0df1af496288a702John Reck *left_pad = 0; 1373c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 1383c5ee0fc482e93912b9b090d0df1af496288a702John Reck tmp = ((int64_t) unit_x - 1 - vx + max_vx) / unit_x - *left_pad; 1393c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (tmp < 0) { 1403c5ee0fc482e93912b9b090d0df1af496288a702John Reck *right_pad = *width; 1413c5ee0fc482e93912b9b090d0df1af496288a702John Reck *width = 0; 1423c5ee0fc482e93912b9b090d0df1af496288a702John Reck } else if (tmp >= *width) { 1433c5ee0fc482e93912b9b090d0df1af496288a702John Reck *right_pad = 0; 1443c5ee0fc482e93912b9b090d0df1af496288a702John Reck } else { 1453c5ee0fc482e93912b9b090d0df1af496288a702John Reck *right_pad = *width - (int32_t) tmp; 1463c5ee0fc482e93912b9b090d0df1af496288a702John Reck *width = (int32_t) tmp; 1473c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 1483c5ee0fc482e93912b9b090d0df1af496288a702John Reck} 1493c5ee0fc482e93912b9b090d0df1af496288a702John Reck 1503c5ee0fc482e93912b9b090d0df1af496288a702John Reckstatic force_inline void bilinear_pad_repeat_get_scanline_bounds( 1513c5ee0fc482e93912b9b090d0df1af496288a702John Reck int32_t source_image_width, pixman_fixed_t vx, pixman_fixed_t unit_x, 1523c5ee0fc482e93912b9b090d0df1af496288a702John Reck int32_t * left_pad, int32_t * left_tz, int32_t * width, 1533c5ee0fc482e93912b9b090d0df1af496288a702John Reck int32_t * right_tz, int32_t * right_pad) { 1543c5ee0fc482e93912b9b090d0df1af496288a702John Reck int width1 = *width, left_pad1, right_pad1; 1553c5ee0fc482e93912b9b090d0df1af496288a702John Reck int width2 = *width, left_pad2, right_pad2; 1563c5ee0fc482e93912b9b090d0df1af496288a702John Reck 1573c5ee0fc482e93912b9b090d0df1af496288a702John Reck pad_repeat_get_scanline_bounds(source_image_width, vx, unit_x, &width1, 1583c5ee0fc482e93912b9b090d0df1af496288a702John Reck &left_pad1, &right_pad1); 1593c5ee0fc482e93912b9b090d0df1af496288a702John Reck pad_repeat_get_scanline_bounds(source_image_width, vx + pixman_fixed_1, 1603c5ee0fc482e93912b9b090d0df1af496288a702John Reck unit_x, &width2, &left_pad2, &right_pad2); 1613c5ee0fc482e93912b9b090d0df1af496288a702John Reck 1623c5ee0fc482e93912b9b090d0df1af496288a702John Reck *left_pad = left_pad2; 1633c5ee0fc482e93912b9b090d0df1af496288a702John Reck *left_tz = left_pad1 - left_pad2; 1643c5ee0fc482e93912b9b090d0df1af496288a702John Reck *right_tz = right_pad2 - right_pad1; 1653c5ee0fc482e93912b9b090d0df1af496288a702John Reck *right_pad = right_pad1; 1663c5ee0fc482e93912b9b090d0df1af496288a702John Reck *width -= *left_pad + *left_tz + *right_tz + *right_pad; 1673c5ee0fc482e93912b9b090d0df1af496288a702John Reck} 1683c5ee0fc482e93912b9b090d0df1af496288a702John Reck 1695e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck#ifdef USE_ARM_NEON 1705e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reckvoid pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(uint32_t *dst, 1715e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck const uint32_t *top, const uint32_t *bottom, int wt, int wb, 1725e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_fixed_t x, pixman_fixed_t ux, int width); 1735e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck 1745e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reckstatic void android_bilinear_filter_neon(android_simple_image* src_image, 175780fc14f48491c5e922475d9e46226a7ca23179eJohn Reck android_simple_image* dst_image, float scale, int src_x, int src_y) { 1763c5ee0fc482e93912b9b090d0df1af496288a702John Reck int32_t src_width = src_image->width; 1773c5ee0fc482e93912b9b090d0df1af496288a702John Reck int32_t src_height = src_image->height; 1783c5ee0fc482e93912b9b090d0df1af496288a702John Reck pixman_vector_t v; 1793c5ee0fc482e93912b9b090d0df1af496288a702John Reck int32_t left_pad, left_tz, right_tz, right_pad; 1803c5ee0fc482e93912b9b090d0df1af496288a702John Reck pixman_fixed_t unit_x, unit_y; 1813c5ee0fc482e93912b9b090d0df1af496288a702John Reck int32_t width = dst_image->width; 1823c5ee0fc482e93912b9b090d0df1af496288a702John Reck int32_t height = dst_image->height; 1833c5ee0fc482e93912b9b090d0df1af496288a702John Reck uint32_t dst_line = 0; 1843c5ee0fc482e93912b9b090d0df1af496288a702John Reck uint32_t* dst; 1853c5ee0fc482e93912b9b090d0df1af496288a702John Reck int y1, y2; 1863c5ee0fc482e93912b9b090d0df1af496288a702John Reck pixman_fixed_t vx, vy; 187780fc14f48491c5e922475d9e46226a7ca23179eJohn Reck /* reference point is the center of the pixel */ 1880ccffae8bfc5eb66b3de3c361c3f449ff7126df2John Reck v.vector[0] = pixman_double_to_fixed((src_x + 0.5f) * scale); 1890ccffae8bfc5eb66b3de3c361c3f449ff7126df2John Reck v.vector[1] = pixman_double_to_fixed((src_y + 0.5f) * scale); 190780fc14f48491c5e922475d9e46226a7ca23179eJohn Reck v.vector[2] = pixman_fixed_1; 1910ccffae8bfc5eb66b3de3c361c3f449ff7126df2John Reck unit_x = unit_y = pixman_double_to_fixed(scale); 1923c5ee0fc482e93912b9b090d0df1af496288a702John Reck vy = v.vector[1]; 1933c5ee0fc482e93912b9b090d0df1af496288a702John Reck bilinear_pad_repeat_get_scanline_bounds(src_width, v.vector[0], unit_x, 1943c5ee0fc482e93912b9b090d0df1af496288a702John Reck &left_pad, &left_tz, &width, &right_tz, &right_pad); 1953c5ee0fc482e93912b9b090d0df1af496288a702John Reck v.vector[0] += left_pad * unit_x; 1963c5ee0fc482e93912b9b090d0df1af496288a702John Reck while (--height >= 0) { 1973c5ee0fc482e93912b9b090d0df1af496288a702John Reck int weight1, weight2; 1983c5ee0fc482e93912b9b090d0df1af496288a702John Reck dst_image->get_scanline(dst_image, (void**)(&dst), dst_line); 1993c5ee0fc482e93912b9b090d0df1af496288a702John Reck dst_line++; 2003c5ee0fc482e93912b9b090d0df1af496288a702John Reck vx = v.vector[0]; 201780fc14f48491c5e922475d9e46226a7ca23179eJohn Reck y1 = pixman_fixed_to_int(vy); 2023c5ee0fc482e93912b9b090d0df1af496288a702John Reck weight2 = pixman_fixed_to_bilinear_weight(vy); 2033c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (weight2) { 204780fc14f48491c5e922475d9e46226a7ca23179eJohn Reck /* both weight1 and weight2 are smaller than BILINEAR_INTERPOLATION_RANGE */ 2053c5ee0fc482e93912b9b090d0df1af496288a702John Reck y2 = y1 + 1; 206780fc14f48491c5e922475d9e46226a7ca23179eJohn Reck weight1 = BILINEAR_INTERPOLATION_RANGE - weight2; 2073c5ee0fc482e93912b9b090d0df1af496288a702John Reck } else { 208780fc14f48491c5e922475d9e46226a7ca23179eJohn Reck /* set both top and bottom row to the same scanline and tweak weights */ 2093c5ee0fc482e93912b9b090d0df1af496288a702John Reck y2 = y1; 210780fc14f48491c5e922475d9e46226a7ca23179eJohn Reck weight1 = weight2 = BILINEAR_INTERPOLATION_RANGE / 2; 2113c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 2123c5ee0fc482e93912b9b090d0df1af496288a702John Reck vy += unit_y; 2133c5ee0fc482e93912b9b090d0df1af496288a702John Reck uint32_t buf1[2]; 2143c5ee0fc482e93912b9b090d0df1af496288a702John Reck uint32_t buf2[2]; 2153c5ee0fc482e93912b9b090d0df1af496288a702John Reck uint32_t* src1; 2163c5ee0fc482e93912b9b090d0df1af496288a702John Reck uint32_t* src2; 217780fc14f48491c5e922475d9e46226a7ca23179eJohn Reck /* handle top/bottom zero padding by just setting weights to 0 if needed */ 2183c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (y1 < 0) { 2193c5ee0fc482e93912b9b090d0df1af496288a702John Reck weight1 = 0; 2203c5ee0fc482e93912b9b090d0df1af496288a702John Reck y1 = 0; 2213c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 2223c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (y1 >= src_height) { 2233c5ee0fc482e93912b9b090d0df1af496288a702John Reck weight1 = 0; 2243c5ee0fc482e93912b9b090d0df1af496288a702John Reck y1 = src_height - 1; 2253c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 2263c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (y2 < 0) { 2273c5ee0fc482e93912b9b090d0df1af496288a702John Reck weight2 = 0; 2283c5ee0fc482e93912b9b090d0df1af496288a702John Reck y2 = 0; 2293c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 2303c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (y2 >= src_height) { 2313c5ee0fc482e93912b9b090d0df1af496288a702John Reck weight2 = 0; 2323c5ee0fc482e93912b9b090d0df1af496288a702John Reck y2 = src_height - 1; 2333c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 2343c5ee0fc482e93912b9b090d0df1af496288a702John Reck src_image->get_scanline(src_image, (void**)(&src1), y1); 2353c5ee0fc482e93912b9b090d0df1af496288a702John Reck src_image->get_scanline(src_image, (void**)(&src2), y2); 2363c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (left_pad > 0) { 2373c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf1[0] = buf1[1] = 0; 2383c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf2[0] = buf2[1] = 0; 2395e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon( 2405e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst, buf1, buf2, weight1, weight2, 0, 0, left_pad); 2413c5ee0fc482e93912b9b090d0df1af496288a702John Reck dst += left_pad; 2423c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 2433c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (left_tz > 0) { 2443c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf1[0] = 0; 2453c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf1[1] = src1[0]; 2463c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf2[0] = 0; 2473c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf2[1] = src2[0]; 2485e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon( 2495e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst, buf1, buf2, weight1, weight2, 2505e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_fixed_frac(vx), unit_x, left_tz); 2513c5ee0fc482e93912b9b090d0df1af496288a702John Reck dst += left_tz; 2523c5ee0fc482e93912b9b090d0df1af496288a702John Reck vx += left_tz * unit_x; 2533c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 2543c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (width > 0) { 2555e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon( 2565e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst, src1, src2, weight1, weight2, vx, unit_x, width); 2573c5ee0fc482e93912b9b090d0df1af496288a702John Reck dst += width; 2583c5ee0fc482e93912b9b090d0df1af496288a702John Reck vx += width * unit_x; 2593c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 2603c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (right_tz > 0) { 2613c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf1[0] = src1[src_width - 1]; 2623c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf1[1] = 0; 2633c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf2[0] = src2[src_width - 1]; 2643c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf2[1] = 0; 2655e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon( 2665e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst, buf1, buf2, weight1, weight2, 2675e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_fixed_frac(vx), unit_x, right_tz); 2683c5ee0fc482e93912b9b090d0df1af496288a702John Reck dst += right_tz; 2693c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 2703c5ee0fc482e93912b9b090d0df1af496288a702John Reck if (right_pad > 0) { 2713c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf1[0] = buf1[1] = 0; 2723c5ee0fc482e93912b9b090d0df1af496288a702John Reck buf2[0] = buf2[1] = 0; 2735e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon( 2745e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst, buf1, buf2, weight1, weight2, 0, 0, right_pad); 2755e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck } 2765e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck } 2775e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck} 2785e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck#endif // ARM_USE_NEON 2795e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck 2805e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reckstatic void android_nearest_filter(android_simple_image* src_image, 2815e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck android_simple_image* dst_image, float scale, int src_x, int src_y) { 2825e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck int32_t src_width = src_image->width; 2835e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck int32_t src_height = src_image->height; 2845e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck int32_t width = dst_image->width; 2855e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck int32_t height = dst_image->height; 2865e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck uint32_t dst_line = 0; 2875e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck int y; 2885e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_fixed_t src_width_fixed = pixman_int_to_fixed(src_width); 2895e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_fixed_t max_vy; 2905e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_vector_t v; 2915e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_fixed_t vx, vy; 2925e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pixman_fixed_t unit_x, unit_y; 2935e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck int32_t left_pad, right_pad; 2945e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck uint32_t *src; 2955e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck uint32_t *dst; 2965e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck /* reference point is the center of the pixel */ 2975e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck v.vector[0] = pixman_double_to_fixed((src_x + 0.5f) * scale); 2985e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck v.vector[1] = pixman_double_to_fixed((src_y + 0.5f) * scale); 2995e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck v.vector[2] = pixman_fixed_1; 3005e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck unit_x = unit_y = pixman_double_to_fixed(scale); 3015e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck vx = v.vector[0]; 3025e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck vy = v.vector[1]; 3035e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck pad_repeat_get_scanline_bounds(src_width, vx, unit_x, 3045e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck &width, &left_pad, &right_pad); 3055e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck vx += left_pad * unit_x; 3065e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck while (--height >= 0) { 3075e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst_image->get_scanline(dst_image, (void**)(&dst), dst_line); 3085e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst_line++; 3095e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck y = ((int) ((vy) >> 16)); 3105e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck vy += unit_y; 3115e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck static const uint32_t zero[1] = { 0 }; 3125e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck if (y < 0 || y >= src_height) { 3135e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck scaled_nearest_scanline_8888_8888_none_SRC( 3145e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst, zero + 1, left_pad + width + right_pad, 3155e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck -((pixman_fixed_t) 1), 0, src_width_fixed); 3165e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck continue; 3173c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 3185e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck src_image->get_scanline(src_image, (void**)(&src), y); 3195e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck if (left_pad > 0) { 3205e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck scaled_nearest_scanline_8888_8888_none_SRC( 3215e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst, zero + 1, left_pad, -((pixman_fixed_t) 1), 0, 3225e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck src_width_fixed); 3235e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck } 3245e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck if (width > 0) { 3255e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck scaled_nearest_scanline_8888_8888_none_SRC( 3265e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst + left_pad, src + src_width, width, 3275e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck vx - src_width_fixed, unit_x, src_width_fixed); 3285e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck } 3295e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck if (right_pad > 0) { 3305e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck scaled_nearest_scanline_8888_8888_none_SRC( 3315e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck dst + left_pad + width, zero + 1, right_pad, 3325e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck -((pixman_fixed_t) 1), 0, src_width_fixed); 3335e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck } 3345e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck } 3355e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck} 3365e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck 3375e97fcc235901c1018da86118c427d84d9f6a0dcJohn ReckPIXMAN_EXPORT void android_simple_scale(android_simple_image* src_image, 3385e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck android_simple_image* dst_image, float scale, int src_x, int src_y) { 3395e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck#ifdef USE_ARM_NEON 3405e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM 3415e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON)) { 3425e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck android_bilinear_filter_neon(src_image, dst_image, scale, src_x, src_y); 3435e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck return; 3443c5ee0fc482e93912b9b090d0df1af496288a702John Reck } 3455e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck#endif 3465e97fcc235901c1018da86118c427d84d9f6a0dcJohn Reck android_nearest_filter(src_image, dst_image, scale, src_x, src_y); 3473c5ee0fc482e93912b9b090d0df1af496288a702John Reck} 348