Revert "Revert "Add a new non-AA rect op that does not inherit from GrLegacyMeshDrawOp.""

This reverts commit 0f353327968530506dd3dd15fca79ef59fe013f1.

Bug: skia:
Change-Id: I8def56fa55bfc70de4386bf0b7a7867f6e91c173
Reviewed-on: https://skia-review.googlesource.com/15251
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
new file mode 100644
index 0000000..f64f9ec
--- /dev/null
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
@@ -0,0 +1,194 @@
+/*
+ * 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 GrSimpleMeshDrawOpHelper_DEFINED
+#define GrSimpleMeshDrawOpHelper_DEFINED
+
+#include "GrAppliedClip.h"
+#include "GrOpFlushState.h"
+#include "GrPipeline.h"
+#include "GrProcessorSet.h"
+#include "GrUserStencilSettings.h"
+
+/**
+ * This class can be used to help implement simple mesh draw ops. It reduces the amount of
+ * boilerplate code to type and also provides a mechanism for optionally allocating space for a
+ * GrProcessorSet based on a GrPaint. It is intended to be used by ops that construct a single
+ * GrPipeline for a uniform primitive color and a GrPaint.
+ */
+class GrSimpleMeshDrawOpHelper {
+public:
+    struct MakeArgs;
+
+    /**
+     * This can be used by a Op class to perform allocation and initialization such that a
+     * GrProcessorSet (if required) is allocated at the same time as the Op instance. It requires
+     * that Op implements a constructor of the form:
+     *      Op(MakeArgs, GrColor, OpArgs...)
+     * which is public or made accessible via 'friend'.
+     */
+    template <typename Op, typename... OpArgs>
+    static std::unique_ptr<GrDrawOp> FactoryHelper(GrPaint&& paint, OpArgs... opArgs);
+
+    GrSimpleMeshDrawOpHelper(const MakeArgs& args, GrAAType aaType,
+                             GrUserStencilSettings* stencilSettings = nullptr)
+            : fProcessors(args.fProcessorSet)
+            , fPipelineFlags(args.fSRGBFlags)
+            , fAAType((int)aaType) {
+        SkASSERT(!stencilSettings);
+        if (GrAATypeIsHW(aaType)) {
+            fPipelineFlags |= GrPipeline::kHWAntialias_Flag;
+        }
+    }
+
+    ~GrSimpleMeshDrawOpHelper() {
+        if (fProcessors) {
+            fProcessors->~GrProcessorSet();
+        }
+    }
+
+    GrSimpleMeshDrawOpHelper() = delete;
+    GrSimpleMeshDrawOpHelper(const GrSimpleMeshDrawOpHelper&) = delete;
+    GrSimpleMeshDrawOpHelper& operator=(const GrSimpleMeshDrawOpHelper&) = delete;
+
+    GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const {
+        return GrAATypeIsHW((this->aaType())) ? GrDrawOp::FixedFunctionFlags::kUsesHWAA
+                                              : GrDrawOp::FixedFunctionFlags::kNone;
+    }
+
+    bool isCompatible(const GrSimpleMeshDrawOpHelper& that) const {
+        if (SkToBool(fProcessors) != SkToBool(that.fProcessors)) {
+            return false;
+        }
+        if (SkToBool(fProcessors) && *fProcessors != *that.fProcessors) {
+            return false;
+        }
+        return fPipelineFlags == that.fPipelineFlags && fAAType == that.fAAType;
+    }
+
+    bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip,
+                              GrProcessorAnalysisCoverage geometryCoverage, GrColor* color) {
+        if (fProcessors) {
+            GrProcessorAnalysisCoverage coverage = geometryCoverage;
+            if (GrProcessorAnalysisCoverage::kNone == coverage) {
+                coverage = clip->clipCoverageFragmentProcessor()
+                                   ? GrProcessorAnalysisCoverage::kSingleChannel
+                                   : GrProcessorAnalysisCoverage::kNone;
+            }
+            bool isMixedSamples = this->aaType() == GrAAType::kMixedSamples;
+            GrProcessorSet::Analysis analysis =
+                    fProcessors->finalize(*color, coverage, clip, isMixedSamples, caps, color);
+            return analysis.requiresDstTexture();
+        } else {
+            return GrProcessorSet::EmptySetAnalysis().requiresDstTexture();
+        }
+    }
+
+    GrPipeline* makePipeline(GrMeshDrawOp::Target* target) const {
+        return target->allocPipeline(this->pipelineInitArgs(target));
+    }
+
+    struct MakeArgs {
+    private:
+        MakeArgs() = default;
+
+        GrProcessorSet* fProcessorSet;
+        uint32_t fSRGBFlags;
+
+        friend class GrSimpleMeshDrawOpHelper;
+    };
+
+protected:
+    GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
+    uint32_t pipelineFlags() const { return fPipelineFlags; }
+    const GrProcessorSet& processors() const {
+        return fProcessors ? *fProcessors : GrProcessorSet::EmptySet();
+    }
+
+    GrPipeline::InitArgs pipelineInitArgs(GrMeshDrawOp::Target* target) const {
+        GrPipeline::InitArgs args;
+        args.fFlags = this->pipelineFlags();
+        args.fProcessors = &this->processors();
+        args.fRenderTarget = target->renderTarget();
+        args.fAppliedClip = target->clip();
+        args.fDstTexture = target->dstTexture();
+        args.fCaps = &target->caps();
+        return args;
+    }
+
+private:
+    GrProcessorSet* fProcessors;
+    unsigned fPipelineFlags : 8;
+    unsigned fAAType : 2;
+};
+
+/**
+ * This class extends GrSimpleMeshDrawOpHelper to support an optional GrUserStencilSettings. This
+ * uses private inheritance because it non-virtually overrides methods in the base class and should
+ * never be used with a GrSimpleMeshDrawOpHelper pointer or reference.
+ */
+class GrSimpleMeshDrawOpHelperWithStencil : private GrSimpleMeshDrawOpHelper {
+public:
+    using MakeArgs = GrSimpleMeshDrawOpHelper::MakeArgs;
+
+    // using declarations can't be templated, so this is a pass through function instead.
+    template <typename Op, typename... OpArgs>
+    static std::unique_ptr<GrDrawOp> FactoryHelper(GrPaint&& paint, OpArgs... opArgs) {
+        return GrSimpleMeshDrawOpHelper::FactoryHelper<Op, OpArgs...>(
+                std::move(paint), std::forward<OpArgs>(opArgs)...);
+    }
+
+    GrSimpleMeshDrawOpHelperWithStencil(const MakeArgs& args, GrAAType aaType,
+                                         const GrUserStencilSettings* stencilSettings)
+            : INHERITED(args, aaType)
+            , fStencilSettings(stencilSettings ? stencilSettings
+                                               : &GrUserStencilSettings::kUnused) {}
+
+    GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const {
+        GrDrawOp::FixedFunctionFlags flags = INHERITED::fixedFunctionFlags();
+        if (fStencilSettings != &GrUserStencilSettings::kUnused) {
+            flags |= GrDrawOp::FixedFunctionFlags::kUsesStencil;
+        }
+        return flags;
+    }
+
+    using GrSimpleMeshDrawOpHelper::xpRequiresDstTexture;
+
+    bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that) const {
+        return INHERITED::isCompatible(that) && fStencilSettings == that.fStencilSettings;
+    }
+
+    GrPipeline* makePipeline(GrMeshDrawOp::Target* target) const {
+        auto args = INHERITED::pipelineInitArgs(target);
+        args.fUserStencil = fStencilSettings;
+        return target->allocPipeline(args);
+    }
+
+private:
+    const GrUserStencilSettings* fStencilSettings;
+    typedef GrSimpleMeshDrawOpHelper INHERITED;
+};
+
+template <typename Op, typename... OpArgs>
+std::unique_ptr<GrDrawOp> GrSimpleMeshDrawOpHelper::FactoryHelper(GrPaint&& paint,
+                                                                  OpArgs... opArgs) {
+    MakeArgs makeArgs;
+    makeArgs.fSRGBFlags = GrPipeline::SRGBFlagsFromPaint(paint);
+    GrColor color = paint.getColor();
+    if (paint.isTrivial()) {
+        makeArgs.fProcessorSet = nullptr;
+        return std::unique_ptr<GrDrawOp>(new Op(makeArgs, color, std::forward<OpArgs>(opArgs)...));
+    } else {
+        char* mem = (char*)GrOp::operator new(sizeof(Op) + sizeof(GrProcessorSet));
+        char* setMem = mem + sizeof(Op);
+        makeArgs.fProcessorSet = new (setMem) GrProcessorSet(std::move(paint));
+        return std::unique_ptr<GrDrawOp>(
+                new (mem) Op(makeArgs, color, std::forward<OpArgs>(opArgs)...));
+    }
+}
+
+#endif