Implement clone() for Gradient GrFragmentProcessors

Also removes the hard stop gradient conditional compilation macro.

Change-Id: Idd56b5f3061db063d650a0090406ec192acc0b53
Reviewed-on: https://skia-review.googlesource.com/27661
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 17eb700..9f9b73f 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -1292,13 +1292,11 @@
 
 static inline int color_type_to_color_count(GrGradientEffect::ColorType colorType) {
     switch (colorType) {
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
         case GrGradientEffect::kSingleHardStop_ColorType:
             return 4;
         case GrGradientEffect::kHardStopLeftEdged_ColorType:
         case GrGradientEffect::kHardStopRightEdged_ColorType:
             return 3;
-#endif
         case GrGradientEffect::kTwo_ColorType:
             return 2;
         case GrGradientEffect::kThree_ColorType:
@@ -1313,7 +1311,6 @@
 
 GrGradientEffect::ColorType GrGradientEffect::determineColorType(
         const SkGradientShaderBase& shader) {
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
     if (shader.fOrigPos) {
         if (4 == shader.fColorCount) {
             if (SkScalarNearlyEqual(shader.fOrigPos[0], 0.0f) &&
@@ -1336,7 +1333,6 @@
             }
         }
     }
-#endif
 
     if (SkShader::kClamp_TileMode == shader.getTileMode()) {
         if (2 == shader.fColorCount) {
@@ -1461,13 +1457,11 @@
     const GrGradientEffect& e = processor.cast<GrGradientEffect>();
 
     switch (e.getColorType()) {
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
         case GrGradientEffect::kSingleHardStop_ColorType:
             pdman.set1f(fHardStopT, e.fPositions[1]);
             // fall through
         case GrGradientEffect::kHardStopLeftEdged_ColorType:
         case GrGradientEffect::kHardStopRightEdged_ColorType:
-#endif
         case GrGradientEffect::kTwo_ColorType:
         case GrGradientEffect::kThree_ColorType: {
             if (e.fColors4f.count() > 0) {
@@ -1518,9 +1512,7 @@
         key |= kTwoColorKey;
     } else if (GrGradientEffect::kThree_ColorType == e.getColorType()) {
         key |= kThreeColorKey;
-    }
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
-    else if (GrGradientEffect::kSingleHardStop_ColorType == e.getColorType()) {
+    } else if (GrGradientEffect::kSingleHardStop_ColorType == e.getColorType()) {
         key |= kHardStopCenteredKey;
     } else if (GrGradientEffect::kHardStopLeftEdged_ColorType == e.getColorType()) {
         key |= kHardStopZeroZeroOneKey;
@@ -1535,7 +1527,6 @@
     } else {
         key |= kMirrorTileMode;
     }
-#endif
 
     key |= GrColorSpaceXform::XformKey(e.fColorSpaceXform.get()) << kReservedBits;
 
@@ -1551,7 +1542,6 @@
                                                 const char* inputColor,
                                                 const TextureSamplers& texSamplers) {
     switch (ge.getColorType()) {
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
         case kSingleHardStop_ColorType: {
             const char* t      = gradientTValue;
             const char* colors = uniformHandler->getUniformCStr(fColorsUni);
@@ -1672,7 +1662,6 @@
 
             break;
         }
-#endif
 
         case kTwo_ColorType: {
             const char* t      = gradientTValue;
@@ -1772,26 +1761,20 @@
             fColors = SkTDArray<SkColor>(shader.fOrigColors, shader.fColorCount);
         }
 
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
         if (shader.fOrigPos) {
             fPositions = SkTDArray<SkScalar>(shader.fOrigPos, shader.fColorCount);
         }
-#endif
     }
 
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
     fTileMode = args.fTileMode;
-#endif
 
     switch (fColorType) {
         // The two and three color specializations do not currently support tiling.
         case kTwo_ColorType:
         case kThree_ColorType:
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
         case kHardStopLeftEdged_ColorType:
         case kHardStopRightEdged_ColorType:
         case kSingleHardStop_ColorType:
-#endif
             fRow = -1;
 
             if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGradFlags()) {
@@ -1877,6 +1860,30 @@
     this->addCoordTransform(&fCoordTransform);
 }
 
+GrGradientEffect::GrGradientEffect(const GrGradientEffect& that)
+        : INHERITED(OptFlags(that.fIsOpaque))
+        , fColors(that.fColors)
+        , fColors4f(that.fColors4f)
+        , fColorSpaceXform(that.fColorSpaceXform)
+        , fPositions(that.fPositions)
+        , fTileMode(that.fTileMode)
+        , fCoordTransform(that.fCoordTransform)
+        , fTextureSampler(that.fTextureSampler)
+        , fYCoord(that.fYCoord)
+        , fAtlas(that.fAtlas)
+        , fRow(that.fRow)
+        , fIsOpaque(that.fIsOpaque)
+        , fColorType(that.fColorType)
+        , fPremulType(that.fPremulType) {
+    this->addCoordTransform(&fCoordTransform);
+    if (kTexture_ColorType == fColorType) {
+        this->addTextureSampler(&fTextureSampler);
+    }
+    if (this->useAtlas()) {
+        fAtlas->lockRow(fRow);
+    }
+}
+
 GrGradientEffect::~GrGradientEffect() {
     if (this->useAtlas()) {
         fAtlas->unlockRow(fRow);
diff --git a/src/shaders/gradients/SkGradientShaderPriv.h b/src/shaders/gradients/SkGradientShaderPriv.h
index 47ef70c..07ba7e3 100644
--- a/src/shaders/gradients/SkGradientShaderPriv.h
+++ b/src/shaders/gradients/SkGradientShaderPriv.h
@@ -24,10 +24,6 @@
 #include "SkUtils.h"
 #include "SkWriteBuffer.h"
 
-#if SK_SUPPORT_GPU
-    #define GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1
-#endif
-
 static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
                                int count) {
     if (count > 0) {
@@ -374,12 +370,9 @@
         kTwo_ColorType,
         kThree_ColorType, // Symmetric three color
         kTexture_ColorType,
-
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
         kSingleHardStop_ColorType,     // 0, t, t, 1
         kHardStopLeftEdged_ColorType,  // 0, 0, 1
         kHardStopRightEdged_ColorType, // 0, 1, 1
-#endif
     };
 
     ColorType getColorType() const { return fColorType; }
@@ -414,6 +407,7 @@
 
 protected:
     GrGradientEffect(const CreateArgs&, bool isOpaque);
+    explicit GrGradientEffect(const GrGradientEffect&);  // facilitates clone() implementations
 
     #if GR_TEST_UTILS
     /** Helper struct that stores (and populates) parameters to construct a random gradient.
@@ -519,7 +513,7 @@
         // hard stop cases (neither means using texture atlas)
         kTwoColorKey            =  2,
         kThreeColorKey          =  4,
-#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
+
         kHardStopCenteredKey    =  6,
         kHardStopZeroZeroOneKey =  8,
         kHardStopZeroOneOneKey  = 10,
@@ -531,7 +525,6 @@
 
         // Lower six bits for premul, 2/3 color type, and tile mode
         kReservedBits           = 6,
-#endif
     };
 
     SkScalar fCachedYCoord;
diff --git a/src/shaders/gradients/SkLinearGradient.cpp b/src/shaders/gradients/SkLinearGradient.cpp
index d127f8d..5ad4075 100644
--- a/src/shaders/gradients/SkLinearGradient.cpp
+++ b/src/shaders/gradients/SkLinearGradient.cpp
@@ -345,12 +345,19 @@
         return processor->isValid() ? std::move(processor) : nullptr;
     }
 
-    ~GrLinearGradient() override {}
-
     const char* name() const override { return "Linear Gradient"; }
 
+    sk_sp<GrFragmentProcessor> clone() const override {
+        return sk_sp<GrFragmentProcessor>(new GrLinearGradient(*this));
+    }
+
 private:
-    GrLinearGradient(const CreateArgs& args) : INHERITED(args, args.fShader->colorsAreOpaque()) {
+    explicit GrLinearGradient(const CreateArgs& args)
+            : INHERITED(args, args.fShader->colorsAreOpaque()) {
+        this->initClassID<GrLinearGradient>();
+    }
+
+    explicit GrLinearGradient(const GrLinearGradient& that) : INHERITED(that) {
         this->initClassID<GrLinearGradient>();
     }
 
@@ -370,8 +377,6 @@
 public:
     GLSLLinearProcessor(const GrProcessor&) {}
 
-    ~GLSLLinearProcessor() override {}
-
     virtual void emitCode(EmitArgs&) override;
 
     static void GenKey(const GrProcessor& processor, const GrShaderCaps&, GrProcessorKeyBuilder* b) {
diff --git a/src/shaders/gradients/SkRadialGradient.cpp b/src/shaders/gradients/SkRadialGradient.cpp
index c2ca2fa..a8e48db 100644
--- a/src/shaders/gradients/SkRadialGradient.cpp
+++ b/src/shaders/gradients/SkRadialGradient.cpp
@@ -234,12 +234,19 @@
         return processor->isValid() ? std::move(processor) : nullptr;
     }
 
-    ~GrRadialGradient() override {}
-
     const char* name() const override { return "Radial Gradient"; }
 
+    sk_sp<GrFragmentProcessor> clone() const override {
+        return sk_sp<GrFragmentProcessor>(new GrRadialGradient(*this));
+    }
+
 private:
-    GrRadialGradient(const CreateArgs& args) : INHERITED(args, args.fShader->colorsAreOpaque()) {
+    explicit GrRadialGradient(const CreateArgs& args)
+            : INHERITED(args, args.fShader->colorsAreOpaque()) {
+        this->initClassID<GrRadialGradient>();
+    }
+
+    explicit GrRadialGradient(const GrRadialGradient& that) : INHERITED(that) {
         this->initClassID<GrRadialGradient>();
     }
 
@@ -258,7 +265,6 @@
 class GrRadialGradient::GLSLRadialProcessor : public GrGradientEffect::GLSLProcessor {
 public:
     GLSLRadialProcessor(const GrProcessor&) {}
-    ~GLSLRadialProcessor() override {}
 
     virtual void emitCode(EmitArgs&) override;
 
diff --git a/src/shaders/gradients/SkSweepGradient.cpp b/src/shaders/gradients/SkSweepGradient.cpp
index 0a1d83e..da9eaef 100644
--- a/src/shaders/gradients/SkSweepGradient.cpp
+++ b/src/shaders/gradients/SkSweepGradient.cpp
@@ -67,12 +67,19 @@
         return processor->isValid() ? std::move(processor) : nullptr;
     }
 
-    ~GrSweepGradient() override {}
-
     const char* name() const override { return "Sweep Gradient"; }
 
+    sk_sp<GrFragmentProcessor> clone() const override {
+        return sk_sp<GrFragmentProcessor>(new GrSweepGradient(*this));
+    }
+
 private:
-    GrSweepGradient(const CreateArgs& args) : INHERITED(args, args.fShader->colorsAreOpaque()) {
+    explicit GrSweepGradient(const CreateArgs& args)
+            : INHERITED(args, args.fShader->colorsAreOpaque()) {
+        this->initClassID<GrSweepGradient>();
+    }
+
+    explicit GrSweepGradient(const GrSweepGradient& that) : INHERITED(that) {
         this->initClassID<GrSweepGradient>();
     }
 
@@ -91,7 +98,6 @@
 class GrSweepGradient::GLSLSweepProcessor : public GrGradientEffect::GLSLProcessor {
 public:
     GLSLSweepProcessor(const GrProcessor&) {}
-    ~GLSLSweepProcessor() override {}
 
     virtual void emitCode(EmitArgs&) override;
 
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
index 5277265..41e1843 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
@@ -66,8 +66,6 @@
         return processor->isValid() ? std::move(processor) : nullptr;
     }
 
-    ~Edge2PtConicalEffect() override {}
-
     const char* name() const override {
         return "Two-Point Conical Gradient Edge Touching";
     }
@@ -77,6 +75,10 @@
     SkScalar diffRadius() const { return fDiffRadius; }
     SkScalar radius() const { return fRadius0; }
 
+    sk_sp<GrFragmentProcessor> clone() const override {
+        return sk_sp<GrFragmentProcessor>(new Edge2PtConicalEffect(*this));
+    }
+
 private:
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
 
@@ -90,7 +92,7 @@
                 this->fDiffRadius == s.fDiffRadius);
     }
 
-    Edge2PtConicalEffect(const CreateArgs& args)
+    explicit Edge2PtConicalEffect(const CreateArgs& args)
             : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */) {
         const SkTwoPointConicalGradient& shader =
             *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
@@ -121,6 +123,16 @@
         this->addCoordTransform(&fBTransform);
     }
 
+    explicit Edge2PtConicalEffect(const Edge2PtConicalEffect& that)
+            : INHERITED(that)
+            , fBTransform(that.fBTransform)
+            , fCenterX1(that.fCenterX1)
+            , fRadius0(that.fRadius0)
+            , fDiffRadius(that.fDiffRadius) {
+        this->initClassID<Edge2PtConicalEffect>();
+        this->addCoordTransform(&fBTransform);
+    }
+
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
 
     // @{
@@ -140,7 +152,6 @@
 class Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor : public GrGradientEffect::GLSLProcessor {
 public:
     GLSLEdge2PtConicalProcessor(const GrProcessor&);
-    ~GLSLEdge2PtConicalProcessor() override {}
 
     virtual void emitCode(EmitArgs&) override;
 
@@ -376,12 +387,14 @@
         return processor->isValid() ? std::move(processor) : nullptr;
     }
 
-    ~FocalOutside2PtConicalEffect() override {}
-
     const char* name() const override {
         return "Two-Point Conical Gradient Focal Outside";
     }
 
+    sk_sp<GrFragmentProcessor> clone() const override {
+        return sk_sp<GrFragmentProcessor>(new FocalOutside2PtConicalEffect(*this));
+    }
+
     bool isFlipped() const { return fIsFlipped; }
     SkScalar focal() const { return fFocalX; }
 
@@ -409,6 +422,11 @@
         this->initClassID<FocalOutside2PtConicalEffect>();
     }
 
+    explicit FocalOutside2PtConicalEffect(const FocalOutside2PtConicalEffect& that)
+            : INHERITED(that), fFocalX(that.fFocalX), fIsFlipped(that.fIsFlipped) {
+        this->initClassID<FocalOutside2PtConicalEffect>();
+    }
+
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
 
     SkScalar         fFocalX;
@@ -421,7 +439,6 @@
     : public GrGradientEffect::GLSLProcessor {
 public:
     GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
-    ~GLSLFocalOutside2PtConicalProcessor() override {}
 
     virtual void emitCode(EmitArgs&) override;
 
@@ -590,12 +607,14 @@
         return processor->isValid() ? std::move(processor) : nullptr;
     }
 
-    ~FocalInside2PtConicalEffect() override {}
-
     const char* name() const override {
         return "Two-Point Conical Gradient Focal Inside";
     }
 
+    sk_sp<GrFragmentProcessor> clone() const override {
+        return sk_sp<GrFragmentProcessor>(new FocalInside2PtConicalEffect(*this));
+    }
+
     SkScalar focal() const { return fFocalX; }
 
     typedef FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor GLSLProcessor;
@@ -616,6 +635,11 @@
         this->initClassID<FocalInside2PtConicalEffect>();
     }
 
+    explicit FocalInside2PtConicalEffect(const FocalInside2PtConicalEffect& that)
+            : INHERITED(that), fFocalX(that.fFocalX) {
+        this->initClassID<FocalInside2PtConicalEffect>();
+    }
+
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
 
     SkScalar         fFocalX;
@@ -627,7 +651,6 @@
     : public GrGradientEffect::GLSLProcessor {
 public:
     GLSLFocalInside2PtConicalProcessor(const GrProcessor&);
-    ~GLSLFocalInside2PtConicalProcessor() override {}
 
     virtual void emitCode(EmitArgs&) override;
 
@@ -829,10 +852,12 @@
         return processor->isValid() ? std::move(processor) : nullptr;
     }
 
-    ~CircleInside2PtConicalEffect() override {}
-
     const char* name() const override { return "Two-Point Conical Gradient Inside"; }
 
+    sk_sp<GrFragmentProcessor> clone() const override {
+        return sk_sp<GrFragmentProcessor>(new CircleInside2PtConicalEffect(*this));
+    }
+
     SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
     SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
     SkScalar A() const { return fInfo.fA; }
@@ -859,6 +884,11 @@
         this->initClassID<CircleInside2PtConicalEffect>();
     }
 
+    explicit CircleInside2PtConicalEffect(const CircleInside2PtConicalEffect& that)
+            : INHERITED(that), fInfo(that.fInfo) {
+        this->initClassID<CircleInside2PtConicalEffect>();
+    }
+
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
 
     const CircleConicalInfo fInfo;
@@ -866,11 +896,10 @@
     typedef GrGradientEffect INHERITED;
 };
 
-class CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor 
+class CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
     : public GrGradientEffect::GLSLProcessor {
 public:
     GLSLCircleInside2PtConicalProcessor(const GrProcessor&);
-    ~GLSLCircleInside2PtConicalProcessor() override {}
 
     virtual void emitCode(EmitArgs&) override;
 
@@ -1044,10 +1073,12 @@
             new CircleOutside2PtConicalEffect(args, info));
     }
 
-    ~CircleOutside2PtConicalEffect() override {}
-
     const char* name() const override { return "Two-Point Conical Gradient Outside"; }
 
+    sk_sp<GrFragmentProcessor> clone() const override {
+        return sk_sp<GrFragmentProcessor>(new CircleOutside2PtConicalEffect(*this));
+    }
+
     SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
     SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
     SkScalar A() const { return fInfo.fA; }
@@ -1087,6 +1118,14 @@
         fIsFlipped = shader.isFlippedGrad();
     }
 
+    explicit CircleOutside2PtConicalEffect(const CircleOutside2PtConicalEffect& that)
+            : INHERITED(that)
+            , fInfo(that.fInfo)
+            , fTLimit(that.fTLimit)
+            , fIsFlipped(that.fIsFlipped) {
+        this->initClassID<CircleOutside2PtConicalEffect>();
+    }
+
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
 
     const CircleConicalInfo fInfo;
@@ -1100,7 +1139,6 @@
     : public GrGradientEffect::GLSLProcessor {
 public:
     GLSLCircleOutside2PtConicalProcessor(const GrProcessor&);
-    ~GLSLCircleOutside2PtConicalProcessor() override {}
 
     virtual void emitCode(EmitArgs&) override;