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>
This commit is contained in:
Herb Derby 2017-02-25 16:31:09 -05:00 committed by Skia Commit-Bot
parent 24ac42b373
commit e4259e2224

View File

@ -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);
}