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>
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
index c44d464..aac16af 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 @@
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 @@
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 @@
: 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,