pixman-android.c revision 5e97fcc235901c1018da86118c427d84d9f6a0dc
1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright © 2013 The Android Open Source Project
383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius *
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Permission is hereby granted, free of charge, to any person obtaining a
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * copy of this software and associated documentation files (the "Software"),
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * to deal in the Software without restriction, including without limitation
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and/or sell copies of the Software, and to permit persons to whom the
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Software is furnished to do so, subject to the following conditions:
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The above copyright notice and this permission notice (including the next
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * paragraph) shall be included in all copies or substantial portions of the
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Software.
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * DEALINGS IN THE SOFTWARE.
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
23b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright © 2000 SuSE, Inc.
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright © 2007 Red Hat, Inc.
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Permission to use, copy, modify, distribute, and sell this software and its
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * documentation for any purpose is hereby granted without fee, provided that
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the above copyright notice appear in all copies and that both that
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * copyright notice and this permission notice appear in supporting
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * documentation, and that the name of SuSE not be used in advertising or
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * publicity pertaining to distribution of the software without specific,
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * written prior permission.  SuSE makes no representations about the
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * suitability of this software for any purpose.  It is provided "as is"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * without express or implied warranty.
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Author:  Keith Packard, SuSE, Inc.
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright © 2009 ARM Ltd, Movial Creative Technologies Oy
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Permission to use, copy, modify, distribute, and sell this software and its
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * documentation for any purpose is hereby granted without fee, provided that
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the above copyright notice appear in all copies and that both that
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * copyright notice and this permission notice appear in supporting
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * documentation, and that the name of ARM Ltd not be used in
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * advertising or publicity pertaining to distribution of the software without
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * specific, written prior permission.  ARM Ltd makes no
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * representations about the suitability of this software for any purpose.  It
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is provided "as is" without express or implied warranty.
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * SOFTWARE.
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Author:  Ian Rickards (ian.rickards@arm.com)
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Author:  Jonathan Morton (jonathan.morton@movial.com)
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Author:  Markku Vire (markku.vire@movial.com)
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "config.h"
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "pixman-android.h"
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "pixman-private.h"
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <cpu-features.h>
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic force_inline void scaled_nearest_scanline_8888_8888_none_SRC(
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t *dst, const uint32_t *src, int32_t w, pixman_fixed_t vx,
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pixman_fixed_t unit_x, pixman_fixed_t src_width_fixed) {
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t d;
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t s1, s2;
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint8_t a1, a2;
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int x1, x2;
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while ((w -= 2) >= 0) {
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        x1 = pixman_fixed_to_int(vx);
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        vx += unit_x;
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s1 = *(src + x1);
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        x2 = pixman_fixed_to_int(vx);
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        vx += unit_x;
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s2 = *(src + x2);
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *dst++ = s1;
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *dst++ = s2;
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (w & 1) {
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        x1 = pixman_fixed_to_int(vx);
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s1 = *(src + x1);
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *dst++ = s1;
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic force_inline int pixman_fixed_to_bilinear_weight(pixman_fixed_t x) {
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (x >> (16 - BILINEAR_INTERPOLATION_BITS))
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            & ((1 << BILINEAR_INTERPOLATION_BITS) - 1);
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For each scanline fetched from source image with PAD repeat:
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * - calculate how many pixels need to be padded on the left side
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * - calculate how many pixels need to be padded on the right side
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * - update width to only count pixels which are fetched from the image
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * All this information is returned via 'width', 'left_pad', 'right_pad'
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * arguments. The code is assuming that 'unit_x' is positive.
11683a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius *
11783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius * Note: 64-bit math is used in order to avoid potential overflows, which
11883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius *       is probably excessive in many cases. This particular function
11983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius *       may need its own correctness test and performance tuning.
12083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius */
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic force_inline void pad_repeat_get_scanline_bounds(
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t source_image_width, pixman_fixed_t vx, pixman_fixed_t unit_x,
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t * width, int32_t * left_pad, int32_t * right_pad) {
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int64_t max_vx = (int64_t) source_image_width << 16;
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int64_t tmp;
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (vx < 0) {
12783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        tmp = ((int64_t) unit_x - 1 - vx) / unit_x;
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (tmp > *width) {
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *left_pad = *width;
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *width = 0;
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *left_pad = (int32_t) tmp;
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *width -= (int32_t) tmp;
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *left_pad = 0;
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    tmp = ((int64_t) unit_x - 1 - vx + max_vx) / unit_x - *left_pad;
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (tmp < 0) {
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *right_pad = *width;
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *width = 0;
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if (tmp >= *width) {
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *right_pad = 0;
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *right_pad = *width - (int32_t) tmp;
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *width = (int32_t) tmp;
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic force_inline void bilinear_pad_repeat_get_scanline_bounds(
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t source_image_width, pixman_fixed_t vx, pixman_fixed_t unit_x,
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t * left_pad, int32_t * left_tz, int32_t * width,
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t * right_tz, int32_t * right_pad) {
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int width1 = *width, left_pad1, right_pad1;
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int width2 = *width, left_pad2, right_pad2;
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    pad_repeat_get_scanline_bounds(source_image_width, vx, unit_x, &width1,
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            &left_pad1, &right_pad1);
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pad_repeat_get_scanline_bounds(source_image_width, vx + pixman_fixed_1,
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            unit_x, &width2, &left_pad2, &right_pad2);
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *left_pad = left_pad2;
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *left_tz = left_pad1 - left_pad2;
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *right_tz = right_pad2 - right_pad1;
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *right_pad = right_pad1;
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *width -= *left_pad + *left_tz + *right_tz + *right_pad;
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef USE_ARM_NEON
17083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Corneliusvoid pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(uint32_t *dst,
17183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        const uint32_t *top, const uint32_t *bottom, int wt, int wb,
17283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        pixman_fixed_t x, pixman_fixed_t ux, int width);
17383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius
17483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Corneliusstatic void android_bilinear_filter_neon(android_simple_image* src_image,
17583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        android_simple_image* dst_image, float scale, int src_x, int src_y) {
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t src_width = src_image->width;
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t src_height = src_image->height;
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pixman_vector_t v;
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t left_pad, left_tz, right_tz, right_pad;
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pixman_fixed_t unit_x, unit_y;
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t width = dst_image->width;
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t height = dst_image->height;
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t dst_line = 0;
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t* dst;
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int y1, y2;
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pixman_fixed_t vx, vy;
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* reference point is the center of the pixel */
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    v.vector[0] = pixman_double_to_fixed((src_x + 0.5f) * scale);
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    v.vector[1] = pixman_double_to_fixed((src_y + 0.5f) * scale);
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    v.vector[2] = pixman_fixed_1;
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unit_x = unit_y = pixman_double_to_fixed(scale);
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    vy = v.vector[1];
19383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius    bilinear_pad_repeat_get_scanline_bounds(src_width, v.vector[0], unit_x,
19483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius            &left_pad, &left_tz, &width, &right_tz, &right_pad);
19583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius    v.vector[0] += left_pad * unit_x;
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (--height >= 0) {
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int weight1, weight2;
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        dst_image->get_scanline(dst_image, (void**)(&dst), dst_line);
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        dst_line++;
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        vx = v.vector[0];
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        y1 = pixman_fixed_to_int(vy);
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        weight2 = pixman_fixed_to_bilinear_weight(vy);
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (weight2) {
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* both weight1 and weight2 are smaller than BILINEAR_INTERPOLATION_RANGE */
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            y2 = y1 + 1;
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            weight1 = BILINEAR_INTERPOLATION_RANGE - weight2;
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* set both top and bottom row to the same scanline and tweak weights */
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            y2 = y1;
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            weight1 = weight2 = BILINEAR_INTERPOLATION_RANGE / 2;
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        vy += unit_y;
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t buf1[2];
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t buf2[2];
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t* src1;
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint32_t* src2;
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* handle top/bottom zero padding by just setting weights to 0 if needed */
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (y1 < 0) {
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            weight1 = 0;
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            y1 = 0;
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (y1 >= src_height) {
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            weight1 = 0;
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            y1 = src_height - 1;
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (y2 < 0) {
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            weight2 = 0;
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            y2 = 0;
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (y2 >= src_height) {
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            weight2 = 0;
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            y2 = src_height - 1;
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        src_image->get_scanline(src_image, (void**)(&src1), y1);
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        src_image->get_scanline(src_image, (void**)(&src2), y2);
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (left_pad > 0) {
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf1[0] = buf1[1] = 0;
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf2[0] = buf2[1] = 0;
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    dst, buf1, buf2, weight1, weight2, 0, 0, left_pad);
24183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius            dst += left_pad;
24283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        }
24383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        if (left_tz > 0) {
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf1[0] = 0;
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf1[1] = src1[0];
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf2[0] = 0;
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf2[1] = src2[0];
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    dst, buf1, buf2, weight1, weight2,
25083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius                    pixman_fixed_frac(vx), unit_x, left_tz);
25183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius            dst += left_tz;
25283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius            vx += left_tz * unit_x;
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (width > 0) {
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    dst, src1, src2, weight1, weight2, vx, unit_x, width);
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            dst += width;
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            vx += width * unit_x;
25983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        }
26083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        if (right_tz > 0) {
26183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius            buf1[0] = src1[src_width - 1];
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf1[1] = 0;
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf2[0] = src2[src_width - 1];
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf2[1] = 0;
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    dst, buf1, buf2, weight1, weight2,
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    pixman_fixed_frac(vx), unit_x, right_tz);
26883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius            dst += right_tz;
26983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        }
27083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        if (right_pad > 0) {
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf1[0] = buf1[1] = 0;
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf2[0] = buf2[1] = 0;
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    dst, buf1, buf2, weight1, weight2, 0, 0, right_pad);
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif // ARM_USE_NEON
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void android_nearest_filter(android_simple_image* src_image,
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        android_simple_image* dst_image, float scale, int src_x, int src_y) {
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t src_width = src_image->width;
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t src_height = src_image->height;
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t width = dst_image->width;
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t height = dst_image->height;
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t dst_line = 0;
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int y;
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pixman_fixed_t src_width_fixed = pixman_int_to_fixed(src_width);
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pixman_fixed_t max_vy;
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pixman_vector_t v;
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pixman_fixed_t vx, vy;
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pixman_fixed_t unit_x, unit_y;
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t left_pad, right_pad;
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t *src;
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t *dst;
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* reference point is the center of the pixel */
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    v.vector[0] = pixman_double_to_fixed((src_x + 0.5f) * scale);
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    v.vector[1] = pixman_double_to_fixed((src_y + 0.5f) * scale);
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    v.vector[2] = pixman_fixed_1;
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unit_x = unit_y = pixman_double_to_fixed(scale);
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    vx = v.vector[0];
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    vy = v.vector[1];
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pad_repeat_get_scanline_bounds(src_width, vx, unit_x,
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            &width, &left_pad, &right_pad);
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    vx += left_pad * unit_x;
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (--height >= 0) {
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        dst_image->get_scanline(dst_image, (void**)(&dst), dst_line);
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        dst_line++;
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        y = ((int) ((vy) >> 16));
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        vy += unit_y;
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        static const uint32_t zero[1] = { 0 };
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (y < 0 || y >= src_height) {
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            scaled_nearest_scanline_8888_8888_none_SRC(
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    dst, zero + 1, left_pad + width + right_pad,
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    -((pixman_fixed_t) 1), 0, src_width_fixed);
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            continue;
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        src_image->get_scanline(src_image, (void**)(&src), y);
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (left_pad > 0) {
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            scaled_nearest_scanline_8888_8888_none_SRC(
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    dst, zero + 1, left_pad, -((pixman_fixed_t) 1), 0,
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    src_width_fixed);
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (width > 0) {
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            scaled_nearest_scanline_8888_8888_none_SRC(
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    dst + left_pad, src + src_width, width,
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    vx - src_width_fixed, unit_x, src_width_fixed);
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (right_pad > 0) {
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            scaled_nearest_scanline_8888_8888_none_SRC(
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    dst + left_pad + width, zero + 1, right_pad,
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    -((pixman_fixed_t) 1), 0, src_width_fixed);
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruPIXMAN_EXPORT void android_simple_scale(android_simple_image* src_image,
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        android_simple_image* dst_image, float scale, int src_x, int src_y) {
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef USE_ARM_NEON
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON)) {
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        android_bilinear_filter_neon(src_image, dst_image, scale, src_x, src_y);
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    android_nearest_filter(src_image, dst_image, scale, src_x, src_y);
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru