aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2015-08-04 14:09:09 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-08-04 14:09:09 -0700
commitd029ded92d409a004f2096c78f5a99b524206481 (patch)
tree84016b58d7c62b1251ed1408bff7d08ca3915c2e
parent9f8754f5910764b1722573050b481be7e65f7c03 (diff)
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
-rw-r--r--gyp/opts.gypi7
-rw-r--r--src/core/SkOpts.cpp13
-rw-r--r--src/core/SkOpts.h3
-rw-r--r--src/effects/SkMorphologyImageFilter.cpp108
-rw-r--r--src/opts/SkBlurImageFilter_opts.h56
-rw-r--r--src/opts/SkMorphologyImageFilter_opts.h137
-rw-r--r--src/opts/SkMorphology_opts.h22
-rw-r--r--src/opts/SkMorphology_opts_SSE2.cpp81
-rw-r--r--src/opts/SkMorphology_opts_SSE2.h22
-rw-r--r--src/opts/SkMorphology_opts_arm.cpp34
-rw-r--r--src/opts/SkMorphology_opts_neon.cpp80
-rw-r--r--src/opts/SkMorphology_opts_neon.h15
-rw-r--r--src/opts/SkMorphology_opts_none.cpp12
-rw-r--r--src/opts/SkOpts_neon.cpp13
-rw-r--r--src/opts/SkOpts_sse2.cpp13
-rw-r--r--src/opts/SkOpts_sse41.cpp7
-rw-r--r--src/opts/opts_check_x86.cpp22
17 files changed, 207 insertions, 438 deletions
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<x,x>;
- decltype(box_blur_xy) box_blur_xy = portable::box_blur<x,y>;
- decltype(box_blur_yx) box_blur_yx = portable::box_blur<y,x>;
+ 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<MorphDirection direction>
-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<MorphDirection direction>
-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<kX>;
- }
- Proc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorphologyProcType);
- if (!erodeYProc) {
- erodeYProc = erode<kY>;
- }
- 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<kX>;
- }
- Proc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorphologyProcType);
- if (!dilateYProc) {
- dilateYProc = dilate<kY>;
- }
- 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<Direction srcDirection, Direction dstDirection>
+template<BlurDirection srcDirection, BlurDirection dstDirection>
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<const char*>(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<Direction srcDirection, Direction dstDirection>
+template<BlurDirection srcDirection, BlurDirection dstDirection>
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<Direction srcDirection, Direction dstDirection>
+template<BlurDirection srcDirection, BlurDirection dstDirection>
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<Direction srcDirection, Direction dstDirection>
+template<BlurDirection srcDirection, BlurDirection dstDirection>
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<BlurDirection::kX, BlurDirection::kX>,
+ box_blur_xy = &box_blur<BlurDirection::kX, BlurDirection::kY>,
+ box_blur_yx = &box_blur<BlurDirection::kY, BlurDirection::kX>;
+
} // 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<MorphType type, MorphDirection direction>
+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<MorphType type, MorphDirection direction>
+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<MorphType type, MorphDirection direction>
+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<kDilate, MorphDirection::kX>,
+ dilate_y = &morph<kDilate, MorphDirection::kY>,
+ erode_x = &morph<kErode, MorphDirection::kX>,
+ erode_y = &morph<kErode, MorphDirection::kY>;
+
+} // 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 <emmintrin.h>
-#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<MorphType type, MorphDirection direction>
-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<kDilate, kX>(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<kErode, kX>(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<kDilate, kY>(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<kErode, kY>(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 <arm_neon.h>
-
-/* neon version of dilateX, dilateY, erodeX, erodeY.
- * portable versions are in src/effects/SkMorphologyImageFilter.cpp.
- */
-
-enum MorphType {
- kDilate, kErode
-};
-
-enum MorphDirection {
- kX, kY
-};
-
-template<MorphType type, MorphDirection direction>
-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<kDilate, kX>(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<kErode, kX>(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<kDilate, kY>(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<kErode, kY>(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<x,x>;
- box_blur_xy = neon::box_blur<x,y>;
- box_blur_yx = neon::box_blur<y,x>;
+ 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<x,x>;
- box_blur_xy = sse2::box_blur<x,y>;
- box_blur_yx = sse2::box_blur<y,x>;
+ 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<x,x>;
- box_blur_xy = sse41::box_blur<x,y>;
- box_blur_yx = sse41::box_blur<y,x>;
+ 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;
- }
-}