Skip to content

Commit

Permalink
Reland "Increase precision of some quad AA calculations"
Browse files Browse the repository at this point in the history
This reverts commit 5195673.

Reason for revert: Just waiting for the test suppression
Original change's description:
> Revert "Increase precision of some quad AA calculations"
> 
> This reverts commit 40a1353.
> 
> Reason for revert: layout tests need rebaseline
> 
> Original change's description:
> > Increase precision of some quad AA calculations
> > 
> > This stops using the low precision rsqrt and instead does a divide + sqrt.
> > It also separates the single kTolerance value used in GrQuadUtils' math
> > into a fairly fuzzy tolerance for edges/distances being close to zero
> > (e.g. a degenerate quad), and a more precise tolerance for linear systems
> > solutions.
> > 
> > The smaller tolerance value used for denominators in these solutions prevents
> > the solved-for coordinates from being mis-classified as "bad". The bad coord
> > resolution works on the assumption that its correcting points that are
> > co-located, but if the input coords were sufficiently large the linear
> > equations would have small denominators that were less than the fuzzy tolerance
> > and then the geometry would be improperly collapsed to a line.
> > 
> > For the selected zoom level of GM_crbug_10141204, this change is sufficient
> > to prevent the draw from being discarded. However, when animating the zoom
> > level, the input shape is sometimes still considered a fullscreen clear when
> > it shouldn't be. A follow up change will improve precision in CropToRect()
> > 
> > Bug: skia:9779, chromium:10141204
> > Change-Id: Id1518a908c03e7813868c4eff014d18388f8f62e
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/265976
> > Reviewed-by: Robert Phillips <[email protected]>
> > Commit-Queue: Michael Ludwig <[email protected]>
> 
> [email protected],[email protected]
> 
> Change-Id: I44012a2728f75e235678f733c6da8870b84ae3ab
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:9779, chromium:10141204
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/266220
> Reviewed-by: Michael Ludwig <[email protected]>
> Commit-Queue: Michael Ludwig <[email protected]>

[email protected],[email protected]

Change-Id: Ie7f19c1f7c4b742f34b24157aa7800f2a974e5bf
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:9779, chromium:10141204
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/266221
Reviewed-by: Michael Ludwig <[email protected]>
Commit-Queue: Michael Ludwig <[email protected]>
  • Loading branch information
lhkbob authored and Skia Commit-Bot committed Jan 24, 2020
1 parent cfca5c6 commit a7e557f
Showing 1 changed file with 19 additions and 14 deletions.
33 changes: 19 additions & 14 deletions src/gpu/geometry/GrQuadUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ using M4f = skvx::Vec<4, int32_t>;

#define AI SK_ALWAYS_INLINE

static constexpr float kTolerance = 1e-2f;
// General tolerance used for denominators, checking div-by-0
static constexpr float kTolerance = 1e-9f;
// Increased slop when comparing signed distances / lengths
static constexpr float kDistTolerance = 1e-2f;
static constexpr float kDist2Tolerance = kDistTolerance * kDistTolerance;
static constexpr float kInvDistTolerance = 1.f / kDistTolerance;

// These rotate the points/edge values either clockwise or counterclockwise assuming tri strip
// order.
Expand Down Expand Up @@ -487,7 +492,7 @@ void TessellationHelper::EdgeVectors::reset(const skvx::Vec<4, float>& xs,
GrQuad::Type quadType) {
// Calculate all projected edge vector values for this quad.
if (quadType == GrQuad::Type::kPerspective) {
V4f iw = 1.0 / ws;
V4f iw = 1.f / ws;
fX2D = xs * iw;
fY2D = ys * iw;
} else {
Expand All @@ -497,7 +502,7 @@ void TessellationHelper::EdgeVectors::reset(const skvx::Vec<4, float>& xs,

fDX = next_ccw(fX2D) - fX2D;
fDY = next_ccw(fY2D) - fY2D;
fInvLengths = rsqrt(mad(fDX, fDX, fDY * fDY));
fInvLengths = 1.f / sqrt(mad(fDX, fDX, fDY * fDY));

// Normalize edge vectors
fDX *= fInvLengths;
Expand All @@ -511,7 +516,7 @@ void TessellationHelper::EdgeVectors::reset(const skvx::Vec<4, float>& xs,
fCosTheta = mad(fDX, next_cw(fDX), fDY * next_cw(fDY));
// NOTE: if cosTheta is close to 1, inset/outset math will avoid the fast paths that rely
// on thefInvSinTheta since it will approach infinity.
fInvSinTheta = rsqrt(1.f - fCosTheta * fCosTheta);
fInvSinTheta = 1.f / sqrt(1.f - fCosTheta * fCosTheta);
}
}

Expand All @@ -521,12 +526,12 @@ void TessellationHelper::EdgeEquations::reset(const EdgeVectors& edgeVectors) {
V4f dx = edgeVectors.fDX;
V4f dy = edgeVectors.fDY;
// Correct for bad edges by copying adjacent edge information into the bad component
correct_bad_edges(edgeVectors.fInvLengths >= 1.f / kTolerance, &dx, &dy, nullptr);
correct_bad_edges(edgeVectors.fInvLengths >= kInvDistTolerance, &dx, &dy, nullptr);

V4f c = mad(dx, edgeVectors.fY2D, -dy * edgeVectors.fX2D);
// Make sure normals point into the shape
V4f test = mad(dy, next_cw(edgeVectors.fX2D), mad(-dx, next_cw(edgeVectors.fY2D), c));
if (any(test < -kTolerance)) {
if (any(test < -kDistTolerance)) {
fA = -dy;
fB = dx;
fC = -c;
Expand Down Expand Up @@ -585,8 +590,8 @@ int TessellationHelper::EdgeEquations::computeDegenerateQuad(const V4f& signedEd
// wrong side of 1 edge, one edge has crossed over another and we use a line to represent it.
// Otherwise, use a triangle that replaces the bad points with the intersections of
// (e1, e2) or (e0, e3) as needed.
M4f d1v0 = dists1 < kTolerance;
M4f d2v0 = dists2 < kTolerance;
M4f d1v0 = dists1 < kDistTolerance;
M4f d2v0 = dists2 < kDistTolerance;
M4f d1And2 = d1v0 & d2v0;
M4f d1Or2 = d1v0 | d2v0;

Expand All @@ -608,7 +613,7 @@ int TessellationHelper::EdgeEquations::computeDegenerateQuad(const V4f& signedEd
} else if (all(d1Or2)) {
// Degenerates to a line. Compare p[2] and p[3] to edge 0. If they are on the wrong side,
// that means edge 0 and 3 crossed, and otherwise edge 1 and 2 crossed.
if (dists1[2] < kTolerance && dists1[3] < kTolerance) {
if (dists1[2] < kDistTolerance && dists1[3] < kDistTolerance) {
// Edges 0 and 3 have crossed over, so make the line from average of (p0,p2) and (p1,p3)
*x2d = 0.5f * (skvx::shuffle<0, 1, 0, 1>(px) + skvx::shuffle<2, 3, 2, 3>(px));
*y2d = 0.5f * (skvx::shuffle<0, 1, 0, 1>(py) + skvx::shuffle<2, 3, 2, 3>(py));
Expand Down Expand Up @@ -664,7 +669,7 @@ void TessellationHelper::OutsetRequest::reset(const EdgeVectors& edgeVectors, Gr
fInsetDegenerate =
(widthChange > 0.f && edgeVectors.fInvLengths[1] > 1.f / widthChange) ||
(heightChange > 0.f && edgeVectors.fInvLengths[0] > 1.f / heightChange);
} else if (any(edgeVectors.fInvLengths >= 1.f / kTolerance)) {
} else if (any(edgeVectors.fInvLengths >= kInvDistTolerance)) {
// Have an edge that is effectively length 0, so we're dealing with a triangle, which
// must always go through the degenerate code path.
fOutsetDegenerate = true;
Expand Down Expand Up @@ -776,13 +781,13 @@ void TessellationHelper::Vertices::moveTo(const V4f& x2d, const V4f& y2d, const
V4f e1x = skvx::shuffle<2, 3, 2, 3>(fX) - skvx::shuffle<0, 1, 0, 1>(fX);
V4f e1y = skvx::shuffle<2, 3, 2, 3>(fY) - skvx::shuffle<0, 1, 0, 1>(fY);
V4f e1w = skvx::shuffle<2, 3, 2, 3>(fW) - skvx::shuffle<0, 1, 0, 1>(fW);
correct_bad_edges(mad(e1x, e1x, e1y * e1y) < kTolerance * kTolerance, &e1x, &e1y, &e1w);
correct_bad_edges(mad(e1x, e1x, e1y * e1y) < kDist2Tolerance, &e1x, &e1y, &e1w);

// // Top to bottom, in device space, for each point
V4f e2x = skvx::shuffle<1, 1, 3, 3>(fX) - skvx::shuffle<0, 0, 2, 2>(fX);
V4f e2y = skvx::shuffle<1, 1, 3, 3>(fY) - skvx::shuffle<0, 0, 2, 2>(fY);
V4f e2w = skvx::shuffle<1, 1, 3, 3>(fW) - skvx::shuffle<0, 0, 2, 2>(fW);
correct_bad_edges(mad(e2x, e2x, e2y * e2y) < kTolerance * kTolerance, &e2x, &e2y, &e2w);
correct_bad_edges(mad(e2x, e2x, e2y * e2y) < kDist2Tolerance, &e2x, &e2y, &e2w);

// Can only move along e1 and e2 to reach the new 2D point, so we have
// x2d = (x + a*e1x + b*e2x) / (w + a*e1w + b*e2w) and
Expand Down Expand Up @@ -858,12 +863,12 @@ void TessellationHelper::Vertices::moveTo(const V4f& x2d, const V4f& y2d, const
V4f e1u = skvx::shuffle<2, 3, 2, 3>(fU) - skvx::shuffle<0, 1, 0, 1>(fU);
V4f e1v = skvx::shuffle<2, 3, 2, 3>(fV) - skvx::shuffle<0, 1, 0, 1>(fV);
V4f e1r = skvx::shuffle<2, 3, 2, 3>(fR) - skvx::shuffle<0, 1, 0, 1>(fR);
correct_bad_edges(mad(e1u, e1u, e1v * e1v) < kTolerance * kTolerance, &e1u, &e1v, &e1r);
correct_bad_edges(mad(e1u, e1u, e1v * e1v) < kDist2Tolerance, &e1u, &e1v, &e1r);

V4f e2u = skvx::shuffle<1, 1, 3, 3>(fU) - skvx::shuffle<0, 0, 2, 2>(fU);
V4f e2v = skvx::shuffle<1, 1, 3, 3>(fV) - skvx::shuffle<0, 0, 2, 2>(fV);
V4f e2r = skvx::shuffle<1, 1, 3, 3>(fR) - skvx::shuffle<0, 0, 2, 2>(fR);
correct_bad_edges(mad(e2u, e2u, e2v * e2v) < kTolerance * kTolerance, &e2u, &e2v, &e2r);
correct_bad_edges(mad(e2u, e2u, e2v * e2v) < kDist2Tolerance, &e2u, &e2v, &e2r);

fU += a * e1u + b * e2u;
fV += a * e1v + b * e2v;
Expand Down

0 comments on commit a7e557f

Please sign in to comment.