aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2013-08-30 16:56:54 -0700
committerJohn Reck <jreck@google.com>2013-08-30 16:56:54 -0700
commit3c5ee0fc482e93912b9b090d0df1af496288a702 (patch)
tree9d0f8fe0787e4fb7e4dfd43467ce967e0ac78ca1
parent70005f9fa14753353faf0fe2e57359913ed3e75a (diff)
downloadpixman-3c5ee0fc482e93912b9b090d0df1af496288a702.tar.gz
Add custom filtering function
Operates on scanlines Minimal code footprint Change-Id: If7d88e9dae9003647fc813aab40eb43aa49bb7f2
-rw-r--r--pixman/Android.mk4
-rw-r--r--pixman/pixman-android.c277
-rw-r--r--pixman/pixman-android.h33
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_ */