aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gn/gpu.gni1
-rw-r--r--src/gpu/ccpr/GrCCCoverageProcessor.cpp55
-rw-r--r--src/gpu/ccpr/GrCCCoverageProcessor.h18
-rw-r--r--src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp99
-rw-r--r--src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp71
-rw-r--r--src/gpu/ccpr/GrCCCubicShader.cpp40
-rw-r--r--src/gpu/ccpr/GrCCCubicShader.h9
-rw-r--r--src/gpu/ccpr/GrCCQuadraticShader.cpp61
-rw-r--r--src/gpu/ccpr/GrCCQuadraticShader.h12
-rw-r--r--src/gpu/ccpr/GrCCTriangleShader.h46
-rw-r--r--src/gpu/glsl/GrGLSLShaderBuilder.h1
11 files changed, 220 insertions, 193 deletions
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 6aa950fc11..b3f4eb1680 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -314,7 +314,6 @@ skia_gpu_sources = [
"$_src/gpu/ccpr/GrCCPathProcessor.h",
"$_src/gpu/ccpr/GrCCQuadraticShader.cpp",
"$_src/gpu/ccpr/GrCCQuadraticShader.h",
- "$_src/gpu/ccpr/GrCCTriangleShader.h",
"$_src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp",
"$_src/gpu/ccpr/GrCoverageCountingPathRenderer.h",
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
index c44d464826..aac16afe90 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
@@ -12,20 +12,36 @@
#include "SkMakeUnique.h"
#include "ccpr/GrCCCubicShader.h"
#include "ccpr/GrCCQuadraticShader.h"
-#include "ccpr/GrCCTriangleShader.h"
#include "glsl/GrGLSLVertexGeoBuilder.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLVertexGeoBuilder.h"
-void GrCCCoverageProcessor::Shader::emitFragmentCode(const GrCCCoverageProcessor& proc,
- GrGLSLFPFragmentBuilder* f,
- const char* skOutputColor,
- const char* skOutputCoverage) const {
- f->codeAppendf("half coverage = 0;");
- this->onEmitFragmentCode(f, "coverage");
- f->codeAppendf("%s.a = coverage;", skOutputColor);
- f->codeAppendf("%s = half4(1);", skOutputCoverage);
-}
+class GrCCCoverageProcessor::TriangleShader : public GrCCCoverageProcessor::Shader {
+ void onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, GrGLSLVarying::Scope scope,
+ SkString* code, const char* position, const char* coverage,
+ const char* cornerCoverage) override {
+ if (!cornerCoverage) {
+ fCoverages.reset(kHalf_GrSLType, scope);
+ varyingHandler->addVarying("coverage", &fCoverages);
+ code->appendf("%s = %s;", OutName(fCoverages), coverage);
+ } else {
+ fCoverages.reset(kHalf3_GrSLType, scope);
+ varyingHandler->addVarying("coverages", &fCoverages);
+ code->appendf("%s = half3(%s, %s);", OutName(fCoverages), coverage, cornerCoverage);
+ }
+ }
+
+ void onEmitFragmentCode(GrGLSLFPFragmentBuilder* f, const char* outputCoverage) const override {
+ if (kHalf_GrSLType == fCoverages.type()) {
+ f->codeAppendf("%s = %s;", outputCoverage, fCoverages.fsIn());
+ } else {
+ f->codeAppendf("%s = %s.z * %s.y + %s.x;",
+ outputCoverage, fCoverages.fsIn(), fCoverages.fsIn(), fCoverages.fsIn());
+ }
+ }
+
+ GrGLSLVarying fCoverages;
+};
void GrCCCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLVertexGeoBuilder* s,
const char* leftPt,
@@ -92,10 +108,9 @@ void GrCCCoverageProcessor::Shader::CalcEdgeCoveragesAtBloatVertices(GrGLSLVerte
s->codeAppendf("}");
}
-void GrCCCoverageProcessor::Shader::CalcCornerCoverageAttenuation(GrGLSLVertexGeoBuilder* s,
- const char* leftDir,
- const char* rightDir,
- const char* outputAttenuation) {
+void GrCCCoverageProcessor::Shader::CalcCornerAttenuation(GrGLSLVertexGeoBuilder* s,
+ const char* leftDir, const char* rightDir,
+ const char* outputAttenuation) {
// obtuseness = cos(corner_angle) if corner_angle > 90 degrees
// 0 if corner_angle <= 90 degrees
s->codeAppendf("half obtuseness = max(dot(%s, %s), 0);", leftDir, rightDir);
@@ -153,7 +168,7 @@ GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createGLSLInstance(const GrShad
std::unique_ptr<Shader> shader;
switch (fPrimitiveType) {
case PrimitiveType::kTriangles:
- shader = skstd::make_unique<GrCCTriangleShader>();
+ shader = skstd::make_unique<TriangleShader>();
break;
case PrimitiveType::kQuadratics:
shader = skstd::make_unique<GrCCQuadraticShader>();
@@ -166,6 +181,16 @@ GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createGLSLInstance(const GrShad
: this->createVSImpl(std::move(shader));
}
+void GrCCCoverageProcessor::Shader::emitFragmentCode(const GrCCCoverageProcessor& proc,
+ GrGLSLFPFragmentBuilder* f,
+ const char* skOutputColor,
+ const char* skOutputCoverage) const {
+ f->codeAppendf("half coverage = 0;");
+ this->onEmitFragmentCode(f, "coverage");
+ f->codeAppendf("%s.a = coverage;", skOutputColor);
+ f->codeAppendf("%s = half4(1);", skOutputCoverage);
+}
+
void GrCCCoverageProcessor::draw(GrOpFlushState* flushState, const GrPipeline& pipeline,
const GrMesh meshes[],
const GrPipeline::DynamicState dynamicStates[], int meshCount,
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.h b/src/gpu/ccpr/GrCCCoverageProcessor.h
index 8824646a05..9b83fc9275 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.h
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.h
@@ -126,10 +126,9 @@ public:
void emitVaryings(GrGLSLVaryingHandler* varyingHandler, GrGLSLVarying::Scope scope,
SkString* code, const char* position, const char* coverage,
- const char* attenuatedCoverage) {
+ const char* cornerCoverage) {
SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope);
- this->onEmitVaryings(varyingHandler, scope, code, position, coverage,
- attenuatedCoverage);
+ this->onEmitVaryings(varyingHandler, scope, code, position, coverage, cornerCoverage);
}
void emitFragmentCode(const GrCCCoverageProcessor&, GrGLSLFPFragmentBuilder*,
@@ -163,9 +162,8 @@ public:
// regular (linearly-interpolated) coverage. This function calculates the attenuation value
// to use in the single, outermost vertex. The remaining three vertices of the corner box
// all use an attenuation value of 1.
- static void CalcCornerCoverageAttenuation(GrGLSLVertexGeoBuilder*, const char* leftDir,
- const char* rightDir,
- const char* outputAttenuation);
+ static void CalcCornerAttenuation(GrGLSLVertexGeoBuilder*, const char* leftDir,
+ const char* rightDir, const char* outputAttenuation);
virtual ~Shader() {}
@@ -177,7 +175,7 @@ public:
// 'coverage' will only be +1 or -1 on curves.
virtual void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
const char* position, const char* coverage,
- const char* attenuatedCoverage) = 0;
+ const char* cornerCoverage) = 0;
// Emits the fragment code that calculates a pixel's signed coverage value.
virtual void onEmitFragmentCode(GrGLSLFPFragmentBuilder*,
@@ -190,15 +188,19 @@ public:
SkASSERT(Scope::kVertToGeo != varying.scope());
return Scope::kGeoToFrag == varying.scope() ? varying.gsOut() : varying.vsOut();
}
+
+ // Our friendship with GrGLSLShaderBuilder does not propogate to subclasses.
+ inline static SkString& AccessCodeString(GrGLSLShaderBuilder* s) { return s->code(); }
};
+private:
class GSImpl;
class GSTriangleHullImpl;
class GSCurveHullImpl;
class GSCornerImpl;
class VSImpl;
+ class TriangleShader;
-private:
// Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't
// accidentally bleed into neighbor pixels.
static constexpr float kAABloatRadius = 0.491111f;
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);
}
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp b/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
index 7af1a739fc..a63b37e19e 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
@@ -369,22 +369,18 @@ void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs)
v->codeAppend ("float2 vertex = corner + bloatdir * bloat;");
gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
- v->codeAppend ("half left_coverage; {");
- Shader::CalcEdgeCoverageAtBloatVertex(v, "left", "corner", "bloatdir", "left_coverage");
- v->codeAppend ("}");
-
- v->codeAppend ("half right_coverage; {");
- Shader::CalcEdgeCoverageAtBloatVertex(v, "corner", "right", "bloatdir", "right_coverage");
- v->codeAppend ("}");
-
- v->codeAppend ("half attenuation; {");
- Shader::CalcCornerCoverageAttenuation(v, "leftdir", "rightdir", "attenuation");
- v->codeAppend ("}");
-
// Hulls have a coverage of +1 all around.
v->codeAppend ("half coverage = +1;");
if (3 == fNumSides) {
+ v->codeAppend ("half left_coverage; {");
+ Shader::CalcEdgeCoverageAtBloatVertex(v, "left", "corner", "bloatdir", "left_coverage");
+ v->codeAppend ("}");
+
+ v->codeAppend ("half right_coverage; {");
+ Shader::CalcEdgeCoverageAtBloatVertex(v, "corner", "right", "bloatdir", "right_coverage");
+ v->codeAppend ("}");
+
v->codeAppendf("if (0 != (%s & %i)) {", // Are we an edge?
proc.getAttrib(kAttribIdx_VertexData).fName, kVertexData_IsEdgeBit);
v->codeAppend ( "coverage = left_coverage;");
@@ -397,39 +393,52 @@ void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs)
v->codeAppend ("}");
}
- // Corner boxes require attenuation.
- v->codeAppend ("half2 attenuated_coverage = half2(0, 1);");
+ // Non-corner geometry should have zero effect from corner coverage.
+ v->codeAppend ("half2 corner_coverage = half2(0);");
v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner?
proc.getAttrib(kAttribIdx_VertexData).fName, kVertexData_IsCornerBit);
// We use coverage=-1 to erase what the hull geometry wrote.
+ //
+ // In the context of curves, this effectively means "wind = -wind" and
+ // causes the Shader to erase what it had written previously for the hull.
+ //
+ // For triangles it just erases the "+1" value written by the hull geometry.
v->codeAppend ( "coverage = -1;");
if (3 == fNumSides) {
// Triangle corners also have to erase what the edge geometry wrote.
v->codeAppend ("coverage -= left_coverage + right_coverage;");
}
- // The x and y components of "attenuated_coverage" are multiplied
- // together by the fragment shader. They ramp to 0 with attenuation in
- // the diagonal that points out of the corner, and linearly from
- // left-edge coverage to right in the opposite diagonal.
- // bloatidx=0 is the outermost vertex; the one that has attenuation.
- v->codeAppend ( "attenuated_coverage = (0 == bloatidx)"
- "? half2(0, attenuation) : half2(1);");
- v->codeAppend ( "if (1 == bloatidx || 2 == bloatidx) {");
- v->codeAppend ( "attenuated_coverage.x += right_coverage;");
- v->codeAppend ( "}");
- v->codeAppend ( "if (bloatidx >= 2) {");
- v->codeAppend ( "attenuated_coverage.x += left_coverage;");
+
+ // Corner boxes require attenuated coverage.
+ v->codeAppend ( "half attenuation; {");
+ Shader::CalcCornerAttenuation(v, "leftdir", "rightdir", "attenuation");
v->codeAppend ( "}");
+
+ // Attenuate corner coverage towards the outermost vertex (where bloatidx=0).
+ // This is all that curves need: At each vertex of the corner box, the curve
+ // 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.
+ v->codeAppend ( "corner_coverage = (0 == bloatidx) ? half2(0, attenuation) : half2(1);");
+
+ if (3 == fNumSides) {
+ // For triangles we also provide the actual coverage values at each vertex of
+ // the corner box.
+ v->codeAppend ("if (1 == bloatidx || 2 == bloatidx) {");
+ v->codeAppend ( "corner_coverage.x += right_coverage;");
+ v->codeAppend ("}");
+ v->codeAppend ("if (bloatidx >= 2) {");
+ v->codeAppend ( "corner_coverage.x += left_coverage;");
+ v->codeAppend ("}");
+ }
v->codeAppend ("}");
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
- SkString varyingCode;
v->codeAppend ("coverage *= wind;");
- v->codeAppend ("attenuated_coverage.x *= wind;");
- fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &varyingCode,
- gpArgs->fPositionVar.c_str(), "coverage", "attenuated_coverage");
- v->codeAppend(varyingCode.c_str());
+ v->codeAppend ("corner_coverage.x *= wind;");
+ fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &v->code(),
+ gpArgs->fPositionVar.c_str(), "coverage", "corner_coverage");
varyingHandler->emitAttributes(proc);
SkASSERT(!args.fFPCoordTransformHandler->nextCoordTransform());
diff --git a/src/gpu/ccpr/GrCCCubicShader.cpp b/src/gpu/ccpr/GrCCCubicShader.cpp
index c5fefdd78e..4c9485eba0 100644
--- a/src/gpu/ccpr/GrCCCubicShader.cpp
+++ b/src/gpu/ccpr/GrCCCubicShader.cpp
@@ -99,16 +99,16 @@ void GrCCCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts,
void GrCCCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, SkString* code,
const char* position, const char* coverage,
- const char* attenuatedCoverage) {
- fKLMD.reset(kFloat4_GrSLType, scope);
- varyingHandler->addVarying("klmd", &fKLMD);
+ const char* cornerCoverage) {
+ fKLM_fEdge.reset(kFloat4_GrSLType, scope);
+ varyingHandler->addVarying("klm_and_edge", &fKLM_fEdge);
code->appendf("float3 klm = float3(%s, 1) * %s;", position, fKLMMatrix.c_str());
// We give L & M both the same sign as wind, in order to pass this value to the fragment shader.
// (Cubics are pre-chopped such that L & M do not change sign within any individual segment.)
code->appendf("%s.xyz = klm * float3(1, %s, %s);",
- OutName(fKLMD), coverage, coverage); // coverage == wind on curves.
+ OutName(fKLM_fEdge), coverage, coverage); // coverage == wind on curves.
code->appendf("%s.w = dot(float3(%s, 1), %s);", // Flat edge opposite the curve.
- OutName(fKLMD), position, fEdgeDistanceEquation.c_str());
+ OutName(fKLM_fEdge), position, fEdgeDistanceEquation.c_str());
fGradMatrix.reset(kFloat2x2_GrSLType, scope);
varyingHandler->addVarying("grad_matrix", &fGradMatrix);
@@ -117,28 +117,27 @@ void GrCCCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
code->appendf("%s[1] = -2*bloat * (klm[1] * %s[2].xy + klm[2] * %s[1].xy);",
OutName(fGradMatrix), fKLMMatrix.c_str(), fKLMMatrix.c_str());
- if (attenuatedCoverage) {
+ if (cornerCoverage) {
+ code->appendf("half hull_coverage; {");
+ this->calcHullCoverage(code, OutName(fKLM_fEdge), OutName(fGradMatrix), "hull_coverage");
+ code->appendf("}");
fCornerCoverage.reset(kHalf2_GrSLType, scope);
varyingHandler->addVarying("corner_coverage", &fCornerCoverage);
- code->appendf("%s = %s;", // Attenuated corner coverage.
- OutName(fCornerCoverage), attenuatedCoverage);
+ code->appendf("%s = half2(hull_coverage, 1) * %s;",
+ OutName(fCornerCoverage), cornerCoverage);
}
}
void GrCCCubicShader::onEmitFragmentCode(GrGLSLFPFragmentBuilder* f,
const char* outputCoverage) const {
- f->codeAppendf("float k = %s.x, l = %s.y, m = %s.z;", fKLMD.fsIn(), fKLMD.fsIn(), fKLMD.fsIn());
- f->codeAppend ("float f = k*k*k - l*m;");
- f->codeAppendf("float2 grad = %s * float2(k, 1);", fGradMatrix.fsIn());
- f->codeAppend ("float fwidth = abs(grad.x) + abs(grad.y);");
- f->codeAppendf("%s = clamp(0.5 - f/fwidth, 0, 1);", outputCoverage);
+ this->calcHullCoverage(&AccessCodeString(f), fKLM_fEdge.fsIn(), fGradMatrix.fsIn(),
+ outputCoverage);
- f->codeAppendf("half d = min(%s.w, 0);", fKLMD.fsIn()); // Flat edge opposite the curve.
// Wind is the sign of both L and/or M. Take the sign of whichever has the larger magnitude.
// (In reality, either would be fine because we chop cubics with more than a half pixel of
// padding around the L & M lines, so neither should approach zero.)
f->codeAppend ("half wind = sign(l + m);");
- f->codeAppendf("%s = (%s + d) * wind;", outputCoverage, outputCoverage);
+ f->codeAppendf("%s *= wind;", outputCoverage);
if (fCornerCoverage.fsIn()) {
f->codeAppendf("%s = %s.x * %s.y + %s;", // Attenuated corner coverage.
@@ -146,3 +145,14 @@ void GrCCCubicShader::onEmitFragmentCode(GrGLSLFPFragmentBuilder* f,
outputCoverage);
}
}
+
+void GrCCCubicShader::calcHullCoverage(SkString* code, const char* klmAndEdge,
+ const char* gradMatrix, const char* outputCoverage) const {
+ code->appendf("float k = %s.x, l = %s.y, m = %s.z;", klmAndEdge, klmAndEdge, klmAndEdge);
+ code->append ("float f = k*k*k - l*m;");
+ code->appendf("float2 grad = %s * float2(k, 1);", gradMatrix);
+ code->append ("float fwidth = abs(grad.x) + abs(grad.y);");
+ code->appendf("%s = min(0.5 - f/fwidth, 1);", outputCoverage); // Curve coverage.
+ code->appendf("half d = min(%s.w, 0);", klmAndEdge); // Flat edge opposite the curve.
+ code->appendf("%s = max(%s + d, 0);", outputCoverage, outputCoverage); // Total hull coverage.
+}
diff --git a/src/gpu/ccpr/GrCCCubicShader.h b/src/gpu/ccpr/GrCCCubicShader.h
index 39ca55fd9e..24558804a6 100644
--- a/src/gpu/ccpr/GrCCCubicShader.h
+++ b/src/gpu/ccpr/GrCCCubicShader.h
@@ -22,18 +22,23 @@
* (Use GrCCGeometry::cubicTo().)
*/
class GrCCCubicShader : public GrCCCoverageProcessor::Shader {
+public:
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* wind,
const char** tighterHull) const override;
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
const char* position, const char* coverage,
- const char* attenuatedCoverage) override;
+ const char* cornerCoverage) override;
void onEmitFragmentCode(GrGLSLFPFragmentBuilder*, const char* outputCoverage) const override;
+private:
+ void calcHullCoverage(SkString* code, const char* klmAndEdge, const char* gradMatrix,
+ const char* outputCoverage) const;
+
const GrShaderVar fKLMMatrix{"klm_matrix", kFloat3x3_GrSLType};
const GrShaderVar fEdgeDistanceEquation{"edge_distance_equation", kFloat3_GrSLType};
- GrGLSLVarying fKLMD;
+ GrGLSLVarying fKLM_fEdge;
GrGLSLVarying fGradMatrix;
GrGLSLVarying fCornerCoverage;
};
diff --git a/src/gpu/ccpr/GrCCQuadraticShader.cpp b/src/gpu/ccpr/GrCCQuadraticShader.cpp
index 236c407ade..2398282755 100644
--- a/src/gpu/ccpr/GrCCQuadraticShader.cpp
+++ b/src/gpu/ccpr/GrCCQuadraticShader.cpp
@@ -48,40 +48,51 @@ void GrCCQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* p
void GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
GrGLSLVarying::Scope scope, SkString* code,
const char* position, const char* coverage,
- const char* attenuatedCoverage) {
- fCoord.reset(kFloat4_GrSLType, scope);
- varyingHandler->addVarying("coord", &fCoord);
+ const char* cornerCoverage) {
+ fCoord_fGrad.reset(kFloat4_GrSLType, scope);
+ varyingHandler->addVarying("coord_and_grad", &fCoord_fGrad);
code->appendf("%s.xy = %s * (%s - %s);", // Quadratic coords.
- OutName(fCoord), fQCoordMatrix.c_str(), position, fQCoord0.c_str());
+ OutName(fCoord_fGrad), fQCoordMatrix.c_str(), position, fQCoord0.c_str());
code->appendf("%s.zw = 2*bloat * float2(2 * %s.x, -1) * %s;", // Gradient.
- OutName(fCoord), OutName(fCoord), fQCoordMatrix.c_str());
+ OutName(fCoord_fGrad), OutName(fCoord_fGrad), fQCoordMatrix.c_str());
// Coverages need full precision since distance to the opposite edge can be large.
- fCoverages.reset(attenuatedCoverage ? kFloat4_GrSLType : kFloat2_GrSLType, scope);
- varyingHandler->addVarying("coverages", &fCoverages);
- code->appendf("%s.x = dot(%s, float3(%s, 1));", // Distance to flat edge opposite the curve.
- OutName(fCoverages), fEdgeDistanceEquation.c_str(), position);
- code->appendf("%s.y = %s;", OutName(fCoverages), coverage); // Wind.
- if (attenuatedCoverage) {
- code->appendf("%s.zw = %s;", // Attenuated corner coverage.
- OutName(fCoverages), attenuatedCoverage);
+ fEdge_fWind_fCorner.reset(cornerCoverage ? kFloat4_GrSLType : kFloat2_GrSLType, scope);
+ varyingHandler->addVarying("edge_and_wind_and_corner", &fEdge_fWind_fCorner);
+ code->appendf("float edge = dot(%s, float3(%s, 1));", // Distance to flat opposite edge.
+ fEdgeDistanceEquation.c_str(), position);
+ code->appendf("%s.x = edge;", OutName(fEdge_fWind_fCorner));
+ code->appendf("%s.y = %s;", OutName(fEdge_fWind_fCorner), coverage); // coverage == wind.
+
+ if (cornerCoverage) {
+ code->appendf("half hull_coverage;");
+ this->calcHullCoverage(code, OutName(fCoord_fGrad), "edge", "hull_coverage");
+ code->appendf("%s.zw = half2(hull_coverage, 1) * %s;",
+ OutName(fEdge_fWind_fCorner), cornerCoverage);
}
}
void GrCCQuadraticShader::onEmitFragmentCode(GrGLSLFPFragmentBuilder* f,
const char* outputCoverage) const {
- f->codeAppendf("float x = %s.x, y = %s.y;", fCoord.fsIn(), fCoord.fsIn());
- f->codeAppend ("float f = x*x - y;");
- f->codeAppendf("float2 grad = %s.zw;", fCoord.fsIn());
- f->codeAppend ("float fwidth = abs(grad.x) + abs(grad.y);");
- f->codeAppendf("%s = clamp(0.5 - f/fwidth, 0, 1);", outputCoverage);
-
- f->codeAppendf("half d = min(%s.x, 0);", fCoverages.fsIn()); // Flat edge opposite the curve.
- f->codeAppendf("half wind = %s.y;", fCoverages.fsIn());
- f->codeAppendf("%s = (%s + d) * wind;", outputCoverage, outputCoverage);
+ this->calcHullCoverage(&AccessCodeString(f), fCoord_fGrad.fsIn(),
+ SkStringPrintf("%s.x", fEdge_fWind_fCorner.fsIn()).c_str(),
+ outputCoverage);
+ f->codeAppendf("%s *= %s.y;", outputCoverage, fEdge_fWind_fCorner.fsIn()); // Wind.
- if (kFloat4_GrSLType == fCoverages.type()) {
- f->codeAppendf("%s = %s.z * %s.w + %s;", // Attenuated corner coverage.
- outputCoverage, fCoverages.fsIn(), fCoverages.fsIn(), outputCoverage);
+ if (kFloat4_GrSLType == fEdge_fWind_fCorner.type()) {
+ f->codeAppendf("%s = %s.z * %s.w + %s;",// Attenuated corner coverage.
+ outputCoverage, fEdge_fWind_fCorner.fsIn(), fEdge_fWind_fCorner.fsIn(),
+ outputCoverage);
}
}
+
+void GrCCQuadraticShader::calcHullCoverage(SkString* code, const char* coordAndGrad,
+ const char* edge, const char* outputCoverage) const {
+ code->appendf("float x = %s.x, y = %s.y;", coordAndGrad, coordAndGrad);
+ code->appendf("float2 grad = %s.zw;", coordAndGrad);
+ code->append ("float f = x*x - y;");
+ code->append ("float fwidth = abs(grad.x) + abs(grad.y);");
+ code->appendf("%s = min(0.5 - f/fwidth, 1);", outputCoverage); // Curve coverage.
+ code->appendf("half d = min(%s, 0);", edge); // Flat edge opposite the curve.
+ code->appendf("%s = max(%s + d, 0);", outputCoverage, outputCoverage); // Total hull coverage.
+}
diff --git a/src/gpu/ccpr/GrCCQuadraticShader.h b/src/gpu/ccpr/GrCCQuadraticShader.h
index 30c5230154..daf9eee1ab 100644
--- a/src/gpu/ccpr/GrCCQuadraticShader.h
+++ b/src/gpu/ccpr/GrCCQuadraticShader.h
@@ -21,21 +21,25 @@
* (Use GrCCGeometry::quadraticTo().)
*/
class GrCCQuadraticShader : public GrCCCoverageProcessor::Shader {
-protected:
+public:
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* wind,
const char** tighterHull) const override;
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
const char* position, const char* coverage,
- const char* attenuatedCoverage) override;
+ const char* cornerCoverage) override;
void onEmitFragmentCode(GrGLSLFPFragmentBuilder*, const char* outputCoverage) const override;
+private:
+ void calcHullCoverage(SkString* code, const char* coordAndGrad, const char* d,
+ const char* outputCoverage) const;
+
const GrShaderVar fQCoordMatrix{"qcoord_matrix", kFloat2x2_GrSLType};
const GrShaderVar fQCoord0{"qcoord0", kFloat2_GrSLType};
const GrShaderVar fEdgeDistanceEquation{"edge_distance_equation", kFloat3_GrSLType};
- GrGLSLVarying fCoord;
- GrGLSLVarying fCoverages;
+ GrGLSLVarying fCoord_fGrad;
+ GrGLSLVarying fEdge_fWind_fCorner;
};
#endif
diff --git a/src/gpu/ccpr/GrCCTriangleShader.h b/src/gpu/ccpr/GrCCTriangleShader.h
deleted file mode 100644
index f9af13c3be..0000000000
--- a/src/gpu/ccpr/GrCCTriangleShader.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrCCTriangleShader_DEFINED
-#define GrCCTriangleShader_DEFINED
-
-#include "ccpr/GrCCCoverageProcessor.h"
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-
-/**
- * This class renders AA triangles. It relies on the coverage processor to set up the geometry and
- * provide coverage values at each vertex, then simply interpolates these values in the fragment
- * shader.
- */
-class GrCCTriangleShader : public GrCCCoverageProcessor::Shader {
- void onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, GrGLSLVarying::Scope scope,
- SkString* code, const char* position, const char* coverage,
- const char* attenuatedCoverage) override {
- if (!attenuatedCoverage) {
- fCoverages.reset(kHalf_GrSLType, scope);
- varyingHandler->addVarying("coverage", &fCoverages);
- code->appendf("%s = %s;", OutName(fCoverages), coverage);
- } else {
- fCoverages.reset(kHalf3_GrSLType, scope);
- varyingHandler->addVarying("coverages", &fCoverages);
- code->appendf("%s = half3(%s, %s);", OutName(fCoverages), attenuatedCoverage, coverage);
- }
- }
-
- void onEmitFragmentCode(GrGLSLFPFragmentBuilder* f, const char* outputCoverage) const override {
- if (kHalf_GrSLType == fCoverages.type()) {
- f->codeAppendf("%s = %s;", outputCoverage, fCoverages.fsIn());
- } else {
- f->codeAppendf("%s = %s.x * %s.y + %s.z;",
- outputCoverage, fCoverages.fsIn(), fCoverages.fsIn(), fCoverages.fsIn());
- }
- }
-
- GrGLSLVarying fCoverages;
-};
-
-#endif
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index 8459218059..cfddbfff15 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -250,6 +250,7 @@ protected:
int fCodeIndex;
bool fFinalized;
+ friend class GrCCCoverageProcessor; // to access code().
friend class GrGLSLProgramBuilder;
friend class GrGLProgramBuilder;
friend class GrGLSLVaryingHandler; // to access noperspective interpolation feature.