Use GrSurfaceProxyView for dst proxies.

Bug: skia:9556
Change-Id: I41ae112a3d22f6c6481cba1afc3937b5e5115cf5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/252043
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp
index 05e42e1..15eeab5 100644
--- a/src/gpu/GrOpFlushState.cpp
+++ b/src/gpu/GrOpFlushState.cpp
@@ -38,7 +38,7 @@
 
     GrPipeline::InitArgs pipelineArgs;
     pipelineArgs.fInputFlags = pipelineFlags;
-    pipelineArgs.fDstProxy = this->dstProxy();
+    pipelineArgs.fDstProxyView = this->dstProxyView();
     pipelineArgs.fCaps = &this->caps();
     pipelineArgs.fUserStencil = stencilSettings;
     pipelineArgs.fOutputSwizzle = this->drawOpArgs().outputSwizzle();
diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h
index 1ee262d..db83d20 100644
--- a/src/gpu/GrOpFlushState.h
+++ b/src/gpu/GrOpFlushState.h
@@ -59,11 +59,11 @@
     /** Additional data required on a per-op basis when executing GrOps. */
     struct OpArgs {
         explicit OpArgs(GrOp* op, GrSurfaceProxyView* surfaceView, GrAppliedClip* appliedClip,
-                        const GrXferProcessor::DstProxy& dstProxy)
+                        const GrXferProcessor::DstProxyView& dstProxyView)
                 : fOp(op)
                 , fSurfaceView(surfaceView)
                 , fAppliedClip(appliedClip)
-                , fDstProxy(dstProxy) {
+                , fDstProxyView(dstProxyView) {
             SkASSERT(surfaceView->asRenderTargetProxy());
         }
 
@@ -76,7 +76,7 @@
         GrRenderTarget* renderTarget() const { return this->proxy()->peekRenderTarget(); }
         GrAppliedClip* appliedClip() { return fAppliedClip; }
         const GrAppliedClip* appliedClip() const { return fAppliedClip; }
-        const GrXferProcessor::DstProxy& dstProxy() const { return fDstProxy; }
+        const GrXferProcessor::DstProxyView& dstProxyView() const { return fDstProxyView; }
 
 #ifdef SK_DEBUG
         void validate() const {
@@ -86,10 +86,10 @@
 #endif
 
     private:
-        GrOp*                     fOp;
-        GrSurfaceProxyView*       fSurfaceView;
-        GrAppliedClip*            fAppliedClip;
-        GrXferProcessor::DstProxy fDstProxy;     // TODO: do we still need the dst proxy here?
+        GrOp*                         fOp;
+        GrSurfaceProxyView*           fSurfaceView;
+        GrAppliedClip*                fAppliedClip;
+        GrXferProcessor::DstProxyView fDstProxyView;   // TODO: do we still need the dst proxy here?
     };
 
     void setOpArgs(OpArgs* opArgs) { fOpArgs = opArgs; }
@@ -132,7 +132,9 @@
     GrRenderTargetProxy* proxy() const final { return fOpArgs->proxy(); }
     const GrAppliedClip* appliedClip() final { return fOpArgs->appliedClip(); }
     GrAppliedClip detachAppliedClip() final;
-    const GrXferProcessor::DstProxy& dstProxy() const final { return fOpArgs->dstProxy(); }
+    const GrXferProcessor::DstProxyView& dstProxyView() const final {
+        return fOpArgs->dstProxyView();
+    }
     GrDeferredUploadTarget* deferredUploadTarget() final { return this; }
     const GrCaps& caps() const final;
     GrResourceProvider* resourceProvider() const final { return fResourceProvider; }
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index 2d61afe..ed4aba5 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -35,7 +35,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-using DstProxy = GrXferProcessor::DstProxy;
+using DstProxyView = GrXferProcessor::DstProxyView;
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -123,13 +123,13 @@
 
 GrOpsTask::OpChain::OpChain(std::unique_ptr<GrOp> op,
                             GrProcessorSet::Analysis processorAnalysis,
-                            GrAppliedClip* appliedClip, const DstProxy* dstProxy)
+                            GrAppliedClip* appliedClip, const DstProxyView* dstProxyView)
         : fList{std::move(op)}
         , fProcessorAnalysis(processorAnalysis)
         , fAppliedClip(appliedClip) {
     if (fProcessorAnalysis.requiresDstTexture()) {
-        SkASSERT(dstProxy && dstProxy->proxy());
-        fDstProxy = *dstProxy;
+        SkASSERT(dstProxyView && dstProxyView->proxy());
+        fDstProxyView = *dstProxyView;
     }
     fBounds = fList.head()->bounds();
 }
@@ -141,8 +141,8 @@
     for (const auto& op : GrOp::ChainRange<>(fList.head())) {
         op.visitProxies(func);
     }
-    if (fDstProxy.proxy()) {
-        func(fDstProxy.proxy(), GrMipMapped::kNo);
+    if (fDstProxyView.proxy()) {
+        func(fDstProxyView.proxy(), GrMipMapped::kNo);
     }
     if (fAppliedClip) {
         fAppliedClip->visitProxies(func);
@@ -234,13 +234,13 @@
 // Attempts to concatenate the given chain onto our own and merge ops across the chains. Returns
 // whether the operation succeeded. On success, the provided list will be returned empty.
 bool GrOpsTask::OpChain::tryConcat(
-        List* list, GrProcessorSet::Analysis processorAnalysis, const DstProxy& dstProxy,
+        List* list, GrProcessorSet::Analysis processorAnalysis, const DstProxyView& dstProxyView,
         const GrAppliedClip* appliedClip, const SkRect& bounds, const GrCaps& caps,
         GrOpMemoryPool* pool, GrAuditTrail* auditTrail) {
     SkASSERT(!fList.empty());
     SkASSERT(!list->empty());
-    SkASSERT(fProcessorAnalysis.requiresDstTexture() == SkToBool(fDstProxy.proxy()));
-    SkASSERT(processorAnalysis.requiresDstTexture() == SkToBool(dstProxy.proxy()));
+    SkASSERT(fProcessorAnalysis.requiresDstTexture() == SkToBool(fDstProxyView.proxy()));
+    SkASSERT(processorAnalysis.requiresDstTexture() == SkToBool(dstProxyView.proxy()));
     // All returns use explicit tuple constructor rather than {a, b} to work around old GCC bug.
     if (fList.head()->classID() != list->head()->classID() ||
         SkToBool(fAppliedClip) != SkToBool(appliedClip) ||
@@ -253,7 +253,7 @@
                 // chain nor combine overlapping Ops.
                 GrRectsTouchOrOverlap(fBounds, bounds)) ||
         (fProcessorAnalysis.requiresDstTexture() != processorAnalysis.requiresDstTexture()) ||
-        (fProcessorAnalysis.requiresDstTexture() && fDstProxy != dstProxy)) {
+        (fProcessorAnalysis.requiresDstTexture() && fDstProxyView != dstProxyView)) {
         return false;
     }
 
@@ -293,8 +293,8 @@
 
 bool GrOpsTask::OpChain::prependChain(OpChain* that, const GrCaps& caps, GrOpMemoryPool* pool,
                                       GrAuditTrail* auditTrail) {
-    if (!that->tryConcat(
-            &fList, fProcessorAnalysis, fDstProxy, fAppliedClip, fBounds, caps, pool, auditTrail)) {
+    if (!that->tryConcat(&fList, fProcessorAnalysis, fDstProxyView, fAppliedClip, fBounds, caps,
+                         pool, auditTrail)) {
         this->validate();
         // append failed
         return false;
@@ -305,7 +305,7 @@
     fList = std::move(that->fList);
     fBounds = that->fBounds;
 
-    that->fDstProxy.setProxy(nullptr);
+    that->fDstProxyView.setProxyView({});
     if (that->fAppliedClip) {
         for (int i = 0; i < that->fAppliedClip->numClipCoverageFragmentProcessors(); ++i) {
             that->fAppliedClip->detachClipCoverageFragmentProcessor(i);
@@ -317,17 +317,18 @@
 
 std::unique_ptr<GrOp> GrOpsTask::OpChain::appendOp(
         std::unique_ptr<GrOp> op, GrProcessorSet::Analysis processorAnalysis,
-        const DstProxy* dstProxy, const GrAppliedClip* appliedClip, const GrCaps& caps,
+        const DstProxyView* dstProxyView, const GrAppliedClip* appliedClip, const GrCaps& caps,
         GrOpMemoryPool* pool, GrAuditTrail* auditTrail) {
-    const GrXferProcessor::DstProxy noDstProxy;
-    if (!dstProxy) {
-        dstProxy = &noDstProxy;
+    const GrXferProcessor::DstProxyView noDstProxyView;
+    if (!dstProxyView) {
+        dstProxyView = &noDstProxyView;
     }
     SkASSERT(op->isChainHead() && op->isChainTail());
     SkRect opBounds = op->bounds();
     List chain(std::move(op));
     if (!this->tryConcat(
-            &chain, processorAnalysis, *dstProxy, appliedClip, opBounds, caps, pool, auditTrail)) {
+            &chain, processorAnalysis, *dstProxyView, appliedClip, opBounds, caps, pool,
+            auditTrail)) {
         // append failed, give the op back to the caller.
         this->validate();
         return chain.popHead();
@@ -436,7 +437,7 @@
             GrOpFlushState::OpArgs opArgs(chain.head(),
                                           &fTargetView,
                                           chain.appliedClip(),
-                                          chain.dstProxy());
+                                          chain.dstProxyView());
 
             flushState->setOpArgs(&opArgs);
             // GrOp::prePrepare may or may not have been called at this point
@@ -557,7 +558,7 @@
         GrOpFlushState::OpArgs opArgs(chain.head(),
                                       &fTargetView,
                                       chain.appliedClip(),
-                                      chain.dstProxy());
+                                      chain.dstProxyView());
 
         flushState->setOpArgs(&opArgs);
         chain.head()->execute(flushState, chain.bounds());
@@ -754,9 +755,9 @@
 
 void GrOpsTask::recordOp(
         std::unique_ptr<GrOp> op, GrProcessorSet::Analysis processorAnalysis, GrAppliedClip* clip,
-        const DstProxy* dstProxy, const GrCaps& caps) {
+        const DstProxyView* dstProxyView, const GrCaps& caps) {
     SkDEBUGCODE(op->validate();)
-    SkASSERT(processorAnalysis.requiresDstTexture() == (dstProxy && dstProxy->proxy()));
+    SkASSERT(processorAnalysis.requiresDstTexture() == (dstProxyView && dstProxyView->proxy()));
     GrSurfaceProxy* proxy = fTargetView.proxy();
     SkASSERT(proxy);
 
@@ -790,7 +791,7 @@
         int i = 0;
         while (true) {
             OpChain& candidate = fOpChains.fromBack(i);
-            op = candidate.appendOp(std::move(op), processorAnalysis, dstProxy, clip, caps,
+            op = candidate.appendOp(std::move(op), processorAnalysis, dstProxyView, clip, caps,
                                     fOpMemoryPool.get(), fAuditTrail);
             if (!op) {
                 return;
@@ -813,7 +814,7 @@
         clip = fClipAllocator.make<GrAppliedClip>(std::move(*clip));
         SkDEBUGCODE(fNumClips++;)
     }
-    fOpChains.emplace_back(std::move(op), processorAnalysis, clip, dstProxy);
+    fOpChains.emplace_back(std::move(op), processorAnalysis, clip, dstProxyView);
 }
 
 void GrOpsTask::forwardCombine(const GrCaps& caps) {
diff --git a/src/gpu/GrOpsTask.h b/src/gpu/GrOpsTask.h
index 61507e3..1a4c517 100644
--- a/src/gpu/GrOpsTask.h
+++ b/src/gpu/GrOpsTask.h
@@ -35,7 +35,7 @@
 
 class GrOpsTask : public GrRenderTask {
 private:
-    using DstProxy = GrXferProcessor::DstProxy;
+    using DstProxyView = GrXferProcessor::DstProxyView;
 
 public:
     GrOpsTask(sk_sp<GrOpMemoryPool>, GrSurfaceProxyView, GrAuditTrail*);
@@ -81,7 +81,7 @@
     }
 
     void addDrawOp(std::unique_ptr<GrDrawOp> op, const GrProcessorSet::Analysis& processorAnalysis,
-                   GrAppliedClip&& clip, const DstProxy& dstProxy,
+                   GrAppliedClip&& clip, const DstProxyView& dstProxyView,
                    GrTextureResolveManager textureResolveManager, const GrCaps& caps) {
         auto addDependency = [ textureResolveManager, &caps, this ] (
                 GrTextureProxy* p, GrMipMapped mipmapped) {
@@ -91,13 +91,13 @@
 
         op->visitProxies(addDependency);
         clip.visitProxies(addDependency);
-        if (dstProxy.proxy()) {
-            this->addSampledTexture(dstProxy.proxy());
-            addDependency(dstProxy.proxy(), GrMipMapped::kNo);
+        if (dstProxyView.proxy()) {
+            this->addSampledTexture(dstProxyView.proxy());
+            addDependency(dstProxyView.proxy(), GrMipMapped::kNo);
         }
 
         this->recordOp(std::move(op), processorAnalysis, clip.doesClip() ? &clip : nullptr,
-                       &dstProxy, caps);
+                       &dstProxyView, caps);
     }
 
     void discard();
@@ -164,7 +164,8 @@
     public:
         OpChain(const OpChain&) = delete;
         OpChain& operator=(const OpChain&) = delete;
-        OpChain(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxy*);
+        OpChain(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*,
+                const DstProxyView*);
 
         ~OpChain() {
             // The ops are stored in a GrMemoryPool and must be explicitly deleted via the pool.
@@ -176,7 +177,7 @@
         GrOp* head() const { return fList.head(); }
 
         GrAppliedClip* appliedClip() const { return fAppliedClip; }
-        const DstProxy& dstProxy() const { return fDstProxy; }
+        const DstProxyView& dstProxyView() const { return fDstProxyView; }
         const SkRect& bounds() const { return fBounds; }
 
         // Deletes all the ops in the chain via the pool.
@@ -191,7 +192,7 @@
         // 'op' to the caller upon failure, otherwise null. Fails when the op and chain aren't of
         // the same op type, have different clips or dst proxies.
         std::unique_ptr<GrOp> appendOp(std::unique_ptr<GrOp> op, GrProcessorSet::Analysis,
-                                       const DstProxy*, const GrAppliedClip*, const GrCaps&,
+                                       const DstProxyView*, const GrAppliedClip*, const GrCaps&,
                                        GrOpMemoryPool*, GrAuditTrail*);
 
         void setSkipExecuteFlag() { fSkipExecute = true; }
@@ -225,13 +226,13 @@
 
         void validate() const;
 
-        bool tryConcat(List*, GrProcessorSet::Analysis, const DstProxy&, const GrAppliedClip*,
+        bool tryConcat(List*, GrProcessorSet::Analysis, const DstProxyView&, const GrAppliedClip*,
                        const SkRect& bounds, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
         static List DoConcat(List, List, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
 
         List fList;
         GrProcessorSet::Analysis fProcessorAnalysis;
-        DstProxy fDstProxy;
+        DstProxyView fDstProxyView;
         GrAppliedClip* fAppliedClip;
         SkRect fBounds;
 
@@ -247,8 +248,8 @@
 
     void gatherProxyIntervals(GrResourceAllocator*) const override;
 
-    void recordOp(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxy*,
-                  const GrCaps& caps);
+    void recordOp(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*,
+                  const DstProxyView*, const GrCaps& caps);
 
     void forwardCombine(const GrCaps&);
 
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index 3e5e18d..a246c85 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -38,11 +38,11 @@
 
     fXferProcessor = processors.refXferProcessor();
 
-    if (args.fDstProxy.proxy()) {
-        SkASSERT(args.fDstProxy.proxy()->isInstantiated());
+    if (args.fDstProxyView.proxy()) {
+        SkASSERT(args.fDstProxyView.proxy()->isInstantiated());
 
-        fDstTextureProxy = args.fDstProxy.refProxy();
-        fDstTextureOffset = args.fDstProxy.offset();
+        fDstProxyView = args.fDstProxyView.proxyView();
+        fDstTextureOffset = args.fDstProxyView.offset();
     }
 
     // Copy GrFragmentProcessors from GrProcessorSet to Pipeline
@@ -74,7 +74,8 @@
 }
 
 GrXferBarrierType GrPipeline::xferBarrierType(GrTexture* texture, const GrCaps& caps) const {
-    if (fDstTextureProxy && fDstTextureProxy->peekTexture() == texture) {
+    auto proxy = fDstProxyView.proxy();
+    if (proxy && proxy->peekTexture() == texture) {
         return kTexture_GrXferBarrierType;
     }
     return this->getXferProcessor().xferBarrierType(caps);
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index b57e66d..ea409c1 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -16,6 +16,7 @@
 #include "src/gpu/GrProcessorSet.h"
 #include "src/gpu/GrProgramDesc.h"
 #include "src/gpu/GrScissorState.h"
+#include "src/gpu/GrSurfaceProxyView.h"
 #include "src/gpu/GrUserStencilSettings.h"
 #include "src/gpu/GrWindowRectsState.h"
 #include "src/gpu/effects/GrCoverageSetOpXP.h"
@@ -58,7 +59,7 @@
         InputFlags fInputFlags = InputFlags::kNone;
         const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused;
         const GrCaps* fCaps = nullptr;
-        GrXferProcessor::DstProxy fDstProxy;
+        GrXferProcessor::DstProxyView fDstProxyView;
         GrSwizzle fOutputSwizzle;
     };
 
@@ -133,19 +134,24 @@
     }
 
     /**
+     * This returns the GrSurfaceProxyView for the texture used to access the dst color. If the
+     * GrXferProcessor does not use the dst color then the proxy on the GrSurfaceProxyView will be
+     * nullptr.
+     */
+    const GrSurfaceProxyView& dstProxyView() const {
+        return fDstProxyView;
+    }
+
+    /**
      * 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.
      */
-    GrTextureProxy* dstTextureProxy(SkIPoint* offset = nullptr) const {
+    GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const {
         if (offset) {
             *offset = fDstTextureOffset;
         }
 
-        return fDstTextureProxy.get();
-    }
-
-    GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const {
-        if (GrTextureProxy* dstProxy = this->dstTextureProxy(offset)) {
+        if (GrTextureProxy* dstProxy = fDstProxyView.asTextureProxy()) {
             return dstProxy->peekTexture();
         }
 
@@ -217,7 +223,7 @@
 
     using FragmentProcessorArray = SkAutoSTArray<8, std::unique_ptr<const GrFragmentProcessor>>;
 
-    sk_sp<GrTextureProxy> fDstTextureProxy;
+    GrSurfaceProxyView fDstProxyView;
     SkIPoint fDstTextureOffset;
     GrWindowRectsState fWindowRectsState;
     const GrUserStencilSettings* fUserStencilSettings;
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index a4a7548..6ef7e6f 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -225,8 +225,8 @@
     const GrXferProcessor& xp = programInfo.pipeline().getXferProcessor();
     const GrSurfaceOrigin* originIfDstTexture = nullptr;
     GrSurfaceOrigin origin;
-    if (programInfo.pipeline().dstTextureProxy()) {
-        origin = programInfo.pipeline().dstTextureProxy()->origin();
+    if (programInfo.pipeline().dstProxyView().proxy()) {
+        origin = programInfo.pipeline().dstProxyView().origin();
         originIfDstTexture = &origin;
     }
     xp.getGLSLProcessorKey(shaderCaps, &b, originIfDstTexture);
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index a6141c6..a8cccbf 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -2331,9 +2331,9 @@
     GrProcessorSet::Analysis analysis = op->finalize(
             *this->caps(), &appliedClip, hasMixedSampledCoverage, clampType);
 
-    GrXferProcessor::DstProxy dstProxy;
+    GrXferProcessor::DstProxyView dstProxyView;
     if (analysis.requiresDstTexture()) {
-        if (!this->setupDstProxy(clip, *op, &dstProxy)) {
+        if (!this->setupDstProxyView(clip, *op, &dstProxyView)) {
             fContext->priv().opMemoryPool()->release(std::move(op));
             return;
         }
@@ -2344,12 +2344,12 @@
     if (willAddFn) {
         willAddFn(op.get(), opsTask->uniqueID());
     }
-    opsTask->addDrawOp(std::move(op), analysis, std::move(appliedClip), dstProxy,
+    opsTask->addDrawOp(std::move(op), analysis, std::move(appliedClip), dstProxyView,
                        GrTextureResolveManager(this->drawingManager()), *this->caps());
 }
 
-bool GrRenderTargetContext::setupDstProxy(const GrClip& clip, const GrOp& op,
-                                          GrXferProcessor::DstProxy* dstProxy) {
+bool GrRenderTargetContext::setupDstProxyView(const GrClip& clip, const GrOp& op,
+                                              GrXferProcessor::DstProxyView* dstProxyView) {
     // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
     // don't actually have a VkImage to make a copy of. Additionally we don't have the power to
     // start and stop the render pass in order to make the copy.
@@ -2358,11 +2358,11 @@
     }
 
     if (this->caps()->textureBarrierSupport() && !fRenderTargetProxy->requiresManualMSAAResolve()) {
-        if (GrTextureProxy* texProxy = fRenderTargetProxy->asTextureProxy()) {
+        if (fRenderTargetProxy->asTextureProxy()) {
             // The render target is a texture, so we can read from it directly in the shader. The XP
             // will be responsible to detect this situation and request a texture barrier.
-            dstProxy->setProxy(sk_ref_sp(texProxy));
-            dstProxy->setOffset(0, 0);
+            dstProxyView->setProxyView(this->textureSurfaceView());
+            dstProxyView->setOffset(0, 0);
             return true;
         }
     }
@@ -2415,8 +2415,8 @@
             copyRect, fit, SkBudgeted::kYes, restrictions.fRectsMustMatch);
     SkASSERT(newProxy);
 
-    dstProxy->setProxy(std::move(newProxy));
-    dstProxy->setOffset(dstOffset);
+    dstProxyView->setProxyView({std::move(newProxy), this->origin(), this->textureSwizzle()});
+    dstProxyView->setOffset(dstOffset);
     return true;
 }
 
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index 19d240a..eacff51 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -637,8 +637,8 @@
     // Makes a copy of the proxy if it is necessary for the draw and places the texture that should
     // be used by GrXferProcessor to access the destination color in 'result'. If the return
     // value is false then a texture copy could not be made.
-    bool SK_WARN_UNUSED_RESULT setupDstProxy(const GrClip&, const GrOp& op,
-                                             GrXferProcessor::DstProxy* result);
+    bool SK_WARN_UNUSED_RESULT setupDstProxyView(const GrClip&, const GrOp& op,
+                                                 GrXferProcessor::DstProxyView* result);
 
     class AsyncReadResult;
 
diff --git a/src/gpu/GrSurfaceContext.h b/src/gpu/GrSurfaceContext.h
index b30e531..29e5d7f 100644
--- a/src/gpu/GrSurfaceContext.h
+++ b/src/gpu/GrSurfaceContext.h
@@ -40,6 +40,7 @@
 
     const GrColorInfo& colorInfo() const { return fColorInfo; }
     GrSurfaceOrigin origin() const { return fOrigin; }
+    const GrSwizzle& textureSwizzle() const { return fTextureSwizzle; }
     GrSurfaceProxyView textureSurfaceView() {
         return { this->asSurfaceProxyRef(), fOrigin, fTextureSwizzle };
     }
diff --git a/src/gpu/GrSurfaceProxyView.h b/src/gpu/GrSurfaceProxyView.h
index 419c117..268f035 100644
--- a/src/gpu/GrSurfaceProxyView.h
+++ b/src/gpu/GrSurfaceProxyView.h
@@ -37,8 +37,18 @@
     bool operator!=(const GrSurfaceProxyView& other) const { return !(*this == other); }
 
     GrSurfaceProxy* proxy() const { return fProxy.get(); }
-    GrTextureProxy* asTextureProxy() const { return fProxy->asTextureProxy(); }
-    GrRenderTargetProxy* asRenderTargetProxy() const { return fProxy->asRenderTargetProxy(); }
+    GrTextureProxy* asTextureProxy() const {
+        if (!fProxy) {
+            return nullptr;
+        }
+        return fProxy->asTextureProxy();
+    }
+    GrRenderTargetProxy* asRenderTargetProxy() const {
+        if (!fProxy) {
+            return nullptr;
+        }
+        return fProxy->asRenderTargetProxy();
+    }
 
     GrSurfaceOrigin origin() const { return fOrigin; }
     const GrSwizzle& swizzle() const { return fSwizzle; }
diff --git a/src/gpu/GrXferProcessor.h b/src/gpu/GrXferProcessor.h
index f84c49a..983d272 100644
--- a/src/gpu/GrXferProcessor.h
+++ b/src/gpu/GrXferProcessor.h
@@ -13,6 +13,7 @@
 #include "src/gpu/GrNonAtomicRef.h"
 #include "src/gpu/GrProcessor.h"
 #include "src/gpu/GrProcessorAnalysis.h"
+#include "src/gpu/GrSurfaceProxyView.h"
 
 class GrGLSLXferProcessor;
 class GrProcessorSet;
@@ -53,52 +54,52 @@
      * to the space of the texture. Depending on GPU capabilities a DstTexture may be used by a
      * GrXferProcessor for blending in the fragment shader.
      */
-    class DstProxy {
+    class DstProxyView {
     public:
-        DstProxy() { fOffset.set(0, 0); }
+        DstProxyView() { fOffset.set(0, 0); }
 
-        DstProxy(const DstProxy& other) {
+        DstProxyView(const DstProxyView& other) {
             *this = other;
         }
 
-        DstProxy(sk_sp<GrTextureProxy> proxy, const SkIPoint& offset)
-            : fProxy(std::move(proxy)) {
-            if (fProxy) {
+        DstProxyView(GrSurfaceProxyView view, const SkIPoint& offset)
+            : fProxyView(std::move(view)) {
+            if (fProxyView.proxy()) {
                 fOffset = offset;
             } else {
                 fOffset.set(0, 0);
             }
         }
 
-        DstProxy& operator=(const DstProxy& other) {
-            fProxy = other.fProxy;
+        DstProxyView& operator=(const DstProxyView& other) {
+            fProxyView = other.fProxyView;
             fOffset = other.fOffset;
             return *this;
         }
 
-        bool operator==(const DstProxy& that) const {
-            return fProxy == that.fProxy && fOffset == that.fOffset;
+        bool operator==(const DstProxyView& that) const {
+            return fProxyView == that.fProxyView && fOffset == that.fOffset;
         }
-        bool operator!=(const DstProxy& that) const { return !(*this == that); }
+        bool operator!=(const DstProxyView& that) const { return !(*this == that); }
 
         const SkIPoint& offset() const { return fOffset; }
 
         void setOffset(const SkIPoint& offset) { fOffset = offset; }
         void setOffset(int ox, int oy) { fOffset.set(ox, oy); }
 
-        GrTextureProxy* proxy() const { return fProxy.get(); }
-        sk_sp<GrTextureProxy> refProxy() const { return fProxy; }
+        GrTextureProxy* proxy() const { return fProxyView.asTextureProxy(); }
+        const GrSurfaceProxyView& proxyView() const { return fProxyView; }
 
-        void setProxy(sk_sp<GrTextureProxy> proxy) {
-            fProxy = std::move(proxy);
-            if (!fProxy) {
+        void setProxyView(GrSurfaceProxyView view) {
+            fProxyView = std::move(view);
+            if (!fProxyView.proxy()) {
                 fOffset = {0, 0};
             }
         }
 
     private:
-        sk_sp<GrTextureProxy> fProxy;
-        SkIPoint              fOffset;
+        GrSurfaceProxyView fProxyView;
+        SkIPoint           fOffset;
     };
 
     /**
@@ -250,7 +251,7 @@
 #endif
 class GrXPFactory {
 public:
-    typedef GrXferProcessor::DstProxy DstProxy;
+    typedef GrXferProcessor::DstProxyView DstProxyView;
 
     enum class AnalysisProperties : unsigned {
         kNone = 0x0,
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index 06556c4..a19f201 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -433,7 +433,7 @@
 
     GrPipeline::InitArgs initArgs;
     initArgs.fCaps = &flushState->caps();
-    initArgs.fDstProxy = flushState->drawOpArgs().dstProxy();
+    initArgs.fDstProxyView = flushState->drawOpArgs().dstProxyView();
     initArgs.fOutputSwizzle = flushState->drawOpArgs().outputSwizzle();
     auto clip = flushState->detachAppliedClip();
     GrPipeline::FixedDynamicState fixedDynamicState(clip.scissorState().rect());
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 38f81ca..1e79e9f 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -101,7 +101,7 @@
     fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset);
     if (dstTexture) {
         fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerState::ClampNearest(),
-                          programInfo.pipeline().dstTextureProxy()->textureSwizzle(),
+                          programInfo.pipeline().dstProxyView().swizzle(),
                           static_cast<GrGLTexture*>(dstTexture));
     }
     SkASSERT(nextTexSamplerIdx == fNumTextureSamplers);
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 8cdf43d..906cd99 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -248,12 +248,13 @@
     SamplerHandle dstTextureSamplerHandle;
     GrSurfaceOrigin dstTextureOrigin = kTopLeft_GrSurfaceOrigin;
 
-    if (GrTextureProxy* dstTextureProxy = this->pipeline().dstTextureProxy()) {
+    const GrSurfaceProxyView& dstView = this->pipeline().dstProxyView();
+    if (GrTextureProxy* dstTextureProxy = dstView.asTextureProxy()) {
         // GrProcessor::TextureSampler sampler(dstTexture);
-        const GrSwizzle& swizzle = dstTextureProxy->textureSwizzle();
+        const GrSwizzle& swizzle = dstView.swizzle();
         dstTextureSamplerHandle = this->emitSampler(dstTextureProxy, GrSamplerState(),
                                                     swizzle, "DstTextureSampler");
-        dstTextureOrigin = dstTextureProxy->origin();
+        dstTextureOrigin = dstView.origin();
         SkASSERT(dstTextureProxy->textureType() != GrTextureType::kExternal);
     }
 
diff --git a/src/gpu/mtl/GrMtlPipelineState.mm b/src/gpu/mtl/GrMtlPipelineState.mm
index 9b4dc40..2b7463a 100644
--- a/src/gpu/mtl/GrMtlPipelineState.mm
+++ b/src/gpu/mtl/GrMtlPipelineState.mm
@@ -97,7 +97,7 @@
                                 dstTexture, offset);
     }
 
-    if (GrTextureProxy* dstTextureProxy = programInfo.pipeline().dstTextureProxy()) {
+    if (GrTextureProxy* dstTextureProxy = programInfo.pipeline().dstProxyView().asTextureProxy()) {
         fSamplerBindings.emplace_back(GrSamplerState::ClampNearest(),
                                       dstTextureProxy->peekTexture(),
                                       fGpu);
diff --git a/src/gpu/ops/GrDrawPathOp.cpp b/src/gpu/ops/GrDrawPathOp.cpp
index 526ebc0..7b2bcef 100644
--- a/src/gpu/ops/GrDrawPathOp.cpp
+++ b/src/gpu/ops/GrDrawPathOp.cpp
@@ -50,7 +50,7 @@
     }
     args.fUserStencil = &kCoverPass;
     args.fCaps = &state.caps();
-    args.fDstProxy = state.drawOpArgs().dstProxy();
+    args.fDstProxyView = state.drawOpArgs().dstProxyView();
     args.fOutputSwizzle = state.drawOpArgs().outputSwizzle();
     return args;
 }
diff --git a/src/gpu/ops/GrFillRRectOp.cpp b/src/gpu/ops/GrFillRRectOp.cpp
index 026ea89..28d6f81 100644
--- a/src/gpu/ops/GrFillRRectOp.cpp
+++ b/src/gpu/ops/GrFillRRectOp.cpp
@@ -743,7 +743,7 @@
         initArgs.fInputFlags = GrPipeline::InputFlags::kHWAntialias;
     }
     initArgs.fCaps = &flushState->caps();
-    initArgs.fDstProxy = flushState->drawOpArgs().dstProxy();
+    initArgs.fDstProxyView = flushState->drawOpArgs().dstProxyView();
     initArgs.fOutputSwizzle = flushState->drawOpArgs().outputSwizzle();
     auto clip = flushState->detachAppliedClip();
     GrPipeline::FixedDynamicState* fixedDynamicState =
diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h
index 5b335be..896add8 100644
--- a/src/gpu/ops/GrMeshDrawOp.h
+++ b/src/gpu/ops/GrMeshDrawOp.h
@@ -180,7 +180,7 @@
     virtual const GrAppliedClip* appliedClip() = 0;
     virtual GrAppliedClip detachAppliedClip() = 0;
 
-    virtual const GrXferProcessor::DstProxy& dstProxy() const = 0;
+    virtual const GrXferProcessor::DstProxyView& dstProxyView() const = 0;
 
     virtual GrResourceProvider* resourceProvider() const = 0;
     uint32_t contextUniqueID() const { return this->resourceProvider()->contextUniqueID(); }
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index 6120fd3..117e4fc 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -179,10 +179,9 @@
     }
     SkASSERT(!fp && !glslFP);
 
-    if (GrTextureProxy* dstTextureProxy = pipeline.dstTextureProxy()) {
+    if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
         samplerBindings[currTextureBinding++] = {
-                GrSamplerState::ClampNearest(),
-                static_cast<GrVkTexture*>(dstTextureProxy->peekTexture())};
+                GrSamplerState::ClampNearest(), static_cast<GrVkTexture*>(dstTexture)};
     }
 
     // Get new descriptor set
diff --git a/tests/DrawOpAtlasTest.cpp b/tests/DrawOpAtlasTest.cpp
index faccf27..826d53d 100644
--- a/tests/DrawOpAtlasTest.cpp
+++ b/tests/DrawOpAtlasTest.cpp
@@ -216,7 +216,8 @@
     GrOpFlushState::OpArgs opArgs(op.get(),
                                   &surfaceView,
                                   nullptr,
-                                  GrXferProcessor::DstProxy(nullptr, SkIPoint::Make(0, 0)));
+                                  GrXferProcessor::DstProxyView(GrSurfaceProxyView(),
+                                                                SkIPoint::Make(0, 0)));
 
     // Cripple the atlas manager so it can't allocate any pages. This will force a failure
     // in the preparation of the text op
diff --git a/tests/GrPorterDuffTest.cpp b/tests/GrPorterDuffTest.cpp
index 533ff0f..a5756bf 100644
--- a/tests/GrPorterDuffTest.cpp
+++ b/tests/GrPorterDuffTest.cpp
@@ -997,12 +997,14 @@
         ctx->createBackendTexture(100, 100, kRGBA_8888_SkColorType, SkColors::kTransparent,
                                   GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
 
-    GrXferProcessor::DstProxy fakeDstProxy;
+    GrXferProcessor::DstProxyView fakeDstProxyView;
     {
         sk_sp<GrTextureProxy> proxy = proxyProvider->wrapBackendTexture(
                 backendTex, GrColorType::kRGBA_8888, kTopLeft_GrSurfaceOrigin,
                 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType);
-        fakeDstProxy.setProxy(std::move(proxy));
+        GrSwizzle swizzle = caps.getTextureSwizzle(backendTex.getBackendFormat(),
+                                                   GrColorType::kRGBA_8888);
+        fakeDstProxyView.setProxyView({std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle});
     }
 
     static const GrProcessorAnalysisColor colorInputs[] = {