From d029ded92d409a004f2096c78f5a99b524206481 Mon Sep 17 00:00:00 2001 From: mtklein Date: Tue, 4 Aug 2015 14:09:09 -0700 Subject: Port morphology to SkOpts. Nothing too fancy. Direction enums become enum classes so they don't get all confused. An alternative is to create one single Direction enum that both blur and morphology opts use. BUG=skia:4117 Review URL: https://codereview.chromium.org/1267343004 --- gyp/opts.gypi | 7 -- src/core/SkOpts.cpp | 13 ++- src/core/SkOpts.h | 3 + src/effects/SkMorphologyImageFilter.cpp | 108 ++----------------------- src/opts/SkBlurImageFilter_opts.h | 56 +++++++------ src/opts/SkMorphologyImageFilter_opts.h | 137 ++++++++++++++++++++++++++++++++ src/opts/SkMorphology_opts.h | 22 ----- src/opts/SkMorphology_opts_SSE2.cpp | 81 ------------------- src/opts/SkMorphology_opts_SSE2.h | 22 ----- src/opts/SkMorphology_opts_arm.cpp | 34 -------- src/opts/SkMorphology_opts_neon.cpp | 80 ------------------- src/opts/SkMorphology_opts_neon.h | 15 ---- src/opts/SkMorphology_opts_none.cpp | 12 --- src/opts/SkOpts_neon.cpp | 13 ++- src/opts/SkOpts_sse2.cpp | 13 ++- src/opts/SkOpts_sse41.cpp | 7 +- src/opts/opts_check_x86.cpp | 22 ----- 17 files changed, 207 insertions(+), 438 deletions(-) create mode 100644 src/opts/SkMorphologyImageFilter_opts.h delete mode 100644 src/opts/SkMorphology_opts.h delete mode 100644 src/opts/SkMorphology_opts_SSE2.cpp delete mode 100644 src/opts/SkMorphology_opts_SSE2.h delete mode 100644 src/opts/SkMorphology_opts_arm.cpp delete mode 100644 src/opts/SkMorphology_opts_neon.cpp delete mode 100644 src/opts/SkMorphology_opts_neon.h delete mode 100644 src/opts/SkMorphology_opts_none.cpp diff --git a/gyp/opts.gypi b/gyp/opts.gypi index 09bdde65d6..adb1942121 100644 --- a/gyp/opts.gypi +++ b/gyp/opts.gypi @@ -7,7 +7,6 @@ '<(skia_src_path)/opts/SkBitmapProcState_opts_none.cpp', '<(skia_src_path)/opts/SkBlitMask_opts_none.cpp', '<(skia_src_path)/opts/SkBlitRow_opts_none.cpp', - '<(skia_src_path)/opts/SkMorphology_opts_none.cpp', '<(skia_src_path)/opts/SkTextureCompression_opts_none.cpp', ], @@ -15,7 +14,6 @@ '<(skia_src_path)/opts/SkBitmapProcState_opts_arm.cpp', '<(skia_src_path)/opts/SkBlitMask_opts_arm.cpp', '<(skia_src_path)/opts/SkBlitRow_opts_arm.cpp', - '<(skia_src_path)/opts/SkMorphology_opts_arm.cpp', '<(skia_src_path)/opts/SkTextureCompression_opts_arm.cpp', ], 'neon_sources': [ @@ -23,7 +21,6 @@ '<(skia_src_path)/opts/SkBitmapProcState_matrixProcs_neon.cpp', '<(skia_src_path)/opts/SkBlitMask_opts_arm_neon.cpp', '<(skia_src_path)/opts/SkBlitRow_opts_arm_neon.cpp', - '<(skia_src_path)/opts/SkMorphology_opts_neon.cpp', '<(skia_src_path)/opts/SkTextureCompression_opts_neon.cpp', '<(skia_src_path)/opts/SkOpts_neon.cpp', ], @@ -35,8 +32,6 @@ '<(skia_src_path)/opts/SkBlitMask_opts_arm_neon.cpp', '<(skia_src_path)/opts/SkBlitRow_opts_arm.cpp', '<(skia_src_path)/opts/SkBlitRow_opts_arm_neon.cpp', - '<(skia_src_path)/opts/SkMorphology_opts_arm.cpp', - '<(skia_src_path)/opts/SkMorphology_opts_neon.cpp', '<(skia_src_path)/opts/SkTextureCompression_opts_none.cpp', '<(skia_src_path)/opts/SkOpts_neon.cpp', ], @@ -45,7 +40,6 @@ '<(skia_src_path)/opts/SkBitmapProcState_opts_mips_dsp.cpp', '<(skia_src_path)/opts/SkBlitMask_opts_none.cpp', '<(skia_src_path)/opts/SkBlitRow_opts_mips_dsp.cpp', - '<(skia_src_path)/opts/SkMorphology_opts_none.cpp', '<(skia_src_path)/opts/SkTextureCompression_opts_none.cpp', ], @@ -53,7 +47,6 @@ '<(skia_src_path)/opts/SkBitmapFilter_opts_SSE2.cpp', '<(skia_src_path)/opts/SkBitmapProcState_opts_SSE2.cpp', '<(skia_src_path)/opts/SkBlitRow_opts_SSE2.cpp', - '<(skia_src_path)/opts/SkMorphology_opts_SSE2.cpp', '<(skia_src_path)/opts/SkTextureCompression_opts_none.cpp', '<(skia_src_path)/opts/opts_check_x86.cpp', '<(skia_src_path)/opts/SkOpts_sse2.cpp', diff --git a/src/core/SkOpts.cpp b/src/core/SkOpts.cpp index 815216b026..86981b9cf9 100644 --- a/src/core/SkOpts.cpp +++ b/src/core/SkOpts.cpp @@ -11,6 +11,7 @@ #define SK_OPTS_NS portable #include "SkBlurImageFilter_opts.h" #include "SkFloatingPoint_opts.h" +#include "SkMorphologyImageFilter_opts.h" #include "SkUtils_opts.h" #include "SkXfermode_opts.h" @@ -36,10 +37,14 @@ namespace SkOpts { decltype(memset32) memset32 = portable::memset32; decltype(create_xfermode) create_xfermode = SkCreate4pxXfermode; - static const auto x = portable::kX, y = portable::kY; - decltype(box_blur_xx) box_blur_xx = portable::box_blur; - decltype(box_blur_xy) box_blur_xy = portable::box_blur; - decltype(box_blur_yx) box_blur_yx = portable::box_blur; + decltype(box_blur_xx) box_blur_xx = portable::box_blur_xx; + decltype(box_blur_xy) box_blur_xy = portable::box_blur_xy; + decltype(box_blur_yx) box_blur_yx = portable::box_blur_yx; + + decltype(dilate_x) dilate_x = portable::dilate_x; + decltype(dilate_y) dilate_y = portable::dilate_y; + decltype( erode_x) erode_x = portable::erode_x; + decltype( erode_y) erode_y = portable::erode_y; // Each Init_foo() is defined in src/opts/SkOpts_foo.cpp. void Init_sse2(); diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h index 0fa12c63cd..dad16b93d5 100644 --- a/src/core/SkOpts.h +++ b/src/core/SkOpts.h @@ -33,6 +33,9 @@ namespace SkOpts { typedef void (*BoxBlur)(const SkPMColor*, int, SkPMColor*, int, int, int, int, int); extern BoxBlur box_blur_xx, box_blur_xy, box_blur_yx; + + typedef void (*Morph)(const SkPMColor*, SkPMColor*, int, int, int, int, int); + extern Morph dilate_x, dilate_y, erode_x, erode_y; } #endif//SkOpts_DEFINED diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp index eca5f00d0b..163f9d975a 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -8,10 +8,10 @@ #include "SkMorphologyImageFilter.h" #include "SkBitmap.h" #include "SkColorPriv.h" +#include "SkOpts.h" #include "SkReadBuffer.h" -#include "SkWriteBuffer.h" #include "SkRect.h" -#include "SkMorphology_opts.h" +#include "SkWriteBuffer.h" #if SK_SUPPORT_GPU #include "GrContext.h" #include "GrDrawContext.h" @@ -35,86 +35,6 @@ void SkMorphologyImageFilter::flatten(SkWriteBuffer& buffer) const { buffer.writeInt(fRadius.fHeight); } -enum MorphDirection { - kX, kY -}; - -template -static void erode(const SkPMColor* src, SkPMColor* dst, - int radius, int width, int height, - int srcStride, int dstStride) -{ - const int srcStrideX = direction == kX ? 1 : srcStride; - const int dstStrideX = direction == kX ? 1 : dstStride; - const int srcStrideY = direction == kX ? srcStride : 1; - const int dstStrideY = direction == kX ? dstStride : 1; - radius = SkMin32(radius, width - 1); - const SkPMColor* upperSrc = src + radius * srcStrideX; - for (int x = 0; x < width; ++x) { - const SkPMColor* lp = src; - const SkPMColor* up = upperSrc; - SkPMColor* dptr = dst; - for (int y = 0; y < height; ++y) { - int minB = 255, minG = 255, minR = 255, minA = 255; - for (const SkPMColor* p = lp; p <= up; p += srcStrideX) { - int b = SkGetPackedB32(*p); - int g = SkGetPackedG32(*p); - int r = SkGetPackedR32(*p); - int a = SkGetPackedA32(*p); - if (b < minB) minB = b; - if (g < minG) minG = g; - if (r < minR) minR = r; - if (a < minA) minA = a; - } - *dptr = SkPackARGB32(minA, minR, minG, minB); - dptr += dstStrideY; - lp += srcStrideY; - up += srcStrideY; - } - if (x >= radius) src += srcStrideX; - if (x + radius < width - 1) upperSrc += srcStrideX; - dst += dstStrideX; - } -} - -template -static void dilate(const SkPMColor* src, SkPMColor* dst, - int radius, int width, int height, - int srcStride, int dstStride) -{ - const int srcStrideX = direction == kX ? 1 : srcStride; - const int dstStrideX = direction == kX ? 1 : dstStride; - const int srcStrideY = direction == kX ? srcStride : 1; - const int dstStrideY = direction == kX ? dstStride : 1; - radius = SkMin32(radius, width - 1); - const SkPMColor* upperSrc = src + radius * srcStrideX; - for (int x = 0; x < width; ++x) { - const SkPMColor* lp = src; - const SkPMColor* up = upperSrc; - SkPMColor* dptr = dst; - for (int y = 0; y < height; ++y) { - int maxB = 0, maxG = 0, maxR = 0, maxA = 0; - for (const SkPMColor* p = lp; p <= up; p += srcStrideX) { - int b = SkGetPackedB32(*p); - int g = SkGetPackedG32(*p); - int r = SkGetPackedR32(*p); - int a = SkGetPackedA32(*p); - if (b > maxB) maxB = b; - if (g > maxG) maxG = g; - if (r > maxR) maxR = r; - if (a > maxA) maxA = a; - } - *dptr = SkPackARGB32(maxA, maxR, maxG, maxB); - dptr += dstStrideY; - lp += srcStrideY; - up += srcStrideY; - } - if (x >= radius) src += srcStrideX; - if (x + radius < width - 1) upperSrc += srcStrideX; - dst += dstStrideX; - } -} - static void callProcX(SkMorphologyImageFilter::Proc procX, const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds) { procX(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), @@ -203,29 +123,15 @@ bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc p bool SkErodeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, const Context& ctx, SkBitmap* dst, SkIPoint* offset) const { - Proc erodeXProc = SkMorphologyGetPlatformProc(kErodeX_SkMorphologyProcType); - if (!erodeXProc) { - erodeXProc = erode; - } - Proc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorphologyProcType); - if (!erodeYProc) { - erodeYProc = erode; - } - return this->filterImageGeneric(erodeXProc, erodeYProc, proxy, source, ctx, dst, offset); + return this->filterImageGeneric(SkOpts::erode_x, SkOpts::erode_y, + proxy, source, ctx, dst, offset); } bool SkDilateImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, const Context& ctx, SkBitmap* dst, SkIPoint* offset) const { - Proc dilateXProc = SkMorphologyGetPlatformProc(kDilateX_SkMorphologyProcType); - if (!dilateXProc) { - dilateXProc = dilate; - } - Proc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorphologyProcType); - if (!dilateYProc) { - dilateYProc = dilate; - } - return this->filterImageGeneric(dilateXProc, dilateYProc, proxy, source, ctx, dst, offset); + return this->filterImageGeneric(SkOpts::dilate_x, SkOpts::dilate_y, + proxy, source, ctx, dst, offset); } void SkMorphologyImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { @@ -714,7 +620,7 @@ bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, SkIPoint* offset) const { SkBitmap input = src; SkIPoint srcOffset = SkIPoint::Make(0, 0); - if (this->getInput(0) && + if (this->getInput(0) && !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) { return false; } diff --git a/src/opts/SkBlurImageFilter_opts.h b/src/opts/SkBlurImageFilter_opts.h index fb3fc19c0d..31d9d5fdbc 100644 --- a/src/opts/SkBlurImageFilter_opts.h +++ b/src/opts/SkBlurImageFilter_opts.h @@ -13,10 +13,10 @@ namespace SK_OPTS_NS { -enum Direction { kX, kY }; +enum class BlurDirection { kX, kY }; #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 -template +template void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSize, int leftOffset, int rightOffset, int width, int height) { #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41 @@ -57,10 +57,10 @@ void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSiz }; #endif const int rightBorder = SkMin32(rightOffset + 1, width); - const int srcStrideX = srcDirection == kX ? 1 : srcStride; - const int dstStrideX = dstDirection == kX ? 1 : height; - const int srcStrideY = srcDirection == kX ? srcStride : 1; - const int dstStrideY = dstDirection == kX ? width : 1; + const int srcStrideX = srcDirection == BlurDirection::kX ? 1 : srcStride; + const int dstStrideX = dstDirection == BlurDirection::kX ? 1 : height; + const int srcStrideY = srcDirection == BlurDirection::kX ? srcStride : 1; + const int dstStrideY = dstDirection == BlurDirection::kX ? width : 1; const __m128i scale = _mm_set1_epi32((1 << 24) / kernelSize); const __m128i half = _mm_set1_epi32(1 << 23); for (int y = 0; y < height; ++y) { @@ -93,7 +93,7 @@ void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSiz sum = _mm_add_epi32(sum, expand(r)); } sptr += srcStrideX; - if (srcDirection == kY) { + if (srcDirection == BlurDirection::kY) { // TODO(mtklein): experiment with moving this prefetch forward _mm_prefetch(reinterpret_cast(sptr + (rightOffset + 1) * srcStrideX), _MM_HINT_T0); @@ -108,12 +108,12 @@ void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSiz #elif defined(SK_ARM_HAS_NEON) // Fast path for kernel sizes between 2 and 127, working on two rows at a time. -template +template void box_blur_double(const SkPMColor** src, int srcStride, SkPMColor** dst, int kernelSize, int leftOffset, int rightOffset, int width, int* height) { // Load 2 pixels from adjacent rows. auto load_2_pixels = [&](const SkPMColor* s) { - if (srcDirection == kX) { + if (srcDirection == BlurDirection::kX) { // 10% faster by adding these 2 prefetches SK_PREFETCH(s + 16); SK_PREFETCH(s + 16 + srcStride); @@ -125,10 +125,10 @@ void box_blur_double(const SkPMColor** src, int srcStride, SkPMColor** dst, int } }; const int rightBorder = SkMin32(rightOffset + 1, width); - const int srcStrideX = srcDirection == kX ? 1 : srcStride; - const int dstStrideX = dstDirection == kX ? 1 : *height; - const int srcStrideY = srcDirection == kX ? srcStride : 1; - const int dstStrideY = dstDirection == kX ? width : 1; + const int srcStrideX = srcDirection == BlurDirection::kX ? 1 : srcStride; + const int dstStrideX = dstDirection == BlurDirection::kX ? 1 : *height; + const int srcStrideY = srcDirection == BlurDirection::kX ? srcStride : 1; + const int dstStrideY = dstDirection == BlurDirection::kX ? width : 1; const uint16x8_t scale = vdupq_n_u16((1 << 15) / kernelSize); for (; *height >= 2; *height -= 2) { @@ -145,7 +145,7 @@ void box_blur_double(const SkPMColor** src, int srcStride, SkPMColor** dst, int // val = (sum * scale * 2 + 0x8000) >> 16 uint16x8_t resultPixels = vreinterpretq_u16_s16(vqrdmulhq_s16( vreinterpretq_s16_u16(sum), vreinterpretq_s16_u16(scale))); - if (dstDirection == kX) { + if (dstDirection == BlurDirection::kX) { uint32x2_t px2 = vreinterpret_u32_u8(vmovn_u16(resultPixels)); vst1_lane_u32(dptr + 0, px2, 0); vst1_lane_u32(dptr + width, px2, 1); @@ -167,7 +167,7 @@ void box_blur_double(const SkPMColor** src, int srcStride, SkPMColor** dst, int } } -template +template void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSize, int leftOffset, int rightOffset, int width, int height) { // ARGB -> 0A0R 0G0B @@ -175,10 +175,10 @@ void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSiz return vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vdup_n_u32(p)))); }; const int rightBorder = SkMin32(rightOffset + 1, width); - const int srcStrideX = srcDirection == kX ? 1 : srcStride; - const int dstStrideX = dstDirection == kX ? 1 : height; - const int srcStrideY = srcDirection == kX ? srcStride : 1; - const int dstStrideY = dstDirection == kX ? width : 1; + const int srcStrideX = srcDirection == BlurDirection::kX ? 1 : srcStride; + const int dstStrideX = dstDirection == BlurDirection::kX ? 1 : height; + const int srcStrideY = srcDirection == BlurDirection::kX ? srcStride : 1; + const int dstStrideY = dstDirection == BlurDirection::kX ? width : 1; const uint32x4_t scale = vdupq_n_u32((1 << 24) / kernelSize); const uint32x4_t half = vdupq_n_u32(1 << 23); @@ -222,7 +222,7 @@ void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSiz sum = vaddw_u16(sum, expand(*r)); } sptr += srcStrideX; - if (srcDirection == kX) { + if (srcDirection == BlurDirection::kX) { SK_PREFETCH(sptr + (rightOffset + 16) * srcStrideX); } dptr += dstStrideX; @@ -234,14 +234,14 @@ void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSiz #else // Neither NEON nor >=SSE2. -template +template static void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int kernelSize, int leftOffset, int rightOffset, int width, int height) { int rightBorder = SkMin32(rightOffset + 1, width); - int srcStrideX = srcDirection == kX ? 1 : srcStride; - int dstStrideX = dstDirection == kX ? 1 : height; - int srcStrideY = srcDirection == kX ? srcStride : 1; - int dstStrideY = dstDirection == kX ? width : 1; + int srcStrideX = srcDirection == BlurDirection::kX ? 1 : srcStride; + int dstStrideX = dstDirection == BlurDirection::kX ? 1 : height; + int srcStrideY = srcDirection == BlurDirection::kX ? srcStride : 1; + int dstStrideY = dstDirection == BlurDirection::kX ? width : 1; uint32_t scale = (1 << 24) / kernelSize; uint32_t half = 1 << 23; for (int y = 0; y < height; ++y) { @@ -277,7 +277,7 @@ static void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int ke sumB += SkGetPackedB32(r); } sptr += srcStrideX; - if (srcDirection == kY) { + if (srcDirection == BlurDirection::kY) { SK_PREFETCH(sptr + (rightOffset + 1) * srcStrideX); } dptr += dstStrideX; @@ -289,6 +289,10 @@ static void box_blur(const SkPMColor* src, int srcStride, SkPMColor* dst, int ke #endif +static auto box_blur_xx = &box_blur, + box_blur_xy = &box_blur, + box_blur_yx = &box_blur; + } // namespace SK_OPTS_NS #endif diff --git a/src/opts/SkMorphologyImageFilter_opts.h b/src/opts/SkMorphologyImageFilter_opts.h new file mode 100644 index 0000000000..e30a9e4973 --- /dev/null +++ b/src/opts/SkMorphologyImageFilter_opts.h @@ -0,0 +1,137 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkMorphologyImageFilter_opts_DEFINED +#define SkMorphologyImageFilter_opts_DEFINED + +namespace SK_OPTS_NS { + +enum MorphType { kDilate, kErode }; +enum class MorphDirection { kX, kY }; + +#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 +template +static void morph(const SkPMColor* src, SkPMColor* dst, + int radius, int width, int height, int srcStride, int dstStride) { + const int srcStrideX = direction == MorphDirection::kX ? 1 : srcStride; + const int dstStrideX = direction == MorphDirection::kX ? 1 : dstStride; + const int srcStrideY = direction == MorphDirection::kX ? srcStride : 1; + const int dstStrideY = direction == MorphDirection::kX ? dstStride : 1; + radius = SkMin32(radius, width - 1); + const SkPMColor* upperSrc = src + radius * srcStrideX; + for (int x = 0; x < width; ++x) { + const SkPMColor* lp = src; + const SkPMColor* up = upperSrc; + SkPMColor* dptr = dst; + for (int y = 0; y < height; ++y) { + __m128i extreme = (type == kDilate) ? _mm_setzero_si128() + : _mm_set1_epi32(0xFFFFFFFF); + for (const SkPMColor* p = lp; p <= up; p += srcStrideX) { + __m128i src_pixel = _mm_cvtsi32_si128(*p); + extreme = (type == kDilate) ? _mm_max_epu8(src_pixel, extreme) + : _mm_min_epu8(src_pixel, extreme); + } + *dptr = _mm_cvtsi128_si32(extreme); + dptr += dstStrideY; + lp += srcStrideY; + up += srcStrideY; + } + if (x >= radius) { src += srcStrideX; } + if (x + radius < width - 1) { upperSrc += srcStrideX; } + dst += dstStrideX; + } +} + +#elif defined(SK_ARM_HAS_NEON) +template +static void morph(const SkPMColor* src, SkPMColor* dst, + int radius, int width, int height, int srcStride, int dstStride) { + const int srcStrideX = direction == MorphDirection::kX ? 1 : srcStride; + const int dstStrideX = direction == MorphDirection::kX ? 1 : dstStride; + const int srcStrideY = direction == MorphDirection::kX ? srcStride : 1; + const int dstStrideY = direction == MorphDirection::kX ? dstStride : 1; + radius = SkMin32(radius, width - 1); + const SkPMColor* upperSrc = src + radius * srcStrideX; + for (int x = 0; x < width; ++x) { + const SkPMColor* lp = src; + const SkPMColor* up = upperSrc; + SkPMColor* dptr = dst; + for (int y = 0; y < height; ++y) { + uint8x8_t extreme = vdup_n_u8(type == kDilate ? 0 : 255); + for (const SkPMColor* p = lp; p <= up; p += srcStrideX) { + uint8x8_t src_pixel = vreinterpret_u8_u32(vdup_n_u32(*p)); + extreme = (type == kDilate) ? vmax_u8(src_pixel, extreme) + : vmin_u8(src_pixel, extreme); + } + *dptr = vget_lane_u32(vreinterpret_u32_u8(extreme), 0); + dptr += dstStrideY; + lp += srcStrideY; + up += srcStrideY; + } + if (x >= radius) src += srcStrideX; + if (x + radius < width - 1) upperSrc += srcStrideX; + dst += dstStrideX; + } +} + +#else +template +static void morph(const SkPMColor* src, SkPMColor* dst, + int radius, int width, int height, int srcStride, int dstStride) { + const int srcStrideX = direction == MorphDirection::kX ? 1 : srcStride; + const int dstStrideX = direction == MorphDirection::kX ? 1 : dstStride; + const int srcStrideY = direction == MorphDirection::kX ? srcStride : 1; + const int dstStrideY = direction == MorphDirection::kX ? dstStride : 1; + radius = SkMin32(radius, width - 1); + const SkPMColor* upperSrc = src + radius * srcStrideX; + for (int x = 0; x < width; ++x) { + const SkPMColor* lp = src; + const SkPMColor* up = upperSrc; + SkPMColor* dptr = dst; + for (int y = 0; y < height; ++y) { + // If we're maxing (dilate), start from 0; if minning (erode), start from 255. + const int start = (type == kDilate) ? 0 : 255; + int B = start, G = start, R = start, A = start; + for (const SkPMColor* p = lp; p <= up; p += srcStrideX) { + int b = SkGetPackedB32(*p), + g = SkGetPackedG32(*p), + r = SkGetPackedR32(*p), + a = SkGetPackedA32(*p); + if (type == kDilate) { + B = SkTMax(b, B); + G = SkTMax(g, G); + R = SkTMax(r, R); + A = SkTMax(a, A); + } else { + B = SkTMin(b, B); + G = SkTMin(g, G); + R = SkTMin(r, R); + A = SkTMin(a, A); + } + } + *dptr = SkPackARGB32(A, R, G, B); + dptr += dstStrideY; + lp += srcStrideY; + up += srcStrideY; + } + if (x >= radius) { src += srcStrideX; } + if (x + radius < width - 1) { upperSrc += srcStrideX; } + dst += dstStrideX; + } +} + +#endif + +static auto dilate_x = &morph, + dilate_y = &morph, + erode_x = &morph, + erode_y = &morph; + +} // namespace SK_OPTS_NS + +#endif//SkMorphologyImageFilter_opts_DEFINED + diff --git a/src/opts/SkMorphology_opts.h b/src/opts/SkMorphology_opts.h deleted file mode 100644 index 7813efb191..0000000000 --- a/src/opts/SkMorphology_opts.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2013 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkMorphology_opts_DEFINED -#define SkMorphology_opts_DEFINED - -#include "SkMorphologyImageFilter.h" - -enum SkMorphologyProcType { - kDilateX_SkMorphologyProcType, - kDilateY_SkMorphologyProcType, - kErodeX_SkMorphologyProcType, - kErodeY_SkMorphologyProcType -}; - -SkMorphologyImageFilter::Proc SkMorphologyGetPlatformProc(SkMorphologyProcType type); - -#endif diff --git a/src/opts/SkMorphology_opts_SSE2.cpp b/src/opts/SkMorphology_opts_SSE2.cpp deleted file mode 100644 index e782950956..0000000000 --- a/src/opts/SkMorphology_opts_SSE2.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2013 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include -#include "SkColorPriv.h" -#include "SkMorphology_opts_SSE2.h" - -/* SSE2 version of dilateX, dilateY, erodeX, erodeY. - * portable versions are in src/effects/SkMorphologyImageFilter.cpp. - */ - -enum MorphType { - kDilate, kErode -}; - -enum MorphDirection { - kX, kY -}; - -template -static void SkMorph_SSE2(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride) -{ - const int srcStrideX = direction == kX ? 1 : srcStride; - const int dstStrideX = direction == kX ? 1 : dstStride; - const int srcStrideY = direction == kX ? srcStride : 1; - const int dstStrideY = direction == kX ? dstStride : 1; - radius = SkMin32(radius, width - 1); - const SkPMColor* upperSrc = src + radius * srcStrideX; - for (int x = 0; x < width; ++x) { - const SkPMColor* lp = src; - const SkPMColor* up = upperSrc; - SkPMColor* dptr = dst; - for (int y = 0; y < height; ++y) { - __m128i max = type == kDilate ? _mm_setzero_si128() : _mm_set1_epi32(0xFFFFFFFF); - for (const SkPMColor* p = lp; p <= up; p += srcStrideX) { - __m128i src_pixel = _mm_cvtsi32_si128(*p); - max = type == kDilate ? _mm_max_epu8(src_pixel, max) : _mm_min_epu8(src_pixel, max); - } - *dptr = _mm_cvtsi128_si32(max); - dptr += dstStrideY; - lp += srcStrideY; - up += srcStrideY; - } - if (x >= radius) { - src += srcStrideX; - } - if (x + radius < width - 1) { - upperSrc += srcStrideX; - } - dst += dstStrideX; - } -} - -void SkDilateX_SSE2(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride) -{ - SkMorph_SSE2(src, dst, radius, width, height, srcStride, dstStride); -} - -void SkErodeX_SSE2(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride) -{ - SkMorph_SSE2(src, dst, radius, width, height, srcStride, dstStride); -} - -void SkDilateY_SSE2(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride) -{ - SkMorph_SSE2(src, dst, radius, width, height, srcStride, dstStride); -} - -void SkErodeY_SSE2(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride) -{ - SkMorph_SSE2(src, dst, radius, width, height, srcStride, dstStride); -} diff --git a/src/opts/SkMorphology_opts_SSE2.h b/src/opts/SkMorphology_opts_SSE2.h deleted file mode 100644 index bf5aa03b09..0000000000 --- a/src/opts/SkMorphology_opts_SSE2.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2013 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkMorphology_opts_SSE2_DEFINED -#define SkMorphology_opts_SSE2_DEFINED - -#include "SkColor.h" - -void SkDilateX_SSE2(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride); -void SkDilateY_SSE2(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride); -void SkErodeX_SSE2(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride); -void SkErodeY_SSE2(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride); - -#endif diff --git a/src/opts/SkMorphology_opts_arm.cpp b/src/opts/SkMorphology_opts_arm.cpp deleted file mode 100644 index 2bba4929c2..0000000000 --- a/src/opts/SkMorphology_opts_arm.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2014 ARM Ltd. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkMorphology_opts.h" -#include "SkMorphology_opts_neon.h" -#include "SkUtilsArm.h" - -SkMorphologyImageFilter::Proc SkMorphologyGetPlatformProc(SkMorphologyProcType type) { -#if SK_ARM_NEON_IS_NONE - return NULL; -#else -#if SK_ARM_NEON_IS_DYNAMIC - if (!sk_cpu_arm_has_neon()) { - return NULL; - } -#endif - switch (type) { - case kDilateX_SkMorphologyProcType: - return SkDilateX_neon; - case kDilateY_SkMorphologyProcType: - return SkDilateY_neon; - case kErodeX_SkMorphologyProcType: - return SkErodeX_neon; - case kErodeY_SkMorphologyProcType: - return SkErodeY_neon; - default: - return NULL; - } -#endif -} diff --git a/src/opts/SkMorphology_opts_neon.cpp b/src/opts/SkMorphology_opts_neon.cpp deleted file mode 100644 index 571b5c8b17..0000000000 --- a/src/opts/SkMorphology_opts_neon.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2013 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - -#include "SkColorPriv.h" -#include "SkMorphology_opts.h" -#include "SkMorphology_opts_neon.h" - -#include - -/* neon version of dilateX, dilateY, erodeX, erodeY. - * portable versions are in src/effects/SkMorphologyImageFilter.cpp. - */ - -enum MorphType { - kDilate, kErode -}; - -enum MorphDirection { - kX, kY -}; - -template -static void SkMorph_neon(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride) -{ - const int srcStrideX = direction == kX ? 1 : srcStride; - const int dstStrideX = direction == kX ? 1 : dstStride; - const int srcStrideY = direction == kX ? srcStride : 1; - const int dstStrideY = direction == kX ? dstStride : 1; - radius = SkMin32(radius, width - 1); - const SkPMColor* upperSrc = src + radius * srcStrideX; - for (int x = 0; x < width; ++x) { - const SkPMColor* lp = src; - const SkPMColor* up = upperSrc; - SkPMColor* dptr = dst; - for (int y = 0; y < height; ++y) { - uint8x8_t max = vdup_n_u8(type == kDilate ? 0 : 255); - for (const SkPMColor* p = lp; p <= up; p += srcStrideX) { - uint8x8_t src_pixel = vreinterpret_u8_u32(vdup_n_u32(*p)); - max = type == kDilate ? vmax_u8(src_pixel, max) : vmin_u8(src_pixel, max); - } - *dptr = vget_lane_u32(vreinterpret_u32_u8(max), 0); - dptr += dstStrideY; - lp += srcStrideY; - up += srcStrideY; - } - if (x >= radius) src += srcStrideX; - if (x + radius < width - 1) upperSrc += srcStrideX; - dst += dstStrideX; - } -} - -void SkDilateX_neon(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride) -{ - SkMorph_neon(src, dst, radius, width, height, srcStride, dstStride); -} - -void SkErodeX_neon(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride) -{ - SkMorph_neon(src, dst, radius, width, height, srcStride, dstStride); -} - -void SkDilateY_neon(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride) -{ - SkMorph_neon(src, dst, radius, width, height, srcStride, dstStride); -} - -void SkErodeY_neon(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride) -{ - SkMorph_neon(src, dst, radius, width, height, srcStride, dstStride); -} diff --git a/src/opts/SkMorphology_opts_neon.h b/src/opts/SkMorphology_opts_neon.h deleted file mode 100644 index 0b962bdad6..0000000000 --- a/src/opts/SkMorphology_opts_neon.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2013 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -void SkDilateX_neon(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride); -void SkDilateY_neon(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride); -void SkErodeX_neon(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride); -void SkErodeY_neon(const SkPMColor* src, SkPMColor* dst, int radius, - int width, int height, int srcStride, int dstStride); diff --git a/src/opts/SkMorphology_opts_none.cpp b/src/opts/SkMorphology_opts_none.cpp deleted file mode 100644 index ade261fc7d..0000000000 --- a/src/opts/SkMorphology_opts_none.cpp +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2013 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkMorphology_opts.h" - -SkMorphologyImageFilter::Proc SkMorphologyGetPlatformProc(SkMorphologyProcType) { - return NULL; -} diff --git a/src/opts/SkOpts_neon.cpp b/src/opts/SkOpts_neon.cpp index 2db976d5c9..f75dc7c55c 100644 --- a/src/opts/SkOpts_neon.cpp +++ b/src/opts/SkOpts_neon.cpp @@ -10,6 +10,7 @@ #define SK_OPTS_NS neon #include "SkBlurImageFilter_opts.h" #include "SkFloatingPoint_opts.h" +#include "SkMorphologyImageFilter_opts.h" #include "SkUtils_opts.h" #include "SkXfermode_opts.h" @@ -20,9 +21,13 @@ namespace SkOpts { memset32 = neon::memset32; create_xfermode = SkCreate4pxXfermode; - static const auto x = neon::kX, y = neon::kY; - box_blur_xx = neon::box_blur; - box_blur_xy = neon::box_blur; - box_blur_yx = neon::box_blur; + box_blur_xx = neon::box_blur_xx; + box_blur_xy = neon::box_blur_xy; + box_blur_yx = neon::box_blur_yx; + + dilate_x = neon::dilate_x; + dilate_y = neon::dilate_y; + erode_x = neon::erode_x; + erode_y = neon::erode_y; } } diff --git a/src/opts/SkOpts_sse2.cpp b/src/opts/SkOpts_sse2.cpp index ef0f96a0a1..8837efee55 100644 --- a/src/opts/SkOpts_sse2.cpp +++ b/src/opts/SkOpts_sse2.cpp @@ -9,6 +9,7 @@ #define SK_OPTS_NS sse2 #include "SkBlurImageFilter_opts.h" +#include "SkMorphologyImageFilter_opts.h" #include "SkUtils_opts.h" #include "SkXfermode_opts.h" @@ -18,9 +19,13 @@ namespace SkOpts { memset32 = sse2::memset32; create_xfermode = SkCreate4pxXfermode; - static const auto x = sse2::kX, y = sse2::kY; - box_blur_xx = sse2::box_blur; - box_blur_xy = sse2::box_blur; - box_blur_yx = sse2::box_blur; + box_blur_xx = sse2::box_blur_xx; + box_blur_xy = sse2::box_blur_xy; + box_blur_yx = sse2::box_blur_yx; + + dilate_x = sse2::dilate_x; + dilate_y = sse2::dilate_y; + erode_x = sse2::erode_x; + erode_y = sse2::erode_y; } } diff --git a/src/opts/SkOpts_sse41.cpp b/src/opts/SkOpts_sse41.cpp index 189810c11e..938b2f9e83 100644 --- a/src/opts/SkOpts_sse41.cpp +++ b/src/opts/SkOpts_sse41.cpp @@ -12,9 +12,8 @@ namespace SkOpts { void Init_sse41() { - static const auto x = sse41::kX, y = sse41::kY; - box_blur_xx = sse41::box_blur; - box_blur_xy = sse41::box_blur; - box_blur_yx = sse41::box_blur; + box_blur_xx = sse41::box_blur_xx; + box_blur_xy = sse41::box_blur_xy; + box_blur_yx = sse41::box_blur_yx; } } diff --git a/src/opts/opts_check_x86.cpp b/src/opts/opts_check_x86.cpp index d0423377a1..c560b914f9 100644 --- a/src/opts/opts_check_x86.cpp +++ b/src/opts/opts_check_x86.cpp @@ -14,8 +14,6 @@ #include "SkBlitRow_opts_SSE2.h" #include "SkBlitRow_opts_SSE4.h" #include "SkLazyPtr.h" -#include "SkMorphology_opts.h" -#include "SkMorphology_opts_SSE2.h" #include "SkRTConf.h" #if defined(_MSC_VER) && defined(_WIN64) @@ -294,23 +292,3 @@ SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) { SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkColorType, SkMask::Format, RowFlags) { return NULL; } - -//////////////////////////////////////////////////////////////////////////////// - -SkMorphologyImageFilter::Proc SkMorphologyGetPlatformProc(SkMorphologyProcType type) { - if (!supports_simd(SK_CPU_SSE_LEVEL_SSE2)) { - return NULL; - } - switch (type) { - case kDilateX_SkMorphologyProcType: - return SkDilateX_SSE2; - case kDilateY_SkMorphologyProcType: - return SkDilateY_SSE2; - case kErodeX_SkMorphologyProcType: - return SkErodeX_SSE2; - case kErodeY_SkMorphologyProcType: - return SkErodeY_SSE2; - default: - return NULL; - } -} -- cgit v1.2.3