From e4259e2224a9bf3aa2229cc14f5e08c1cbeeb8c8 Mon Sep 17 00:00:00 2001 From: Herb Derby Date: Sat, 25 Feb 2017 16:31:09 -0500 Subject: 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 Reviewed-by: Mike Klein --- src/core/SkLinearBitmapPipeline_core.h | 17 +++++++++++------ 1 file 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); } -- cgit v1.2.3