Implement clone() for GrDisplacementEffect

This also adds copy constructors for:
GrTextureDomain
GrFragmentProcessor::TextureSampler
GrCoordTransform
Change-Id: I23cb85113e236f8b6fd1d91163c80d2a41931691
Reviewed-on: https://skia-review.googlesource.com/26621
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 06e7e68..6a7378b 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -191,7 +191,13 @@
     const GrTextureDomain& domain() const { return fDomain; }
     GrColorSpaceXform* colorSpaceXform() const { return fColorSpaceXform.get(); }
 
+    sk_sp<GrFragmentProcessor> clone() const override;
+
 private:
+    static OptimizationFlags OptimizationFlags(GrPixelConfig colorConfig);
+
+    GrDisplacementMapEffect(const GrDisplacementMapEffect&);
+
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
 
     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
@@ -444,6 +450,13 @@
     GrGLDisplacementMapEffect::GenKey(*this, caps, b);
 }
 
+GrFragmentProcessor::OptimizationFlags GrDisplacementMapEffect::OptimizationFlags(
+        GrPixelConfig colorConfig) {
+    return GrPixelConfigIsOpaque(colorConfig)
+                   ? GrFragmentProcessor::kPreservesOpaqueInput_OptimizationFlag
+                   : GrFragmentProcessor::kNone_OptimizationFlags;
+}
+
 GrDisplacementMapEffect::GrDisplacementMapEffect(
         SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
         SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
@@ -453,8 +466,7 @@
         sk_sp<GrTextureProxy> color,
         sk_sp<GrColorSpaceXform> colorSpaceXform,
         const SkISize& colorDimensions)
-        : INHERITED(GrPixelConfigIsOpaque(color->config()) ? kPreservesOpaqueInput_OptimizationFlag
-                                                           : kNone_OptimizationFlags)
+        : INHERITED(OptimizationFlags(color->config()))
         , fDisplacementTransform(offsetMatrix, displacement.get())
         , fDisplacementSampler(displacement)
         , fColorTransform(color.get())
@@ -472,7 +484,28 @@
     this->addTextureSampler(&fColorSampler);
 }
 
-GrDisplacementMapEffect::~GrDisplacementMapEffect() {
+GrDisplacementMapEffect::GrDisplacementMapEffect(const GrDisplacementMapEffect& that)
+        : INHERITED(OptimizationFlags(that.fColorSampler.proxy()->config()))
+        , fDisplacementTransform(that.fDisplacementTransform)
+        , fDisplacementSampler(that.fDisplacementSampler)
+        , fColorTransform(that.fColorTransform)
+        , fDomain(that.fDomain)
+        , fColorSampler(that.fColorSampler)
+        , fColorSpaceXform(that.fColorSpaceXform)
+        , fXChannelSelector(that.fXChannelSelector)
+        , fYChannelSelector(that.fYChannelSelector)
+        , fScale(that.fScale) {
+    this->initClassID<GrDisplacementMapEffect>();
+    this->addCoordTransform(&fDisplacementTransform);
+    this->addTextureSampler(&fDisplacementSampler);
+    this->addCoordTransform(&fColorTransform);
+    this->addTextureSampler(&fColorSampler);
+}
+
+GrDisplacementMapEffect::~GrDisplacementMapEffect() {}
+
+sk_sp<GrFragmentProcessor> GrDisplacementMapEffect::clone() const {
+    return sk_sp<GrFragmentProcessor>(new GrDisplacementMapEffect(*this));
 }
 
 bool GrDisplacementMapEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
@@ -512,6 +545,7 @@
                                          std::move(colorProxy), colorSpaceXform,
                                          colorDimensions);
 }
+
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrCoordTransform.h b/src/gpu/GrCoordTransform.h
index 5bccf5c..5d3faa3 100644
--- a/src/gpu/GrCoordTransform.h
+++ b/src/gpu/GrCoordTransform.h
@@ -18,7 +18,7 @@
  * A class representing a linear transformation of local coordinates. GrFragnentProcessors
  * these transformations, and the GrGeometryProcessor implements the transformation.
  */
-class GrCoordTransform : SkNoncopyable {
+class GrCoordTransform {
 public:
     GrCoordTransform()
         : fProxy(nullptr)
@@ -27,6 +27,8 @@
         SkDEBUGCODE(fInProcessor = false);
     }
 
+    GrCoordTransform(const GrCoordTransform&) = default;
+
     /**
      * Create a transformation that maps [0, 1] to a proxy's boundaries. The proxy origin also
      * implies whether a y-reversal should be performed.
@@ -129,7 +131,6 @@
     const GrTextureProxy*   fProxy;
     bool                    fNormalize;
     bool                    fReverseY;
-    typedef SkNoncopyable INHERITED;
 
 #ifdef SK_DEBUG
 public:
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index a2be518..2afebb7 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -212,12 +212,21 @@
  * along with an associated GrSamplerParams. TextureSamplers don't perform any coord manipulation to
  * account for texture origin.
  */
-class GrResourceIOProcessor::TextureSampler : public SkNoncopyable {
+class GrResourceIOProcessor::TextureSampler {
 public:
     /**
      * Must be initialized before adding to a GrProcessor's texture access list.
      */
     TextureSampler();
+    /**
+     * This copy constructor is used by GrFragmentProcessor::clone() implementations. The copy
+     * always takes a new ref on the texture proxy as the new fragment processor will not yet be
+     * in pending execution state.
+     */
+    explicit TextureSampler(const TextureSampler& that)
+            : fProxyRef(sk_ref_sp(that.fProxyRef.get()), that.fProxyRef.ioType())
+            , fParams(that.fParams)
+            , fVisibility(that.fVisibility) {}
 
     TextureSampler(sk_sp<GrTextureProxy>, const GrSamplerParams&);
     explicit TextureSampler(sk_sp<GrTextureProxy>,
@@ -264,8 +273,6 @@
     GrSurfaceProxyRef               fProxyRef;
     GrSamplerParams                 fParams;
     GrShaderFlags                   fVisibility;
-
-    typedef SkNoncopyable INHERITED;
 };
 
 /**
diff --git a/src/gpu/effects/GrTextureDomain.h b/src/gpu/effects/GrTextureDomain.h
index 8be1a2b..f6970ea 100644
--- a/src/gpu/effects/GrTextureDomain.h
+++ b/src/gpu/effects/GrTextureDomain.h
@@ -55,6 +55,8 @@
      */
     GrTextureDomain(GrTextureProxy*, const SkRect& domain, Mode, int index = -1);
 
+    GrTextureDomain(const GrTextureDomain&) = default;
+
     const SkRect& domain() const { return fDomain; }
     Mode mode() const { return fMode; }