aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Herb Derby <herb@google.com>2017-02-25 16:31:09 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-02-27 19:38:32 +0000
commite4259e2224a9bf3aa2229cc14f5e08c1cbeeb8c8 (patch)
treef019a2f2cc2334492494885f0a95c10262e3e7df
parent24ac42b373d9202a89538a1873df9275870c7632 (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.h17
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);
}