Remove GrPipeline from GrDrawOp.

GrDrawOp subclasses are now free to construct their pipelines at flush time and now in theory could use multiple GrPipelines for multipass rendering.

GrProcessorSet may be used to retain the processors from a GrPaint with "pending execution" style refs.

NVPR and Instanced rendering are updated to create their pipelines at flush time without a GrPipelineBuilder.

The monolithic pipeline creation/management that was on GrDrawOp is moved to GrMeshDrawOp. However, this is temporary and will be removed in coming changes.

Change-Id: I124282e3cea5d070970b5460c8a679fcaf7a8eff
Reviewed-on: https://skia-review.googlesource.com/7279
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/instanced/InstancedRendering.cpp b/src/gpu/instanced/InstancedRendering.cpp
index ef2264b..179552c 100644
--- a/src/gpu/instanced/InstancedRendering.cpp
+++ b/src/gpu/instanced/InstancedRendering.cpp
@@ -22,32 +22,31 @@
 }
 
 std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
-                                                         const SkMatrix& viewMatrix, GrColor color,
+                                                         const SkMatrix& viewMatrix,
+                                                         GrPaint&& paint, GrAA aa,
+                                                         const GrInstancedPipelineInfo& info) {
+    return this->recordShape(ShapeType::kRect, rect, viewMatrix, std::move(paint), rect, aa, info);
+}
+
+std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
+                                                         const SkMatrix& viewMatrix,
+                                                         GrPaint&& paint, const SkRect& localRect,
                                                          GrAA aa,
-                                                         const GrInstancedPipelineInfo& info,
-                                                         GrAAType* aaType) {
-    return this->recordShape(ShapeType::kRect, rect, viewMatrix, color, rect, aa, info, aaType);
+                                                         const GrInstancedPipelineInfo& info) {
+    return this->recordShape(ShapeType::kRect, rect, viewMatrix, std::move(paint), localRect, aa,
+                             info);
 }
 
 std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
-                                                         const SkMatrix& viewMatrix, GrColor color,
-                                                         const SkRect& localRect, GrAA aa,
-                                                         const GrInstancedPipelineInfo& info,
-                                                         GrAAType* aaType) {
-    return this->recordShape(ShapeType::kRect, rect, viewMatrix, color, localRect, aa, info,
-                             aaType);
-}
-
-std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
-                                                         const SkMatrix& viewMatrix, GrColor color,
+                                                         const SkMatrix& viewMatrix,
+                                                         GrPaint&& paint,
                                                          const SkMatrix& localMatrix, GrAA aa,
-                                                         const GrInstancedPipelineInfo& info,
-                                                         GrAAType* aaType) {
+                                                         const GrInstancedPipelineInfo& info) {
     if (localMatrix.hasPerspective()) {
         return nullptr; // Perspective is not yet supported in the local matrix.
     }
-    if (std::unique_ptr<Op> op = this->recordShape(ShapeType::kRect, rect, viewMatrix, color, rect,
-                                                   aa, info, aaType)) {
+    if (std::unique_ptr<Op> op = this->recordShape(ShapeType::kRect, rect, viewMatrix,
+                                                   std::move(paint), rect, aa, info)) {
         op->getSingleInstance().fInfo |= kLocalMatrix_InfoFlag;
         op->appendParamsTexel(localMatrix.getScaleX(), localMatrix.getSkewX(),
                               localMatrix.getTranslateX());
@@ -60,39 +59,39 @@
 }
 
 std::unique_ptr<GrDrawOp> InstancedRendering::recordOval(const SkRect& oval,
-                                                         const SkMatrix& viewMatrix, GrColor color,
-                                                         GrAA aa,
-                                                         const GrInstancedPipelineInfo& info,
-                                                         GrAAType* aaType) {
-    return this->recordShape(ShapeType::kOval, oval, viewMatrix, color, oval, aa, info, aaType);
+                                                         const SkMatrix& viewMatrix,
+                                                         GrPaint&& paint, GrAA aa,
+                                                         const GrInstancedPipelineInfo& info) {
+    return this->recordShape(ShapeType::kOval, oval, viewMatrix, std::move(paint), oval, aa, info);
 }
 
 std::unique_ptr<GrDrawOp> InstancedRendering::recordRRect(const SkRRect& rrect,
-                                                          const SkMatrix& viewMatrix, GrColor color,
-                                                          GrAA aa,
-                                                          const GrInstancedPipelineInfo& info,
-                                                          GrAAType* aaType) {
+                                                          const SkMatrix& viewMatrix,
+                                                          GrPaint&& paint, GrAA aa,
+                                                          const GrInstancedPipelineInfo& info) {
     if (std::unique_ptr<Op> op =
-                this->recordShape(GetRRectShapeType(rrect), rrect.rect(), viewMatrix, color,
-                                  rrect.rect(), aa, info, aaType)) {
+                this->recordShape(GetRRectShapeType(rrect), rrect.rect(), viewMatrix,
+                                  std::move(paint), rrect.rect(), aa, info)) {
         op->appendRRectParams(rrect);
         return std::move(op);
     }
     return nullptr;
 }
 
-std::unique_ptr<GrDrawOp> InstancedRendering::recordDRRect(
-        const SkRRect& outer, const SkRRect& inner, const SkMatrix& viewMatrix, GrColor color,
-        GrAA aa, const GrInstancedPipelineInfo& info, GrAAType* aaType) {
+std::unique_ptr<GrDrawOp> InstancedRendering::recordDRRect(const SkRRect& outer,
+                                                           const SkRRect& inner,
+                                                           const SkMatrix& viewMatrix,
+                                                           GrPaint&& paint, GrAA aa,
+                                                           const GrInstancedPipelineInfo& info) {
     if (inner.getType() > SkRRect::kSimple_Type) {
        return nullptr; // Complex inner round rects are not yet supported.
     }
     if (SkRRect::kEmpty_Type == inner.getType()) {
-        return this->recordRRect(outer, viewMatrix, color, aa, info, aaType);
+        return this->recordRRect(outer, viewMatrix, std::move(paint), aa, info);
     }
     if (std::unique_ptr<Op> op =
-                this->recordShape(GetRRectShapeType(outer), outer.rect(), viewMatrix, color,
-                                  outer.rect(), aa, info, aaType)) {
+                this->recordShape(GetRRectShapeType(outer), outer.rect(), viewMatrix,
+                                  std::move(paint), outer.rect(), aa, info)) {
         op->appendRRectParams(outer);
         ShapeType innerShapeType = GetRRectShapeType(inner);
         op->fInfo.fInnerShapeTypes |= GetShapeFlag(innerShapeType);
@@ -105,28 +104,31 @@
 }
 
 std::unique_ptr<InstancedRendering::Op> InstancedRendering::recordShape(
-        ShapeType type, const SkRect& bounds, const SkMatrix& viewMatrix, GrColor color,
-        const SkRect& localRect, GrAA aa, const GrInstancedPipelineInfo& info, GrAAType* aaType) {
+        ShapeType type, const SkRect& bounds, const SkMatrix& viewMatrix, GrPaint&& paint,
+        const SkRect& localRect, GrAA aa, const GrInstancedPipelineInfo& info) {
     SkASSERT(State::kRecordingDraws == fState);
 
     if (info.fIsRenderingToFloat && fGpu->caps()->avoidInstancedDrawsToFPTargets()) {
         return nullptr;
     }
 
-    if (!this->selectAntialiasMode(viewMatrix, aa, info, aaType)) {
+    GrAAType aaType;
+    if (!this->selectAntialiasMode(viewMatrix, aa, info, &aaType)) {
         return nullptr;
     }
 
-    std::unique_ptr<Op> op = this->makeOp();
-    op->fInfo.setAAType(*aaType);
+    GrColor color = paint.getColor();
+    std::unique_ptr<Op> op = this->makeOp(std::move(paint));
+    op->fInfo.setAAType(aaType);
     op->fInfo.fShapeTypes = GetShapeFlag(type);
     op->fInfo.fCannotDiscard = true;
-
+    op->fDrawColorsAreOpaque = GrColorIsOpaque(color);
+    op->fDrawColorsAreSame = true;
     Instance& instance = op->getSingleInstance();
     instance.fInfo = (int)type << kShapeType_InfoBit;
 
     Op::HasAABloat aaBloat =
-            (*aaType == GrAAType::kCoverage) ? Op::HasAABloat::kYes : Op::HasAABloat::kNo;
+            (aaType == GrAAType::kCoverage) ? Op::HasAABloat::kYes : Op::HasAABloat::kNo;
     Op::IsZeroArea zeroArea = (bounds.isEmpty()) ? Op::IsZeroArea::kYes : Op::IsZeroArea::kNo;
 
     // The instanced shape renderer draws rectangles of [-1, -1, +1, +1], so we find the matrix that
@@ -229,9 +231,10 @@
     return false;
 }
 
-InstancedRendering::Op::Op(uint32_t classID, InstancedRendering* ir)
+InstancedRendering::Op::Op(uint32_t classID, GrPaint&& paint, InstancedRendering* ir)
         : INHERITED(classID)
         , fInstancedRendering(ir)
+        , fProcessors(std::move(paint))
         , fIsTracked(false)
         , fNumDraws(1)
         , fNumChangesInGeometry(0) {
@@ -329,20 +332,17 @@
     fInfo.fHasParams = true;
 }
 
-void InstancedRendering::Op::getFragmentProcessorAnalysisInputs(
-        FragmentProcessorAnalysisInputs* input) const {
-    input->colorInput()->setToConstant(this->getSingleInstance().fColor);
-
+bool InstancedRendering::Op::xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) {
+    GrProcessorSet::FragmentProcessorAnalysis analysis;
+    GrPipelineInput coverageInput;
     if (GrAAType::kCoverage == fInfo.aaType() ||
         (GrAAType::kNone == fInfo.aaType() && !fInfo.isSimpleRects() && fInfo.fCannotDiscard)) {
-        input->coverageInput()->setToUnknown();
+        coverageInput = GrPipelineInput();
     } else {
-        input->coverageInput()->setToSolidCoverage();
+        coverageInput = GrColor_WHITE;
     }
-}
+    analysis.init(this->getSingleInstance().fColor, coverageInput, fProcessors, clip, caps);
 
-void InstancedRendering::Op::applyPipelineOptimizations(
-        const GrPipelineOptimizations& optimizations) {
     Draw& draw = this->getSingleDraw(); // This will assert if we have > 1 command.
     SkASSERT(draw.fGeometry.isEmpty());
     SkASSERT(SkIsPow2(fInfo.fShapeTypes));
@@ -363,17 +363,23 @@
     }
 
     GrColor overrideColor;
-    if (optimizations.getOverrideColorIfSet(&overrideColor)) {
+    if (analysis.initialColorProcessorsToEliminate(&overrideColor)) {
         SkASSERT(State::kRecordingDraws == fInstancedRendering->fState);
-        this->getSingleInstance().fColor = overrideColor;
+        this->getSingleDraw().fInstance.fColor = overrideColor;
     }
-    fInfo.fUsesLocalCoords = optimizations.readsLocalCoords();
-    fInfo.fCannotTweakAlphaForCoverage = !optimizations.canTweakAlphaForCoverage();
+    fInfo.fCannotTweakAlphaForCoverage =
+            !analysis.isCompatibleWithCoverageAsAlpha() ||
+            !GrXPFactory::CompatibleWithCoverageAsAlpha(fProcessors.xpFactory(),
+                                                        analysis.isOutputColorOpaque());
+
+    fInfo.fUsesLocalCoords = analysis.usesLocalCoords();
+    return GrXPFactory::WillNeedDstTexture(fProcessors.xpFactory(), caps, analysis);
 }
 
 void InstancedRendering::Op::wasRecorded() {
     SkASSERT(!fIsTracked);
     fInstancedRendering->fTrackedOps.addToTail(this);
+    fProcessors.makePendingExecution();
     fIsTracked = true;
 }
 
@@ -383,9 +389,7 @@
     SkASSERT(fTailDraw);
     SkASSERT(that->fTailDraw);
 
-    if (!OpInfo::CanCombine(fInfo, that->fInfo) ||
-        !GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
-                                that->bounds(), caps)) {
+    if (!OpInfo::CanCombine(fInfo, that->fInfo) || fProcessors != that->fProcessors) {
         return false;
     }
 
@@ -406,7 +410,9 @@
     this->joinBounds(*that);
     fInfo = combinedInfo;
     fPixelLoad += that->fPixelLoad;
-
+    fDrawColorsAreOpaque = fDrawColorsAreOpaque && that->fDrawColorsAreOpaque;
+    fDrawColorsAreSame = fDrawColorsAreSame && that->fDrawColorsAreSame &&
+                         fHeadDraw->fInstance.fColor == that->fHeadDraw->fInstance.fColor;
     // Adopt the other op's draws.
     fNumDraws += that->fNumDraws;
     fNumChangesInGeometry += that->fNumChangesInGeometry;
@@ -462,12 +468,40 @@
     SkASSERT(state->gpu() == fInstancedRendering->gpu());
 
     state->gpu()->handleDirtyContext();
-    if (GrXferBarrierType barrierType = this->pipeline()->xferBarrierType(*state->gpu()->caps())) {
-        state->gpu()->xferBarrier(this->pipeline()->getRenderTarget(), barrierType);
-    }
 
+    GrProcessorSet::FragmentProcessorAnalysis analysis;
+    GrPipelineInput coverageInput;
+    if (GrAAType::kCoverage == fInfo.aaType() ||
+        (GrAAType::kNone == fInfo.aaType() && !fInfo.isSimpleRects() && fInfo.fCannotDiscard)) {
+        coverageInput = GrPipelineInput();
+    } else {
+        coverageInput = GrColor_WHITE;
+    }
+    GrPipelineInput colorInput;
+    if (fDrawColorsAreSame) {
+        colorInput = fHeadDraw->fInstance.fColor;
+    } else if (fDrawColorsAreOpaque) {
+        colorInput = GrPipelineInput::Opaque::kYes;
+    }
+    const GrAppliedClip* clip = state->drawOpArgs().fAppliedClip;
+    analysis.init(colorInput, coverageInput, fProcessors, clip, state->caps());
+
+    GrPipeline pipeline;
+    GrPipeline::InitArgs args;
+    args.fAnalysis = &analysis;
+    args.fAppliedClip = clip;
+    args.fCaps = &state->caps();
+    args.fProcessors = &fProcessors;
+    args.fFlags = GrAATypeIsHW(fInfo.aaType()) ? GrPipeline::kHWAntialias_Flag : 0;
+    args.fRenderTarget = state->drawOpArgs().fRenderTarget;
+    args.fDstTexture = state->drawOpArgs().fDstTexture;
+    pipeline.init(args);
+
+    if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*state->gpu()->caps())) {
+        state->gpu()->xferBarrier(pipeline.getRenderTarget(), barrierType);
+    }
     InstanceProcessor instProc(fInfo, fInstancedRendering->fParamsBuffer.get());
-    fInstancedRendering->onDraw(*this->pipeline(), instProc, this);
+    fInstancedRendering->onDraw(pipeline, instProc, this);
 }
 
 void InstancedRendering::endFlush() {