Coverage counting path renderer
Initial implementation of a GPU path renderer that draws antialiased
paths by counting coverage in an offscreen buffer.
Initially disabled until it has had time to soak.
Bug: skia:
Change-Id: I003d8cfdf8dc62641581b5ea2dc4f0aa00108df6
Reviewed-on: https://skia-review.googlesource.com/21541
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ccpr/GrCCPRTriangleProcessor.h b/src/gpu/ccpr/GrCCPRTriangleProcessor.h
new file mode 100644
index 0000000..1e52d51
--- /dev/null
+++ b/src/gpu/ccpr/GrCCPRTriangleProcessor.h
@@ -0,0 +1,109 @@
+/*
+ * 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 GrCCPRTriangleProcessor_DEFINED
+#define GrCCPRTriangleProcessor_DEFINED
+
+#include "ccpr/GrCCPRCoverageProcessor.h"
+
+/**
+ * This class renders the coverage of triangles.
+ *
+ * Triangles are rendered in three passes:
+ *
+ * Pass 1: Draw the triangle's conservative raster hull with a coverage of 1. (Conservative raster
+ * is drawn by considering 3 pixel size boxes, one centered at each vertex, and drawing the
+ * convex hull of those boxes.)
+ *
+ * Pass 2: Smooth the edges that were over-rendered during Pass 1. Draw the conservative raster of
+ * each edge (i.e. convex hull of two pixel-size boxes at the endpoints), interpolating from
+ * coverage=-1 on the outside edge to coverage=0 on the inside edge.
+ *
+ * Pass 3: Touch up the corner pixels to have the correct coverage.
+ */
+class GrCCPRTriangleProcessor : public GrCCPRCoverageProcessor::PrimitiveProcessor {
+public:
+ GrCCPRTriangleProcessor(CoverageType initialCoverage) : INHERITED(initialCoverage) {}
+
+ void onEmitVertexShader(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*,
+ const TexelBufferHandle& pointsBuffer, const char* atlasOffset,
+ const char* rtAdjust, GrGPArgs*) const override;
+ void emitWind(GrGLSLGeometryBuilder*, const char* rtAdjust, const char* outputWind) const final;
+
+protected:
+ void defineInputVertices(GrGLSLGeometryBuilder*) const;
+
+private:
+ typedef GrCCPRCoverageProcessor::PrimitiveProcessor INHERITED;
+};
+
+class GrCCPRTriangleHullAndEdgeProcessor : public GrCCPRTriangleProcessor {
+public:
+ enum class GeometryType {
+ kHulls,
+ kEdges,
+ kHullsAndEdges
+ };
+
+ GrCCPRTriangleHullAndEdgeProcessor(GeometryType geometryType)
+ : INHERITED(GeometryType::kHulls == geometryType ?
+ CoverageType::kOne : CoverageType::kInterpolated)
+ , fGeometryType(geometryType) {}
+
+ void onEmitGeometryShader(GrGLSLGeometryBuilder*, const char* emitVertexFn, const char* wind,
+ const char* rtAdjust) const override;
+
+private:
+ const GeometryType fGeometryType;
+
+ typedef GrCCPRTriangleProcessor INHERITED;
+};
+
+/**
+ * This pass fixes the corner pixels of a triangle. It erases the (incorrect) coverage that was
+ * written at the corners during the previous hull and edge passes, and then approximates the true
+ * coverage by sampling the triangle with horizontal lines.
+ */
+class GrCCPRTriangleCornerProcessor : public GrCCPRTriangleProcessor {
+public:
+ GrCCPRTriangleCornerProcessor()
+ : INHERITED(CoverageType::kShader)
+ , fEdgeDistance(kVec3f_GrSLType)
+ , fDevCoord(kVec2f_GrSLType)
+ , fNeighbors(kVec4f_GrSLType)
+ , fEdgeDistances(kMat33f_GrSLType)
+ , fCornerIdx(kInt_GrSLType) {}
+
+ void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
+ this->INHERITED::resetVaryings(varyingHandler);
+ varyingHandler->addFlatVarying("edge_distance", &fEdgeDistance, kHigh_GrSLPrecision);
+ varyingHandler->addFlatVarying("devcoord", &fDevCoord, kHigh_GrSLPrecision);
+ varyingHandler->addFlatVarying("neighbors", &fNeighbors, kHigh_GrSLPrecision);
+ varyingHandler->addFlatVarying("edge_distances", &fEdgeDistances, kHigh_GrSLPrecision);
+ varyingHandler->addFlatVarying("corner_idx", &fCornerIdx, kLow_GrSLPrecision);
+ }
+
+ void onEmitVertexShader(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*,
+ const TexelBufferHandle& pointsBuffer, const char* atlasOffset,
+ const char* rtAdjust, GrGPArgs*) const override;
+ void onEmitGeometryShader(GrGLSLGeometryBuilder*, const char* emitVertexFn, const char* wind,
+ const char* rtAdjust) const override;
+ void emitPerVertexGeometryCode(SkString* fnBody, const char* position, const char* coverage,
+ const char* wind) const override;
+ void emitShaderCoverage(GrGLSLFragmentBuilder*, const char* outputCoverage) const override;
+
+private:
+ GrGLSLVertToGeo fEdgeDistance;
+ GrGLSLVertToGeo fDevCoord;
+ GrGLSLGeoToFrag fNeighbors;
+ GrGLSLGeoToFrag fEdgeDistances;
+ GrGLSLGeoToFrag fCornerIdx;
+
+ typedef GrCCPRTriangleProcessor INHERITED;
+};
+
+#endif