Implement per-edge aa as extra vertices instead of interpolated edge distances

It appears that using vertex interpolation to handle coverage, instead of
evaluating per-pixel, helps significantly on Adreno GPUs. Will see after
perf comes in if it's worth having both strategies and switch depending
on the platform.

Bug: chromium:914833
Bug: b/120946388
Change-Id: Ie33417938a72aa14eba4e22711e0abf97fcfbc7d
Reviewed-on: https://skia-review.googlesource.com/c/179255
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.h b/src/gpu/ops/GrQuadPerEdgeAA.h
index 68e798c..232a10d 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.h
+++ b/src/gpu/ops/GrQuadPerEdgeAA.h
@@ -10,6 +10,7 @@
 
 #include "GrColor.h"
 #include "GrGeometryProcessor.h"
+#include "GrMeshDrawOp.h"
 #include "GrQuad.h"
 #include "GrSamplerState.h"
 #include "GrTypesPriv.h"
@@ -32,13 +33,14 @@
     struct VertexSpec {
     public:
         VertexSpec(GrQuadType deviceQuadType, ColorType colorType, GrQuadType localQuadType,
-                   bool hasLocalCoords, Domain domain, GrAAType aa)
+                   bool hasLocalCoords, Domain domain, GrAAType aa, bool alphaAsCoverage)
                 : fDeviceQuadType(static_cast<unsigned>(deviceQuadType))
                 , fLocalQuadType(static_cast<unsigned>(localQuadType))
                 , fHasLocalCoords(hasLocalCoords)
                 , fColorType(static_cast<unsigned>(colorType))
                 , fHasDomain(static_cast<unsigned>(domain))
-                , fUsesCoverageAA(aa == GrAAType::kCoverage) { }
+                , fUsesCoverageAA(aa == GrAAType::kCoverage)
+                , fCompatibleWithAlphaAsCoverage(alphaAsCoverage) { }
 
         GrQuadType deviceQuadType() const { return static_cast<GrQuadType>(fDeviceQuadType); }
         GrQuadType localQuadType() const { return static_cast<GrQuadType>(fLocalQuadType); }
@@ -47,12 +49,14 @@
         bool hasVertexColors() const { return ColorType::kNone != this->colorType(); }
         bool hasDomain() const { return fHasDomain; }
         bool usesCoverageAA() const { return fUsesCoverageAA; }
+        bool compatibleWithAlphaAsCoverage() const { return fCompatibleWithAlphaAsCoverage; }
 
         // Will always be 2 or 3
         int deviceDimensionality() const;
         // Will always be 0 if hasLocalCoords is false, otherwise will be 2 or 3
         int localDimensionality() const;
 
+        int verticesPerQuad() const { return fUsesCoverageAA ? 8 : 4; }
     private:
         static_assert(kGrQuadTypeCount <= 4, "GrQuadType doesn't fit in 2 bits");
         static_assert(kColorTypeCount <= 4, "Color doesn't fit in 2 bits");
@@ -63,6 +67,7 @@
         unsigned fColorType : 2;
         unsigned fHasDomain: 1;
         unsigned fUsesCoverageAA: 1;
+        unsigned fCompatibleWithAlphaAsCoverage: 1;
     };
 
     sk_sp<GrGeometryProcessor> MakeProcessor(const VertexSpec& spec);
@@ -82,6 +87,16 @@
                      const SkPMColor4f& color, const GrPerspQuad& localQuad, const SkRect& domain,
                      GrQuadAAFlags aa);
 
+    // The mesh will have its index data configured to meet the expectations of the Tessellate()
+    // function, but it the calling code must handle filling a vertex buffer via Tessellate() and
+    // then assigning it to the returned mesh.
+    //
+    // Returns false if the index data could not be allocated.
+    bool ConfigureMeshIndices(GrMeshDrawOp::Target* target, GrMesh* mesh, const VertexSpec& spec,
+                              int quadCount);
+
+    static constexpr int kNumAAQuadsInIndexBuffer = 512;
+
 } // namespace GrQuadPerEdgeAA
 
 #endif // GrQuadPerEdgeAA_DEFINED