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 <reed@google.com>
Commit-Queue: Yuqian Li <liyuqian@google.com>
This commit is contained in:
Yuqian Li 2017-01-17 16:15:06 -05:00 committed by Skia Commit-Bot
parent fc50dda7ad
commit 98cf99b3ae
4 changed files with 15 additions and 20 deletions

View File

@ -39,7 +39,11 @@ bool SkAnalyticEdge::updateLine(SkFixed x0, SkFixed y0, SkFixed x1, SkFixed y1,
fY = y0; fY = y0;
fUpperY = y0; fUpperY = y0;
fLowerY = y1; fLowerY = y1;
#ifdef SK_SUPPORT_LEGACY_AAA
fDY = (absSlope | dx) == 0 fDY = (absSlope | dx) == 0
#else
fDY = (dx == 0 || slope == 0)
#endif
? SK_MaxS32 ? SK_MaxS32
: absSlope < kInverseTableSize : absSlope < kInverseTableSize
? QuickFDot6Inverse::Lookup(absSlope) ? QuickFDot6Inverse::Lookup(absSlope)
@ -113,7 +117,7 @@ bool SkAnalyticQuadraticEdge::updateQuadratic() {
#ifndef SK_SUPPORT_LEGACY_AAA #ifndef SK_SUPPORT_LEGACY_AAA
SkASSERT(slope == SK_MaxS32 || SkASSERT(slope == SK_MaxS32 ||
SkAbs32(fSnappedX + SkFixedMul(slope, newSnappedY - fSnappedY) - newSnappedX) SkAbs32(fSnappedX + SkFixedMul(slope, newSnappedY - fSnappedY) - newSnappedX)
< SK_FixedHalf); < SkFixedMul(SK_Fixed1 >> 4, SkTMax(SK_Fixed1, SkAbs32(slope))));
#endif #endif
dx += fQEdge.fQDDx; dx += fQEdge.fQDDx;
dy += fQEdge.fQDDy; dy += fQEdge.fQDDy;

View File

@ -10,11 +10,6 @@
#include "SkEdge.h" #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 { struct SkAnalyticEdge {
// Similar to SkEdge, the conic edges will be converted to quadratic edges // Similar to SkEdge, the conic edges will be converted to quadratic edges
enum Type { enum Type {
@ -166,7 +161,6 @@ bool SkAnalyticEdge::setLine(const SkPoint& p0, const SkPoint& p1) {
SkFDot6 dy = SkFixedToFDot6(y1 - y0); SkFDot6 dy = SkFixedToFDot6(y1 - y0);
SkFDot6 dx = SkFixedToFDot6(x1 - x0); SkFDot6 dx = SkFixedToFDot6(x1 - x0);
SkFixed slope = dy ? QuickSkFDot6Div(dx, dy) : SK_MaxS32; SkFixed slope = dy ? QuickSkFDot6Div(dx, dy) : SK_MaxS32;
SkASSERT(dx == 0 || slope != 0);
SkFixed absSlope = SkAbs32(slope); SkFixed absSlope = SkAbs32(slope);
#endif #endif
@ -179,9 +173,9 @@ bool SkAnalyticEdge::setLine(const SkPoint& p0, const SkPoint& p1) {
#ifdef SK_SUPPORT_LEGACY_AAA #ifdef SK_SUPPORT_LEGACY_AAA
fDY = x1 != x0 ? SkAbs32(SkFixedDiv(y1 - y0, x1 - x0)) : SK_MaxS32; fDY = x1 != x0 ? SkAbs32(SkFixedDiv(y1 - y0, x1 - x0)) : SK_MaxS32;
#else #else
fDY = dx == 0 ? SK_MaxS32 : absSlope < kInverseTableSize fDY = dx == 0 || slope == 0 ? SK_MaxS32 : absSlope < kInverseTableSize
? QuickFDot6Inverse::Lookup(absSlope) ? QuickFDot6Inverse::Lookup(absSlope)
: SkAbs32(QuickSkFDot6Div(dy, dx)); : SkAbs32(QuickSkFDot6Div(dy, dx));
#endif #endif
fCurveCount = 0; fCurveCount = 0;
fWinding = SkToS8(winding); fWinding = SkToS8(winding);

View File

@ -23,11 +23,6 @@ class SkPath;
*/ */
typedef SkIRect SkXRect; 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<bool> gSkUseAnalyticAA; extern std::atomic<bool> gSkUseAnalyticAA;
extern std::atomic<bool> gSkForceAnalyticAA; extern std::atomic<bool> gSkForceAnalyticAA;

View File

@ -736,14 +736,14 @@ static void blit_aaa_trapezoid_row(AdditiveBlitter* blitter, int y,
int uL = SkFixedFloorToInt(ul); int uL = SkFixedFloorToInt(ul);
int lL = SkFixedCeilToInt(ll); int lL = SkFixedCeilToInt(ll);
if (uL + 2 == lL) { // We only need to compute two triangles, accelerate this special case 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; SkFixed second = ll - ul - first;
SkAlpha a1 = fullAlpha - partialTriangleToAlpha(first, lDY); SkAlpha a1 = fullAlpha - partialTriangleToAlpha(first, lDY);
SkAlpha a2 = partialTriangleToAlpha(second, lDY); SkAlpha a2 = partialTriangleToAlpha(second, lDY);
alphas[0] = alphas[0] > a1 ? alphas[0] - a1 : 0; alphas[0] = alphas[0] > a1 ? alphas[0] - a1 : 0;
alphas[1] = alphas[1] > a2 ? alphas[1] - a2 : 0; alphas[1] = alphas[1] > a2 ? alphas[1] - a2 : 0;
} else { } else {
computeAlphaBelowLine(tempAlphas + uL - L, ul - (uL << 16), ll - (uL << 16), computeAlphaBelowLine(tempAlphas + uL - L, ul - SkIntToFixed(uL), ll - SkIntToFixed(uL),
lDY, fullAlpha); lDY, fullAlpha);
for (int i = uL; i < lL; ++i) { for (int i = uL; i < lL; ++i) {
if (alphas[i - L] > tempAlphas[i - L]) { 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 uR = SkFixedFloorToInt(ur);
int lR = SkFixedCeilToInt(lr); int lR = SkFixedCeilToInt(lr);
if (uR + 2 == lR) { // We only need to compute two triangles, accelerate this special case 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; SkFixed second = lr - ur - first;
SkAlpha a1 = partialTriangleToAlpha(first, rDY); SkAlpha a1 = partialTriangleToAlpha(first, rDY);
SkAlpha a2 = fullAlpha - partialTriangleToAlpha(second, rDY); SkAlpha a2 = fullAlpha - partialTriangleToAlpha(second, rDY);
alphas[len-2] = alphas[len-2] > a1 ? alphas[len-2] - a1 : 0; alphas[len-2] = alphas[len-2] > a1 ? alphas[len-2] - a1 : 0;
alphas[len-1] = alphas[len-1] > a2 ? alphas[len-1] - a2 : 0; alphas[len-1] = alphas[len-1] > a2 ? alphas[len-1] - a2 : 0;
} else { } else {
computeAlphaAboveLine(tempAlphas + uR - L, ur - (uR << 16), lr - (uR << 16), computeAlphaAboveLine(tempAlphas + uR - L, ur - SkIntToFixed(uR), lr - SkIntToFixed(uR),
rDY, fullAlpha); rDY, fullAlpha);
for (int i = uR; i < lR; ++i) { for (int i = uR; i < lR; ++i) {
if (alphas[i - L] > tempAlphas[i - L]) { 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, leftEnds, false, blitter, maskRow, isUsingMask, noRealBlitter,
leftClip, rightClip, yShift); leftClip, rightClip, yShift);
} else { } 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, leftDY, 0, fullAlpha, maskRow, isUsingMask,
noRealBlitter || noRealBlitter ||
(fullAlpha == 0xFF && edges_too_close(leftE->fPrev, leftE, nextY)), (fullAlpha == 0xFF && edges_too_close(leftE->fPrev, leftE, nextY)),