Store the dst texture used by an XP in GrPipeline rather than in the XP.

This will allow the XP to be created before the dst texture.

Change-Id: I3e5bdfa8e5d47e58a3560792ce5cf3899d30a024
Reviewed-on: https://skia-review.googlesource.com/11011
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index 2917dcb..960cd8a 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -61,18 +61,20 @@
         sk_sp<GrXferProcessor> xferProcessor;
         const GrXPFactory* xpFactory = args.fProcessors->xpFactory();
         if (xpFactory) {
-            xferProcessor.reset(xpFactory->createXferProcessor(args.fInputColor,
-                                                               args.fInputCoverage, hasMixedSamples,
-                                                               &args.fDstTexture, *args.fCaps));
+            xferProcessor.reset(xpFactory->createXferProcessor(
+                    args.fInputColor, args.fInputCoverage, hasMixedSamples, *args.fCaps));
             SkASSERT(xferProcessor);
         } else {
             // This may return nullptr in the common case of src-over implemented using hw blending.
             xferProcessor.reset(GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
-                    *args.fCaps, args.fInputColor, args.fInputCoverage, hasMixedSamples,
-                    &args.fDstTexture));
+                    *args.fCaps, args.fInputColor, args.fInputCoverage, hasMixedSamples));
         }
         fXferProcessor.reset(xferProcessor.get());
     }
+    if (args.fDstTexture.texture()) {
+        fDstTexture.reset(args.fDstTexture.texture());
+        fDstTextureOffset = args.fDstTexture.offset();
+    }
 
     // This is for the legacy GrPipeline creation in GrLegacyMeshDrawOp where analysis does not
     // eliminate fragment processors from GrProcessorSet.
@@ -130,12 +132,9 @@
         add_dependencies_for_processor(fFragmentProcessors[i].get(), rt);
     }
 
-    const GrXferProcessor& xfer = this->getXferProcessor();
-
-    for (int i = 0; i < xfer.numTextureSamplers(); ++i) {
-        GrTexture* texture = xfer.textureSampler(i).texture();
+    if (fDstTexture) {
         SkASSERT(rt->getLastOpList());
-        rt->getLastOpList()->addDependency(texture);
+        rt->getLastOpList()->addDependency(fDstTexture.get());
     }
 }
 
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index 91cd164..d7a4f4e 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -144,6 +144,17 @@
         }
     }
 
+    /**
+     * If the GrXferProcessor uses a texture to access the dst color, then this returns that
+     * texture and the offset to the dst contents within that texture.
+     */
+    GrTexture* dstTexture(SkIPoint* offset = nullptr) const {
+        if (offset) {
+            *offset = fDstTextureOffset;
+        }
+        return fDstTexture.get();
+    }
+
     const GrFragmentProcessor& getColorFragmentProcessor(int idx) const {
         SkASSERT(idx < this->numColorFragmentProcessors());
         return *fFragmentProcessors[idx].get();
@@ -194,7 +205,10 @@
     }
 
     GrXferBarrierType xferBarrierType(const GrCaps& caps) const {
-        return this->getXferProcessor().xferBarrierType(fRenderTarget.get(), caps);
+        if (fDstTexture.get() && fDstTexture.get() == fRenderTarget.get()->asTexture()) {
+            return kTexture_GrXferBarrierType;
+        }
+        return this->getXferProcessor().xferBarrierType(caps);
     }
 
     /**
@@ -214,21 +228,25 @@
         kStencilEnabled_Flag = 0x40,
     };
 
-    typedef GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> RenderTarget;
-    typedef GrPendingProgramElement<const GrFragmentProcessor> PendingFragmentProcessor;
-    typedef SkAutoSTArray<8, PendingFragmentProcessor> FragmentProcessorArray;
-    typedef GrPendingProgramElement<const GrXferProcessor> ProgramXferProcessor;
-    RenderTarget                        fRenderTarget;
-    GrScissorState                      fScissorState;
-    GrWindowRectsState                  fWindowRectsState;
-    const GrUserStencilSettings*        fUserStencilSettings;
-    uint16_t                            fDrawFace;
-    uint16_t                            fFlags;
-    ProgramXferProcessor                fXferProcessor;
-    FragmentProcessorArray              fFragmentProcessors;
+    using RenderTarget = GrPendingIOResource<GrRenderTarget, kWrite_GrIOType>;
+    using DstTexture = GrPendingIOResource<GrTexture, kRead_GrIOType>;
+    using PendingFragmentProcessor = GrPendingProgramElement<const GrFragmentProcessor>;
+    using FragmentProcessorArray = SkAutoSTArray<8, PendingFragmentProcessor>;
+    using ProgramXferProcessor = GrPendingProgramElement<const GrXferProcessor>;
+
+    DstTexture fDstTexture;
+    SkIPoint fDstTextureOffset;
+    RenderTarget fRenderTarget;
+    GrScissorState fScissorState;
+    GrWindowRectsState fWindowRectsState;
+    const GrUserStencilSettings* fUserStencilSettings;
+    uint16_t fDrawFace;
+    uint16_t fFlags;
+    ProgramXferProcessor fXferProcessor;
+    FragmentProcessorArray fFragmentProcessors;
 
     // This value is also the index in fFragmentProcessors where coverage processors begin.
-    int                                 fNumColorProcessors;
+    int fNumColorProcessors;
 
     typedef SkRefCnt INHERITED;
 };
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index 0e40a85..0b7d2c3 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -180,7 +180,13 @@
     }
 
     const GrXferProcessor& xp = pipeline.getXferProcessor();
-    xp.getGLSLProcessorKey(shaderCaps, &b);
+    const GrSurfaceOrigin* originIfDstTexture = nullptr;
+    GrSurfaceOrigin origin;
+    if (pipeline.dstTexture()) {
+        origin = pipeline.dstTexture()->origin();
+        originIfDstTexture = &origin;
+    }
+    xp.getGLSLProcessorKey(shaderCaps, &b, originIfDstTexture);
     if (!gen_meta_key(xp, shaderCaps, 0, &b)) {
         desc->key().reset();
         return false;
diff --git a/src/gpu/GrXferProcessor.cpp b/src/gpu/GrXferProcessor.cpp
index 839fea6..b04a5cc 100644
--- a/src/gpu/GrXferProcessor.cpp
+++ b/src/gpu/GrXferProcessor.cpp
@@ -9,25 +9,11 @@
 #include "GrPipeline.h"
 #include "gl/GrGLCaps.h"
 
-GrXferProcessor::GrXferProcessor()
-    : fWillReadDstColor(false)
-    , fDstReadUsesMixedSamples(false)
-    , fDstTextureOffset() {
-}
+GrXferProcessor::GrXferProcessor() : fWillReadDstColor(false), fDstReadUsesMixedSamples(false) {}
 
-GrXferProcessor::GrXferProcessor(const DstTexture* dstTexture,
-                                 bool willReadDstColor,
-                                 bool hasMixedSamples)
-    : fWillReadDstColor(willReadDstColor)
-    , fDstReadUsesMixedSamples(willReadDstColor && hasMixedSamples)
-    , fDstTextureOffset() {
-    if (dstTexture && dstTexture->texture()) {
-        SkASSERT(willReadDstColor);
-        fDstTexture.reset(dstTexture->texture());
-        fDstTextureOffset = dstTexture->offset();
-        this->addTextureSampler(&fDstTexture);
-    }
-}
+GrXferProcessor::GrXferProcessor(bool willReadDstColor, bool hasMixedSamples)
+        : fWillReadDstColor(willReadDstColor)
+        , fDstReadUsesMixedSamples(willReadDstColor && hasMixedSamples) {}
 
 bool GrXferProcessor::hasSecondaryOutput() const {
     if (!this->willReadDstColor()) {
@@ -45,13 +31,13 @@
     }
 }
 
-void GrXferProcessor::getGLSLProcessorKey(const GrShaderCaps& caps,
-                                          GrProcessorKeyBuilder* b) const {
+void GrXferProcessor::getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b,
+                                          const GrSurfaceOrigin* originIfDstTexture) const {
     uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
     if (key) {
-        if (const GrTexture* dstTexture = this->getDstTexture()) {
+        if (originIfDstTexture) {
             key |= 0x2;
-            if (kTopLeft_GrSurfaceOrigin == dstTexture->origin()) {
+            if (kTopLeft_GrSurfaceOrigin == *originIfDstTexture) {
                 key |= 0x4;
             }
         }
@@ -63,17 +49,6 @@
     this->onGetGLSLProcessorKey(caps, b);
 }
 
-GrXferBarrierType GrXferProcessor::xferBarrierType(const GrRenderTarget* rt,
-                                                   const GrCaps& caps) const {
-    SkASSERT(rt);
-    if (static_cast<const GrSurface*>(rt) == this->getDstTexture()) {
-        // Texture barriers are required when a shader reads and renders to the same texture.
-        SkASSERT(caps.textureBarrierSupport());
-        return kTexture_GrXferBarrierType;
-    }
-    return this->onXferBarrier(caps);
-}
-
 #ifdef SK_DEBUG
 static const char* equation_string(GrBlendEquation eq) {
     switch (eq) {
@@ -195,8 +170,7 @@
 GrXferProcessor* GrXPFactory::createXferProcessor(const GrProcessorAnalysisColor& color,
                                                   GrProcessorAnalysisCoverage coverage,
                                                   bool hasMixedSamples,
-                                                  const DstTexture* dstTexture,
                                                   const GrCaps& caps) const {
     SkASSERT(!hasMixedSamples || caps.shaderCaps()->dualSourceBlendingSupport());
-    return this->onCreateXferProcessor(caps, color, coverage, hasMixedSamples, dstTexture);
+    return this->onCreateXferProcessor(caps, color, coverage, hasMixedSamples);
 }
diff --git a/src/gpu/GrXferProcessor.h b/src/gpu/GrXferProcessor.h
index 596e849..b65a125 100644
--- a/src/gpu/GrXferProcessor.h
+++ b/src/gpu/GrXferProcessor.h
@@ -97,8 +97,10 @@
     /**
      * Sets a unique key on the GrProcessorKeyBuilder calls onGetGLSLProcessorKey(...) to get the
      * specific subclass's key.
-     */ 
-    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const;
+     */
+    void getGLSLProcessorKey(const GrShaderCaps&,
+                             GrProcessorKeyBuilder*,
+                             const GrSurfaceOrigin* originIfDstTexture) const;
 
     /** Returns a new instance of the appropriate *GL* implementation class
         for the given GrXferProcessor; caller is responsible for deleting
@@ -106,10 +108,13 @@
     virtual GrGLSLXferProcessor* createGLSLInstance() const = 0;
 
     /**
-     * Returns whether this XP will require an Xfer barrier on the given rt. If true, outBarrierType
-     * is updated to contain the type of barrier needed.
+     * Returns the barrier type, if any, that this XP will require. Note that the possibility
+     * that a kTexture type barrier is required is handled by the GrPipeline and need not be
+     * considered by subclass overrides of this function.
      */
-    GrXferBarrierType xferBarrierType(const GrRenderTarget* rt, const GrCaps& caps) const;
+    virtual GrXferBarrierType xferBarrierType(const GrCaps& caps) const {
+        return kNone_GrXferBarrierType;
+    }
 
     struct BlendInfo {
         void reset() {
@@ -134,22 +139,6 @@
     bool willReadDstColor() const { return fWillReadDstColor; }
 
     /**
-     * Returns the texture to be used as the destination when reading the dst in the fragment
-     * shader. If the returned texture is NULL then the XP is either not reading the dst or we have
-     * extentions that support framebuffer fetching and thus don't need a copy of the dst texture.
-     */
-    const GrTexture* getDstTexture() const { return fDstTexture.texture(); }
-
-    /**
-     * Returns the offset in device coords to use when accessing the dst texture to get the dst
-     * pixel color in the shader. This value is only valid if getDstTexture() != NULL.
-     */
-    const SkIPoint& dstTextureOffset() const {
-        SkASSERT(this->getDstTexture());
-        return fDstTextureOffset;
-    }
-
-    /**
      * If we are performing a dst read, returns whether the base class will use mixed samples to
      * antialias the shader's final output. If not doing a dst read, the subclass is responsible
      * for antialiasing and this returns false.
@@ -177,12 +166,6 @@
         if (this->fWillReadDstColor != that.fWillReadDstColor) {
             return false;
         }
-        if (this->fDstTexture.texture() != that.fDstTexture.texture()) {
-            return false;
-        }
-        if (this->fDstTextureOffset != that.fDstTextureOffset) {
-            return false;
-        }
         if (this->fDstReadUsesMixedSamples != that.fDstReadUsesMixedSamples) {
             return false;
         }
@@ -191,7 +174,7 @@
 
 protected:
     GrXferProcessor();
-    GrXferProcessor(const DstTexture*, bool willReadDstColor, bool hasMixedSamples);
+    GrXferProcessor(bool willReadDstColor, bool hasMixedSamples);
 
 private:
     void notifyRefCntIsZero() const final {}
@@ -203,15 +186,6 @@
     virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
 
     /**
-     * Determines the type of barrier (if any) required by the subclass. Note that the possibility
-     * that a kTexture type barrier is required is handled by the base class and need not be
-     * considered by subclass overrides of this function.
-     */
-    virtual GrXferBarrierType onXferBarrier(const GrCaps&) const {
-        return kNone_GrXferBarrierType;
-    }
-
-    /**
      * If we are not performing a dst read, returns whether the subclass will set a secondary
      * output. When using dst reads, the base class controls the secondary output and this method
      * will not be called.
@@ -229,8 +203,6 @@
 
     bool                    fWillReadDstColor;
     bool                    fDstReadUsesMixedSamples;
-    SkIPoint                fDstTextureOffset;
-    TextureSampler          fDstTexture;
 
     typedef GrFragmentProcessor INHERITED;
 };
@@ -267,7 +239,6 @@
     GrXferProcessor* createXferProcessor(const GrProcessorAnalysisColor&,
                                          GrProcessorAnalysisCoverage,
                                          bool hasMixedSamples,
-                                         const DstTexture*,
                                          const GrCaps& caps) const;
 
     enum class AnalysisProperties : unsigned {
@@ -314,8 +285,7 @@
     virtual GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
                                                    const GrProcessorAnalysisColor&,
                                                    GrProcessorAnalysisCoverage,
-                                                   bool hasMixedSamples,
-                                                   const DstTexture*) const = 0;
+                                                   bool hasMixedSamples) const = 0;
 
     /**
      * Subclass analysis implementation. This should not return kNeedsDstInTexture as that will be
diff --git a/src/gpu/effects/GrCoverageSetOpXP.cpp b/src/gpu/effects/GrCoverageSetOpXP.cpp
index 1319c1f..4d4b00a 100644
--- a/src/gpu/effects/GrCoverageSetOpXP.cpp
+++ b/src/gpu/effects/GrCoverageSetOpXP.cpp
@@ -221,8 +221,7 @@
 GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& caps,
                                                                  const GrProcessorAnalysisColor&,
                                                                  GrProcessorAnalysisCoverage,
-                                                                 bool hasMixedSamples,
-                                                                 const DstTexture*) const {
+                                                                 bool hasMixedSamples) const {
     // We don't support inverting coverage with mixed samples. We don't expect to ever want this in
     // the future, however we could at some point make this work using an inverted coverage
     // modulation table. Note that an inverted table still won't work if there are coverage procs.
diff --git a/src/gpu/effects/GrCoverageSetOpXP.h b/src/gpu/effects/GrCoverageSetOpXP.h
index 2e1feed..a0fe4f9 100644
--- a/src/gpu/effects/GrCoverageSetOpXP.h
+++ b/src/gpu/effects/GrCoverageSetOpXP.h
@@ -31,8 +31,8 @@
     constexpr GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage);
 
     GrXferProcessor* onCreateXferProcessor(const GrCaps&, const GrProcessorAnalysisColor&,
-                                           GrProcessorAnalysisCoverage, bool hasMixedSamples,
-                                           const DstTexture*) const override;
+                                           GrProcessorAnalysisCoverage,
+                                           bool hasMixedSamples) const override;
 
     AnalysisProperties analysisProperties(const GrProcessorAnalysisColor&,
                                           const GrProcessorAnalysisCoverage&,
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index 5f21c75..8d7c410 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -78,10 +78,10 @@
         this->initClassID<CustomXP>();
     }
 
-    CustomXP(const DstTexture* dstTexture, bool hasMixedSamples, SkBlendMode mode)
-        : INHERITED(dstTexture, true, hasMixedSamples),
-          fMode(mode),
-          fHWBlendEquation(static_cast<GrBlendEquation>(-1)) {
+    CustomXP(bool hasMixedSamples, SkBlendMode mode)
+            : INHERITED(true, hasMixedSamples)
+            , fMode(mode)
+            , fHWBlendEquation(static_cast<GrBlendEquation>(-1)) {
         this->initClassID<CustomXP>();
     }
 
@@ -97,11 +97,11 @@
         return fHWBlendEquation;
     }
 
+    GrXferBarrierType xferBarrierType(const GrCaps&) const override;
+
 private:
     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
 
-    GrXferBarrierType onXferBarrier(const GrCaps&) const override;
-
     void onGetBlendInfo(BlendInfo*) const override;
 
     bool onIsEqual(const GrXferProcessor& xpBase) const override;
@@ -187,7 +187,7 @@
     return fMode == s.fMode && fHWBlendEquation == s.fHWBlendEquation;
 }
 
-GrXferBarrierType CustomXP::onXferBarrier(const GrCaps& caps) const {
+GrXferBarrierType CustomXP::xferBarrierType(const GrCaps& caps) const {
     if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport()) {
         return kBlend_GrXferBarrierType;
     }
@@ -214,8 +214,8 @@
 
 private:
     GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, const GrProcessorAnalysisColor&,
-                                           GrProcessorAnalysisCoverage, bool hasMixedSamples,
-                                           const DstTexture*) const override;
+                                           GrProcessorAnalysisCoverage,
+                                           bool hasMixedSamples) const override;
 
     AnalysisProperties analysisProperties(const GrProcessorAnalysisColor&,
                                           const GrProcessorAnalysisCoverage&,
@@ -235,14 +235,12 @@
 GrXferProcessor* CustomXPFactory::onCreateXferProcessor(const GrCaps& caps,
                                                         const GrProcessorAnalysisColor&,
                                                         GrProcessorAnalysisCoverage coverage,
-                                                        bool hasMixedSamples,
-                                                        const DstTexture* dstTexture) const {
+                                                        bool hasMixedSamples) const {
     SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
     if (can_use_hw_blend_equation(fHWBlendEquation, coverage, caps)) {
-        SkASSERT(!dstTexture || !dstTexture->texture());
         return new CustomXP(fMode, fHWBlendEquation);
     }
-    return new CustomXP(dstTexture, hasMixedSamples, fMode);
+    return new CustomXP(hasMixedSamples, fMode);
 }
 
 GrXPFactory::AnalysisProperties CustomXPFactory::analysisProperties(
diff --git a/src/gpu/effects/GrDisableColorXP.cpp b/src/gpu/effects/GrDisableColorXP.cpp
index 4780b28..917f5c8 100644
--- a/src/gpu/effects/GrDisableColorXP.cpp
+++ b/src/gpu/effects/GrDisableColorXP.cpp
@@ -84,8 +84,7 @@
 GrXferProcessor* GrDisableColorXPFactory::onCreateXferProcessor(const GrCaps& caps,
                                                                 const GrProcessorAnalysisColor&,
                                                                 GrProcessorAnalysisCoverage,
-                                                                bool hasMixedSamples,
-                                                                const DstTexture* dst) const {
+                                                                bool hasMixedSamples) const {
     return DisableColorXP::Create();
 }
 
diff --git a/src/gpu/effects/GrDisableColorXP.h b/src/gpu/effects/GrDisableColorXP.h
index ccd85c7..b3c4677 100644
--- a/src/gpu/effects/GrDisableColorXP.h
+++ b/src/gpu/effects/GrDisableColorXP.h
@@ -32,8 +32,8 @@
     }
 
     GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, const GrProcessorAnalysisColor&,
-                                           GrProcessorAnalysisCoverage, bool hasMixedSamples,
-                                           const DstTexture* dstTexture) const override;
+                                           GrProcessorAnalysisCoverage,
+                                           bool hasMixedSamples) const override;
 
     GR_DECLARE_XP_FACTORY_TEST;
 
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index 646f942..da73f4b 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -447,11 +447,8 @@
 
 class ShaderPDXferProcessor : public GrXferProcessor {
 public:
-    ShaderPDXferProcessor(const DstTexture* dstTexture,
-                          bool hasMixedSamples,
-                          SkBlendMode xfermode)
-        : INHERITED(dstTexture, true, hasMixedSamples)
-        , fXfermode(xfermode) {
+    ShaderPDXferProcessor(bool hasMixedSamples, SkBlendMode xfermode)
+            : INHERITED(true, hasMixedSamples), fXfermode(xfermode) {
         this->initClassID<ShaderPDXferProcessor>();
     }
 
@@ -702,8 +699,7 @@
 GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
                                                               const GrProcessorAnalysisColor& color,
                                                               GrProcessorAnalysisCoverage coverage,
-                                                              bool hasMixedSamples,
-                                                              const DstTexture* dstTexture) const {
+                                                              bool hasMixedSamples) const {
     BlendFormula blendFormula;
     if (coverage == GrProcessorAnalysisCoverage::kLCD) {
         if (SkBlendMode::kSrcOver == fBlendMode && color.isConstant() &&
@@ -711,7 +707,6 @@
             !caps.shaderCaps()->dstReadInShaderSupport()) {
             // If we don't have dual source blending or in shader dst reads, we fall back to this
             // trick for rendering SrcOver LCD text instead of doing a dst copy.
-            SkASSERT(!dstTexture || !dstTexture->texture());
             return PDLCDXferProcessor::Create(fBlendMode, color);
         }
         blendFormula = get_lcd_blend_formula(fBlendMode);
@@ -722,10 +717,8 @@
     }
 
     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
-        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fBlendMode);
+        return new ShaderPDXferProcessor(hasMixedSamples, fBlendMode);
     }
-
-    SkASSERT(!dstTexture || !dstTexture->texture());
     return new PorterDuffXferProcessor(blendFormula);
 }
 
@@ -813,8 +806,7 @@
         const GrCaps& caps,
         const GrProcessorAnalysisColor& color,
         GrProcessorAnalysisCoverage coverage,
-        bool hasMixedSamples,
-        const GrXferProcessor::DstTexture* dstTexture) {
+        bool hasMixedSamples) {
     // We want to not make an xfer processor if possible. Thus for the simple case where we are not
     // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
     // the general case where we convert a src-over blend that has solid coverage and an opaque
@@ -832,17 +824,14 @@
         // If we don't have dual source blending or in shader dst reads, we fall
         // back to this trick for rendering SrcOver LCD text instead of doing a
         // dst copy.
-        SkASSERT(!dstTexture || !dstTexture->texture());
         return PDLCDXferProcessor::Create(SkBlendMode::kSrcOver, color);
     }
 
     BlendFormula blendFormula;
     blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
-        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkBlendMode::kSrcOver);
+        return new ShaderPDXferProcessor(hasMixedSamples, SkBlendMode::kSrcOver);
     }
-
-    SkASSERT(!dstTexture || !dstTexture->texture());
     return new PorterDuffXferProcessor(blendFormula);
 }
 
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.h b/src/gpu/effects/GrPorterDuffXferProcessor.h
index d42146a..6effc18 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.h
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.h
@@ -26,8 +26,7 @@
     static GrXferProcessor* CreateSrcOverXferProcessor(const GrCaps& caps,
                                                        const GrProcessorAnalysisColor& color,
                                                        GrProcessorAnalysisCoverage coverage,
-                                                       bool hasMixedSamples,
-                                                       const GrXferProcessor::DstTexture*);
+                                                       bool hasMixedSamples);
 
     /** Returns a simple non-LCD porter duff blend XP with no optimizations or coverage. */
     static sk_sp<GrXferProcessor> CreateNoCoverageXP(SkBlendMode);
@@ -44,8 +43,8 @@
     constexpr GrPorterDuffXPFactory(SkBlendMode);
 
     GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, const GrProcessorAnalysisColor&,
-                                           GrProcessorAnalysisCoverage, bool hasMixedSamples,
-                                           const DstTexture*) const override;
+                                           GrProcessorAnalysisCoverage,
+                                           bool hasMixedSamples) const override;
 
     AnalysisProperties analysisProperties(const GrProcessorAnalysisColor&,
                                           const GrProcessorAnalysisCoverage&,
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 2aa572d..29fe35c 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -78,8 +78,13 @@
     this->setFragmentData(primProc, pipeline, &nextSamplerIdx);
 
     const GrXferProcessor& xp = pipeline.getXferProcessor();
-    fXferProcessor->setData(fProgramDataManager, xp);
-    this->bindTextures(xp, pipeline.getAllowSRGBInputs(), &nextSamplerIdx);
+    SkIPoint offset;
+    GrTexture* dstTexture = pipeline.dstTexture(&offset);
+    fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset);
+    if (dstTexture) {
+        fGpu->bindTexture(nextSamplerIdx++, GrSamplerParams::ClampNoFilter(), true,
+                          static_cast<GrGLTexture*>(dstTexture));
+    }
 }
 
 void GrGLProgram::generateMipmaps(const GrPrimitiveProcessor& primProc,
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 1fcf040..4cd4fd6 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -62,7 +62,7 @@
     this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage);
 
     this->emitAndInstallFragProcs(inputColor, inputCoverage);
-    this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor, *inputCoverage);
+    this->emitAndInstallXferProc(*inputColor, *inputCoverage);
     this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
 
     return this->checkSamplerCounts() && this->checkImageStorageCounts();
@@ -211,13 +211,13 @@
     fFS.codeAppend("}");
 }
 
-void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
-                                                  const GrGLSLExpr4& colorIn,
+void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrGLSLExpr4& colorIn,
                                                   const GrGLSLExpr4& coverageIn) {
     // Program builders have a bit of state we need to clear with each effect
     AutoStageAdvance adv(this);
 
     SkASSERT(!fXferProcessor);
+    const GrXferProcessor& xp = fPipeline.getXferProcessor();
     fXferProcessor = xp.createGLSLInstance();
 
     // Enable dual source secondary output if we have one
@@ -233,21 +233,28 @@
     openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
     fFS.codeAppend(openBrace.c_str());
 
-    SkSTArray<4, SamplerHandle>      texSamplers(xp.numTextureSamplers());
-    SkSTArray<2, SamplerHandle>      bufferSamplers(xp.numBuffers());
-    SkSTArray<2, ImageStorageHandle> imageStorageArray(xp.numImageStorages());
-    this->emitSamplersAndImageStorages(xp, &texSamplers, &bufferSamplers, &imageStorageArray);
+    SamplerHandle dstTextureSamplerHandle;
+    GrSurfaceOrigin dstTextureOrigin = kTopLeft_GrSurfaceOrigin;
+    if (GrTexture* dstTexture = fPipeline.dstTexture()) {
+        // GrProcessor::TextureSampler sampler(dstTexture);
+        SkString name("DstTextureSampler");
+        dstTextureSamplerHandle =
+                this->emitSampler(dstTexture->texturePriv().samplerType(), dstTexture->config(),
+                                  "DstTextureSampler", kFragment_GrShaderFlag);
+        dstTextureOrigin = dstTexture->origin();
+        SkASSERT(kTextureExternalSampler_GrSLType != dstTexture->texturePriv().samplerType());
+    }
 
     GrGLSLXferProcessor::EmitArgs args(&fFS,
                                        this->uniformHandler(),
                                        this->shaderCaps(),
-                                       xp, colorIn.c_str(),
+                                       xp,
+                                       colorIn.c_str(),
                                        coverageIn.c_str(),
                                        fFS.getPrimaryColorOutputName(),
                                        fFS.getSecondaryColorOutputName(),
-                                       texSamplers.begin(),
-                                       bufferSamplers.begin(),
-                                       imageStorageArray.begin());
+                                       dstTextureSamplerHandle,
+                                       dstTextureOrigin);
     fXferProcessor->emitCode(args);
 
     // We have to check that effects and the code they emit are consistent, ie if an effect
@@ -276,11 +283,9 @@
                              1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature,
                              externalFeatureString);
         }
-        this->emitSampler(samplerType, sampler.texture()->config(), name.c_str(),
-                          sampler.visibility(), outTexSamplerHandles);
-
+        outTexSamplerHandles->emplace_back(this->emitSampler(
+                samplerType, sampler.texture()->config(), name.c_str(), sampler.visibility()));
     }
-
     if (int numBuffers = processor.numBuffers()) {
         SkASSERT(this->shaderCaps()->texelBufferSupport());
         GrShaderFlags texelBufferVisibility = kNone_GrShaderFlags;
@@ -288,8 +293,9 @@
         for (int b = 0; b < numBuffers; ++b) {
             const GrProcessor::BufferAccess& access = processor.bufferAccess(b);
             name.printf("BufferSampler_%d", outBufferSamplerHandles->count());
-            this->emitSampler(kBufferSampler_GrSLType, access.texelConfig(), name.c_str(),
-                              access.visibility(), outBufferSamplerHandles);
+            outBufferSamplerHandles->emplace_back(
+                    this->emitSampler(kBufferSampler_GrSLType, access.texelConfig(), name.c_str(),
+                                      access.visibility()));
             texelBufferVisibility |= access.visibility();
         }
 
@@ -303,15 +309,15 @@
     for (int i = 0; i < numImageStorages; ++i) {
         const GrProcessor::ImageStorageAccess& imageStorageAccess = processor.imageStorageAccess(i);
         name.printf("Image_%d", outImageStorageHandles->count());
-        this->emitImageStorage(imageStorageAccess, name.c_str(), outImageStorageHandles);
+        outImageStorageHandles->emplace_back(
+                this->emitImageStorage(imageStorageAccess, name.c_str()));
     }
 }
 
-void GrGLSLProgramBuilder::emitSampler(GrSLType samplerType,
-                                       GrPixelConfig config,
-                                       const char* name,
-                                       GrShaderFlags visibility,
-                                       SkTArray<SamplerHandle>* outSamplerHandles) {
+GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(GrSLType samplerType,
+                                                                      GrPixelConfig config,
+                                                                      const char* name,
+                                                                      GrShaderFlags visibility) {
     if (visibility & kVertex_GrShaderFlag) {
         ++fNumVertexSamplers;
     }
@@ -324,16 +330,11 @@
     }
     GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility);
     GrSwizzle swizzle = this->shaderCaps()->configTextureSwizzle(config);
-    outSamplerHandles->emplace_back(this->uniformHandler()->addSampler(visibility,
-                                                                       swizzle,
-                                                                       samplerType,
-                                                                       precision,
-                                                                       name));
+    return this->uniformHandler()->addSampler(visibility, swizzle, samplerType, precision, name);
 }
 
-void GrGLSLProgramBuilder::emitImageStorage(const GrProcessor::ImageStorageAccess& access,
-                                            const char* name,
-                                            SkTArray<ImageStorageHandle>* outImageStorageHandles) {
+GrGLSLProgramBuilder::ImageStorageHandle GrGLSLProgramBuilder::emitImageStorage(
+        const GrProcessor::ImageStorageAccess& access, const char* name) {
     if (access.visibility() & kVertex_GrShaderFlag) {
         ++fNumVertexImageStorages;
     }
@@ -345,10 +346,9 @@
         ++fNumFragmentImageStorages;
     }
     GrSLType uniformType = access.texture()->texturePriv().imageStorageType();
-    ImageStorageHandle handle = this->uniformHandler()->addImageStorage(access.visibility(),
-         uniformType, access.format(), access.memoryModel(), access.restrict(), access.ioType(),
-         name);
-    outImageStorageHandles->emplace_back(handle);
+    return this->uniformHandler()->addImageStorage(access.visibility(), uniformType,
+                                                   access.format(), access.memoryModel(),
+                                                   access.restrict(), access.ioType(), name);
 }
 
 void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h
index 7486646..2d2ab47 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.h
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.h
@@ -152,18 +152,14 @@
                                 int transformedCoordVarsIdx,
                                 const GrGLSLExpr4& input,
                                 GrGLSLExpr4* output);
-    void emitAndInstallXferProc(const GrXferProcessor&,
-                                const GrGLSLExpr4& colorIn,
-                                const GrGLSLExpr4& coverageIn);
+    void emitAndInstallXferProc(const GrGLSLExpr4& colorIn, const GrGLSLExpr4& coverageIn);
     void emitSamplersAndImageStorages(const GrProcessor& processor,
                                       SkTArray<SamplerHandle>* outTexSamplerHandles,
                                       SkTArray<SamplerHandle>* outBufferSamplerHandles,
                                       SkTArray<ImageStorageHandle>* outImageStorageHandles);
-    void emitSampler(GrSLType samplerType, GrPixelConfig, const char* name,
-                     GrShaderFlags visibility, SkTArray<SamplerHandle >* outSamplerHandles);
-    void emitImageStorage(const GrProcessor::ImageStorageAccess&,
-                          const char* name,
-                          SkTArray<ImageStorageHandle>* outImageStorageHandles);
+    SamplerHandle emitSampler(GrSLType samplerType, GrPixelConfig, const char* name,
+                              GrShaderFlags visibility);
+    ImageStorageHandle emitImageStorage(const GrProcessor::ImageStorageAccess&, const char* name);
     void emitFSOutputSwizzle(bool hasSecondaryOutput);
     bool checkSamplerCounts();
     bool checkImageStorageCounts();
diff --git a/src/gpu/glsl/GrGLSLXferProcessor.cpp b/src/gpu/glsl/GrGLSLXferProcessor.cpp
index 4101080..545a9fd 100644
--- a/src/gpu/glsl/GrGLSLXferProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLXferProcessor.cpp
@@ -25,8 +25,8 @@
 
     bool needsLocalOutColor = false;
 
-    if (args.fXP.getDstTexture()) {
-        bool topDown = kTopLeft_GrSurfaceOrigin == args.fXP.getDstTexture()->origin();
+    if (args.fDstTextureSamplerHandle.isValid()) {
+        bool flipY = kBottomLeft_GrSurfaceOrigin == args.fDstTextureOrigin;
 
         if (args.fInputCoverage) {
             // We don't think any shaders actually output negative coverage, but just as a safety
@@ -54,12 +54,13 @@
         fragBuilder->codeAppendf("vec2 _dstTexCoord = (sk_FragCoord.xy - %s) * %s;",
                                  dstTopLeftName, dstCoordScaleName);
 
-        if (!topDown) {
+        if (flipY) {
             fragBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
         }
 
         fragBuilder->codeAppendf("vec4 %s = ", dstColor);
-        fragBuilder->appendTextureLookup(args.fTexSamplers[0], "_dstTexCoord", kVec2f_GrSLType);
+        fragBuilder->appendTextureLookup(args.fDstTextureSamplerHandle, "_dstTexCoord",
+                                         kVec2f_GrSLType);
         fragBuilder->codeAppend(";");
     } else {
         needsLocalOutColor = args.fShaderCaps->requiresLocalOutputColorForFBFetch();
@@ -85,13 +86,13 @@
     }
 }
 
-void GrGLSLXferProcessor::setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) {
-    if (xp.getDstTexture()) {
+void GrGLSLXferProcessor::setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp,
+                                  const GrTexture* dstTexture, const SkIPoint& dstTextureOffset) {
+    if (dstTexture) {
         if (fDstTopLeftUni.isValid()) {
-            pdm.set2f(fDstTopLeftUni, static_cast<float>(xp.dstTextureOffset().fX),
-                      static_cast<float>(xp.dstTextureOffset().fY));
-            pdm.set2f(fDstScaleUni, 1.f / xp.getDstTexture()->width(),
-                      1.f / xp.getDstTexture()->height());
+            pdm.set2f(fDstTopLeftUni, static_cast<float>(dstTextureOffset.fX),
+                      static_cast<float>(dstTextureOffset.fY));
+            pdm.set2f(fDstScaleUni, 1.f / dstTexture->width(), 1.f / dstTexture->height());
         } else {
             SkASSERT(!fDstScaleUni.isValid());
         }
diff --git a/src/gpu/glsl/GrGLSLXferProcessor.h b/src/gpu/glsl/GrGLSLXferProcessor.h
index b4bde37..791bb06 100644
--- a/src/gpu/glsl/GrGLSLXferProcessor.h
+++ b/src/gpu/glsl/GrGLSLXferProcessor.h
@@ -8,6 +8,7 @@
 #ifndef GrGLSLXferProcessor_DEFINED
 #define GrGLSLXferProcessor_DEFINED
 
+#include "SkPoint.h"
 #include "glsl/GrGLSLProgramDataManager.h"
 #include "glsl/GrGLSLUniformHandler.h"
 
@@ -15,14 +16,15 @@
 class GrGLSLXPBuilder;
 class GrGLSLXPFragmentBuilder;
 class GrShaderCaps;
+class GrTexture;
 
 class GrGLSLXferProcessor {
 public:
     GrGLSLXferProcessor() {}
     virtual ~GrGLSLXferProcessor() {}
 
-    using SamplerHandle        = GrGLSLUniformHandler::SamplerHandle;
-    using ImageStorageHandle   = GrGLSLUniformHandler::ImageStorageHandle;
+    using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
+    using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle;
 
     struct EmitArgs {
         EmitArgs(GrGLSLXPFragmentBuilder* fragBuilder,
@@ -33,9 +35,8 @@
                  const char* inputCoverage,
                  const char* outputPrimary,
                  const char* outputSecondary,
-                 const SamplerHandle* texSamplers,
-                 const SamplerHandle* bufferSamplers,
-                 const ImageStorageHandle* imageStorages)
+                 const SamplerHandle dstTextureSamplerHandle,
+                 GrSurfaceOrigin dstTextureOrigin)
                 : fXPFragBuilder(fragBuilder)
                 , fUniformHandler(uniformHandler)
                 , fShaderCaps(caps)
@@ -44,10 +45,8 @@
                 , fInputCoverage(inputCoverage)
                 , fOutputPrimary(outputPrimary)
                 , fOutputSecondary(outputSecondary)
-                , fTexSamplers(texSamplers)
-                , fBufferSamplers(bufferSamplers)
-                , fImageStorages(imageStorages) {}
-
+                , fDstTextureSamplerHandle(dstTextureSamplerHandle)
+                , fDstTextureOrigin(dstTextureOrigin) {}
         GrGLSLXPFragmentBuilder* fXPFragBuilder;
         GrGLSLUniformHandler* fUniformHandler;
         const GrShaderCaps* fShaderCaps;
@@ -56,9 +55,8 @@
         const char* fInputCoverage;
         const char* fOutputPrimary;
         const char* fOutputSecondary;
-        const SamplerHandle* fTexSamplers;
-        const SamplerHandle* fBufferSamplers;
-        const ImageStorageHandle* fImageStorages;
+        const SamplerHandle fDstTextureSamplerHandle;
+        GrSurfaceOrigin fDstTextureOrigin;
     };
     /**
      * This is similar to emitCode() in the base class, except it takes a full shader builder.
@@ -73,7 +71,8 @@
         to have an identical processor key as the one that created this GrGLSLXferProcessor. This
         function calls onSetData on the subclass of GrGLSLXferProcessor
      */
-    void setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp);
+    void setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp,
+                 const GrTexture* dstTexture, const SkIPoint& dstTextureOffset);
 
 protected:
     static void DefaultCoverageModulation(GrGLSLXPFragmentBuilder* fragBuilder,
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index 6b2cd8e..8baf60e 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -481,6 +481,17 @@
     return pipelineState;
 }
 
+static void set_texture_layout(GrVkTexture* vkTexture, GrVkGpu* gpu) {
+    // TODO: If we ever decide to create the secondary command buffers ahead of time before we
+    // are actually going to submit them, we will need to track the sampled images and delay
+    // adding the layout change/barrier until we are ready to submit.
+    vkTexture->setImageLayout(gpu,
+                              VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                              VK_ACCESS_SHADER_READ_BIT,
+                              VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+                              false);
+}
+
 static void prepare_sampled_images(const GrProcessor& processor, GrVkGpu* gpu) {
     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
         const GrProcessor::TextureSampler& sampler = processor.textureSampler(i);
@@ -501,15 +512,7 @@
                 vkTexture->texturePriv().dirtyMipMaps(false);
             }
         }
-
-        // TODO: If we ever decide to create the secondary command buffers ahead of time before we
-        // are actually going to submit them, we will need to track the sampled images and delay
-        // adding the layout change/barrier until we are ready to submit.
-        vkTexture->setImageLayout(gpu,
-                                  VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
-                                  VK_ACCESS_SHADER_READ_BIT,
-                                  VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
-                                  false);
+        set_texture_layout(vkTexture, gpu);
     }
 }
 
@@ -532,7 +535,9 @@
     while (const GrFragmentProcessor* fp = iter.next()) {
         prepare_sampled_images(*fp, fGpu);
     }
-    prepare_sampled_images(pipeline.getXferProcessor(), fGpu);
+    if (GrVkTexture* dstTexture = static_cast<GrVkTexture*>(pipeline.dstTexture())) {
+        set_texture_layout(dstTexture, fGpu);
+    }
 
     GrPrimitiveType primitiveType = meshes[0].primitiveType();
     sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline,
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index 91fdc3f..b689866 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -214,8 +214,14 @@
     }
     SkASSERT(!fp && !glslFP);
 
-    fXferProcessor->setData(fDataManager, pipeline.getXferProcessor());
-    append_texture_bindings(pipeline.getXferProcessor(), &textureBindings);
+    SkIPoint offset;
+    GrTexture* dstTexture = pipeline.dstTexture(&offset);
+    fXferProcessor->setData(fDataManager, pipeline.getXferProcessor(), dstTexture, offset);
+    GrProcessor::TextureSampler dstTextureSampler;
+    if (dstTexture) {
+        dstTextureSampler.reset(dstTexture);
+        textureBindings.push_back(&dstTextureSampler);
+    }
 
     // Get new descriptor sets
     if (fNumSamplers) {
diff --git a/tests/GrPorterDuffTest.cpp b/tests/GrPorterDuffTest.cpp
index a2ba916..28465c2 100644
--- a/tests/GrPorterDuffTest.cpp
+++ b/tests/GrPorterDuffTest.cpp
@@ -66,7 +66,7 @@
             fCanCombineOverlappedStencilAndCover = analysis.canCombineOverlappedStencilAndCover();
             fIgnoresInputColor = analysis.isInputColorIgnored();
             sk_sp<GrXferProcessor> xp(
-                    xpf->createXferProcessor(inputColor, inputCoverage, false, nullptr, caps));
+                    xpf->createXferProcessor(inputColor, inputCoverage, false, caps));
             TEST_ASSERT(!analysis.requiresDstTexture());
             GetXPOutputTypes(xp.get(), &fPrimaryOutputType, &fSecondaryOutputType);
             xp->getBlendInfo(&fBlendInfo);
@@ -992,7 +992,7 @@
     GrProcessorAnalysisCoverage coverage = GrProcessorAnalysisCoverage::kLCD;
     SkASSERT(!(GrXPFactory::GetAnalysisProperties(xpf, color, coverage, caps) &
                GrXPFactory::AnalysisProperties::kRequiresDstTexture));
-    sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(color, coverage, false, nullptr, caps));
+    sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(color, coverage, false, caps));
     if (!xp) {
         ERRORF(reporter, "Failed to create an XP with LCD coverage.");
         return;
@@ -1042,10 +1042,8 @@
                 const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode);
                 GrProcessorSet::Analysis analysis;
                 analysis = GrProcessorSet::Analysis(colorInput, coverageType, xpf, caps);
-                GrXferProcessor::DstTexture* dstTexture =
-                        analysis.requiresDstTexture() ? &fakeDstTexture : nullptr;
-                sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(colorInput, coverageType, false,
-                                                                   dstTexture, caps));
+                sk_sp<GrXferProcessor> xp(
+                        xpf->createXferProcessor(colorInput, coverageType, false, caps));
                 if (!xp) {
                     ERRORF(reporter, "Failed to create an XP without dual source blending.");
                     return;