Add "meshCount" to GrProgramInfo

This improves the encapsulation of the GrProgramInfo class.

Bug: skia:9455
Change-Id: Ic241ba4a2c2edea3e774522065371e5ed8cc2da3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/247438
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/gm/clockwise.cpp b/gm/clockwise.cpp
index ab72288..78b1da8 100644
--- a/gm/clockwise.cpp
+++ b/gm/clockwise.cpp
@@ -173,7 +173,7 @@
                                   flushState->drawOpArgs().origin(),
                                   pipeline,
                                   primProc,
-                                  nullptr, nullptr);
+                                  nullptr, nullptr, 0);
 
         flushState->opsRenderPass()->draw(programInfo, &mesh, 1, SkRect::MakeXYWH(0, fY, 100, 100));
     }
diff --git a/gm/fwidth_squircle.cpp b/gm/fwidth_squircle.cpp
index e75891e..cc51cce 100644
--- a/gm/fwidth_squircle.cpp
+++ b/gm/fwidth_squircle.cpp
@@ -180,7 +180,7 @@
                                   flushState->drawOpArgs().origin(),
                                   pipeline,
                                   primProc,
-                                  nullptr, nullptr);
+                                  nullptr, nullptr, 0);
 
         GrMesh mesh(GrPrimitiveType::kTriangleStrip);
         mesh.setNonIndexedNonInstanced(4);
diff --git a/gm/samplelocations.cpp b/gm/samplelocations.cpp
index c7cc73c..7e48f15 100644
--- a/gm/samplelocations.cpp
+++ b/gm/samplelocations.cpp
@@ -241,7 +241,7 @@
                                   flushState->drawOpArgs().origin(),
                                   pipeline,
                                   primProc,
-                                  nullptr, nullptr);
+                                  nullptr, nullptr, 0);
 
         GrMesh mesh(GrPrimitiveType::kTriangleStrip);
         mesh.setInstanced(nullptr, 200*200, 0, 4);
diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp
index 93a6026..05e42e1 100644
--- a/src/gpu/GrOpFlushState.cpp
+++ b/src/gpu/GrOpFlushState.cpp
@@ -59,7 +59,8 @@
                                   *pipeline,
                                   *fCurrDraw->fGeometryProcessor,
                                   fCurrDraw->fFixedDynamicState,
-                                  fCurrDraw->fDynamicStateArrays);
+                                  fCurrDraw->fDynamicStateArrays,
+                                  fCurrDraw->fMeshCnt);
 
         this->opsRenderPass()->draw(programInfo, fCurrDraw->fMeshes,
                                     fCurrDraw->fMeshCnt, chainBounds);
diff --git a/src/gpu/GrOpsRenderPass.cpp b/src/gpu/GrOpsRenderPass.cpp
index 548bbb4..1b8ebea 100644
--- a/src/gpu/GrOpsRenderPass.cpp
+++ b/src/gpu/GrOpsRenderPass.cpp
@@ -45,13 +45,9 @@
     SkASSERT(!programInfo.primProc().hasInstanceAttributes() ||
              this->gpu()->caps()->instanceAttribSupport());
 
-    for (int i = 0; i < meshCount; ++i) {
-        SkASSERT(programInfo.primProc().hasVertexAttributes() == meshes[i].hasVertexData());
-        SkASSERT(programInfo.primProc().hasInstanceAttributes() == meshes[i].hasInstanceData());
-    }
-
-    programInfo.checkAllInstantiated(meshCount);
-    programInfo.checkMSAAAndMIPSAreResolved(meshCount);
+    programInfo.compatibleWithMeshes(meshes, meshCount);
+    programInfo.checkAllInstantiated();
+    programInfo.checkMSAAAndMIPSAreResolved();
 #endif
 
     if (programInfo.primProc().numVertexAttributes() > this->gpu()->caps()->maxVertexAttributes()) {
diff --git a/src/gpu/GrProgramInfo.cpp b/src/gpu/GrProgramInfo.cpp
index 0abc7c2..3391b61 100644
--- a/src/gpu/GrProgramInfo.cpp
+++ b/src/gpu/GrProgramInfo.cpp
@@ -9,6 +9,7 @@
 
 
 #ifdef SK_DEBUG
+#include "src/gpu/GrMesh.h"
 #include "src/gpu/GrTexturePriv.h"
 
 void GrProgramInfo::validate() const {
@@ -25,25 +26,8 @@
 
     SkASSERT(!fPipeline.isScissorEnabled() || this->hasFixedScissor() ||
              this->hasDynamicScissors());
-}
-
-void GrProgramInfo::checkAllInstantiated(int meshCount) const {
-    if (this->hasFixedPrimProcTextures()) {
-        auto fixedPrimProcTextures = this->fixedPrimProcTextures();
-        for (int s = 0; s < this->primProc().numTextureSamplers(); ++s) {
-            SkASSERT(fixedPrimProcTextures[s]->isInstantiated());
-        }
-    }
 
     if (this->hasDynamicPrimProcTextures()) {
-        for (int m = 0; m < meshCount; ++m) {
-            auto dynamicPrimProcTextures = this->dynamicPrimProcTextures(m);
-            for (int s = 0; s < this->primProc().numTextureSamplers(); ++s) {
-                SkASSERT(dynamicPrimProcTextures[s]->isInstantiated());
-            }
-        }
-
-        // TODO: if GrProgramInfo had the mesh count we could do this in validate!
         // Check that, for a given sampler, the properties of the dynamic textures remain
         // the same for all the meshes
         for (int s = 0; s < this->primProc().numTextureSamplers(); ++s) {
@@ -53,7 +37,7 @@
             GrTextureType type = dynamicPrimProcTextures[s]->textureType();
             GrPixelConfig config = dynamicPrimProcTextures[s]->config();
 
-            for (int m = 1; m < meshCount; ++m) {
+            for (int m = 1; m < fNumDynamicStateArrays; ++m) {
                 dynamicPrimProcTextures = this->dynamicPrimProcTextures(m);
 
                 auto testProxy = dynamicPrimProcTextures[s];
@@ -65,7 +49,25 @@
     }
 }
 
-void GrProgramInfo::checkMSAAAndMIPSAreResolved(int meshCount) const {
+void GrProgramInfo::checkAllInstantiated() const {
+    if (this->hasFixedPrimProcTextures()) {
+        auto fixedPrimProcTextures = this->fixedPrimProcTextures();
+        for (int s = 0; s < this->primProc().numTextureSamplers(); ++s) {
+            SkASSERT(fixedPrimProcTextures[s]->isInstantiated());
+        }
+    }
+
+    if (this->hasDynamicPrimProcTextures()) {
+        for (int m = 0; m < fNumDynamicStateArrays; ++m) {
+            auto dynamicPrimProcTextures = this->dynamicPrimProcTextures(m);
+            for (int s = 0; s < this->primProc().numTextureSamplers(); ++s) {
+                SkASSERT(dynamicPrimProcTextures[s]->isInstantiated());
+            }
+        }
+    }
+}
+
+void GrProgramInfo::checkMSAAAndMIPSAreResolved() const {
 
     auto assertResolved = [](GrTexture* tex, const GrSamplerState& sampler) {
         SkASSERT(tex);
@@ -81,7 +83,7 @@
     };
 
     if (this->hasDynamicPrimProcTextures()) {
-        for (int m = 0; m < meshCount; ++m) {
+        for (int m = 0; m < fNumDynamicStateArrays; ++m) {
             auto dynamicPrimProcTextures = this->dynamicPrimProcTextures(m);
 
             for (int s = 0; s < this->primProc().numTextureSamplers(); ++s) {
@@ -107,4 +109,13 @@
     }
 }
 
+void GrProgramInfo::compatibleWithMeshes(const GrMesh meshes[], int meshCount) const {
+    SkASSERT(!fNumDynamicStateArrays || meshCount == fNumDynamicStateArrays);
+
+    for (int i = 0; i < meshCount; ++i) {
+        SkASSERT(fPrimProc.hasVertexAttributes() == meshes[i].hasVertexData());
+        SkASSERT(fPrimProc.hasInstanceAttributes() == meshes[i].hasInstanceData());
+    }
+}
+
 #endif
diff --git a/src/gpu/GrProgramInfo.h b/src/gpu/GrProgramInfo.h
index 63f5e1a..671147a 100644
--- a/src/gpu/GrProgramInfo.h
+++ b/src/gpu/GrProgramInfo.h
@@ -12,29 +12,32 @@
 #include "src/gpu/GrPipeline.h"
 #include "src/gpu/GrPrimitiveProcessor.h"
 
+class GrMesh;
+
 class GrProgramInfo {
 public:
-    // TODO: it seems like this object should also get the number of copies in
-    // dynamicStateArrays. If that were true a portion of checkAllInstantiated could be moved
-    // to validate.
     GrProgramInfo(int numSamples,
                   GrSurfaceOrigin origin,
                   const GrPipeline& pipeline,
                   const GrPrimitiveProcessor& primProc,
                   const GrPipeline::FixedDynamicState* fixedDynamicState,
-                  const GrPipeline::DynamicStateArrays* dynamicStateArrays)
+                  const GrPipeline::DynamicStateArrays* dynamicStateArrays,
+                  int numDynamicStateArrays)
             : fNumSamples(numSamples)
             , fOrigin(origin)
             , fPipeline(pipeline)
             , fPrimProc(primProc)
             , fFixedDynamicState(fixedDynamicState)
-            , fDynamicStateArrays(dynamicStateArrays) {
+            , fDynamicStateArrays(dynamicStateArrays)
+            , fNumDynamicStateArrays(numDynamicStateArrays) {
         fRequestedFeatures = fPrimProc.requestedFeatures();
         for (int i = 0; i < fPipeline.numFragmentProcessors(); ++i) {
             fRequestedFeatures |= fPipeline.getFragmentProcessor(i).requestedFeatures();
         }
         fRequestedFeatures |= fPipeline.getXferProcessor().requestedFeatures();
+
         SkDEBUGCODE(this->validate();)
+        (void) fNumDynamicStateArrays;  // touch this to quiet unused member warnings
     }
 
     GrProcessor::CustomFeatures requestedFeatures() const { return fRequestedFeatures; }
@@ -44,7 +47,6 @@
     const GrPipeline& pipeline() const { return fPipeline; }
     const GrPrimitiveProcessor& primProc() const { return fPrimProc; }
     const GrPipeline::FixedDynamicState* fixedDynamicState() const { return fFixedDynamicState; }
-    const GrPipeline::DynamicStateArrays* dynamicStateArrays() const { return fDynamicStateArrays; }
 
     // TODO: can this be removed?
     const GrTextureProxy* const* primProcProxies() const {
@@ -84,6 +86,7 @@
 
     const GrTextureProxy* const* dynamicPrimProcTextures(int i) const {
         SkASSERT(this->hasDynamicPrimProcTextures());
+        SkASSERT(i < fNumDynamicStateArrays);
 
         return fDynamicStateArrays->fPrimitiveProcessorTextures +
                                                                 i * fPrimProc.numTextureSamplers();
@@ -101,8 +104,9 @@
 
 #ifdef SK_DEBUG
     void validate() const;
-    void checkAllInstantiated(int meshCount) const;
-    void checkMSAAAndMIPSAreResolved(int meshCount) const;
+    void checkAllInstantiated() const;
+    void checkMSAAAndMIPSAreResolved() const;
+    void compatibleWithMeshes(const GrMesh meshes[], int meshCount) const;
 
     bool isNVPR() const {
         return fPrimProc.isPathRendering() && !fPrimProc.willUseGeoShader() &&
@@ -117,6 +121,7 @@
     const GrPrimitiveProcessor&           fPrimProc;
     const GrPipeline::FixedDynamicState*  fFixedDynamicState;
     const GrPipeline::DynamicStateArrays* fDynamicStateArrays;
+    const int                             fNumDynamicStateArrays;
     GrProcessor::CustomFeatures           fRequestedFeatures;
 };
 
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
index c36075e..6abb04e 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
@@ -208,7 +208,7 @@
                               pipeline,
                               *this,
                               nullptr,
-                              &dynamicStateArrays);
+                              &dynamicStateArrays, 0);
 
 
     renderPass->draw(programInfo, meshes, meshCount, drawBounds);
diff --git a/src/gpu/ccpr/GrCCPathProcessor.cpp b/src/gpu/ccpr/GrCCPathProcessor.cpp
index 4a7a136..dd6bcae 100644
--- a/src/gpu/ccpr/GrCCPathProcessor.cpp
+++ b/src/gpu/ccpr/GrCCPathProcessor.cpp
@@ -146,7 +146,7 @@
                               pipeline,
                               *this,
                               fixedDynamicState,
-                              nullptr);
+                              nullptr, 0);
 
     flushState->opsRenderPass()->draw(programInfo, &mesh, 1, bounds);
 }
diff --git a/src/gpu/ccpr/GrCCStroker.cpp b/src/gpu/ccpr/GrCCStroker.cpp
index c768991..cbfa5ae 100644
--- a/src/gpu/ccpr/GrCCStroker.cpp
+++ b/src/gpu/ccpr/GrCCStroker.cpp
@@ -782,7 +782,7 @@
                               pipeline,
                               processor,
                               nullptr,
-                              &dynamicStateArrays);
+                              &dynamicStateArrays, 0);
 
     flushState->opsRenderPass()->draw(programInfo,
                                       fMeshesBuffer.begin(), fMeshesBuffer.count(),
diff --git a/src/gpu/ccpr/GrStencilAtlasOp.cpp b/src/gpu/ccpr/GrStencilAtlasOp.cpp
index 2701ce4..c7ec6da 100644
--- a/src/gpu/ccpr/GrStencilAtlasOp.cpp
+++ b/src/gpu/ccpr/GrStencilAtlasOp.cpp
@@ -156,7 +156,7 @@
                               resolvePipeline,
                               primProc,
                               &scissorRectState,
-                              nullptr);
+                              nullptr, 0);
 
     flushState->opsRenderPass()->draw(programInfo, &mesh, 1, SkRect::Make(drawBoundsRect));
 }
diff --git a/src/gpu/ops/GrDrawPathOp.cpp b/src/gpu/ops/GrDrawPathOp.cpp
index d6700d3..526ebc0 100644
--- a/src/gpu/ops/GrDrawPathOp.cpp
+++ b/src/gpu/ops/GrDrawPathOp.cpp
@@ -98,7 +98,7 @@
                               pipeline,
                               *pathProc,
                               &fixedDynamicState,
-                              nullptr);
+                              nullptr, 0);
 
     GrStencilSettings stencil;
     init_stencil_pass_settings(*state, this->fillType(), &stencil);
diff --git a/src/gpu/ops/GrFillRRectOp.cpp b/src/gpu/ops/GrFillRRectOp.cpp
index c3f86a3..6b3c023 100644
--- a/src/gpu/ops/GrFillRRectOp.cpp
+++ b/src/gpu/ops/GrFillRRectOp.cpp
@@ -756,7 +756,7 @@
                               *pipeline,
                               *proc,
                               fixedDynamicState,
-                              nullptr);
+                              nullptr, 0);
 
     GrMesh* mesh = flushState->allocator()->make<GrMesh>(GrPrimitiveType::kTriangles);
     mesh->setIndexedInstanced(
diff --git a/tests/GrMeshTest.cpp b/tests/GrMeshTest.cpp
index 16ceaeb..d45aa7f 100644
--- a/tests/GrMeshTest.cpp
+++ b/tests/GrMeshTest.cpp
@@ -416,7 +416,7 @@
                               fState->drawOpArgs().origin(),
                               pipeline,
                               mtp,
-                              nullptr, nullptr);
+                              nullptr, nullptr, 0);
 
     fState->opsRenderPass()->draw(programInfo, &mesh, 1,
                                   SkRect::MakeIWH(kImageWidth, kImageHeight));
diff --git a/tests/GrPipelineDynamicStateTest.cpp b/tests/GrPipelineDynamicStateTest.cpp
index 46d834c..485aa14 100644
--- a/tests/GrPipelineDynamicStateTest.cpp
+++ b/tests/GrPipelineDynamicStateTest.cpp
@@ -160,7 +160,7 @@
                                   pipeline,
                                   primProc,
                                   nullptr,
-                                  &dynamicState);
+                                  &dynamicState, 0);
 
         flushState->opsRenderPass()->draw(programInfo, meshes.begin(), 4,
                                           SkRect::MakeIWH(kScreenSize, kScreenSize));