ccpr: Cull extremely thin triangles
When triangles get too thin it's possible for FP round-off error to
actually give us the wrong winding direction, causing rendering
artifacts. This change also allows us to unblacklist ANGLE.
Bug: skia:7805
Bug: skia:7820
Change-Id: Ibaa0f033eba625d720e3a594c4515d8264cc413d
Reviewed-on: https://skia-review.googlesource.com/123262
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
index d38db27..75d0667 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
@@ -44,6 +44,36 @@
GrGLSLVarying fCoverages;
};
+void GrCCCoverageProcessor::Shader::CalcWind(const GrCCCoverageProcessor& proc,
+ GrGLSLVertexGeoBuilder* s, const char* pts,
+ const char* outputWind) {
+ if (3 == proc.numInputPoints()) {
+ s->codeAppendf("float2 a = %s[0] - %s[1], "
+ "b = %s[0] - %s[2];", pts, pts, pts, pts);
+ } else {
+ // All inputs are convex, so it's sufficient to just average the middle two input points.
+ SkASSERT(4 == proc.numInputPoints());
+ s->codeAppendf("float2 p12 = (%s[1] + %s[2]) * .5;", pts, pts);
+ s->codeAppendf("float2 a = %s[0] - p12, "
+ "b = %s[0] - %s[3];", pts, pts, pts);
+ }
+
+ s->codeAppend ("float area_x2 = determinant(float2x2(a, b));");
+ if (proc.isTriangles()) {
+ // We cull extremely thin triangles by zeroing wind. When a triangle gets too thin it's
+ // possible for FP round-off error to actually give us the wrong winding direction, causing
+ // rendering artifacts. The criteria we choose is "height <~ 1/1024". So we drop a triangle
+ // if the max effect it can have on any single pixel is <~ 1/1024, or 1/4 of a bit in 8888.
+ s->codeAppend ("float2 bbox_size = max(abs(a), abs(b));");
+ s->codeAppend ("float basewidth = max(bbox_size.x + bbox_size.y, 1);");
+ s->codeAppendf("%s = (abs(area_x2 * 1024) > basewidth) ? sign(area_x2) : 0;", outputWind);
+ } else {
+ // We already converted nearly-flat curves to lines on the CPU, so no need to worry about
+ // thin curve hulls at this point.
+ s->codeAppendf("%s = sign(area_x2);", outputWind);
+ }
+}
+
void GrCCCoverageProcessor::Shader::EmitEdgeDistanceEquation(GrGLSLVertexGeoBuilder* s,
const char* leftPt,
const char* rightPt,