ccpr: Remove local matrix data from path instances

Uses the built-in local matrix code instead trying to bake it into the
path instance data. If we find a case that can benefit from this type
of optimization in the future, we can use something like a texel
buffer and send in all of the coord transform data -- not just the
local matrix.

Bug: skia:
Change-Id: I194bc9e4f83e588f8aa93a1a4d40097475d84977
Reviewed-on: https://skia-review.googlesource.com/129332
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 719ab7e..93e1c7f 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -479,6 +479,15 @@
     }
 }
 
+GrFragmentProcessor::Iter::Iter(const GrPaint& paint) {
+    for (int i = paint.numCoverageFragmentProcessors() - 1; i >= 0; --i) {
+        fFPStack.push_back(paint.getCoverageFragmentProcessor(i));
+    }
+    for (int i = paint.numColorFragmentProcessors() - 1; i >= 0; --i) {
+        fFPStack.push_back(paint.getColorFragmentProcessor(i));
+    }
+}
+
 const GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
     if (fFPStack.empty()) {
         return nullptr;
diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h
index fa674d5..b875c79 100644
--- a/src/gpu/GrFragmentProcessor.h
+++ b/src/gpu/GrFragmentProcessor.h
@@ -13,6 +13,7 @@
 class GrCoordTransform;
 class GrGLSLFragmentProcessor;
 class GrInvariantOutput;
+class GrPaint;
 class GrPipeline;
 class GrProcessorKeyBuilder;
 class GrShaderCaps;
@@ -191,6 +192,7 @@
     public:
         explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
         explicit Iter(const GrPipeline& pipeline);
+        explicit Iter(const GrPaint&);
         const GrFragmentProcessor* next();
 
     private:
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index d239812..8030485 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -12,12 +12,23 @@
 #include "ccpr/GrCCPerFlushResources.h"
 #include "ccpr/GrCoverageCountingPathRenderer.h"
 
+static bool has_coord_transforms(const GrPaint& paint) {
+    GrFragmentProcessor::Iter iter(paint);
+    while (const GrFragmentProcessor* fp = iter.next()) {
+        if (!fp->coordTransforms().empty()) {
+            return true;
+        }
+    }
+    return false;
+}
+
 GrCCDrawPathsOp::GrCCDrawPathsOp(GrCoverageCountingPathRenderer* ccpr, GrPaint&& paint,
                                  const SkIRect& clipIBounds, const SkMatrix& viewMatrix,
                                  const SkPath& path, const SkRect& devBounds)
         : GrDrawOp(ClassID())
         , fCCPR(ccpr)
         , fSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint))
+        , fViewMatrixIfUsingLocalCoords(has_coord_transforms(paint) ? viewMatrix : SkMatrix::I())
         , fDraws({clipIBounds, viewMatrix, path, paint.getColor(), nullptr})
         , fProcessors(std::move(paint)) {
     SkDEBUGCODE(fCCPR->incrDrawOpCount_debugOnly());
@@ -57,7 +68,8 @@
     SkASSERT(that->fNumDraws);
 
     if (this->getFillType() != that->getFillType() || fSRGBFlags != that->fSRGBFlags ||
-        fProcessors != that->fProcessors) {
+        fProcessors != that->fProcessors ||
+        fViewMatrixIfUsingLocalCoords != that->fViewMatrixIfUsingLocalCoords) {
         return false;
     }
 
@@ -111,14 +123,8 @@
             currentAtlas = atlas;
         }
 
-        const SkMatrix& m = draw.fMatrix;
-        resources->appendDrawPathInstance(
-                devBounds,
-                devBounds45,
-                {{m.getScaleX(), m.getSkewY(), m.getSkewX(), m.getScaleY()}},
-                {{m.getTranslateX(), m.getTranslateY()}},
-                {{atlasOffsetX, atlasOffsetY}},
-                draw.fColor);
+        resources->appendDrawPathInstance() =
+                {devBounds, devBounds45, {{atlasOffsetX, atlasOffsetY}}, draw.fColor};
     }
 
     SkASSERT(resources->pathInstanceCount() == fBaseInstance + fNumDraws - fNumSkippedInstances);
@@ -154,7 +160,8 @@
         }
 
         GrCCPathProcessor pathProc(flushState->resourceProvider(),
-                                   sk_ref_sp(batch.fAtlas->textureProxy()), this->getFillType());
+                                   sk_ref_sp(batch.fAtlas->textureProxy()), this->getFillType(),
+                                   fViewMatrixIfUsingLocalCoords);
         pathProc.drawPaths(flushState, pipeline, resources->indexBuffer(),
                            resources->vertexBuffer(), resources->instanceBuffer(),
                            baseInstance, batch.fEndInstanceIdx, this->bounds());
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.h b/src/gpu/ccpr/GrCCDrawPathsOp.h
index 7722317..3598172 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.h
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.h
@@ -68,6 +68,7 @@
 
     GrCoverageCountingPathRenderer* const fCCPR;
     const uint32_t fSRGBFlags;
+    const SkMatrix fViewMatrixIfUsingLocalCoords;
 
     struct SingleDraw {
         SkIRect fClipIBounds;
diff --git a/src/gpu/ccpr/GrCCPathProcessor.cpp b/src/gpu/ccpr/GrCCPathProcessor.cpp
index 5dacc6a..588e2bc 100644
--- a/src/gpu/ccpr/GrCCPathProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPathProcessor.cpp
@@ -76,15 +76,14 @@
 }
 
 GrCCPathProcessor::GrCCPathProcessor(GrResourceProvider* resourceProvider,
-                                     sk_sp<GrTextureProxy> atlas, SkPath::FillType fillType)
+                                     sk_sp<GrTextureProxy> atlas, SkPath::FillType fillType,
+                                     const SkMatrix& viewMatrixIfUsingLocalCoords)
         : INHERITED(kGrCCPathProcessor_ClassID)
         , fFillType(fillType)
         , fAtlasAccess(std::move(atlas), GrSamplerState::Filter::kNearest,
                        GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag) {
     this->addInstanceAttrib("devbounds", kFloat4_GrVertexAttribType);
     this->addInstanceAttrib("devbounds45", kFloat4_GrVertexAttribType);
-    this->addInstanceAttrib("view_matrix", kFloat4_GrVertexAttribType);
-    this->addInstanceAttrib("view_translate", kFloat2_GrVertexAttribType);
     this->addInstanceAttrib("atlas_offset", kShort2_GrVertexAttribType);
     this->addInstanceAttrib("color", kUByte4_norm_GrVertexAttribType);
 
@@ -92,25 +91,25 @@
              this->getInstanceAttrib(InstanceAttribs::kDevBounds).fOffsetInRecord);
     SkASSERT(offsetof(Instance, fDevBounds45) ==
              this->getInstanceAttrib(InstanceAttribs::kDevBounds45).fOffsetInRecord);
-    SkASSERT(offsetof(Instance, fViewMatrix) ==
-             this->getInstanceAttrib(InstanceAttribs::kViewMatrix).fOffsetInRecord);
-    SkASSERT(offsetof(Instance, fViewTranslate) ==
-             this->getInstanceAttrib(InstanceAttribs::kViewTranslate).fOffsetInRecord);
     SkASSERT(offsetof(Instance, fAtlasOffset) ==
              this->getInstanceAttrib(InstanceAttribs::kAtlasOffset).fOffsetInRecord);
     SkASSERT(offsetof(Instance, fColor) ==
              this->getInstanceAttrib(InstanceAttribs::kColor).fOffsetInRecord);
     SkASSERT(sizeof(Instance) == this->getInstanceStride());
 
-    GR_STATIC_ASSERT(6 == kNumInstanceAttribs);
+    GR_STATIC_ASSERT(4 == kNumInstanceAttribs);
 
     this->addVertexAttrib("edge_norms", kFloat4_GrVertexAttribType);
 
+    if (resourceProvider->caps()->usePrimitiveRestart()) {
+        this->setWillUsePrimitiveRestart();
+    }
+
     fAtlasAccess.instantiate(resourceProvider);
     this->addTextureSampler(&fAtlasAccess);
 
-    if (resourceProvider->caps()->usePrimitiveRestart()) {
-        this->setWillUsePrimitiveRestart();
+    if (!viewMatrixIfUsingLocalCoords.invert(&fLocalMatrix)) {
+        fLocalMatrix.setIdentity();
     }
 }
 
@@ -128,7 +127,7 @@
         const GrCCPathProcessor& proc = primProc.cast<GrCCPathProcessor>();
         pdman.set2f(fAtlasAdjustUniform, 1.0f / proc.atlas()->width(),
                     1.0f / proc.atlas()->height());
-        this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
+        this->setTransformDataHelper(proc.localMatrix(), pdman, &transformIter);
     }
 
     GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform;
@@ -223,15 +222,8 @@
                        texcoord.vsOut(), atlasAdjust, atlasAdjust);
     }
 
-    // Convert to path/local cordinates.
-    v->codeAppendf("float2x2 viewmatrix = float2x2(%s.xy, %s.zw);", // float2x2(float4) busts Intel.
-                   proc.getInstanceAttrib(InstanceAttribs::kViewMatrix).fName,
-                   proc.getInstanceAttrib(InstanceAttribs::kViewMatrix).fName);
-    v->codeAppendf("float2 pathcoord = inverse(viewmatrix) * (octocoord - %s);",
-                   proc.getInstanceAttrib(InstanceAttribs::kViewTranslate).fName);
-
-    this->emitTransforms(v, varyingHandler, uniHandler, GrShaderVar("pathcoord", kFloat2_GrSLType),
-                         args.fFPCoordTransformHandler);
+    this->emitTransforms(v, varyingHandler, uniHandler, GrShaderVar("octocoord", kFloat2_GrSLType),
+                         proc.localMatrix(), args.fFPCoordTransformHandler);
 
     // Fragment shader.
     GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
diff --git a/src/gpu/ccpr/GrCCPathProcessor.h b/src/gpu/ccpr/GrCCPathProcessor.h
index 40b16a4..4789326 100644
--- a/src/gpu/ccpr/GrCCPathProcessor.h
+++ b/src/gpu/ccpr/GrCCPathProcessor.h
@@ -32,8 +32,6 @@
     enum class InstanceAttribs {
         kDevBounds,
         kDevBounds45,
-        kViewMatrix, // FIXME: This causes a lot of duplication. It could move to a texel buffer.
-        kViewTranslate,
         kAtlasOffset,
         kColor
     };
@@ -43,24 +41,24 @@
         SkRect fDevBounds;
         SkRect fDevBounds45; // Bounding box in "| 1  -1 | * devCoords" space.
                              //                  | 1   1 |
-        std::array<float, 4> fViewMatrix;  // {kScaleX, kSkewy, kSkewX, kScaleY}
-        std::array<float, 2> fViewTranslate;
         std::array<int16_t, 2> fAtlasOffset;
         uint32_t fColor;
 
         GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
     };
 
-    GR_STATIC_ASSERT(4 * 16 == sizeof(Instance));
+    GR_STATIC_ASSERT(4 * 10 == sizeof(Instance));
 
     static sk_sp<const GrBuffer> FindVertexBuffer(GrOnFlushResourceProvider*);
     static sk_sp<const GrBuffer> FindIndexBuffer(GrOnFlushResourceProvider*);
 
-    GrCCPathProcessor(GrResourceProvider*, sk_sp<GrTextureProxy> atlas, SkPath::FillType);
+    GrCCPathProcessor(GrResourceProvider*, sk_sp<GrTextureProxy> atlas, SkPath::FillType,
+                      const SkMatrix& viewMatrixIfUsingLocalCoords = SkMatrix::I());
 
     const char* name() const override { return "GrCCPathProcessor"; }
     const GrSurfaceProxy* atlasProxy() const { return fAtlasAccess.proxy(); }
     const GrTexture* atlas() const { return fAtlasAccess.peekTexture(); }
+    const SkMatrix& localMatrix() const { return fLocalMatrix; }
     SkPath::FillType fillType() const { return fFillType; }
     const Attribute& getInstanceAttrib(InstanceAttribs attribID) const {
         const Attribute& attrib = this->getAttrib((int)attribID);
@@ -84,6 +82,7 @@
 private:
     const SkPath::FillType fFillType;
     const TextureSampler fAtlasAccess;
+    SkMatrix fLocalMatrix;
 
     typedef GrGeometryProcessor INHERITED;
 };
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.h b/src/gpu/ccpr/GrCCPerFlushResources.h
index 89ad6ae..7585a7a 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.h
+++ b/src/gpu/ccpr/GrCCPerFlushResources.h
@@ -30,16 +30,10 @@
                                          const SkPath& devPath, const SkIRect& devPathIBounds,
                                          int16_t* atlasOffsetX, int16_t* atlasOffsetY);
 
-    // See GrCCPathProcessor::Instance.
-    int appendDrawPathInstance(const SkRect& devBounds, const SkRect& devBounds45,
-                               const std::array<float, 4>& viewMatrix,
-                               const std::array<float, 2>& viewTranslate,
-                               const std::array<int16_t, 2>& atlasOffset, uint32_t color) {
+    GrCCPathProcessor::Instance& appendDrawPathInstance() {
         SkASSERT(this->isMapped());
         SkASSERT(fPathInstanceCount < fPathInstanceBufferCount);
-        fPathInstanceData[fPathInstanceCount] = {devBounds, devBounds45, viewMatrix, viewTranslate,
-                                                 atlasOffset, color};
-        return fPathInstanceCount++;
+        return fPathInstanceData[fPathInstanceCount++];
     }
     int pathInstanceCount() const { return fPathInstanceCount; }