1910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger/* 2910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * Copyright 2013 The Android Open Source Project 3910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * 4910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 5910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * found in the LICENSE file. 6910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger */ 7910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 8910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 9910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#include "SkColorPriv.h" 10910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#include "SkMorphology_opts.h" 11910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#include "SkMorphology_opts_neon.h" 12910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 13910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#include <arm_neon.h> 14910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 15910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger/* neon version of dilateX, dilateY, erodeX, erodeY. 16910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * portable versions are in src/effects/SkMorphologyImageFilter.cpp. 17910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger */ 18910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 19910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerenum MorphType { 20910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger kDilate, kErode 21910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger}; 22910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 23910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerenum MorphDirection { 24910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger kX, kY 25910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger}; 26910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 27910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergertemplate<MorphType type, MorphDirection direction> 28910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic void SkMorph_neon(const SkPMColor* src, SkPMColor* dst, int radius, 29910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger int width, int height, int srcStride, int dstStride) 30910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger{ 31910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const int srcStrideX = direction == kX ? 1 : srcStride; 32910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const int dstStrideX = direction == kX ? 1 : dstStride; 33910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const int srcStrideY = direction == kX ? srcStride : 1; 34910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const int dstStrideY = direction == kX ? dstStride : 1; 35910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger radius = SkMin32(radius, width - 1); 36910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const SkPMColor* upperSrc = src + radius * srcStrideX; 37910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger for (int x = 0; x < width; ++x) { 38910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const SkPMColor* lp = src; 39910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const SkPMColor* up = upperSrc; 40910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkPMColor* dptr = dst; 41910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger for (int y = 0; y < height; ++y) { 42910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger uint8x8_t max = vdup_n_u8(type == kDilate ? 0 : 255); 43910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger for (const SkPMColor* p = lp; p <= up; p += srcStrideX) { 44910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger uint8x8_t src_pixel = vreinterpret_u8_u32(vdup_n_u32(*p)); 45910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger max = type == kDilate ? vmax_u8(src_pixel, max) : vmin_u8(src_pixel, max); 46910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger } 47910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *dptr = vget_lane_u32(vreinterpret_u32_u8(max), 0); 48910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger dptr += dstStrideY; 49910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger lp += srcStrideY; 50910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger up += srcStrideY; 51910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger } 52910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger if (x >= radius) src += srcStrideX; 53910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger if (x + radius < width - 1) upperSrc += srcStrideX; 54910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger dst += dstStrideX; 55910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger } 56910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 57910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 58910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergervoid SkDilateX_neon(const SkPMColor* src, SkPMColor* dst, int radius, 59910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger int width, int height, int srcStride, int dstStride) 60910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger{ 61910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkMorph_neon<kDilate, kX>(src, dst, radius, width, height, srcStride, dstStride); 62910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 63910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 64910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergervoid SkErodeX_neon(const SkPMColor* src, SkPMColor* dst, int radius, 65910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger int width, int height, int srcStride, int dstStride) 66910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger{ 67910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkMorph_neon<kErode, kX>(src, dst, radius, width, height, srcStride, dstStride); 68910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 69910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 70910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergervoid SkDilateY_neon(const SkPMColor* src, SkPMColor* dst, int radius, 71910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger int width, int height, int srcStride, int dstStride) 72910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger{ 73910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkMorph_neon<kDilate, kY>(src, dst, radius, width, height, srcStride, dstStride); 74910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 75910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 76910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergervoid SkErodeY_neon(const SkPMColor* src, SkPMColor* dst, int radius, 77910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger int width, int height, int srcStride, int dstStride) 78910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger{ 79910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkMorph_neon<kErode, kY>(src, dst, radius, width, height, srcStride, dstStride); 80910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 81