Use the word "precision" to describe "1/tolerance" for linearization Bug: skia:10419 Change-Id: Ie01122ab8c9130367988fd2e264fcf4761862e89 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/397656 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/bench/TessellateBench.cpp b/bench/TessellateBench.cpp index bbeefd6..38f0d40 100644 --- a/bench/TessellateBench.cpp +++ b/bench/TessellateBench.cpp
@@ -153,7 +153,7 @@ } static void benchmark_wangs_formula_conic(const SkMatrix& matrix, const SkPath& path) { - // Conic version expects tolerance, not intolerance + // Conic version expects tolerance, not "precision" constexpr float kTolerance = 4; int sum = 0; GrVectorXform xform(matrix); @@ -169,7 +169,7 @@ } static void benchmark_wangs_formula_conic_log2(const SkMatrix& matrix, const SkPath& path) { - // Conic version expects tolerance, not intolerance + // Conic version expects tolerance, not "precision" constexpr float kTolerance = 4; int sum = 0; GrVectorXform xform(matrix);
diff --git a/src/gpu/tessellate/GrPathTessellator.cpp b/src/gpu/tessellate/GrPathTessellator.cpp index 756e65f..573a0c1 100644 --- a/src/gpu/tessellate/GrPathTessellator.cpp +++ b/src/gpu/tessellate/GrPathTessellator.cpp
@@ -24,13 +24,13 @@ int level; switch (verb) { case SkPathVerb::kConic: - level = GrWangsFormula::conic_log2(1.f / kLinearizationIntolerance, pts, *w, xform); + level = GrWangsFormula::conic_log2(1.f / kLinearizationPrecision, pts, *w, xform); break; case SkPathVerb::kQuad: - level = GrWangsFormula::quadratic_log2(kLinearizationIntolerance, pts, xform); + level = GrWangsFormula::quadratic_log2(kLinearizationPrecision, pts, xform); break; case SkPathVerb::kCubic: - level = GrWangsFormula::cubic_log2(kLinearizationIntolerance, pts, xform); + level = GrWangsFormula::cubic_log2(kLinearizationPrecision, pts, xform); break; default: continue; @@ -179,14 +179,14 @@ default: continue; case SkPathVerb::kConic: - level = GrWangsFormula::conic_log2(1.f / kLinearizationIntolerance, pts, *w, + level = GrWangsFormula::conic_log2(1.f / kLinearizationPrecision, pts, *w, xform); break; case SkPathVerb::kQuad: - level = GrWangsFormula::quadratic_log2(kLinearizationIntolerance, pts, xform); + level = GrWangsFormula::quadratic_log2(kLinearizationPrecision, pts, xform); break; case SkPathVerb::kCubic: - level = GrWangsFormula::cubic_log2(kLinearizationIntolerance, pts, xform); + level = GrWangsFormula::cubic_log2(kLinearizationPrecision, pts, xform); break; } if (level == 0) {
diff --git a/src/gpu/tessellate/GrPathTessellator.h b/src/gpu/tessellate/GrPathTessellator.h index 2545e60..393ac26 100644 --- a/src/gpu/tessellate/GrPathTessellator.h +++ b/src/gpu/tessellate/GrPathTessellator.h
@@ -56,8 +56,8 @@ void drawHullInstances(GrOpFlushState*) const override; private: - constexpr static float kLinearizationIntolerance = - GrTessellationPathRenderer::kLinearizationIntolerance; + constexpr static float kLinearizationPrecision = + GrTessellationPathRenderer::kLinearizationPrecision; constexpr static int kMaxResolveLevel = GrTessellationPathRenderer::kMaxResolveLevel; const bool fDrawInnerFan;
diff --git a/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp b/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp index 2aea611..aee3ab3 100644 --- a/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp +++ b/src/gpu/tessellate/GrStrokeHardwareTessellator.cpp
@@ -58,14 +58,13 @@ // Subtract 2 because the tessellation shader chops every cubic at two locations, and // each chop has the potential to introduce an extra segment. , fMaxTessellationSegments(target->caps().shaderCaps()->maxTessellationSegments() - 2) - , fParametricIntolerance(GrStrokeTolerances::CalcParametricIntolerance( - matrixMaxScale)) { + , fParametricPrecision(GrStrokeTolerances::CalcParametricPrecision(matrixMaxScale)) { } - // This is the intolerance value, adjusted for the view matrix, to use with Wang's formulas when + // This is the precision value, adjusted for the view matrix, to use with Wang's formulas when // determining how many parametric segments a curve will require. - float parametricIntolerance() const { - return fParametricIntolerance; + float parametricPrecision() const { + return fParametricPrecision; } // Will a line and worst-case previous join both fit in a single patch together? bool lineFitsInPatch_withJoin() { @@ -366,8 +365,7 @@ GrPathShader::WriteConicPatch(p, w, asPatch); } - float numParametricSegments_pow4 = - GrWangsFormula::quadratic_pow4(fParametricIntolerance, p); + float numParametricSegments_pow4 = GrWangsFormula::quadratic_pow4(fParametricPrecision, p); if (this->stroke180FitsInPatch(numParametricSegments_pow4) || maxDepth == 0) { this->internalPatchTo(prevJoinType, this->stroke180FitsInPatch_withJoin(numParametricSegments_pow4), @@ -431,7 +429,7 @@ return; } - float numParametricSegments_pow4 = GrWangsFormula::cubic_pow4(fParametricIntolerance, p); + float numParametricSegments_pow4 = GrWangsFormula::cubic_pow4(fParametricPrecision, p); if (this->stroke180FitsInPatch(numParametricSegments_pow4) || maxDepth == 0) { this->internalPatchTo(prevJoinType, this->stroke180FitsInPatch_withJoin(numParametricSegments_pow4), @@ -600,9 +598,9 @@ // The maximum number of tessellation segments the hardware can emit for a single patch. const int fMaxTessellationSegments; - // This is the intolerance value, adjusted for the view matrix, to use with Wang's formulas when + // This is the precision value, adjusted for the view matrix, to use with Wang's formulas when // determining how many parametric segments a curve will require. - const float fParametricIntolerance; + const float fParametricPrecision; // Number of radial segments required for each radian of rotation in order to look smooth with // the current stroke radius. @@ -703,13 +701,13 @@ float localStrokeWidth = GrStrokeTolerances::GetLocalStrokeWidth(matrixMinMaxScales.data(), stroke.getWidth()); float numRadialSegmentsPerRadian = GrStrokeTolerances::CalcNumRadialSegmentsPerRadian( - patchWriter.parametricIntolerance(), localStrokeWidth); + patchWriter.parametricPrecision(), localStrokeWidth); patchWriter.updateTolerances(numRadialSegmentsPerRadian, stroke.getJoin()); } // Fast SIMD queue that buffers up values for "numRadialSegmentsPerRadian". Only used when we // have dynamic strokes. - GrStrokeToleranceBuffer toleranceBuffer(patchWriter.parametricIntolerance()); + GrStrokeToleranceBuffer toleranceBuffer(patchWriter.parametricPrecision()); for (PathStrokeList* pathStroke = fPathStrokeList; pathStroke; pathStroke = pathStroke->fNext) { const SkStrokeRec& stroke = pathStroke->fStroke; @@ -775,7 +773,7 @@ continue; } float numParametricSegments_pow4 = - GrWangsFormula::quadratic_pow4(patchWriter.parametricIntolerance(), p); + GrWangsFormula::quadratic_pow4(patchWriter.parametricPrecision(), p); if (!patchWriter.stroke180FitsInPatch(numParametricSegments_pow4)) { // The curve requires more tessellation segments than the hardware can // support. This is rare. Recursively chop until each sub-curve fits. @@ -814,7 +812,7 @@ // draws conics. // TODO: Update here when the shader starts using the real conic formula. float numParametricSegments_pow4 = - GrWangsFormula::quadratic_pow4(patchWriter.parametricIntolerance(), p); + GrWangsFormula::quadratic_pow4(patchWriter.parametricPrecision(), p); if (!patchWriter.stroke180FitsInPatch(numParametricSegments_pow4)) { // The curve requires more tessellation segments than the hardware can // support. This is rare. Recursively chop until each sub-curve fits. @@ -839,7 +837,7 @@ continue; } float numParametricSegments_pow4 = - GrWangsFormula::cubic_pow4(patchWriter.parametricIntolerance(), p); + GrWangsFormula::cubic_pow4(patchWriter.parametricPrecision(), p); if (!patchWriter.stroke360FitsInPatch(numParametricSegments_pow4) || cubic_has_cusp(p)) { // Either the curve requires more tessellation segments than the hardware
diff --git a/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp b/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp index f306ad3..93a2ede 100644 --- a/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp +++ b/src/gpu/tessellate/GrStrokeIndirectTessellator.cpp
@@ -81,8 +81,8 @@ 1, kMaxResolveLevel); fIsRoundJoin = isRoundJoin; #if USE_SIMD - fWangsTermQuadratic = GrWangsFormula::length_term<2>(fTolerances.fParametricIntolerance); - fWangsTermCubic = GrWangsFormula::length_term<3>(fTolerances.fParametricIntolerance); + fWangsTermQuadratic = GrWangsFormula::length_term<2>(fTolerances.fParametricPrecision); + fWangsTermCubic = GrWangsFormula::length_term<3>(fTolerances.fParametricPrecision); #endif } @@ -112,7 +112,7 @@ void countQuad(const SkPoint pts[3], SkPoint lastControlPoint, int8_t* resolveLevelPtr) { float numParametricSegments = - GrWangsFormula::quadratic(fTolerances.fParametricIntolerance, pts); + GrWangsFormula::quadratic(fTolerances.fParametricPrecision, pts); float rotation = SkMeasureQuadRotation(pts); if (fIsRoundJoin) { SkVector nextTan = ((pts[0] == pts[1]) ? pts[2] : pts[1]) - pts[0]; @@ -122,8 +122,7 @@ } void countCubic(const SkPoint pts[4], SkPoint lastControlPoint, int8_t* resolveLevelPtr) { - float numParametricSegments = - GrWangsFormula::cubic(fTolerances.fParametricIntolerance, pts); + float numParametricSegments = GrWangsFormula::cubic(fTolerances.fParametricPrecision, pts); SkVector tan0 = ((pts[0] == pts[1]) ? pts[2] : pts[1]) - pts[0]; SkVector tan1 = pts[3] - ((pts[3] == pts[2]) ? pts[1] : pts[2]); float rotation = SkMeasureAngleBetweenVectors(tan0, tan1);
diff --git a/src/gpu/tessellate/GrStrokeTessellateShader.cpp b/src/gpu/tessellate/GrStrokeTessellateShader.cpp index 52c4b56..29d2e9d 100644 --- a/src/gpu/tessellate/GrStrokeTessellateShader.cpp +++ b/src/gpu/tessellate/GrStrokeTessellateShader.cpp
@@ -47,8 +47,8 @@ })"; static const char* kNumRadialSegmentsPerRadian = R"( -float num_radial_segments_per_radian(float parametricIntolerance, float strokeRadius) { - return .5 / acos(max(1.0 - 1.0/(parametricIntolerance * strokeRadius), -1.0)); +float num_radial_segments_per_radian(float parametricPrecision, float strokeRadius) { + return .5 / acos(max(1.0 - 1.0/(parametricPrecision * strokeRadius), -1.0)); })"; // Unlike mix(), this does not return b when t==1. But it otherwise seems to get better @@ -70,7 +70,7 @@ // will be a composition of these parametric segments as well as radial segments. static void append_wangs_formula_fn(SkString* code, bool hasConics) { code->appendf(R"( - float wangs_formula(in float4x2 P, in float w, in float parametricIntolerance) { + float wangs_formula(in float4x2 P, in float w, in float parametricPrecision) { const float CUBIC_TERM_POW2 = %f; float l0 = length_pow2(fma(float2(-2), P[1], P[2]) + P[0]); float l1 = length_pow2(fma(float2(-2), P[2], P[3]) + P[1]); @@ -81,7 +81,7 @@ m = (w > 0.0) ? QUAD_TERM_POW2 * l0 : m;)", GrWangsFormula::length_term_pow2<2>(1)); } code->append(R"( - return max(ceil(sqrt(parametricIntolerance * sqrt(m))), 1.0); + return max(ceil(sqrt(parametricPrecision * sqrt(m))), 1.0); })"); } @@ -150,7 +150,7 @@ } if (!shader.hasDynamicStroke()) { - // [PARAMETRIC_INTOLERANCE, NUM_RADIAL_SEGMENTS_PER_RADIAN, JOIN_TYPE, STROKE_RADIUS] + // [PARAMETRIC_PRECISION, NUM_RADIAL_SEGMENTS_PER_RADIAN, JOIN_TYPE, STROKE_RADIUS] const char* tessArgsName; fTessArgsUniform = uniHandler->addUniform(nullptr, kVertex_GrShaderFlag | @@ -161,17 +161,17 @@ float NUM_RADIAL_SEGMENTS_PER_RADIAN = %s.y; float JOIN_TYPE = %s.z;)", tessArgsName, tessArgsName); } else { - const char* parametricIntoleranceName; + const char* parametricPrecisionName; fTessArgsUniform = uniHandler->addUniform(nullptr, kVertex_GrShaderFlag | kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag, - kFloat_GrSLType, "parametricIntolerance", - ¶metricIntoleranceName); + kFloat_GrSLType, "parametricPrecision", + ¶metricPrecisionName); v->codeAppendf(R"( float STROKE_RADIUS = dynamicStrokeAttr.x; float NUM_RADIAL_SEGMENTS_PER_RADIAN = num_radial_segments_per_radian(%s,STROKE_RADIUS); - float JOIN_TYPE = dynamicStrokeAttr.y;)", parametricIntoleranceName); + float JOIN_TYPE = dynamicStrokeAttr.y;)", parametricPrecisionName); } if (!shader.viewMatrix().isIdentity()) { @@ -432,14 +432,14 @@ } float strokeRadius = (stroke.isHairlineStyle()) ? .5f : stroke.getWidth() * .5; pdman.set4f(fTessArgsUniform, - tolerances.fParametricIntolerance, // PARAMETRIC_INTOLERANCE + tolerances.fParametricPrecision, // PARAMETRIC_PRECISION tolerances.fNumRadialSegmentsPerRadian, // NUM_RADIAL_SEGMENTS_PER_RADIAN GetJoinType(shader.fStroke), // JOIN_TYPE strokeRadius); // STROKE_RADIUS } else { SkASSERT(!stroke.isHairlineStyle()); float maxScale = shader.viewMatrix().getMaxScale(); - pdman.set1f(fTessArgsUniform, GrStrokeTolerances::CalcParametricIntolerance(maxScale)); + pdman.set1f(fTessArgsUniform, GrStrokeTolerances::CalcParametricPrecision(maxScale)); } // Set up the view matrix, if any. @@ -486,11 +486,11 @@ const char* tessArgsName = impl->getTessArgsUniformName(uniformHandler); if (!this->hasDynamicStroke()) { code.appendf("uniform vec4 %s;\n", tessArgsName); - code.appendf("#define PARAMETRIC_INTOLERANCE %s.x\n", tessArgsName); + code.appendf("#define PARAMETRIC_PRECISION %s.x\n", tessArgsName); code.appendf("#define NUM_RADIAL_SEGMENTS_PER_RADIAN %s.y\n", tessArgsName); } else { code.appendf("uniform float %s;\n", tessArgsName); - code.appendf("#define PARAMETRIC_INTOLERANCE %s\n", tessArgsName); + code.appendf("#define PARAMETRIC_PRECISION %s\n", tessArgsName); code.appendf("#define NUM_RADIAL_SEGMENTS_PER_RADIAN vsStrokeArgs[0].x\n"); } @@ -575,7 +575,7 @@ // Calculate the number of parametric segments. The final tessellated strip will be a // composition of these parametric segments as well as radial segments. float w = isinf(P[3].y) ? P[3].x : -1.0; // w<0 means the curve is an integral cubic. - float numParametricSegments = wangs_formula(P, w, PARAMETRIC_INTOLERANCE); + float numParametricSegments = wangs_formula(P, w, PARAMETRIC_PRECISION); if (P[0] == P[1] && P[2] == P[3]) { // This is how the patch builder articulates lineTos but Wang's formula returns // >>1 segment in this scenario. Assign 1 parametric segment. @@ -1020,27 +1020,27 @@ // Tessellation control uniforms and/or dynamic attributes. if (!shader.hasDynamicStroke()) { - // [PARAMETRIC_INTOLERANCE, NUM_RADIAL_SEGMENTS_PER_RADIAN, JOIN_TYPE, STROKE_RADIUS] + // [PARAMETRIC_PRECISION, NUM_RADIAL_SEGMENTS_PER_RADIAN, JOIN_TYPE, STROKE_RADIUS] const char* tessArgsName; fTessControlArgsUniform = args.fUniformHandler->addUniform( nullptr, kVertex_GrShaderFlag, kFloat4_GrSLType, "tessControlArgs", &tessArgsName); args.fVertBuilder->codeAppendf(R"( - float PARAMETRIC_INTOLERANCE = %s.x; + float PARAMETRIC_PRECISION = %s.x; float NUM_RADIAL_SEGMENTS_PER_RADIAN = %s.y; float JOIN_TYPE = %s.z; float STROKE_RADIUS = %s.w;)", tessArgsName, tessArgsName, tessArgsName, tessArgsName); } else { - const char* parametricIntoleranceName; + const char* parametricPrecisionName; fTessControlArgsUniform = args.fUniformHandler->addUniform( - nullptr, kVertex_GrShaderFlag, kFloat_GrSLType, "parametricIntolerance", - ¶metricIntoleranceName); + nullptr, kVertex_GrShaderFlag, kFloat_GrSLType, "parametricPrecision", + ¶metricPrecisionName); args.fVertBuilder->codeAppendf(R"( - float PARAMETRIC_INTOLERANCE = %s; + float PARAMETRIC_PRECISION = %s; float STROKE_RADIUS = dynamicStrokeAttr.x; float NUM_RADIAL_SEGMENTS_PER_RADIAN = num_radial_segments_per_radian( - PARAMETRIC_INTOLERANCE, STROKE_RADIUS); - float JOIN_TYPE = dynamicStrokeAttr.y;)", parametricIntoleranceName); + PARAMETRIC_PRECISION, STROKE_RADIUS); + float JOIN_TYPE = dynamicStrokeAttr.y;)", parametricPrecisionName); } // View matrix uniforms. @@ -1079,7 +1079,7 @@ float numTotalEdges = abs(argsAttr.z); // Find how many parametric segments this stroke requires. - float numParametricSegments = min(wangs_formula(P, w, PARAMETRIC_INTOLERANCE), + float numParametricSegments = min(wangs_formula(P, w, PARAMETRIC_PRECISION), float(1 << MAX_PARAMETRIC_SEGMENTS_LOG2)); if (P[0] == P[1] && P[2] == P[3]) { // This is how we describe lines, but Wang's formula does not return 1 in this case. @@ -1273,7 +1273,7 @@ } float strokeRadius = (stroke.isHairlineStyle()) ? .5f : stroke.getWidth() * .5; pdman.set4f(fTessControlArgsUniform, - tolerances.fParametricIntolerance, // PARAMETRIC_INTOLERANCE + tolerances.fParametricPrecision, // PARAMETRIC_PRECISION tolerances.fNumRadialSegmentsPerRadian, // NUM_RADIAL_SEGMENTS_PER_RADIAN GetJoinType(shader.fStroke), // JOIN_TYPE strokeRadius); // STROKE_RADIUS @@ -1281,7 +1281,7 @@ SkASSERT(!stroke.isHairlineStyle()); float maxScale = shader.viewMatrix().getMaxScale(); pdman.set1f(fTessControlArgsUniform, - GrStrokeTolerances::CalcParametricIntolerance(maxScale)); + GrStrokeTolerances::CalcParametricPrecision(maxScale)); } // Set up the view matrix, if any.
diff --git a/src/gpu/tessellate/GrStrokeTessellator.h b/src/gpu/tessellate/GrStrokeTessellator.h index 8d0ec4e..bbc1a7e 100644 --- a/src/gpu/tessellate/GrStrokeTessellator.h +++ b/src/gpu/tessellate/GrStrokeTessellator.h
@@ -49,20 +49,20 @@ // Decides the number of parametric segments the tessellator adds for each curve. (Uniform // steps in parametric space.) The tessellator will add enough parametric segments so that, // once transformed into device space, they never deviate by more than - // 1/GrTessellationPathRenderer::kLinearizationIntolerance pixels from the true curve. - constexpr static float CalcParametricIntolerance(float matrixMaxScale) { - return matrixMaxScale * GrTessellationPathRenderer::kLinearizationIntolerance; + // 1/GrTessellationPathRenderer::kLinearizationPrecision pixels from the true curve. + constexpr static float CalcParametricPrecision(float matrixMaxScale) { + return matrixMaxScale * GrTessellationPathRenderer::kLinearizationPrecision; } // Decides the number of radial segments the tessellator adds for each curve. (Uniform steps // in tangent angle.) The tessellator will add this number of radial segments for each // radian of rotation in local path space. - static float CalcNumRadialSegmentsPerRadian(float parametricIntolerance, + static float CalcNumRadialSegmentsPerRadian(float parametricPrecision, float strokeWidth) { - return .5f / acosf(std::max(1 - 2 / (parametricIntolerance * strokeWidth), -1.f)); + return .5f / acosf(std::max(1 - 2 / (parametricPrecision * strokeWidth), -1.f)); } template<int N> static grvx::vec<N> ApproxNumRadialSegmentsPerRadian( - float parametricIntolerance, grvx::vec<N> strokeWidths) { - grvx::vec<N> cosTheta = skvx::max(1 - 2 / (parametricIntolerance * strokeWidths), -1); + float parametricPrecision, grvx::vec<N> strokeWidths) { + grvx::vec<N> cosTheta = skvx::max(1 - 2 / (parametricPrecision * strokeWidths), -1); // Subtract GRVX_APPROX_ACOS_MAX_ERROR so we never account for too few segments. return .5f / (grvx::approx_acos(cosTheta) - GRVX_APPROX_ACOS_MAX_ERROR); } @@ -99,11 +99,11 @@ } static GrStrokeTolerances MakeNonHairline(float matrixMaxScale, float strokeWidth) { SkASSERT(strokeWidth > 0); - float parametricIntolerance = CalcParametricIntolerance(matrixMaxScale); - return {parametricIntolerance, - CalcNumRadialSegmentsPerRadian(parametricIntolerance, strokeWidth)}; + float parametricPrecision = CalcParametricPrecision(matrixMaxScale); + return {parametricPrecision, + CalcNumRadialSegmentsPerRadian(parametricPrecision, strokeWidth)}; } - float fParametricIntolerance; + float fParametricPrecision; float fNumRadialSegmentsPerRadian; }; @@ -112,8 +112,8 @@ public: using PathStrokeList = GrStrokeTessellator::PathStrokeList; - GrStrokeToleranceBuffer(float parametricIntolerance) - : fParametricIntolerance(parametricIntolerance) { + GrStrokeToleranceBuffer(float parametricPrecision) + : fParametricPrecision(parametricPrecision) { } float fetchRadialSegmentsPerRadian(PathStrokeList* head) { @@ -128,7 +128,7 @@ do { fStrokeWidths[i++] = peekAhead->fStroke.getWidth(); } while ((peekAhead = peekAhead->fNext) && i < 4); - auto tol = GrStrokeTolerances::ApproxNumRadialSegmentsPerRadian(fParametricIntolerance, + auto tol = GrStrokeTolerances::ApproxNumRadialSegmentsPerRadian(fParametricPrecision, fStrokeWidths); tol.store(fNumRadialSegmentsPerRadian); fBufferIdx = 0; @@ -141,7 +141,7 @@ private: grvx::float4 fStrokeWidths{}; // Must be first for alignment purposes. float fNumRadialSegmentsPerRadian[4]; - const float fParametricIntolerance; + const float fParametricPrecision; int fBufferIdx = 4; // Initialize the buffer as "empty"; };
diff --git a/src/gpu/tessellate/GrTessellationPathRenderer.cpp b/src/gpu/tessellate/GrTessellationPathRenderer.cpp index 154ebc0..7437de1 100644 --- a/src/gpu/tessellate/GrTessellationPathRenderer.cpp +++ b/src/gpu/tessellate/GrTessellationPathRenderer.cpp
@@ -81,10 +81,10 @@ // // Solve the following equation for w: // - // GrWangsFormula::worst_case_cubic(kLinearizationIntolerance, w, kMaxAtlasPathHeight^2 / w) + // GrWangsFormula::worst_case_cubic(kLinearizationPrecision, w, kMaxAtlasPathHeight^2 / w) // == maxTessellationSegments // - float k = GrWangsFormula::length_term<3>(kLinearizationIntolerance); + float k = GrWangsFormula::length_term<3>(kLinearizationPrecision); float h = kMaxAtlasPathHeight; float s = caps.shaderCaps()->maxTessellationSegments(); // Quadratic formula from Numerical Recipes in C: @@ -119,7 +119,7 @@ // Verify GrWangsFormula::worst_case_cubic() still works as we expect. The worst case number of // segments for this bounding box should be maxTessellationSegments. SkASSERT(SkScalarNearlyEqual(GrWangsFormula::worst_case_cubic( - kLinearizationIntolerance, worstCaseWidth, worstCaseHeight), s, 1)); + kLinearizationPrecision, worstCaseWidth, worstCaseHeight), s, 1)); #endif fStencilAtlasFlags &= ~OpFlags::kDisableHWTessellation; fMaxAtlasPathWidth = std::min(fMaxAtlasPathWidth, (int)worstCaseWidth); @@ -157,8 +157,8 @@ GrTessellationPathRenderer::OpFlags opFlags, GrAAType aaType, const SkRect& shapeDevBounds, const SkMatrix& viewMatrix, const GrStyledShape& shape, GrPaint&& paint) { - constexpr static auto kLinearizationIntolerance = - GrTessellationPathRenderer::kLinearizationIntolerance; + constexpr static auto kLinearizationPrecision = + GrTessellationPathRenderer::kLinearizationPrecision; constexpr static auto kMaxResolveLevel = GrTessellationPathRenderer::kMaxResolveLevel; using OpFlags = GrTessellationPathRenderer::OpFlags; @@ -169,7 +169,7 @@ // Find the worst-case log2 number of line segments that a curve in this path might need to be // divided into. - int worstCaseResolveLevel = GrWangsFormula::worst_case_cubic_log2(kLinearizationIntolerance, + int worstCaseResolveLevel = GrWangsFormula::worst_case_cubic_log2(kLinearizationPrecision, shapeDevBounds.width(), shapeDevBounds.height()); if (worstCaseResolveLevel > kMaxResolveLevel) { @@ -205,7 +205,7 @@ SkRect newDevBounds; viewMatrix.mapRect(&newDevBounds, path.getBounds()); - worstCaseResolveLevel = GrWangsFormula::worst_case_cubic_log2(kLinearizationIntolerance, + worstCaseResolveLevel = GrWangsFormula::worst_case_cubic_log2(kLinearizationPrecision, newDevBounds.width(), newDevBounds.height()); // kMaxResolveLevel should be large enough to tessellate paths the size of any screen we @@ -272,7 +272,7 @@ // sufficient for this path. fMaxAtlasPathWidth should have been tuned for this to always be // the case. if (!(fStencilAtlasFlags & OpFlags::kDisableHWTessellation)) { - int worstCaseNumSegments = GrWangsFormula::worst_case_cubic(kLinearizationIntolerance, + int worstCaseNumSegments = GrWangsFormula::worst_case_cubic(kLinearizationPrecision, devIBounds.width(), devIBounds.height()); const GrShaderCaps& shaderCaps = *args.fContext->priv().caps()->shaderCaps();
diff --git a/src/gpu/tessellate/GrTessellationPathRenderer.h b/src/gpu/tessellate/GrTessellationPathRenderer.h index 020ae0d..fd4fe0e 100644 --- a/src/gpu/tessellate/GrTessellationPathRenderer.h +++ b/src/gpu/tessellate/GrTessellationPathRenderer.h
@@ -20,7 +20,7 @@ class GrTessellationPathRenderer : public GrPathRenderer, public GrOnFlushCallbackObject { public: // Don't allow linearized segments to be off by more than 1/4th of a pixel from the true curve. - constexpr static float kLinearizationIntolerance = 4; + constexpr static float kLinearizationPrecision = 4; // This is the maximum resolve level supported by our internal indirect draw shaders. (Indirect // draws are an alternative to hardware tessellation, and we can use them when hardware support @@ -29,7 +29,7 @@ // At a given resolveLevel, a curve gets linearized into 2^resolveLevel line segments. So the // finest resolveLevel supported by our indirect draw shaders is 2^10 == 1024 line segments. // - // 1024 line segments is enough resolution (with intolerance == 4) to guarantee we can render a + // 1024 line segments is enough resolution (with precision == 4) to guarantee we can render a // 123575px x 123575px path. (See GrWangsFormula::worst_case_cubic.) constexpr static int kMaxResolveLevel = 10;
diff --git a/src/gpu/tessellate/GrWangsFormula.h b/src/gpu/tessellate/GrWangsFormula.h index a6118da..fa160af 100644 --- a/src/gpu/tessellate/GrWangsFormula.h +++ b/src/gpu/tessellate/GrWangsFormula.h
@@ -15,22 +15,22 @@ // Wang's formula gives the minimum number of evenly spaced (in the parametric sense) line segments // that a bezier curve must be chopped into in order to guarantee all lines stay within a distance -// of "1/intolerance" pixels from the true curve. Its definition for a bezier curve of degree "n" is +// of "1/precision" pixels from the true curve. Its definition for a bezier curve of degree "n" is // as follows: // // maxLength = max([length(p[i+2] - 2p[i+1] + p[i]) for (0 <= i <= n-2)]) -// numParametricSegments = sqrt(maxLength * intolerance * n*(n - 1)/8) +// numParametricSegments = sqrt(maxLength * precision * n*(n - 1)/8) // // (Goldman, Ron. (2003). 5.6.3 Wang's Formula. "Pyramid Algorithms: A Dynamic Programming Approach // to Curves and Surfaces for Geometric Modeling". Morgan Kaufmann Publishers.) namespace GrWangsFormula { // Returns the value by which to multiply length in Wang's formula. (See above.) -template<int Degree> constexpr float length_term(float intolerance) { - return (Degree * (Degree - 1) / 8.f) * intolerance; +template<int Degree> constexpr float length_term(float precision) { + return (Degree * (Degree - 1) / 8.f) * precision; } -template<int Degree> constexpr float length_term_pow2(float intolerance) { - return ((Degree * Degree) * ((Degree - 1) * (Degree - 1)) / 64.f) * (intolerance * intolerance); +template<int Degree> constexpr float length_term_pow2(float precision) { + return ((Degree * Degree) * ((Degree - 1) * (Degree - 1)) / 64.f) * (precision * precision); } SK_ALWAYS_INLINE static float root4(float x) { @@ -54,7 +54,7 @@ } // Returns Wang's formula, raised to the 4th power, specialized for a quadratic curve. -SK_ALWAYS_INLINE static float quadratic_pow4(float intolerance, const SkPoint pts[], +SK_ALWAYS_INLINE static float quadratic_pow4(float precision, const SkPoint pts[], const GrVectorXform& vectorXform = GrVectorXform()) { using grvx::float2, skvx::bit_pun; float2 p0 = bit_pun<float2>(pts[0]); @@ -63,25 +63,25 @@ float2 v = grvx::fast_madd<2>(-2, p1, p0) + p2; v = vectorXform(v); float2 vv = v*v; - return (vv[0] + vv[1]) * length_term_pow2<2>(intolerance); + return (vv[0] + vv[1]) * length_term_pow2<2>(precision); } // Returns Wang's formula specialized for a quadratic curve. -SK_ALWAYS_INLINE static float quadratic(float intolerance, const SkPoint pts[], +SK_ALWAYS_INLINE static float quadratic(float precision, const SkPoint pts[], const GrVectorXform& vectorXform = GrVectorXform()) { - return root4(quadratic_pow4(intolerance, pts, vectorXform)); + return root4(quadratic_pow4(precision, pts, vectorXform)); } // Returns the log2 value of Wang's formula specialized for a quadratic curve, rounded up to the // next int. -SK_ALWAYS_INLINE static int quadratic_log2(float intolerance, const SkPoint pts[], +SK_ALWAYS_INLINE static int quadratic_log2(float precision, const SkPoint pts[], const GrVectorXform& vectorXform = GrVectorXform()) { // nextlog16(x) == ceil(log2(sqrt(sqrt(x)))) - return nextlog16(quadratic_pow4(intolerance, pts, vectorXform)); + return nextlog16(quadratic_pow4(precision, pts, vectorXform)); } // Returns Wang's formula, raised to the 4th power, specialized for a cubic curve. -SK_ALWAYS_INLINE static float cubic_pow4(float intolerance, const SkPoint pts[], +SK_ALWAYS_INLINE static float cubic_pow4(float precision, const SkPoint pts[], const GrVectorXform& vectorXform = GrVectorXform()) { using grvx::float4; float4 p01 = float4::Load(pts); @@ -90,42 +90,42 @@ float4 v = grvx::fast_madd<4>(-2, p12, p01) + p23; v = vectorXform(v); float4 vv = v*v; - return std::max(vv[0] + vv[1], vv[2] + vv[3]) * length_term_pow2<3>(intolerance); + return std::max(vv[0] + vv[1], vv[2] + vv[3]) * length_term_pow2<3>(precision); } // Returns Wang's formula specialized for a cubic curve. -SK_ALWAYS_INLINE static float cubic(float intolerance, const SkPoint pts[], +SK_ALWAYS_INLINE static float cubic(float precision, const SkPoint pts[], const GrVectorXform& vectorXform = GrVectorXform()) { - return root4(cubic_pow4(intolerance, pts, vectorXform)); + return root4(cubic_pow4(precision, pts, vectorXform)); } // Returns the log2 value of Wang's formula specialized for a cubic curve, rounded up to the next // int. -SK_ALWAYS_INLINE static int cubic_log2(float intolerance, const SkPoint pts[], +SK_ALWAYS_INLINE static int cubic_log2(float precision, const SkPoint pts[], const GrVectorXform& vectorXform = GrVectorXform()) { // nextlog16(x) == ceil(log2(sqrt(sqrt(x)))) - return nextlog16(cubic_pow4(intolerance, pts, vectorXform)); + return nextlog16(cubic_pow4(precision, pts, vectorXform)); } // Returns the maximum number of line segments a cubic with the given device-space bounding box size // would ever need to be divided into. This is simply a special case of the cubic formula where we // maximize its value by placing control points on specific corners of the bounding box. -SK_ALWAYS_INLINE static float worst_case_cubic(float intolerance, float devWidth, float devHeight) { - float k = length_term<3>(intolerance); +SK_ALWAYS_INLINE static float worst_case_cubic(float precision, float devWidth, float devHeight) { + float k = length_term<3>(precision); return sqrtf(2*k * SkVector::Length(devWidth, devHeight)); } // Returns the maximum log2 number of line segments a cubic with the given device-space bounding box // size would ever need to be divided into. -SK_ALWAYS_INLINE static int worst_case_cubic_log2(float intolerance, float devWidth, +SK_ALWAYS_INLINE static int worst_case_cubic_log2(float precision, float devWidth, float devHeight) { - float kk = length_term_pow2<3>(intolerance); + float kk = length_term_pow2<3>(precision); // nextlog16(x) == ceil(log2(sqrt(sqrt(x)))) return nextlog16(4*kk * (devWidth * devWidth + devHeight * devHeight)); } // Returns Wang's formula specialized for a conic curve, raised to the second power. -// Input points should be in projected space, and note tolerance parameter is not intolerance. +// Input points should be in projected space, and note tolerance parameter is not "precision". // // This is not actually due to Wang, but is an analogue from (Theorem 3, corollary 1): // J. Zheng, T. Sederberg. "Estimating Tessellation Parameter Intervals for
diff --git a/tests/StrokeIndirectTest.cpp b/tests/StrokeIndirectTest.cpp index 0451e47..e2c0297 100644 --- a/tests/StrokeIndirectTest.cpp +++ b/tests/StrokeIndirectTest.cpp
@@ -331,7 +331,7 @@ } } float numParametricSegments = (hasCusp) ? 0 : GrWangsFormula::quadratic( - tolerances.fParametricIntolerance, pts); + tolerances.fParametricPrecision, pts); float rotation = (hasCusp) ? 0 : SkMeasureQuadRotation(pts); if (stroke.getJoin() == SkPaint::kRound_Join) { SkVector controlPoint = (pts[0] == pts[1]) ? pts[2] : pts[1]; @@ -374,7 +374,7 @@ // it matches the answer we got already. SkPoint* p = chops + i*3; float numParametricSegments = - GrWangsFormula::cubic(tolerances.fParametricIntolerance, p); + GrWangsFormula::cubic(tolerances.fParametricPrecision, p); SkVector tan0 = ((p[0] == p[1]) ? (p[1] == p[2]) ? p[3] : p[2] : p[1]) - p[0]; SkVector tan1 = @@ -454,8 +454,7 @@ for (unsigned j = 0; j < indirect->fInstanceCount; ++j) { SkASSERT(fabsf(instance->fNumTotalEdges) == indirect->fVertexCount/2); const SkPoint* p = instance->fPts; - float numParametricSegments = GrWangsFormula::cubic( - tolerances.fParametricIntolerance, p); + float numParametricSegments = GrWangsFormula::cubic(tolerances.fParametricPrecision, p); float alternateNumParametricSegments = numParametricSegments; if (p[0] == p[1] && p[2] == p[3]) { // We articulate lines as "p0,p0,p1,p1". This one might actually expect 0 parametric
diff --git a/tests/WangsFormulaTest.cpp b/tests/WangsFormulaTest.cpp index eee1db9..6d3bdff 100644 --- a/tests/WangsFormulaTest.cpp +++ b/tests/WangsFormulaTest.cpp
@@ -10,7 +10,7 @@ #include "src/gpu/tessellate/GrWangsFormula.h" #include "tests/Test.h" -constexpr static int kIntolerance = 4; // 1/4 pixel max error. +constexpr static int kPrecision = 4; // 1/4 pixel max error. const SkPoint kSerp[4] = { {285.625f, 499.687f}, {411.625f, 808.188f}, {1064.62f, 135.688f}, {1042.63f, 585.187f}}; @@ -21,13 +21,13 @@ const SkPoint kQuad[4] = { {460.625f, 557.187f}, {707.121f, 209.688f}, {779.628f, 577.687f}}; -static float wangs_formula_quadratic_reference_impl(float intolerance, const SkPoint p[3]) { - float k = (2 * 1) / 8.f * intolerance; +static float wangs_formula_quadratic_reference_impl(float precision, const SkPoint p[3]) { + float k = (2 * 1) / 8.f * precision; return sqrtf(k * (p[0] - p[1]*2 + p[2]).length()); } -static float wangs_formula_cubic_reference_impl(float intolerance, const SkPoint p[4]) { - float k = (3 * 2) / 8.f * intolerance; +static float wangs_formula_cubic_reference_impl(float precision, const SkPoint p[4]) { + float k = (3 * 2) / 8.f * precision; return sqrtf(k * std::max((p[0] - p[1]*2 + p[2]).length(), (p[1] - p[2]*2 + p[3]).length())); } @@ -40,7 +40,7 @@ // See Thm 3, Corollary 1. // // Input points should be in projected space. -static float wangs_formula_conic_reference_impl(float intolerance, +static float wangs_formula_conic_reference_impl(float precision, const SkPoint P[3], const float w) { // Compute center of bounding box in projected space @@ -63,7 +63,7 @@ SkASSERT(max_len > 0); // Compute delta = parametric step size of linearization - const float eps = 1 / intolerance; + const float eps = 1 / precision; const float r_minus_eps = std::max(0.f, max_len - eps); const float min_w = std::min(w, 1.f); const float numer = 4 * min_w * eps; @@ -199,55 +199,55 @@ // Test cubic boundaries. // f = sqrt(k * length(max(abs(p0 - p1*2 + p2), // abs(p1 - p2*2 + p3)))); - constexpr static float k = (3 * 2) / (8 * (1.f/kIntolerance)); + constexpr static float k = (3 * 2) / (8 * (1.f/kPrecision)); float x = std::ldexp(1, level * 2) / k; setupCubicLengthTerm(level << 1, pts, x - epsilon); - float referenceValue = wangs_formula_cubic_reference_impl(kIntolerance, pts); + float referenceValue = wangs_formula_cubic_reference_impl(kPrecision, pts); REPORTER_ASSERT(r, std::ceil(std::log2(referenceValue)) == level); - float c = GrWangsFormula::cubic(kIntolerance, pts); + float c = GrWangsFormula::cubic(kPrecision, pts); REPORTER_ASSERT(r, SkScalarNearlyEqual(c/referenceValue, 1, kTessellationTolerance)); - REPORTER_ASSERT(r, GrWangsFormula::cubic_log2(kIntolerance, pts) == level); + REPORTER_ASSERT(r, GrWangsFormula::cubic_log2(kPrecision, pts) == level); setupCubicLengthTerm(level << 1, pts, x + epsilon); - referenceValue = wangs_formula_cubic_reference_impl(kIntolerance, pts); + referenceValue = wangs_formula_cubic_reference_impl(kPrecision, pts); REPORTER_ASSERT(r, std::ceil(std::log2(referenceValue)) == level + 1); - c = GrWangsFormula::cubic(kIntolerance, pts); + c = GrWangsFormula::cubic(kPrecision, pts); REPORTER_ASSERT(r, SkScalarNearlyEqual(c/referenceValue, 1, kTessellationTolerance)); - REPORTER_ASSERT(r, GrWangsFormula::cubic_log2(kIntolerance, pts) == level + 1); + REPORTER_ASSERT(r, GrWangsFormula::cubic_log2(kPrecision, pts) == level + 1); } { // Test quadratic boundaries. // f = std::sqrt(k * Length(p0 - p1*2 + p2)); - constexpr static float k = 2 / (8 * (1.f/kIntolerance)); + constexpr static float k = 2 / (8 * (1.f/kPrecision)); float x = std::ldexp(1, level * 2) / k; setupQuadraticLengthTerm(level << 1, pts, x - epsilon); - float referenceValue = wangs_formula_quadratic_reference_impl(kIntolerance, pts); + float referenceValue = wangs_formula_quadratic_reference_impl(kPrecision, pts); REPORTER_ASSERT(r, std::ceil(std::log2(referenceValue)) == level); - float q = GrWangsFormula::quadratic(kIntolerance, pts); + float q = GrWangsFormula::quadratic(kPrecision, pts); REPORTER_ASSERT(r, SkScalarNearlyEqual(q/referenceValue, 1, kTessellationTolerance)); - REPORTER_ASSERT(r, GrWangsFormula::quadratic_log2(kIntolerance, pts) == level); + REPORTER_ASSERT(r, GrWangsFormula::quadratic_log2(kPrecision, pts) == level); setupQuadraticLengthTerm(level << 1, pts, x + epsilon); - referenceValue = wangs_formula_quadratic_reference_impl(kIntolerance, pts); + referenceValue = wangs_formula_quadratic_reference_impl(kPrecision, pts); REPORTER_ASSERT(r, std::ceil(std::log2(referenceValue)) == level+1); - q = GrWangsFormula::quadratic(kIntolerance, pts); + q = GrWangsFormula::quadratic(kPrecision, pts); REPORTER_ASSERT(r, SkScalarNearlyEqual(q/referenceValue, 1, kTessellationTolerance)); - REPORTER_ASSERT(r, GrWangsFormula::quadratic_log2(kIntolerance, pts) == level + 1); + REPORTER_ASSERT(r, GrWangsFormula::quadratic_log2(kPrecision, pts) == level + 1); } } auto check_cubic_log2 = [&](const SkPoint* pts) { - float f = std::max(1.f, wangs_formula_cubic_reference_impl(kIntolerance, pts)); - int f_log2 = GrWangsFormula::cubic_log2(kIntolerance, pts); + float f = std::max(1.f, wangs_formula_cubic_reference_impl(kPrecision, pts)); + int f_log2 = GrWangsFormula::cubic_log2(kPrecision, pts); REPORTER_ASSERT(r, SkScalarCeilToInt(std::log2(f)) == f_log2); - float c = std::max(1.f, GrWangsFormula::cubic(kIntolerance, pts)); + float c = std::max(1.f, GrWangsFormula::cubic(kPrecision, pts)); REPORTER_ASSERT(r, SkScalarNearlyEqual(c/f, 1, kTessellationTolerance)); }; auto check_quadratic_log2 = [&](const SkPoint* pts) { - float f = std::max(1.f, wangs_formula_quadratic_reference_impl(kIntolerance, pts)); - int f_log2 = GrWangsFormula::quadratic_log2(kIntolerance, pts); + float f = std::max(1.f, wangs_formula_quadratic_reference_impl(kPrecision, pts)); + int f_log2 = GrWangsFormula::quadratic_log2(kPrecision, pts); REPORTER_ASSERT(r, SkScalarCeilToInt(std::log2(f)) == f_log2); - float q = std::max(1.f, GrWangsFormula::quadratic(kIntolerance, pts)); + float q = std::max(1.f, GrWangsFormula::quadratic(kPrecision, pts)); REPORTER_ASSERT(r, SkScalarNearlyEqual(q/f, 1, kTessellationTolerance)); }; @@ -279,16 +279,16 @@ auto check_cubic_log2_with_transform = [&](const SkPoint* pts, const SkMatrix& m){ SkPoint ptsXformed[4]; m.mapPoints(ptsXformed, pts, 4); - int expected = GrWangsFormula::cubic_log2(kIntolerance, ptsXformed); - int actual = GrWangsFormula::cubic_log2(kIntolerance, pts, GrVectorXform(m)); + int expected = GrWangsFormula::cubic_log2(kPrecision, ptsXformed); + int actual = GrWangsFormula::cubic_log2(kPrecision, pts, GrVectorXform(m)); REPORTER_ASSERT(r, actual == expected); }; auto check_quadratic_log2_with_transform = [&](const SkPoint* pts, const SkMatrix& m) { SkPoint ptsXformed[3]; m.mapPoints(ptsXformed, pts, 3); - int expected = GrWangsFormula::quadratic_log2(kIntolerance, ptsXformed); - int actual = GrWangsFormula::quadratic_log2(kIntolerance, pts, GrVectorXform(m)); + int expected = GrWangsFormula::quadratic_log2(kPrecision, ptsXformed); + int actual = GrWangsFormula::quadratic_log2(kPrecision, pts, GrVectorXform(m)); REPORTER_ASSERT(r, actual == expected); }; @@ -312,25 +312,25 @@ DEF_TEST(WangsFormula_worst_case_cubic, r) { { SkPoint worstP[] = {{0,0}, {100,100}, {0,0}, {0,0}}; - REPORTER_ASSERT(r, GrWangsFormula::worst_case_cubic(kIntolerance, 100, 100) == - wangs_formula_cubic_reference_impl(kIntolerance, worstP)); - REPORTER_ASSERT(r, GrWangsFormula::worst_case_cubic_log2(kIntolerance, 100, 100) == - GrWangsFormula::cubic_log2(kIntolerance, worstP)); + REPORTER_ASSERT(r, GrWangsFormula::worst_case_cubic(kPrecision, 100, 100) == + wangs_formula_cubic_reference_impl(kPrecision, worstP)); + REPORTER_ASSERT(r, GrWangsFormula::worst_case_cubic_log2(kPrecision, 100, 100) == + GrWangsFormula::cubic_log2(kPrecision, worstP)); } { SkPoint worstP[] = {{100,100}, {100,100}, {200,200}, {100,100}}; - REPORTER_ASSERT(r, GrWangsFormula::worst_case_cubic(kIntolerance, 100, 100) == - wangs_formula_cubic_reference_impl(kIntolerance, worstP)); - REPORTER_ASSERT(r, GrWangsFormula::worst_case_cubic_log2(kIntolerance, 100, 100) == - GrWangsFormula::cubic_log2(kIntolerance, worstP)); + REPORTER_ASSERT(r, GrWangsFormula::worst_case_cubic(kPrecision, 100, 100) == + wangs_formula_cubic_reference_impl(kPrecision, worstP)); + REPORTER_ASSERT(r, GrWangsFormula::worst_case_cubic_log2(kPrecision, 100, 100) == + GrWangsFormula::cubic_log2(kPrecision, worstP)); } auto check_worst_case_cubic = [&](const SkPoint* pts) { SkRect bbox; bbox.setBoundsNoCheck(pts, 4); - float worst = GrWangsFormula::worst_case_cubic(kIntolerance, bbox.width(), bbox.height()); - int worst_log2 = GrWangsFormula::worst_case_cubic_log2(kIntolerance, bbox.width(), + float worst = GrWangsFormula::worst_case_cubic(kPrecision, bbox.width(), bbox.height()); + int worst_log2 = GrWangsFormula::worst_case_cubic_log2(kPrecision, bbox.width(), bbox.height()); - float actual = wangs_formula_cubic_reference_impl(kIntolerance, pts); + float actual = wangs_formula_cubic_reference_impl(kPrecision, pts); REPORTER_ASSERT(r, worst >= actual); REPORTER_ASSERT(r, std::ceil(std::log2(std::max(1.f, worst))) == worst_log2); }; @@ -351,7 +351,7 @@ SkRandom rand; for_random_beziers(3, &rand, [&r](const SkPoint pts[]) { const int nsegs = static_cast<int>( - std::ceil(wangs_formula_quadratic_reference_impl(kIntolerance, pts))); + std::ceil(wangs_formula_quadratic_reference_impl(kPrecision, pts))); const float tdelta = 1.f / nsegs; for (int j = 0; j < nsegs; ++j) { @@ -388,7 +388,7 @@ const float d = std::abs((p - sectionPts[0]).dot(n)) / n.length(); // Check distance is within specified tolerance - REPORTER_ASSERT(r, d <= (1.f / kIntolerance) + SK_ScalarNearlyZero); + REPORTER_ASSERT(r, d <= (1.f / kPrecision) + SK_ScalarNearlyZero); } }, maxExponent); } @@ -401,8 +401,8 @@ SkRandom rand; for (int i = 0; i < 100; ++i) { for_random_beziers(3, &rand, [&r](const SkPoint pts[]) { - const float rational_nsegs = wangs_formula_conic_reference_impl(kIntolerance, pts, 1.f); - const float integral_nsegs = wangs_formula_quadratic_reference_impl(kIntolerance, pts); + const float rational_nsegs = wangs_formula_conic_reference_impl(kPrecision, pts, 1.f); + const float integral_nsegs = wangs_formula_quadratic_reference_impl(kPrecision, pts); REPORTER_ASSERT( r, SkScalarNearlyEqual(rational_nsegs, integral_nsegs, kTessellationTolerance)); }); @@ -447,7 +447,7 @@ 3, &rand, [&](const SkPoint pts[]) { const int nsegs = static_cast<int>( - std::ceil(wangs_formula_conic_reference_impl(kIntolerance, pts, w))); + std::ceil(wangs_formula_conic_reference_impl(kPrecision, pts, w))); const float tdelta = 1.f / nsegs; for (int j = 0; j < nsegs; ++j) { @@ -465,7 +465,7 @@ const double d = std::abs(dot(p1 - p0, n)) / length(n); // Check distance is within tolerance - REPORTER_ASSERT(r, d <= (1.0 / kIntolerance) + SK_ScalarNearlyZero); + REPORTER_ASSERT(r, d <= (1.0 / kPrecision) + SK_ScalarNearlyZero); } }, maxExponent); @@ -474,13 +474,13 @@ // Ensure the vectorized conic version equals the reference implementation DEF_TEST(WangsFormula_conic_matches_reference, r) { - constexpr static float kTolerance = 1.f / kIntolerance; + constexpr static float kTolerance = 1.f / kPrecision; SkRandom rand; for (int i = -10; i <= 10; ++i) { const float w = std::ldexp(1 + rand.nextF(), i); for_random_beziers(3, &rand, [&r, w](const SkPoint pts[]) { - const float ref_nsegs = wangs_formula_conic_reference_impl(kIntolerance, pts, w); + const float ref_nsegs = wangs_formula_conic_reference_impl(kPrecision, pts, w); const float nsegs = GrWangsFormula::conic(kTolerance, pts, w); // Because the Gr version may implement the math differently for performance, @@ -493,7 +493,7 @@ // Ensure using transformations gives the same result as pre-transforming all points. DEF_TEST(WangsFormula_conic_vectorXforms, r) { - constexpr static float kTolerance = 1.f / kIntolerance; + constexpr static float kTolerance = 1.f / kPrecision; auto check_conic_with_transform = [&](const SkPoint* pts, float w, const SkMatrix& m) { SkPoint ptsXformed[3];