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];