aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2018-04-05 18:43:40 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-04-06 15:59:43 +0000
commit4c2393493ad6d5f72eecd1190fee20cce732b959 (patch)
treed72cfd780ec5087ea141e7d9d7290e3424e3f348 /src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp
parent0cfd547b465a3611506dc4c4c0ba973ccb2e7f30 (diff)
ccpr: Make curve corners more seamless
Interpolates the acual curve's local coverage values from the corner box vertices, rather than an approximation based on the tangent. Clamps curve segment total coverage values above 0. This prevents us from using negative coverage (which is obviously wrong) when the curve approximation function is slightly inaccurate. Moves GrCCTriangleShader.h into GrCCCoverageProcessor.cpp. Bug: skia: Change-Id: I95de8e940c1508d4a359f5f802c3a688f2b84094 Reviewed-on: https://skia-review.googlesource.com/119066 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
Diffstat (limited to 'src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp')
-rw-r--r--src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp99
1 files changed, 53 insertions, 46 deletions
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp b/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp
index 0bb34b16a0..4207f85c15 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp
@@ -21,7 +21,6 @@ protected:
GSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
virtual bool hasCoverage() const { return false; }
- virtual bool hasAttenuatedCoverage() const { return false; }
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
FPCoordTransformIter&& transformIter) final {
@@ -81,21 +80,20 @@ protected:
if (this->hasCoverage()) {
coverage = emitArgs.emplace_back("coverage", kHalf_GrSLType).c_str();
}
- const char* attenuatedCoverage = nullptr;
- if (this->hasAttenuatedCoverage()) {
- attenuatedCoverage = emitArgs.emplace_back("attenuated_coverage",
- kHalf2_GrSLType).c_str();
+ const char* cornerCoverage = nullptr;
+ if (GSSubpass::kCorners == proc.fGSSubpass) {
+ cornerCoverage = emitArgs.emplace_back("corner_coverage", kHalf2_GrSLType).c_str();
}
g->emitFunction(kVoid_GrSLType, "emitVertex", emitArgs.count(), emitArgs.begin(), [&]() {
SkString fnBody;
if (coverage) {
fnBody.appendf("%s *= %s;", coverage, wind.c_str());
}
- if (attenuatedCoverage) {
- fnBody.appendf("%s.x *= %s;", attenuatedCoverage, wind.c_str());
+ if (cornerCoverage) {
+ fnBody.appendf("%s.x *= %s;", cornerCoverage, wind.c_str());
}
fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kGeoToFrag, &fnBody,
- position, coverage ? coverage : wind.c_str(), attenuatedCoverage);
+ position, coverage ? coverage : wind.c_str(), cornerCoverage);
g->emitVertex(&fnBody, position, rtAdjust);
return fnBody;
}().c_str(), &emitVertexFn);
@@ -303,7 +301,6 @@ public:
GSCornerImpl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {}
bool hasCoverage() const override { return true; }
- bool hasAttenuatedCoverage() const override { return true; }
void onEmitGeometryShader(const GrCCCoverageProcessor& proc, GrGLSLGeometryBuilder* g,
const GrShaderVar& wind, const char* emitVertexFn) const override {
@@ -334,47 +331,57 @@ public:
"leftdir.y > rightdir.y ? +1 : -1);");
g->codeAppend ("float2 crossbloat = float2(-outbloat.y, +outbloat.x);");
- g->codeAppend ("half2 left_coverages; {");
- Shader::CalcEdgeCoveragesAtBloatVertices(g, "left", "corner", "-outbloat", "-crossbloat",
- "left_coverages");
+ g->codeAppend ("half attenuation; {");
+ Shader::CalcCornerAttenuation(g, "leftdir", "rightdir", "attenuation");
g->codeAppend ("}");
- g->codeAppend ("half2 right_coverages; {");
- Shader::CalcEdgeCoveragesAtBloatVertices(g, "corner", "right", "-outbloat", "crossbloat",
- "right_coverages");
- g->codeAppend ("}");
+ if (isTriangle) {
+ g->codeAppend ("half2 left_coverages; {");
+ Shader::CalcEdgeCoveragesAtBloatVertices(g, "left", "corner", "-outbloat",
+ "-crossbloat", "left_coverages");
+ g->codeAppend ("}");
+
+ g->codeAppend ("half2 right_coverages; {");
+ Shader::CalcEdgeCoveragesAtBloatVertices(g, "corner", "right", "-outbloat",
+ "crossbloat", "right_coverages");
+ g->codeAppend ("}");
+
+ // Emit a corner box. The first coverage argument erases the values that were written
+ // previously by the hull and edge geometry. The second pair are multiplied together by
+ // the fragment shader. They ramp to 0 with attenuation in the direction of outbloat,
+ // and linearly from left-edge coverage to right-edge coverage in the direction of
+ // crossbloat.
+ //
+ // NOTE: Since this is not a linear mapping, it is important that the box's diagonal
+ // shared edge points in the direction of outbloat.
+ g->codeAppendf("%s(corner - crossbloat * bloat, right_coverages[1] - left_coverages[1],"
+ "half2(1 + left_coverages[1], 1));",
+ emitVertexFn);
- g->codeAppend ("half attenuation; {");
- Shader::CalcCornerCoverageAttenuation(g, "leftdir", "rightdir", "attenuation");
- g->codeAppend ("}");
+ g->codeAppendf("%s(corner + outbloat * bloat, "
+ "1 + left_coverages[0] + right_coverages[0], half2(0, attenuation));",
+ emitVertexFn);
- // Emit a corner box. The first coverage argument erases the values that were written
- // previously by the hull and edge geometry. The second pair are multiplied together by the
- // fragment shader. They ramp to 0 with attenuation in the direction of outbloat, and
- // linearly from left-edge coverage to right-edge coverage in the direction of crossbloat.
- //
- // NOTE: Since this is not a linear mapping, it is important that the box's diagonal shared
- // edge points in the direction of outbloat.
- g->codeAppendf("%s(corner - crossbloat * bloat, %s, half2(1 + left_coverages[1], 1));",
- emitVertexFn,
- // Erase what the hull wrote previously.
- isTriangle ? "right_coverages[1] - left_coverages[1]" : "-1");
-
- g->codeAppendf("%s(corner + outbloat * bloat, %s, half2(0, attenuation));",
- emitVertexFn,
- // Erase what the hull wrote previously.
- isTriangle ? "1 + left_coverages[0] + right_coverages[0]" : "-1");
-
- g->codeAppendf("%s(corner - outbloat * bloat, %s, "
- "half2(1 + left_coverages[0] + right_coverages[0], 1));",
- emitVertexFn,
- // Erase what the hull wrote previously.
- isTriangle ? "-1 - left_coverages[0] - right_coverages[0]" : "-1");
-
- g->codeAppendf("%s(corner + crossbloat * bloat, %s, half2(1 + right_coverages[1], 1));",
- emitVertexFn,
- // Erase what the hull wrote previously.
- isTriangle ? "left_coverages[1] - right_coverages[1]" : "-1");
+ g->codeAppendf("%s(corner - outbloat * bloat, "
+ "-1 - left_coverages[0] - right_coverages[0], "
+ "half2(1 + left_coverages[0] + right_coverages[0], 1));",
+ emitVertexFn);
+
+ g->codeAppendf("%s(corner + crossbloat * bloat, left_coverages[1] - right_coverages[1],"
+ "half2(1 + right_coverages[1], 1));",
+ emitVertexFn);
+ } else {
+ // Curves are simpler. The first coverage value of -1 means "wind = -wind", and causes
+ // the Shader to erase what it had written previously for the hull. Then, at each vertex
+ // of the corner box, the Shader will calculate the curve's local coverage value,
+ // interpolate it alongside our attenuation parameter, and multiply the two together for
+ // a final coverage value.
+ g->codeAppendf("%s(corner - crossbloat * bloat, -1, half2(1));", emitVertexFn);
+ g->codeAppendf("%s(corner + outbloat * bloat, -1, half2(0, attenuation));",
+ emitVertexFn);
+ g->codeAppendf("%s(corner - outbloat * bloat, -1, half2(1));", emitVertexFn);
+ g->codeAppendf("%s(corner + crossbloat * bloat, -1, half2(1));", emitVertexFn);
+ }
g->configure(InputType::kLines, OutputType::kTriangleStrip, 4, isTriangle ? 3 : 2);
}