diff options
author | John Reck <jreck@google.com> | 2013-08-30 16:56:54 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2013-08-30 16:56:54 -0700 |
commit | 3c5ee0fc482e93912b9b090d0df1af496288a702 (patch) | |
tree | 9d0f8fe0787e4fb7e4dfd43467ce967e0ac78ca1 | |
parent | 70005f9fa14753353faf0fe2e57359913ed3e75a (diff) | |
download | pixman-3c5ee0fc482e93912b9b090d0df1af496288a702.tar.gz |
Add custom filtering function
Operates on scanlines
Minimal code footprint
Change-Id: If7d88e9dae9003647fc813aab40eb43aa49bb7f2
-rw-r--r-- | pixman/Android.mk | 4 | ||||
-rw-r--r-- | pixman/pixman-android.c | 277 | ||||
-rw-r--r-- | pixman/pixman-android.h | 33 |
3 files changed, 314 insertions, 0 deletions
diff --git a/pixman/Android.mk b/pixman/Android.mk index 777aaf3..6bfad10 100644 --- a/pixman/Android.mk +++ b/pixman/Android.mk @@ -41,6 +41,10 @@ LOCAL_SRC_FILES := \ pixman-trap.c \ pixman-utils.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 diff --git a/pixman/pixman-android.c b/pixman/pixman-android.c new file mode 100644 index 0000000..e316118 --- /dev/null +++ b/pixman/pixman-android.c @@ -0,0 +1,277 @@ +/* + * 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" + +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 inline void scaled_bilinear_scanline_neon_8888_8888_SRC(uint32_t * dst, + const uint32_t * mask, const uint32_t * src_top, + const uint32_t * src_bottom, int32_t w, int wt, int wb, + pixman_fixed_t vx, pixman_fixed_t unit_x, pixman_fixed_t max_vx, + pixman_bool_t zero_src) { + pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon(dst, src_top, + src_bottom, wt, wb, vx, unit_x, w); +} + +static 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; +} + +void android_bilinear_filter(android_simple_image* src_image, + android_simple_image* dst_image, float scale) { + int32_t src_width = src_image->width; + int32_t src_height = src_image->height; + pixman_fixed_t fixed_scale = pixman_double_to_fixed(scale); + pixman_transform_t transform; + pixman_transform_init_scale(&transform, fixed_scale, fixed_scale); + pixman_vector_t v; + int32_t left_pad, left_tz, right_tz, right_pad; + int32_t src_x = 0; + int32_t src_y = 0; + 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* src_first_line; + int32_t dest_y = 0; + int32_t dest_x = 0; + uint32_t* dst; + int y1, y2; + pixman_fixed_t vx, vy; + uint32_t solid_mask; + const uint32_t* mask = &solid_mask; + v.vector[0] = ((pixman_fixed_t) (((src_x) << 16))) + + (((pixman_fixed_t) (((1) << 16)))) / 2; + v.vector[1] = ((pixman_fixed_t) (((src_y) << 16))) + + (((pixman_fixed_t) (((1) << 16)))) / 2; + v.vector[2] = (((pixman_fixed_t) (((1) << 16)))); + if (!pixman_transform_point_3d(&transform, &v)) { + return; + } + unit_x = transform.matrix[0][0]; + unit_y = transform.matrix[1][1]; + v.vector[0] -= (((pixman_fixed_t) (((1) << 16)))) / 2; + v.vector[1] -= (((pixman_fixed_t) (((1) << 16)))) / 2; + 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 = ((int) (((vy) >> 16))); + weight2 = pixman_fixed_to_bilinear_weight(vy); + if (weight2) { + y2 = y1 + 1; + weight1 = (1 << 7) - weight2; + } else { + y2 = y1; + weight1 = weight2 = (1 << 7) / 2; + } + vy += unit_y; + uint32_t buf1[2]; + uint32_t buf2[2]; + uint32_t* src1; + uint32_t* src2; + 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; + scaled_bilinear_scanline_neon_8888_8888_SRC(dst, mask, buf1, buf2, + left_pad, weight1, weight2, 0, 0, 0, 1); + dst += left_pad; + } + if (left_tz > 0) { + buf1[0] = 0; + buf1[1] = src1[0]; + buf2[0] = 0; + buf2[1] = src2[0]; + scaled_bilinear_scanline_neon_8888_8888_SRC(dst, mask, buf1, buf2, + left_tz, weight1, weight2, + ((vx) + & ((((pixman_fixed_t) (((1) << 16)))) + - ((pixman_fixed_t) (1)))), unit_x, 0, 0); + dst += left_tz; + vx += left_tz * unit_x; + } + if (width > 0) { + scaled_bilinear_scanline_neon_8888_8888_SRC(dst, mask, src1, src2, + width, weight1, weight2, vx, unit_x, 0, 0); + 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; + scaled_bilinear_scanline_neon_8888_8888_SRC(dst, mask, buf1, buf2, + right_tz, weight1, weight2, + ((vx) + & ((((pixman_fixed_t) (((1) << 16)))) + - ((pixman_fixed_t) (1)))), unit_x, 0, 0); + dst += right_tz; + } + if (right_pad > 0) { + buf1[0] = buf1[1] = 0; + buf2[0] = buf2[1] = 0; + scaled_bilinear_scanline_neon_8888_8888_SRC(dst, mask, buf1, buf2, + right_pad, weight1, weight2, 0, 0, 0, 1); + } + } +} diff --git a/pixman/pixman-android.h b/pixman/pixman-android.h new file mode 100644 index 0000000..7fd9fed --- /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_bilinear_filter(android_simple_image* src_image, + android_simple_image* dst_image, float scale); + +#endif /* PIXMAN_ANDROID_H_ */ |