From 98cf99b3ae4cc956158d1fd843fc8a84059ae132 Mon Sep 17 00:00:00 2001 From: Yuqian Li Date: Tue, 17 Jan 2017 16:15:06 -0500 Subject: [PATCH] Turn on concave analytic AA This will allow Skia trybots to exercise analytic AA. But there's still a guard flag in Chromium that prevents layout tests failure. Additionally, we 1. fixed nagative shift problem 2. relax the ASSERT when slope is too large: If slope is large, the accuracy of the slope is limited due to conversion to SkFDot6 and division. Hence we have to relax the constraint. 3. handle the special case where dx != 0 while slope == 0 because of very large dy and limited precision. BUG=skia: Change-Id: Ice70164f3f396f0db3896bedc7b96fbd613078dc Reviewed-on: https://skia-review.googlesource.com/7120 Reviewed-by: Mike Reed Commit-Queue: Yuqian Li --- src/core/SkAnalyticEdge.cpp | 6 +++++- src/core/SkAnalyticEdge.h | 12 +++--------- src/core/SkScan.h | 5 ----- src/core/SkScan_AAAPath.cpp | 12 +++++++----- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/core/SkAnalyticEdge.cpp b/src/core/SkAnalyticEdge.cpp index 199fc4ef33..213262f3b2 100644 --- a/src/core/SkAnalyticEdge.cpp +++ b/src/core/SkAnalyticEdge.cpp @@ -39,7 +39,11 @@ bool SkAnalyticEdge::updateLine(SkFixed x0, SkFixed y0, SkFixed x1, SkFixed y1, fY = y0; fUpperY = y0; fLowerY = y1; +#ifdef SK_SUPPORT_LEGACY_AAA fDY = (absSlope | dx) == 0 +#else + fDY = (dx == 0 || slope == 0) +#endif ? SK_MaxS32 : absSlope < kInverseTableSize ? QuickFDot6Inverse::Lookup(absSlope) @@ -113,7 +117,7 @@ bool SkAnalyticQuadraticEdge::updateQuadratic() { #ifndef SK_SUPPORT_LEGACY_AAA SkASSERT(slope == SK_MaxS32 || SkAbs32(fSnappedX + SkFixedMul(slope, newSnappedY - fSnappedY) - newSnappedX) - < SK_FixedHalf); + < SkFixedMul(SK_Fixed1 >> 4, SkTMax(SK_Fixed1, SkAbs32(slope)))); #endif dx += fQEdge.fQDDx; dy += fQEdge.fQDDy; diff --git a/src/core/SkAnalyticEdge.h b/src/core/SkAnalyticEdge.h index 1ed25f39ea..c70772db00 100644 --- a/src/core/SkAnalyticEdge.h +++ b/src/core/SkAnalyticEdge.h @@ -10,11 +10,6 @@ #include "SkEdge.h" -// Use this to check that we successfully guard the change against Chromium layout tests -#ifndef SK_SUPPORT_LEGACY_AAA -# define SK_SUPPORT_LEGACY_AAA -#endif - struct SkAnalyticEdge { // Similar to SkEdge, the conic edges will be converted to quadratic edges enum Type { @@ -166,7 +161,6 @@ bool SkAnalyticEdge::setLine(const SkPoint& p0, const SkPoint& p1) { SkFDot6 dy = SkFixedToFDot6(y1 - y0); SkFDot6 dx = SkFixedToFDot6(x1 - x0); SkFixed slope = dy ? QuickSkFDot6Div(dx, dy) : SK_MaxS32; - SkASSERT(dx == 0 || slope != 0); SkFixed absSlope = SkAbs32(slope); #endif @@ -179,9 +173,9 @@ bool SkAnalyticEdge::setLine(const SkPoint& p0, const SkPoint& p1) { #ifdef SK_SUPPORT_LEGACY_AAA fDY = x1 != x0 ? SkAbs32(SkFixedDiv(y1 - y0, x1 - x0)) : SK_MaxS32; #else - fDY = dx == 0 ? SK_MaxS32 : absSlope < kInverseTableSize - ? QuickFDot6Inverse::Lookup(absSlope) - : SkAbs32(QuickSkFDot6Div(dy, dx)); + fDY = dx == 0 || slope == 0 ? SK_MaxS32 : absSlope < kInverseTableSize + ? QuickFDot6Inverse::Lookup(absSlope) + : SkAbs32(QuickSkFDot6Div(dy, dx)); #endif fCurveCount = 0; fWinding = SkToS8(winding); diff --git a/src/core/SkScan.h b/src/core/SkScan.h index d0c10faf5c..c99554218b 100644 --- a/src/core/SkScan.h +++ b/src/core/SkScan.h @@ -23,11 +23,6 @@ class SkPath; */ typedef SkIRect SkXRect; -// Use this to check that we successfully guard the change against Chromium layout tests -#ifndef SK_SUPPORT_LEGACY_AAA -# define SK_SUPPORT_LEGACY_AAA -#endif - extern std::atomic gSkUseAnalyticAA; extern std::atomic gSkForceAnalyticAA; diff --git a/src/core/SkScan_AAAPath.cpp b/src/core/SkScan_AAAPath.cpp index 126322820f..af45f0094f 100644 --- a/src/core/SkScan_AAAPath.cpp +++ b/src/core/SkScan_AAAPath.cpp @@ -736,14 +736,14 @@ static void blit_aaa_trapezoid_row(AdditiveBlitter* blitter, int y, int uL = SkFixedFloorToInt(ul); int lL = SkFixedCeilToInt(ll); if (uL + 2 == lL) { // We only need to compute two triangles, accelerate this special case - SkFixed first = (uL << 16) + SK_Fixed1 - ul; + SkFixed first = SkIntToFixed(uL) + SK_Fixed1 - ul; SkFixed second = ll - ul - first; SkAlpha a1 = fullAlpha - partialTriangleToAlpha(first, lDY); SkAlpha a2 = partialTriangleToAlpha(second, lDY); alphas[0] = alphas[0] > a1 ? alphas[0] - a1 : 0; alphas[1] = alphas[1] > a2 ? alphas[1] - a2 : 0; } else { - computeAlphaBelowLine(tempAlphas + uL - L, ul - (uL << 16), ll - (uL << 16), + computeAlphaBelowLine(tempAlphas + uL - L, ul - SkIntToFixed(uL), ll - SkIntToFixed(uL), lDY, fullAlpha); for (int i = uL; i < lL; ++i) { if (alphas[i - L] > tempAlphas[i - L]) { @@ -757,14 +757,14 @@ static void blit_aaa_trapezoid_row(AdditiveBlitter* blitter, int y, int uR = SkFixedFloorToInt(ur); int lR = SkFixedCeilToInt(lr); if (uR + 2 == lR) { // We only need to compute two triangles, accelerate this special case - SkFixed first = (uR << 16) + SK_Fixed1 - ur; + SkFixed first = SkIntToFixed(uR) + SK_Fixed1 - ur; SkFixed second = lr - ur - first; SkAlpha a1 = partialTriangleToAlpha(first, rDY); SkAlpha a2 = fullAlpha - partialTriangleToAlpha(second, rDY); alphas[len-2] = alphas[len-2] > a1 ? alphas[len-2] - a1 : 0; alphas[len-1] = alphas[len-1] > a2 ? alphas[len-1] - a2 : 0; } else { - computeAlphaAboveLine(tempAlphas + uR - L, ur - (uR << 16), lr - (uR << 16), + computeAlphaAboveLine(tempAlphas + uR - L, ur - SkIntToFixed(uR), lr - SkIntToFixed(uR), rDY, fullAlpha); for (int i = uR; i < lR; ++i) { if (alphas[i - L] > tempAlphas[i - L]) { @@ -1605,7 +1605,9 @@ static void aaa_walk_edges(SkAnalyticEdge* prevHead, SkAnalyticEdge* nextTail, leftEnds, false, blitter, maskRow, isUsingMask, noRealBlitter, leftClip, rightClip, yShift); } else { - blit_trapezoid_row(blitter, y >> 16, left, rightClip, leftE->fX, rightClip, + blit_trapezoid_row(blitter, y >> 16, + SkTMax(leftClip, left), rightClip, + SkTMax(leftClip, leftE->fX), rightClip, leftDY, 0, fullAlpha, maskRow, isUsingMask, noRealBlitter || (fullAlpha == 0xFF && edges_too_close(leftE->fPrev, leftE, nextY)),