diff options
author | 2017-02-25 16:31:09 -0500 | |
---|---|---|
committer | 2017-02-27 19:38:32 +0000 | |
commit | e4259e2224a9bf3aa2229cc14f5e08c1cbeeb8c8 (patch) | |
tree | f019a2f2cc2334492494885f0a95c10262e3e7df | |
parent | 24ac42b373d9202a89538a1873df9275870c7632 (diff) |
Make the fallback loop very accurate.
The summation xs = xs + dx was causing xs to overflow the bounds of the source.
Change the algorithm to eliminate error accumulation. Performance is not a
concern, because the fallback should only be used in the rare cases.
R=mtklein@google.com
BUG=skia:6216
Change-Id: Iff8e55af5eb79606c7b1e693ae825ceaeda44afd
Reviewed-on: https://skia-review.googlesource.com/8975
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
-rw-r--r-- | src/core/SkLinearBitmapPipeline_core.h | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/src/core/SkLinearBitmapPipeline_core.h b/src/core/SkLinearBitmapPipeline_core.h index 5ef6fcab5b..ce6c05b752 100644 --- a/src/core/SkLinearBitmapPipeline_core.h +++ b/src/core/SkLinearBitmapPipeline_core.h @@ -157,23 +157,28 @@ void span_fallback(Span span, Stage* stage) { SkScalar length; int count; std::tie(start, length, count) = span; - Sk4f xs{X(start)}; + Sk4f startXs{X(start)}; Sk4f ys{Y(start)}; + Sk4f mults = {0.0f, 1.0f, 2.0f, 3.0f}; // Initializing this is not needed, but some compilers can't figure this out. - Sk4s fourDx{0.0f}; + Sk4s dXs{0.0f}; if (count > 1) { SkScalar dx = length / (count - 1); - xs = xs + Sk4f{0.0f, 1.0f, 2.0f, 3.0f} * dx; - // Only used if count is >= 4. - fourDx = Sk4f{4.0f * dx}; + dXs = Sk4f{dx}; } + // Instead of using xs = xs + dx every round, this uses xs = i * dx + X(start). This + // eliminates the rounding error for the sum. + Sk4f xs = startXs + mults * dXs; while (count >= 4) { stage->pointList4(xs, ys); - xs = xs + fourDx; + + mults += Sk4f{4.0f}; + xs = mults * dXs + startXs; count -= 4; } + if (count > 0) { stage->pointListFew(count, xs, ys); } |