Skip to content

Commit a7e557f

Browse files
lhkbobSkia Commit-Bot
authored andcommitted
Reland "Increase precision of some quad AA calculations"
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 <robertphillips@google.com> > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > TBR=robertphillips@google.com,michaelludwig@google.com > > 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 <michaelludwig@google.com> > Commit-Queue: Michael Ludwig <michaelludwig@google.com> TBR=robertphillips@google.com,michaelludwig@google.com 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 <michaelludwig@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
1 parent cfca5c6 commit a7e557f

1 file changed

Lines changed: 19 additions & 14 deletions

File tree

src/gpu/geometry/GrQuadUtils.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ using M4f = skvx::Vec<4, int32_t>;
1818

1919
#define AI SK_ALWAYS_INLINE
2020

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

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

498503
fDX = next_ccw(fX2D) - fX2D;
499504
fDY = next_ccw(fY2D) - fY2D;
500-
fInvLengths = rsqrt(mad(fDX, fDX, fDY * fDY));
505+
fInvLengths = 1.f / sqrt(mad(fDX, fDX, fDY * fDY));
501506

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

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

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

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

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

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

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

868873
fU += a * e1u + b * e2u;
869874
fV += a * e1v + b * e2v;

0 commit comments

Comments
 (0)