aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkAnalyticEdge.cpp
diff options
context:
space:
mode:
authorGravatar Yuqian Li <liyuqian@google.com>2017-01-11 10:58:31 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-12 17:17:32 +0000
commit89a0e72287e991cfa2f860f92fad545ca59defe1 (patch)
treeda5c494a32700a7438357bca4a50a1ac49237224 /src/core/SkAnalyticEdge.cpp
parent108f55ed5d0b63baf653e4e443cc469df887c811 (diff)
Implement Analytic AA for General Paths (with Guard against Chrome)
I've set up a SK_SUPPORT_LEGACY_AAA flag to guard against Chromium layout tests. I also set that flag in this CL so theoretically this CL won't trigger any GM changes. I'll use this to verify my guard, and remove that flag and actually enables concave AAA in a future CL. When enabled, for most simple concave paths (e.g., rectangle stroke, rrect stroke, sawtooth, stars...), the Analytic AA achieves 1.3x-2x speedup, and they look much prettier. And they probably are the majority in our use cases by number. But they probably are not the majority by time cost; a single complicated path may cost 10x-100x more time to render than a rectangle stroke... For those complicated paths, we fall back to supersampling by default as we're likely to be 1.1-1.2x slower and the quality improvement is not visually significant. However, one can use gSkForceAnalyticAA to disable that fallback. BUG=skia: Change-Id: If9549a3acc4a187cfaf7eb51890c148da3083d31 Reviewed-on: https://skia-review.googlesource.com/6091 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Yuqian Li <liyuqian@google.com>
Diffstat (limited to 'src/core/SkAnalyticEdge.cpp')
-rw-r--r--src/core/SkAnalyticEdge.cpp104
1 files changed, 58 insertions, 46 deletions
diff --git a/src/core/SkAnalyticEdge.cpp b/src/core/SkAnalyticEdge.cpp
index 057bc2170a..199fc4ef33 100644
--- a/src/core/SkAnalyticEdge.cpp
+++ b/src/core/SkAnalyticEdge.cpp
@@ -48,34 +48,22 @@ bool SkAnalyticEdge::updateLine(SkFixed x0, SkFixed y0, SkFixed x1, SkFixed y1,
return true;
}
-void SkAnalyticEdge::chopLineWithClip(const SkIRect& clip) {
- int top = SkFixedFloorToInt(fUpperY);
-
- SkASSERT(top < clip.fBottom);
-
- // clip the line to the clip top
- if (top < clip.fTop) {
- SkASSERT(SkFixedCeilToInt(fLowerY) > clip.fTop);
- SkFixed newY = SkIntToFixed(clip.fTop);
- this->goY(newY);
- fUpperY = newY;
- }
-}
-
bool SkAnalyticQuadraticEdge::setQuadratic(const SkPoint pts[3]) {
- if (!fQEdge.setQuadraticWithoutUpdate(pts, 2)) {
+ fRiteE = nullptr;
+
+ if (!fQEdge.setQuadraticWithoutUpdate(pts, kDefaultAccuracy)) {
return false;
}
- fQEdge.fQx >>= 2;
- fQEdge.fQy >>= 2;
- fQEdge.fQDx >>= 2;
- fQEdge.fQDy >>= 2;
- fQEdge.fQDDx >>= 2;
- fQEdge.fQDDy >>= 2;
- fQEdge.fQLastX >>= 2;
- fQEdge.fQLastY >>= 2;
- fQEdge.fQy = snapY(fQEdge.fQy);
- fQEdge.fQLastY = snapY(fQEdge.fQLastY);
+ fQEdge.fQx >>= kDefaultAccuracy;
+ fQEdge.fQy >>= kDefaultAccuracy;
+ fQEdge.fQDx >>= kDefaultAccuracy;
+ fQEdge.fQDy >>= kDefaultAccuracy;
+ fQEdge.fQDDx >>= kDefaultAccuracy;
+ fQEdge.fQDDy >>= kDefaultAccuracy;
+ fQEdge.fQLastX >>= kDefaultAccuracy;
+ fQEdge.fQLastY >>= kDefaultAccuracy;
+ fQEdge.fQy = SnapY(fQEdge.fQy);
+ fQEdge.fQLastY = SnapY(fQEdge.fQLastY);
fWinding = fQEdge.fWinding;
fCurveCount = fQEdge.fCurveCount;
@@ -105,15 +93,28 @@ bool SkAnalyticQuadraticEdge::updateQuadratic() {
{
newx = oldx + (dx >> shift);
newy = oldy + (dy >> shift);
- SkFDot6 diffY = (newy - fSnappedY) >> 10;
- slope = diffY ? QuickSkFDot6Div((newx - fSnappedX) >> 10, diffY) : SK_MaxS32;
if (SkAbs32(dy >> shift) >= SK_Fixed1 * 2) { // only snap when dy is large enough
+ SkFDot6 diffY = SkFixedToFDot6(newy - fSnappedY);
+ slope = diffY ? QuickSkFDot6Div(SkFixedToFDot6(newx - fSnappedX), diffY)
+ : SK_MaxS32;
newSnappedY = SkTMin<SkFixed>(fQEdge.fQLastY, SkFixedRoundToFixed(newy));
newSnappedX = newx - SkFixedMul(slope, newy - newSnappedY);
} else {
- newSnappedY = SkTMin(fQEdge.fQLastY, snapY(newy));
+ newSnappedY = SkTMin(fQEdge.fQLastY, SnapY(newy));
newSnappedX = newx;
+#ifdef SK_SUPPORT_LEGACY_AAA
+ SkFDot6 diffY = SkFixedToFDot6(newy - fSnappedY);
+#else
+ SkFDot6 diffY = SkFixedToFDot6(newSnappedY - fSnappedY);
+#endif
+ slope = diffY ? QuickSkFDot6Div(SkFixedToFDot6(newx - fSnappedX), diffY)
+ : SK_MaxS32;
}
+#ifndef SK_SUPPORT_LEGACY_AAA
+ SkASSERT(slope == SK_MaxS32 ||
+ SkAbs32(fSnappedX + SkFixedMul(slope, newSnappedY - fSnappedY) - newSnappedX)
+ < SK_FixedHalf);
+#endif
dx += fQEdge.fQDDx;
dy += fQEdge.fQDDy;
}
@@ -146,28 +147,32 @@ bool SkAnalyticQuadraticEdge::updateQuadratic() {
}
bool SkAnalyticCubicEdge::setCubic(const SkPoint pts[4]) {
- if (!fCEdge.setCubicWithoutUpdate(pts, 2)) {
+ fRiteE = nullptr;
+
+ if (!fCEdge.setCubicWithoutUpdate(pts, kDefaultAccuracy)) {
return false;
}
- fCEdge.fCx >>= 2;
- fCEdge.fCy >>= 2;
- fCEdge.fCDx >>= 2;
- fCEdge.fCDy >>= 2;
- fCEdge.fCDDx >>= 2;
- fCEdge.fCDDy >>= 2;
- fCEdge.fCDDDx >>= 2;
- fCEdge.fCDDDy >>= 2;
- fCEdge.fCLastX >>= 2;
- fCEdge.fCLastY >>= 2;
- fCEdge.fCy = snapY(fCEdge.fCy);
- fCEdge.fCLastY = snapY(fCEdge.fCLastY);
+ fCEdge.fCx >>= kDefaultAccuracy;
+ fCEdge.fCy >>= kDefaultAccuracy;
+ fCEdge.fCDx >>= kDefaultAccuracy;
+ fCEdge.fCDy >>= kDefaultAccuracy;
+ fCEdge.fCDDx >>= kDefaultAccuracy;
+ fCEdge.fCDDy >>= kDefaultAccuracy;
+ fCEdge.fCDDDx >>= kDefaultAccuracy;
+ fCEdge.fCDDDy >>= kDefaultAccuracy;
+ fCEdge.fCLastX >>= kDefaultAccuracy;
+ fCEdge.fCLastY >>= kDefaultAccuracy;
+ fCEdge.fCy = SnapY(fCEdge.fCy);
+ fCEdge.fCLastY = SnapY(fCEdge.fCLastY);
fWinding = fCEdge.fWinding;
fCurveCount = fCEdge.fCurveCount;
fCurveShift = fCEdge.fCurveShift;
fCubicDShift = fCEdge.fCubicDShift;
+ fSnappedY = fCEdge.fCy;
+
return this->updateCubic();
}
@@ -203,17 +208,24 @@ bool SkAnalyticCubicEdge::updateCubic() {
newy = oldy;
}
- SkFixed snappedOldY = SkAnalyticEdge::snapY(oldy);
- SkFixed snappedNewY = SkAnalyticEdge::snapY(newy);
- SkFixed slope = SkFixedToFDot6(snappedNewY - snappedOldY) == 0
+ SkFixed newSnappedY = SnapY(newy);
+ // we want to SkASSERT(snappedNewY <= fCEdge.fCLastY), but our finite fixedpoint
+ // doesn't always achieve that, so we have to explicitly pin it here.
+ if (fCEdge.fCLastY < newSnappedY) {
+ newSnappedY = fCEdge.fCLastY;
+ count = 0;
+ }
+
+ SkFixed slope = SkFixedToFDot6(newSnappedY - fSnappedY) == 0
? SK_MaxS32
: SkFDot6Div(SkFixedToFDot6(newx - oldx),
- SkFixedToFDot6(snappedNewY - snappedOldY));
+ SkFixedToFDot6(newSnappedY - fSnappedY));
- success = this->updateLine(oldx, snappedOldY, newx, snappedNewY, slope);
+ success = this->updateLine(oldx, fSnappedY, newx, newSnappedY, slope);
oldx = newx;
oldy = newy;
+ fSnappedY = newSnappedY;
} while (count < 0 && !success);
fCEdge.fCx = newx;