diff options
author | Herbert Derby <herb@google.com> | 2018-01-17 17:18:55 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-01-26 19:39:30 +0000 |
commit | 53d57ace9974f04ddde1fa2e3fb6e625ed5ee451 (patch) | |
tree | d65597b4c0efcdd3fbd1ccea00239610cd5d6e83 /src/core/SkMaskBlurFilter.cpp | |
parent | dcb086bd79665930f108444f1d3bcc6466dc346e (diff) |
Remove legacy mask blur code.
This was flag flipped about last year in the chrome code, and
flag flipped about three weeks ago in Android.
All the *_LEGACY_*BLUR flags are gone.
Change-Id: I046f3a040ccbf12ff3a810c41b02131095df3368
Reviewed-on: https://skia-review.googlesource.com/96001
Reviewed-by: Mike Klein <mtklein@chromium.org>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Herb Derby <herb@google.com>
Diffstat (limited to 'src/core/SkMaskBlurFilter.cpp')
-rw-r--r-- | src/core/SkMaskBlurFilter.cpp | 311 |
1 files changed, 9 insertions, 302 deletions
diff --git a/src/core/SkMaskBlurFilter.cpp b/src/core/SkMaskBlurFilter.cpp index e39aa26692..b8e245f36b 100644 --- a/src/core/SkMaskBlurFilter.cpp +++ b/src/core/SkMaskBlurFilter.cpp @@ -17,8 +17,6 @@ static const double kPi = 3.14159265358979323846264338327950288; -static constexpr double kSmallSigma = 2.0; - class BlurScanInterface { public: virtual ~BlurScanInterface() = default; @@ -55,237 +53,6 @@ public: } }; -class PlanBox final : public PlanningInterface { -public: - explicit PlanBox(double sigma) { - // Calculate the radius from sigma. Taken from the old code until something better is - // figured out. - auto possibleRadius = 1.5 * sigma - 0.5; - auto radius = std::max(std::numeric_limits<double>::epsilon(), possibleRadius); - auto outerRadius = std::ceil(radius); - auto outerWindow = 2 * outerRadius + 1; - auto outerFactor = (1 - (outerRadius - radius)) / outerWindow; - fOuterWeight = static_cast<uint32_t>(round(outerFactor * (1ull << 24))); - - auto innerRadius = outerRadius - 1; - auto innerWindow = 2 * innerRadius + 1; - auto innerFactor = (1 - (radius - innerRadius)) / innerWindow; - fInnerWeight = static_cast<uint32_t>(round(innerFactor * (1ull << 24))); - - // Sliding window is defined by the relationship between the outer and inner widows. - // In the single window case, you add the element on the right, and subtract the element on - // the left. But, because two windows are used, this relationship is more complicated; an - // element is added from the right of the outer window, and subtracted from the left of the - // inner window. Because innerWindow = outerWindow - 2, the distance between - // the left and right in the two window case is outerWindow - 1. - fSlidingWindow = static_cast<int>(outerWindow - 1); - } - - size_t bufferSize() const override { - return fSlidingWindow * (sizeof(Sk4u) / sizeof(uint32_t)); - } - - // Remember that sliding window = window - 1. Therefore, radius = sliding window / 2. - int border() const override { return fSlidingWindow / 2; } - - bool needsBlur() const override { return true; } - - BlurScanInterface* makeBlurScan( - SkArenaAlloc* alloc, int width, uint32_t* buffer) const override - { - int noChangeCount, - trailingEdgeZeroCount; - - // The relation between the slidingWindow and the width dictates two operating modes. - // * width >= slidingWindow - both sides of the window are contained in the image while - // scanning. Therefore, we assume that slidingWindow zeros are consumed on the trailing - // edge of the window. After this count, then both edges are traversing the image. - // * slidingWindow > width - both sides of the window are off the image while scanning - // the middle. The front edge of the window can only travel width until it falls off the - // image. At this point, both edges of the window are off the image consuming zeros - // and therefore, the destination value does not change. The scan produces unchanged - // values until the trailing edge of the window enters the image. This count is - // slidingWindow - width. - if (width >= fSlidingWindow) { - noChangeCount = 0; - trailingEdgeZeroCount = fSlidingWindow; - } else { - noChangeCount = fSlidingWindow - width; - trailingEdgeZeroCount = width; - } - - Sk4u* sk4uBuffer = reinterpret_cast<Sk4u*>(buffer); - return alloc->make<Box>(fOuterWeight, fInnerWeight, noChangeCount, trailingEdgeZeroCount, - sk4uBuffer, sk4uBuffer + fSlidingWindow); - } - -private: - class Box final : public BlurScanInterface { - public: - Box(uint32_t outerWeight, uint32_t innerWeight, - int noChangeCount, int trailingEdgeZeroCount, - Sk4u* buffer, Sk4u* bufferEnd) - : fOuterWeight{outerWeight} - , fInnerWeight{innerWeight} - , fNoChangeCount{noChangeCount} - , fTrailingEdgeZeroCount{trailingEdgeZeroCount} - , fBuffer{buffer} - , fBufferEnd{bufferEnd} { } - - void blur(const uint8_t* src, int srcStride, const uint8_t* srcEnd, - uint8_t* dst, int dstStride, uint8_t* dstEnd) const override { - auto rightOuter = src; - auto dstCursor = dst; - - auto interpolateSums = [this](uint32_t outerSum, uint32_t innerSum) { - return SkTo<uint8_t>( - (fOuterWeight * outerSum + fInnerWeight * innerSum + kHalf) >> 24); - }; - - uint32_t outerSum = 0; - uint32_t innerSum = 0; - for (int i = 0; i < fTrailingEdgeZeroCount; i++) { - innerSum = outerSum; - outerSum += *rightOuter; - *dstCursor = interpolateSums(outerSum, innerSum); - - rightOuter += srcStride; - dstCursor += dstStride; - } - - // slidingWindow > width - for (int i = 0; i < fNoChangeCount; i++) { - *dstCursor = interpolateSums(outerSum, innerSum);; - dstCursor += dstStride; - } - - // width > slidingWindow - auto leftInner = src; - while (rightOuter < srcEnd) { - innerSum = outerSum - *leftInner; - outerSum += *rightOuter; - *dstCursor = interpolateSums(outerSum, innerSum); - outerSum -= *leftInner; - - rightOuter += srcStride; - leftInner += srcStride; - dstCursor += dstStride; - } - - auto leftOuter = srcEnd; - dstCursor = dstEnd; - outerSum = 0; - for (int i = 0; i < fTrailingEdgeZeroCount; i++) { - leftOuter -= srcStride; - dstCursor -= dstStride; - - innerSum = outerSum; - outerSum += *leftOuter; - *dstCursor = interpolateSums(outerSum, innerSum); - } - } - - bool canBlur4() override { return true; } - - // NB this is a transposing scan. The next src is src+1, and the next down is - // src+srcStride. - void blur4Transpose( - const uint8_t* src, int srcStride, const uint8_t* srcEnd, - uint8_t* dst, int dstStride, uint8_t* dstEnd) const override { - auto rightOuter = src; - auto dstCursor = dst; - - Sk4u* const bufferStart = fBuffer; - Sk4u* bufferCursor = bufferStart; - Sk4u* const bufferEnd = fBufferEnd; - - const Sk4u outerWeight(SkTo<uint32_t>(fOuterWeight)); - const Sk4u innerWeight(SkTo<uint32_t>(fInnerWeight)); - - auto load = [](const uint8_t* cursor, int stride) -> Sk4u { - return Sk4u(cursor[0*stride], cursor[1*stride], cursor[2*stride], cursor[3*stride]); - }; - - auto interpolateSums = [&] (const Sk4u& outerSum, const Sk4u& innerSum) { - return - SkNx_cast<uint8_t>( - (outerSum * outerWeight + innerSum * innerWeight + kHalf) >> 24); - }; - - Sk4u outerSum = 0; - Sk4u innerSum = 0; - for (int i = 0; i < fTrailingEdgeZeroCount; i++) { - innerSum = outerSum; - - Sk4u leadingEdge = load(rightOuter, srcStride); - outerSum += leadingEdge; - Sk4b blurred = interpolateSums(outerSum, innerSum); - blurred.store(dstCursor); - - leadingEdge.store(bufferCursor); - bufferCursor = (bufferCursor + 1) < bufferEnd ? bufferCursor + 1 : bufferStart; - - rightOuter += 1; - dstCursor += dstStride; - } - - // slidingWindow > width - for (int i = 0; i < fNoChangeCount; i++) { - Sk4b blurred = interpolateSums(outerSum, innerSum); - blurred.store(dstCursor); - dstCursor += dstStride; - } - - // width > slidingWindow - auto leftInner = src; - while (rightOuter < srcEnd) { - Sk4u trailEdge = Sk4u::Load(bufferCursor); - Sk4u leadingEdge = load(rightOuter, srcStride); - innerSum = outerSum - trailEdge; - outerSum += leadingEdge; - - Sk4b blurred = interpolateSums(outerSum, innerSum); - blurred.store(dstCursor); - - outerSum -= trailEdge; - leadingEdge.store(bufferCursor); - bufferCursor = (bufferCursor + 1) < bufferEnd ? bufferCursor + 1 : bufferStart; - - rightOuter += 1; - leftInner += 1; - dstCursor += dstStride; - } - - auto leftOuter = srcEnd; - dstCursor = dstEnd; - outerSum = 0; - for (int i = 0; i < fTrailingEdgeZeroCount; i++) { - leftOuter -= 1; - dstCursor -= dstStride; - - innerSum = outerSum; - outerSum += load(leftOuter, srcStride); - Sk4b blurred = interpolateSums(outerSum, innerSum); - blurred.store(dstCursor); - } - } - - private: - static constexpr uint32_t kHalf = static_cast<uint32_t>(1) << 23; - - const uint32_t fOuterWeight; - const uint32_t fInnerWeight; - const int fNoChangeCount; - const int fTrailingEdgeZeroCount; - Sk4u* const fBuffer; - Sk4u* const fBufferEnd; - }; -private: - uint32_t fOuterWeight; - uint32_t fInnerWeight; - int fSlidingWindow; -}; - class PlanGauss final : public PlanningInterface { public: explicit PlanGauss(double sigma) { @@ -505,20 +272,6 @@ public: int fPass2Size; }; -static PlanningInterface* make_plan(SkArenaAlloc* alloc, double sigma) { - PlanningInterface* plan = nullptr; - - if (3 * sigma <= 1) { - plan = alloc->make<None>(); - } else if (sigma < kSmallSigma) { - plan = alloc->make<PlanBox>(sigma); - } else { - plan = alloc->make<PlanGauss>(sigma); - } - - return plan; -}; - // NB 136 is the largest sigma that will not cause a buffer full of 255 mask values to overflow // using the Gauss filter. It also limits the size of buffers used hold intermediate values. // Explanation of maximums: @@ -569,7 +322,6 @@ static SkMask prepare_destination(int radiusX, int radiusY, const SkMask& src) { return dst; } -#if !defined(SK_USE_LEGACY_INTERP_BLUR) static constexpr uint16_t _____ = 0u; static constexpr uint16_t kHalf = 0x80u; @@ -1197,21 +949,20 @@ static SkIPoint small_blur(double sigmaX, double sigmaY, const SkMask& src, SkMa return {radiusX, radiusY}; } -#endif // SK_USE_LEGACY_INTERP_BLUR +// TODO: assuming sigmaW = sigmaH. Allow different sigmas. Right now the +// API forces the sigmas to be the same. SkIPoint SkMaskBlurFilter::blur(const SkMask& src, SkMask* dst) const { - #if !defined(SK_USE_LEGACY_INTERP_BLUR) - if (fSigmaW < 2.0 && fSigmaH < 2.0) { - return small_blur(fSigmaW, fSigmaH, src, dst); - } - #endif + if (fSigmaW < 2.0 && fSigmaH < 2.0) { + return small_blur(fSigmaW, fSigmaH, src, dst); + } // 1024 is a place holder guess until more analysis can be done. SkSTArenaAlloc<1024> alloc; - PlanningInterface* planW = make_plan(&alloc, fSigmaW); - PlanningInterface* planH = make_plan(&alloc, fSigmaH); + PlanningInterface* planW = alloc.make<PlanGauss>(fSigmaW); + PlanningInterface* planH = alloc.make<PlanGauss>(fSigmaH); int borderW = planW->border(), borderH = planH->border(); @@ -1244,17 +995,7 @@ SkIPoint SkMaskBlurFilter::blur(const SkMask& src, SkMask* dst) const { // Blur horizontally, and transpose. auto scanW = planW->makeBlurScan(&alloc, srcW, buffer); - int y = 0; - if (scanW->canBlur4() && srcH > 4) { - for (;y + 4 <= srcH; y += 4) { - auto srcStart = &src.fImage[y * src.fRowBytes]; - auto tmpStart = &tmp[y]; - scanW->blur4Transpose(srcStart, src.fRowBytes, srcStart + srcW, - tmpStart, tmpW, tmpStart + tmpW * tmpH); - } - } - - for (;y < srcH; y++) { + for (int y = 0; y < srcH; y++) { auto srcStart = &src.fImage[y * src.fRowBytes]; auto tmpStart = &tmp[y]; scanW->blur(srcStart, 1, srcStart + srcW, @@ -1264,47 +1005,13 @@ SkIPoint SkMaskBlurFilter::blur(const SkMask& src, SkMask* dst) const { // Blur vertically (scan in memory order because of the transposition), // and transpose back to the original orientation. auto scanH = planH->makeBlurScan(&alloc, tmpW, buffer); - y = 0; - if (scanH->canBlur4() && tmpH > 4) { - for (;y + 4 <= tmpH; y += 4) { - auto tmpStart = &tmp[y * tmpW]; - auto dstStart = &dst->fImage[y]; - - scanH->blur4Transpose( - tmpStart, tmpW, tmpStart + tmpW, - dstStart, dst->fRowBytes, dstStart + dst->fRowBytes * dstH); - } - } - for (;y < tmpH; y++) { + for (int y = 0; y < tmpH; y++) { auto tmpStart = &tmp[y * tmpW]; auto dstStart = &dst->fImage[y]; scanH->blur(tmpStart, 1, tmpStart + tmpW, dstStart, dst->fRowBytes, dstStart + dst->fRowBytes * dstH); } - } else if (planW->needsBlur()) { - // Blur only horizontally. - - auto scanW = planW->makeBlurScan(&alloc, srcW, buffer); - for (int y = 0; y < srcH; y++) { - auto srcStart = &src.fImage[y * src.fRowBytes]; - auto dstStart = &dst->fImage[y * dst->fRowBytes]; - scanW->blur(srcStart, 1, srcStart + srcW, - dstStart, 1, dstStart + dstW); - - } - } else if (planH->needsBlur()) { - // Blur only vertically. - - auto srcEnd = &src.fImage[src.fRowBytes * srcH]; - auto dstEnd = &dst->fImage[dst->fRowBytes * dstH]; - auto scanH = planH->makeBlurScan(&alloc, srcH, buffer); - for (int x = 0; x < srcW; x++) { - auto srcStart = &src.fImage[x]; - auto dstStart = &dst->fImage[x]; - scanH->blur(srcStart, src.fRowBytes, srcEnd, - dstStart, dst->fRowBytes, dstEnd); - } } else { // Copy to dst. No Blur. SkASSERT(false); // should not get here |