Use GrSurfaceProxyView in RenderTasks.

Bug: skia:9556
Change-Id: Ibe0ae6981e87909848e5af73fc716aac7c8a591f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/249232
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrCopyRenderTask.cpp b/src/gpu/GrCopyRenderTask.cpp
index 9e44187..39fa454 100644
--- a/src/gpu/GrCopyRenderTask.cpp
+++ b/src/gpu/GrCopyRenderTask.cpp
@@ -11,15 +11,17 @@
 #include "src/gpu/GrOpFlushState.h"
 #include "src/gpu/GrResourceAllocator.h"
 
-sk_sp<GrRenderTask> GrCopyRenderTask::Make(sk_sp<GrSurfaceProxy> srcProxy,
+sk_sp<GrRenderTask> GrCopyRenderTask::Make(GrSurfaceProxyView srcView,
                                            const SkIRect& srcRect,
-                                           sk_sp<GrSurfaceProxy> dstProxy,
+                                           GrSurfaceProxyView dstView,
                                            const SkIPoint& dstPoint,
                                            const GrCaps* caps) {
-    SkASSERT(dstProxy);
-    SkASSERT(srcProxy);
+    SkASSERT(dstView.proxy());
+    SkASSERT(srcView.proxy());
     SkIRect clippedSrcRect;
     SkIPoint clippedDstPoint;
+    GrSurfaceProxy* srcProxy = srcView.proxy();
+    GrSurfaceProxy* dstProxy = dstView.proxy();
     // If the rect is outside the srcProxy or dstProxy then we've already succeeded.
     if (!GrClipSrcRectAndDstPoint(dstProxy->dimensions(), srcProxy->dimensions(), srcRect, dstPoint,
                                   &clippedSrcRect, &clippedDstPoint)) {
@@ -30,8 +32,8 @@
         return nullptr;
     }
 
-    SkASSERT(dstProxy->origin() == srcProxy->origin());
-    if (srcProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
+    SkASSERT(dstView.origin() == srcView.origin());
+    if (srcView.origin() == kBottomLeft_GrSurfaceOrigin) {
         int rectHeight = clippedSrcRect.height();
         clippedSrcRect.fTop = srcProxy->height() - clippedSrcRect.fBottom;
         clippedSrcRect.fBottom = clippedSrcRect.fTop + rectHeight;
@@ -39,44 +41,46 @@
     }
 
     sk_sp<GrCopyRenderTask> task(new GrCopyRenderTask(
-            std::move(srcProxy), clippedSrcRect, std::move(dstProxy), clippedDstPoint));
+            std::move(srcView), clippedSrcRect, std::move(dstView), clippedDstPoint));
     return task;
 }
 
-GrCopyRenderTask::GrCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
+GrCopyRenderTask::GrCopyRenderTask(GrSurfaceProxyView srcView,
                                    const SkIRect& srcRect,
-                                   sk_sp<GrSurfaceProxy> dstProxy,
+                                   GrSurfaceProxyView dstView,
                                    const SkIPoint& dstPoint)
-        : GrRenderTask(std::move(dstProxy))
-        , fSrcProxy(std::move(srcProxy))
+        : GrRenderTask(std::move(dstView))
+        , fSrcView(std::move(srcView))
         , fSrcRect(srcRect)
         , fDstPoint(dstPoint) {
-    fTarget->setLastRenderTask(this);
+    fTargetView.proxy()->setLastRenderTask(this);
 }
 
 void GrCopyRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
     // This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so
     // fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that
-    // we read fSrcProxy and copy to fTarget.
-    alloc->addInterval(fSrcProxy.get(), alloc->curOp(), alloc->curOp(),
+    // we read fSrcView and copy to fTargetView.
+    alloc->addInterval(fSrcView.proxy(), alloc->curOp(), alloc->curOp(),
                        GrResourceAllocator::ActualUse::kYes);
-    alloc->addInterval(fTarget.get(), alloc->curOp(), alloc->curOp(),
+    alloc->addInterval(fTargetView.proxy(), alloc->curOp(), alloc->curOp(),
                        GrResourceAllocator::ActualUse::kYes);
     alloc->incOps();
 }
 
 bool GrCopyRenderTask::onExecute(GrOpFlushState* flushState) {
-    if (!fSrcProxy->isInstantiated() || !fTarget->isInstantiated()) {
+    GrSurfaceProxy* dstProxy = fTargetView.proxy();
+    GrSurfaceProxy* srcProxy = fSrcView.proxy();
+    if (!srcProxy->isInstantiated() || !dstProxy->isInstantiated()) {
         return false;
     }
-    GrSurface* srcSurface = fSrcProxy->peekSurface();
-    GrSurface* dstSurface = fTarget->peekSurface();
-    if (fSrcProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
-        if (fSrcProxy->height() != srcSurface->height()) {
-            fSrcRect.offset(0, srcSurface->height() - fSrcProxy->height());
+    GrSurface* srcSurface = srcProxy->peekSurface();
+    GrSurface* dstSurface = dstProxy->peekSurface();
+    if (fSrcView.origin() == kBottomLeft_GrSurfaceOrigin) {
+        if (srcProxy->height() != srcSurface->height()) {
+            fSrcRect.offset(0, srcSurface->height() - srcProxy->height());
         }
-        if (fTarget->height() != dstSurface->height()) {
-            fDstPoint.fY = fDstPoint.fY + (dstSurface->height() - fTarget->height());
+        if (dstProxy->height() != dstSurface->height()) {
+            fDstPoint.fY = fDstPoint.fY + (dstSurface->height() - dstProxy->height());
         }
     }
     return flushState->gpu()->copySurface(dstSurface, srcSurface, fSrcRect, fDstPoint);
diff --git a/src/gpu/GrCopyRenderTask.h b/src/gpu/GrCopyRenderTask.h
index 640bb11..c4f839c 100644
--- a/src/gpu/GrCopyRenderTask.h
+++ b/src/gpu/GrCopyRenderTask.h
@@ -12,21 +12,22 @@
 
 class GrCopyRenderTask final : public GrRenderTask {
 public:
-    static sk_sp<GrRenderTask> Make(sk_sp<GrSurfaceProxy> srcProxy,
+    static sk_sp<GrRenderTask> Make(GrSurfaceProxyView srcView,
                                     const SkIRect& srcRect,
-                                    sk_sp<GrSurfaceProxy> dstProxy,
+                                    GrSurfaceProxyView dstView,
                                     const SkIPoint& dstPoint,
                                     const GrCaps*);
 
 private:
-    GrCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
+    GrCopyRenderTask(GrSurfaceProxyView srcView,
                      const SkIRect& srcRect,
-                     sk_sp<GrSurfaceProxy> dstProxy,
+                     GrSurfaceProxyView dstView,
                      const SkIPoint& dstPoint);
 
     bool onIsUsed(GrSurfaceProxy* proxy) const override {
-        SkASSERT(proxy != fTarget.get());  // This case should be handled by GrRenderTask.
-        return proxy == fSrcProxy.get();
+        // This case should be handled by GrRenderTask.
+        SkASSERT(proxy != fTargetView.proxy());
+        return proxy == fSrcView.proxy();
     }
     // If instantiation failed, at flush time we simply will skip doing the copy.
     void handleInternalAllocationFailure() override {}
@@ -40,11 +41,11 @@
 
 #ifdef SK_DEBUG
     void visitProxies_debugOnly(const VisitSurfaceProxyFunc& fn) const override {
-        fn(fSrcProxy.get(), GrMipMapped::kNo);
+        fn(fSrcView.proxy(), GrMipMapped::kNo);
     }
 #endif
 
-    sk_sp<GrSurfaceProxy> fSrcProxy;
+    GrSurfaceProxyView fSrcView;
     SkIRect fSrcRect;
     SkIPoint fDstPoint;
 };
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index ba89eca..ee7c1cd 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -128,7 +128,7 @@
             GrOpsTask* curOpsTask = fRenderTasks[i]->asOpsTask();
 
             if (prevOpsTask && curOpsTask) {
-                SkASSERT(prevOpsTask->fTarget.get() != curOpsTask->fTarget.get());
+                SkASSERT(prevOpsTask->fTargetView != curOpsTask->fTargetView);
             }
 
             prevOpsTask = curOpsTask;
@@ -670,15 +670,17 @@
     }
 }
 
-sk_sp<GrOpsTask> GrDrawingManager::newOpsTask(sk_sp<GrRenderTargetProxy> rtp, bool managedOpsTask) {
+sk_sp<GrOpsTask> GrDrawingManager::newOpsTask(GrSurfaceProxyView surfaceView,
+                                              bool managedOpsTask) {
     SkDEBUGCODE(this->validate());
     SkASSERT(fContext);
 
-    this->closeRenderTasksForNewRenderTask(rtp.get());
+    GrSurfaceProxy* proxy = surfaceView.proxy();
+    this->closeRenderTasksForNewRenderTask(proxy);
 
-    sk_sp<GrOpsTask> opsTask(new GrOpsTask(fContext->priv().refOpMemoryPool(), rtp,
-                                           fContext->priv().auditTrail()));
-    SkASSERT(rtp->getLastRenderTask() == opsTask.get());
+    sk_sp<GrOpsTask> opsTask(new GrOpsTask(fContext->priv().refOpMemoryPool(),
+                                           std::move(surfaceView), fContext->priv().auditTrail()));
+    SkASSERT(proxy->getLastRenderTask() == opsTask.get());
 
     if (managedOpsTask) {
         fDAG.add(opsTask);
@@ -714,7 +716,8 @@
 
     const GrCaps& caps = *fContext->priv().caps();
 
-    sk_sp<GrWaitRenderTask> waitTask = sk_make_sp<GrWaitRenderTask>(proxy, std::move(semaphores),
+    sk_sp<GrWaitRenderTask> waitTask = sk_make_sp<GrWaitRenderTask>(GrSurfaceProxyView(proxy),
+                                                                    std::move(semaphores),
                                                                     numSemaphores);
     if (fReduceOpsTaskSplitting) {
         GrRenderTask* lastTask = proxy->getLastRenderTask();
@@ -745,7 +748,7 @@
         }
         fDAG.add(waitTask);
     } else {
-        if (fActiveOpsTask && (fActiveOpsTask->fTarget == proxy)) {
+        if (fActiveOpsTask && (fActiveOpsTask->fTargetView.proxy() == proxy.get())) {
             SkASSERT(proxy->getLastRenderTask() == fActiveOpsTask);
             fDAG.addBeforeLast(waitTask);
             // In this case we keep the current renderTask open but just insert the new waitTask
@@ -808,26 +811,28 @@
     SkDEBUGCODE(this->validate());
 }
 
-bool GrDrawingManager::newCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
+bool GrDrawingManager::newCopyRenderTask(GrSurfaceProxyView srcView,
                                          const SkIRect& srcRect,
-                                         sk_sp<GrSurfaceProxy> dstProxy,
+                                         GrSurfaceProxyView dstView,
                                          const SkIPoint& dstPoint) {
     SkDEBUGCODE(this->validate());
     SkASSERT(fContext);
 
-    this->closeRenderTasksForNewRenderTask(dstProxy.get());
+    this->closeRenderTasksForNewRenderTask(dstView.proxy());
     const GrCaps& caps = *fContext->priv().caps();
 
+    GrSurfaceProxy* srcProxy = srcView.proxy();
+
     GrRenderTask* task =
-            fDAG.add(GrCopyRenderTask::Make(srcProxy, srcRect, dstProxy, dstPoint, &caps));
+            fDAG.add(GrCopyRenderTask::Make(std::move(srcView), srcRect, std::move(dstView),
+                                            dstPoint, &caps));
     if (!task) {
         return false;
     }
 
-
     // We always say GrMipMapped::kNo here since we are always just copying from the base layer to
     // another base layer. We don't need to make sure the whole mip map chain is valid.
-    task->addDependency(srcProxy.get(), GrMipMapped::kNo, GrTextureResolveManager(this), caps);
+    task->addDependency(srcProxy, GrMipMapped::kNo, GrTextureResolveManager(this), caps);
     task->makeClosed(caps);
 
     // We have closed the previous active oplist but since a new oplist isn't being added there
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index 72f3211..8db8369 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -26,6 +26,7 @@
 class GrRenderTargetContext;
 class GrRenderTargetProxy;
 class GrSoftwarePathRenderer;
+class GrSurfaceProxyView;
 class GrTextureContext;
 class GrTextureResolveRenderTask;
 class SkDeferredDisplayList;
@@ -48,7 +49,7 @@
 
     // A managed opsTask is controlled by the drawing manager (i.e., sorted & flushed with the
     // others). An unmanaged one is created and used by the onFlushCallback.
-    sk_sp<GrOpsTask> newOpsTask(sk_sp<GrRenderTargetProxy>, bool managedOpsTask);
+    sk_sp<GrOpsTask> newOpsTask(GrSurfaceProxyView, bool managedOpsTask);
 
     // Create a render task that can resolve MSAA and/or regenerate mipmap levels on proxies. This
     // method will only add the new render task to the list. It is up to the caller to call
@@ -72,14 +73,14 @@
                                    GrColorType surfaceColorType, GrColorType dstColorType,
                                    sk_sp<GrGpuBuffer> dstBuffer, size_t dstOffset);
 
-    // Creates a new render task which copies a pixel rectangle from srcProxy into dstProxy. The src
+    // Creates a new render task which copies a pixel rectangle from srcView into dstView. The src
     // pixels copied are specified by srcRect. They are copied to a rect of the same size in
     // dstProxy with top left at dstPoint. If the src rect is clipped by the src bounds then  pixel
     // values in the dst rect corresponding to the area clipped by the src rect are not overwritten.
     // This method is not guaranteed to succeed depending on the type of surface, formats, etc, and
     // the backend-specific limitations.
-    bool newCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy, const SkIRect& srcRect,
-                           sk_sp<GrSurfaceProxy> dstProxy, const SkIPoint& dstPoint);
+    bool newCopyRenderTask(GrSurfaceProxyView srcView, const SkIRect& srcRect,
+                           GrSurfaceProxyView dstView, const SkIPoint& dstPoint);
 
     GrRecordingContext* getContext() { return fContext; }
 
diff --git a/src/gpu/GrOnFlushResourceProvider.cpp b/src/gpu/GrOnFlushResourceProvider.cpp
index 2cf4af8..8cb748f 100644
--- a/src/gpu/GrOnFlushResourceProvider.cpp
+++ b/src/gpu/GrOnFlushResourceProvider.cpp
@@ -50,7 +50,8 @@
     }
     auto task = static_cast<GrTextureResolveRenderTask*>(fDrawingMgr->fOnFlushRenderTasks.push_back(
             sk_make_sp<GrTextureResolveRenderTask>()).get());
-    task->addProxy(textureProxy, resolveFlags, *this->caps());
+    task->addProxy(GrSurfaceProxyView(textureProxy, textureProxy->origin(), GrSwizzle()),
+                   resolveFlags, *this->caps());
     task->makeClosed(*this->caps());
 }
 
diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h
index 27dac24..1ee262d 100644
--- a/src/gpu/GrOpFlushState.h
+++ b/src/gpu/GrOpFlushState.h
@@ -15,6 +15,7 @@
 #include "src/gpu/GrBufferAllocPool.h"
 #include "src/gpu/GrDeferredUpload.h"
 #include "src/gpu/GrRenderTargetProxy.h"
+#include "src/gpu/GrSurfaceProxyView.h"
 #include "src/gpu/ops/GrMeshDrawOp.h"
 
 class GrGpu;
@@ -57,21 +58,22 @@
 
     /** Additional data required on a per-op basis when executing GrOps. */
     struct OpArgs {
-        explicit OpArgs(GrOp* op, GrRenderTargetProxy* proxy, GrAppliedClip* appliedClip,
+        explicit OpArgs(GrOp* op, GrSurfaceProxyView* surfaceView, GrAppliedClip* appliedClip,
                         const GrXferProcessor::DstProxy& dstProxy)
-            : fOp(op)
-            , fProxy(proxy)
-            , fAppliedClip(appliedClip)
-            , fDstProxy(dstProxy) {
+                : fOp(op)
+                , fSurfaceView(surfaceView)
+                , fAppliedClip(appliedClip)
+                , fDstProxy(dstProxy) {
+            SkASSERT(surfaceView->asRenderTargetProxy());
         }
 
-        int numSamples() const { return fProxy->numSamples(); }
-        GrSurfaceOrigin origin() const { return fProxy->origin(); }
-        GrSwizzle outputSwizzle() const { return fProxy->outputSwizzle(); }
+        int numSamples() const { return this->proxy()->numSamples(); }
+        GrSurfaceOrigin origin() const { return fSurfaceView->origin(); }
+        GrSwizzle outputSwizzle() const { return fSurfaceView->swizzle(); }
 
         GrOp* op() { return fOp; }
-        GrRenderTargetProxy* proxy() const { return fProxy; }
-        GrRenderTarget* renderTarget() const { return fProxy->peekRenderTarget(); }
+        GrRenderTargetProxy* proxy() const { return fSurfaceView->asRenderTargetProxy(); }
+        GrRenderTarget* renderTarget() const { return this->proxy()->peekRenderTarget(); }
         GrAppliedClip* appliedClip() { return fAppliedClip; }
         const GrAppliedClip* appliedClip() const { return fAppliedClip; }
         const GrXferProcessor::DstProxy& dstProxy() const { return fDstProxy; }
@@ -79,13 +81,13 @@
 #ifdef SK_DEBUG
         void validate() const {
             SkASSERT(fOp);
-            SkASSERT(fProxy);
+            SkASSERT(fSurfaceView);
         }
 #endif
 
     private:
         GrOp*                     fOp;
-        GrRenderTargetProxy*      fProxy;
+        GrSurfaceProxyView*       fSurfaceView;
         GrAppliedClip*            fAppliedClip;
         GrXferProcessor::DstProxy fDstProxy;     // TODO: do we still need the dst proxy here?
     };
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index 4306ad0..2d61afe 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -352,15 +352,15 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 GrOpsTask::GrOpsTask(sk_sp<GrOpMemoryPool> opMemoryPool,
-                     sk_sp<GrRenderTargetProxy> rtProxy,
+                     GrSurfaceProxyView view,
                      GrAuditTrail* auditTrail)
-        : GrRenderTask(std::move(rtProxy))
+        : GrRenderTask(std::move(view))
         , fOpMemoryPool(std::move(opMemoryPool))
         , fAuditTrail(auditTrail)
         , fLastClipStackGenID(SK_InvalidUniqueID)
         SkDEBUGCODE(, fNumClips(0)) {
     SkASSERT(fOpMemoryPool);
-    fTarget->setLastRenderTask(this);
+    fTargetView.proxy()->setLastRenderTask(this);
 }
 
 void GrOpsTask::deleteOps() {
@@ -381,11 +381,12 @@
     this->deleteOps();
     fClipAllocator.reset();
 
-    if (fTarget && this == fTarget->getLastRenderTask()) {
-        fTarget->setLastRenderTask(nullptr);
+    GrSurfaceProxy* proxy = fTargetView.proxy();
+    if (proxy && this == proxy->getLastRenderTask()) {
+        proxy->setLastRenderTask(nullptr);
     }
 
-    fTarget.reset();
+    fTargetView.reset();
     fDeferredProxies.reset();
     fSampledProxies.reset();
     fAuditTrail = nullptr;
@@ -412,7 +413,7 @@
 }
 
 void GrOpsTask::onPrepare(GrOpFlushState* flushState) {
-    SkASSERT(fTarget->peekRenderTarget());
+    SkASSERT(fTargetView.proxy()->peekRenderTarget());
     SkASSERT(this->isClosed());
 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
@@ -433,7 +434,7 @@
             TRACE_EVENT0("skia.gpu", chain.head()->name());
 #endif
             GrOpFlushState::OpArgs opArgs(chain.head(),
-                                          fTarget->asRenderTargetProxy(),
+                                          &fTargetView,
                                           chain.appliedClip(),
                                           chain.dstProxy());
 
@@ -482,7 +483,9 @@
         return false;
     }
 
-    SkASSERT(fTarget->peekRenderTarget());
+    GrSurfaceProxy* proxy = fTargetView.proxy();
+    SkASSERT(proxy);
+    SkASSERT(proxy->peekRenderTarget());
     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
 
     // Make sure load ops are not kClear if the GPU needs to use draws for clears
@@ -490,7 +493,7 @@
              !flushState->gpu()->caps()->performColorClearsAsDraws());
 
     const GrCaps& caps = *flushState->gpu()->caps();
-    GrRenderTarget* renderTarget = fTarget.get()->peekRenderTarget();
+    GrRenderTarget* renderTarget = proxy->peekRenderTarget();
     SkASSERT(renderTarget);
     GrStencilAttachment* stencil = renderTarget->renderTargetPriv().getStencilAttachment();
 
@@ -536,7 +539,7 @@
             : GrStoreOp::kStore;
 
     GrOpsRenderPass* renderPass = create_render_pass(
-            flushState->gpu(), fTarget->peekRenderTarget(), fTarget->origin(),
+            flushState->gpu(), proxy->peekRenderTarget(), fTargetView.origin(),
             fClippedContentBounds, fColorLoadOp, fLoadClearColor, stencilLoadOp, stencilStoreOp,
             fSampledProxies);
     flushState->setOpsRenderPass(renderPass);
@@ -552,7 +555,7 @@
 #endif
 
         GrOpFlushState::OpArgs opArgs(chain.head(),
-                                      fTarget->asRenderTargetProxy(),
+                                      &fTargetView,
                                       chain.appliedClip(),
                                       chain.dstProxy());
 
@@ -572,7 +575,9 @@
     fColorLoadOp = op;
     fLoadClearColor = color;
     if (GrLoadOp::kClear == fColorLoadOp) {
-        fTotalBounds = fTarget->getBoundsRect();
+        GrSurfaceProxy* proxy = fTargetView.proxy();
+        SkASSERT(proxy);
+        fTotalBounds = proxy->getBoundsRect();
     }
 }
 
@@ -591,7 +596,7 @@
         // If the opsTask is using a render target which wraps a vulkan command buffer, we can't do
         // a clear load since we cannot change the render pass that we are using. Thus we fall back
         // to making a clear op in this case.
-        return !fTarget->asRenderTargetProxy()->wrapsVkSecondaryCB();
+        return !fTargetView.asRenderTargetProxy()->wrapsVkSecondaryCB();
     }
 
     // Could not empty the task, so an op must be added to handle the clear
@@ -717,24 +722,26 @@
         alloc->addInterval(fDeferredProxies[i], 0, 0, GrResourceAllocator::ActualUse::kNo);
     }
 
+    GrSurfaceProxy* targetProxy = fTargetView.proxy();
+
     // Add the interval for all the writes to this GrOpsTasks's target
     if (fOpChains.count()) {
         unsigned int cur = alloc->curOp();
 
-        alloc->addInterval(fTarget.get(), cur, cur + fOpChains.count() - 1,
+        alloc->addInterval(targetProxy, cur, cur + fOpChains.count() - 1,
                            GrResourceAllocator::ActualUse::kYes);
     } else {
         // This can happen if there is a loadOp (e.g., a clear) but no other draws. In this case we
         // still need to add an interval for the destination so we create a fake op# for
         // the missing clear op.
-        alloc->addInterval(fTarget.get(), alloc->curOp(), alloc->curOp(),
+        alloc->addInterval(targetProxy, alloc->curOp(), alloc->curOp(),
                            GrResourceAllocator::ActualUse::kYes);
         alloc->incOps();
     }
 
     auto gather = [ alloc SkDEBUGCODE(, this) ] (GrSurfaceProxy* p, GrMipMapped) {
         alloc->addInterval(p, alloc->curOp(), alloc->curOp(), GrResourceAllocator::ActualUse::kYes
-                           SkDEBUGCODE(, fTarget.get() == p));
+                           SkDEBUGCODE(, fTargetView.proxy() == p));
     };
     for (const OpChain& recordedOp : fOpChains) {
         recordedOp.visitProxies(gather);
@@ -750,7 +757,8 @@
         const DstProxy* dstProxy, const GrCaps& caps) {
     SkDEBUGCODE(op->validate();)
     SkASSERT(processorAnalysis.requiresDstTexture() == (dstProxy && dstProxy->proxy()));
-    SkASSERT(fTarget);
+    GrSurfaceProxy* proxy = fTargetView.proxy();
+    SkASSERT(proxy);
 
     // A closed GrOpsTask should never receive new/more ops
     SkASSERT(!this->isClosed());
@@ -767,7 +775,7 @@
     // 1) check every op
     // 2) intersect with something
     // 3) find a 'blocker'
-    GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(), fTarget->uniqueID());
+    GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(), proxy->uniqueID());
     GrOP_INFO("opsTask: %d Recording (%s, opID: %u)\n"
               "\tBounds [L: %.2f, T: %.2f R: %.2f B: %.2f]\n",
                this->uniqueID(),
@@ -843,9 +851,10 @@
         const GrCaps& caps, SkIRect* targetUpdateBounds) {
     this->forwardCombine(caps);
     if (!this->isNoOp()) {
-        SkRect clippedContentBounds = fTarget->getBoundsRect();
-        // TODO: If we can fix up GLPrograms test to always intersect the fTarget bounds then we can
-        // simply assert here that the bounds intersect.
+        GrSurfaceProxy* proxy = fTargetView.proxy();
+        SkRect clippedContentBounds = proxy->getBoundsRect();
+        // TODO: If we can fix up GLPrograms test to always intersect the fTargetView proxy bounds
+        // then we can simply assert here that the bounds intersect.
         if (clippedContentBounds.intersect(fTotalBounds)) {
             clippedContentBounds.roundOut(&fClippedContentBounds);
             *targetUpdateBounds = fClippedContentBounds;
diff --git a/src/gpu/GrOpsTask.h b/src/gpu/GrOpsTask.h
index c223812..61507e3 100644
--- a/src/gpu/GrOpsTask.h
+++ b/src/gpu/GrOpsTask.h
@@ -38,7 +38,7 @@
     using DstProxy = GrXferProcessor::DstProxy;
 
 public:
-    GrOpsTask(sk_sp<GrOpMemoryPool>, sk_sp<GrRenderTargetProxy>, GrAuditTrail*);
+    GrOpsTask(sk_sp<GrOpMemoryPool>, GrSurfaceProxyView, GrAuditTrail*);
     ~GrOpsTask() override;
 
     GrOpsTask* asOpsTask() override { return this; }
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 9e7b6ce..9b5dd49 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -217,7 +217,7 @@
 
     if (!fOpsTask || fOpsTask->isClosed()) {
         sk_sp<GrOpsTask> newOpsTask =
-                this->drawingManager()->newOpsTask(fRenderTargetProxy, fManagedOpsTask);
+                this->drawingManager()->newOpsTask(this->outputSurfaceView(), fManagedOpsTask);
         if (fOpsTask && fNumStencilSamples > 0) {
             // Store the stencil values in memory upon completion of fOpsTask.
             fOpsTask->setMustPreserveStencil();
diff --git a/src/gpu/GrRenderTask.cpp b/src/gpu/GrRenderTask.cpp
index 2f6c0e6..4699893 100644
--- a/src/gpu/GrRenderTask.cpp
+++ b/src/gpu/GrRenderTask.cpp
@@ -21,16 +21,22 @@
     return id;
 }
 
-GrRenderTask::GrRenderTask(sk_sp<GrSurfaceProxy> target)
-        : fTarget(std::move(target))
+GrRenderTask::GrRenderTask()
+        : fUniqueID(CreateUniqueID())
+        , fFlags(0) {
+}
+
+GrRenderTask::GrRenderTask(GrSurfaceProxyView targetView)
+        : fTargetView(std::move(targetView))
         , fUniqueID(CreateUniqueID())
         , fFlags(0) {
 }
 
 GrRenderTask::~GrRenderTask() {
-    if (fTarget && this == fTarget->getLastRenderTask()) {
+    GrSurfaceProxy* proxy = fTargetView.proxy();
+    if (proxy && this == proxy->getLastRenderTask()) {
         // Ensure the target proxy doesn't keep hold of a dangling back pointer.
-        fTarget->setLastRenderTask(nullptr);
+        proxy->setLastRenderTask(nullptr);
     }
 }
 
@@ -53,12 +59,13 @@
 
     SkIRect targetUpdateBounds;
     if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(caps, &targetUpdateBounds)) {
-        SkASSERT(SkIRect::MakeSize(fTarget->dimensions()).contains(targetUpdateBounds));
-        if (fTarget->requiresManualMSAAResolve()) {
-            SkASSERT(fTarget->asRenderTargetProxy());
-            fTarget->asRenderTargetProxy()->markMSAADirty(targetUpdateBounds);
+        GrSurfaceProxy* proxy = fTargetView.proxy();
+        SkASSERT(SkIRect::MakeSize(proxy->dimensions()).contains(targetUpdateBounds));
+        if (proxy->requiresManualMSAAResolve()) {
+            SkASSERT(fTargetView.asRenderTargetProxy());
+            fTargetView.asRenderTargetProxy()->markMSAADirty(targetUpdateBounds);
         }
-        GrTextureProxy* textureProxy = fTarget->asTextureProxy();
+        GrTextureProxy* textureProxy = fTargetView.asTextureProxy();
         if (textureProxy && GrMipMapped::kYes == textureProxy->mipMapped()) {
             textureProxy->markMipMapsDirty();
         }
@@ -161,7 +168,9 @@
         if (!fTextureResolveTask) {
             fTextureResolveTask = textureResolveManager.newTextureResolveRenderTask(caps);
         }
-        fTextureResolveTask->addProxy(sk_ref_sp(dependedOn), resolveFlags, caps);
+        fTextureResolveTask->addProxy(
+                GrSurfaceProxyView(sk_ref_sp(dependedOn), dependedOn->origin(), GrSwizzle()),
+                resolveFlags, caps);
 
         // addProxy() should have closed the texture proxy's previous task.
         SkASSERT(!dependedOnTask || dependedOnTask->isClosed());
@@ -244,20 +253,21 @@
 
 bool GrRenderTask::isInstantiated() const {
     // Some renderTasks (e.g. GrTransferFromRenderTask) don't have a target.
-    if (!fTarget) {
+    GrSurfaceProxy* proxy = fTargetView.proxy();
+    if (!proxy) {
         return true;
     }
 
-    if (!fTarget->isInstantiated()) {
+    if (!proxy->isInstantiated()) {
         return false;
     }
 
-    int minStencilSampleCount = (fTarget->asRenderTargetProxy())
-            ? fTarget->asRenderTargetProxy()->numStencilSamples()
+    int minStencilSampleCount = (proxy->asRenderTargetProxy())
+            ? proxy->asRenderTargetProxy()->numStencilSamples()
             : 0;
 
     if (minStencilSampleCount) {
-        GrRenderTarget* rt = fTarget->peekRenderTarget();
+        GrRenderTarget* rt = proxy->peekRenderTarget();
         SkASSERT(rt);
 
         GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
@@ -267,7 +277,7 @@
         SkASSERT(stencil->numSamples() >= minStencilSampleCount);
     }
 
-    GrSurface* surface = fTarget->peekSurface();
+    GrSurface* surface = proxy->peekSurface();
     if (surface->wasDestroyed()) {
         return false;
     }
@@ -278,10 +288,11 @@
 #ifdef SK_DEBUG
 void GrRenderTask::dump(bool printDependencies) const {
     SkDebugf("--------------------------------------------------------------\n");
+    GrSurfaceProxy* proxy = fTargetView.proxy();
     SkDebugf("renderTaskID: %d - proxyID: %d - surfaceID: %d\n", fUniqueID,
-             fTarget ? fTarget->uniqueID().asUInt() : -1,
-             fTarget && fTarget->peekSurface()
-                     ? fTarget->peekSurface()->uniqueID().asUInt()
+             proxy ? proxy->uniqueID().asUInt() : -1,
+             proxy && proxy->peekSurface()
+                     ? proxy->peekSurface()->uniqueID().asUInt()
                      : -1);
 
     if (printDependencies) {
diff --git a/src/gpu/GrRenderTask.h b/src/gpu/GrRenderTask.h
index 3fb3a18..efa1305 100644
--- a/src/gpu/GrRenderTask.h
+++ b/src/gpu/GrRenderTask.h
@@ -11,6 +11,7 @@
 #include "include/core/SkRefCnt.h"
 #include "include/private/SkColorData.h"
 #include "include/private/SkTDArray.h"
+#include "src/gpu/GrSurfaceProxyView.h"
 #include "src/gpu/GrTextureProxy.h"
 #include "src/gpu/GrTextureResolveManager.h"
 
@@ -24,7 +25,8 @@
 // contents. (e.g., an opsTask that executes a command buffer, a task to regenerate mipmaps, etc.)
 class GrRenderTask : public SkRefCnt {
 public:
-    GrRenderTask(sk_sp<GrSurfaceProxy> target);
+    GrRenderTask();
+    GrRenderTask(GrSurfaceProxyView);
     ~GrRenderTask() override;
 
     void makeClosed(const GrCaps&);
@@ -80,8 +82,8 @@
 
     void visitTargetAndSrcProxies_debugOnly(const VisitSurfaceProxyFunc& fn) const {
         this->visitProxies_debugOnly(fn);
-        if (fTarget) {
-            fn(fTarget.get(), GrMipMapped::kNo);
+        if (fTargetView.proxy()) {
+            fn(fTargetView.proxy(), GrMipMapped::kNo);
         }
     }
 #endif
@@ -105,7 +107,7 @@
     // targetUpdateBounds must not extend beyond the proxy bounds.
     virtual ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect* targetUpdateBounds) = 0;
 
-    sk_sp<GrSurfaceProxy> fTarget;
+    GrSurfaceProxyView fTargetView;
 
     // List of texture proxies whose contents are being prepared on a worker thread
     // TODO: this list exists so we can fire off the proper upload when an renderTask begins
@@ -117,14 +119,14 @@
     friend class GrDrawingManager;
 
     // Drops any pending operations that reference proxies that are not instantiated.
-    // NOTE: Derived classes don't need to check fTarget. That is handled when the drawingManager
-    // calls isInstantiated.
+    // NOTE: Derived classes don't need to check fTargetView. That is handled when the
+    // drawingManager calls isInstantiated.
     virtual void handleInternalAllocationFailure() = 0;
 
     virtual bool onIsUsed(GrSurfaceProxy*) const = 0;
 
     bool isUsed(GrSurfaceProxy* proxy) const {
-        if (proxy == fTarget.get()) {
+        if (proxy == fTargetView.proxy()) {
             return true;
         }
 
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index f427478..8d4708d 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -430,8 +430,10 @@
         return false;
     }
 
-    return this->drawingManager()->newCopyRenderTask(sk_ref_sp(src), srcRect,
-                                                     this->asSurfaceProxyRef(), dstPoint);
+    // The swizzle doesn't matter for copies and it is not used.
+    return this->drawingManager()->newCopyRenderTask(
+            GrSurfaceProxyView(sk_ref_sp(src), src->origin(), GrSwizzle()), srcRect,
+            this->textureSurfaceView(), dstPoint);
 }
 
 std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(
diff --git a/src/gpu/GrSurfaceContext.h b/src/gpu/GrSurfaceContext.h
index 0d2c4b3..b30e531 100644
--- a/src/gpu/GrSurfaceContext.h
+++ b/src/gpu/GrSurfaceContext.h
@@ -105,7 +105,6 @@
     }
 #endif
 
-
 protected:
     friend class GrSurfaceContextPriv;
 
diff --git a/src/gpu/GrSurfaceProxyView.h b/src/gpu/GrSurfaceProxyView.h
index 9f81713..1649e12 100644
--- a/src/gpu/GrSurfaceProxyView.h
+++ b/src/gpu/GrSurfaceProxyView.h
@@ -15,22 +15,41 @@
 
 class GrSurfaceProxyView {
 public:
+    GrSurfaceProxyView() = default;
+
     GrSurfaceProxyView(sk_sp<GrSurfaceProxy> proxy, GrSurfaceOrigin origin, GrSwizzle swizzle)
             : fProxy(proxy), fOrigin(origin), fSwizzle(swizzle) {}
 
-    GrSurfaceProxyView(GrSurfaceProxyView&& view)
-            : fProxy(std::move(view.fProxy)), fOrigin(view.fOrigin), fSwizzle(view.fSwizzle) {}
+    // This entry point is used when we don't care about the origin or the swizzle.
+    GrSurfaceProxyView(sk_sp<GrSurfaceProxy> proxy)
+            : fProxy(proxy), fOrigin(kTopLeft_GrSurfaceOrigin) {}
 
-    GrSurfaceProxy* asSurfaceProxy() const { return fProxy.get(); }
+    GrSurfaceProxyView(GrSurfaceProxyView&& view) = default;
+    GrSurfaceProxyView(const GrSurfaceProxyView&) = delete;
+
+    GrSurfaceProxyView& operator=(const GrSurfaceProxyView& that) = default;
+
+    bool operator==(const GrSurfaceProxyView& view) {
+        return fProxy.get() == view.fProxy.get() &&
+               fOrigin == view.fOrigin &&
+               fSwizzle == view.fSwizzle;
+    }
+    bool operator!=(const GrSurfaceProxyView& other) { return !(*this == other); }
+
+    GrSurfaceProxy* proxy() const { return fProxy.get(); }
     GrTextureProxy* asTextureProxy() const { return fProxy->asTextureProxy(); }
     GrRenderTargetProxy* asRenderTargetProxy() const { return fProxy->asRenderTargetProxy(); }
 
     GrSurfaceOrigin origin() const { return fOrigin; }
     const GrSwizzle& swizzle() const { return fSwizzle; }
 
+    void reset() {
+        *this = {};
+    }
+
 private:
     sk_sp<GrSurfaceProxy> fProxy;
-    GrSurfaceOrigin fOrigin;
+    GrSurfaceOrigin fOrigin = kTopLeft_GrSurfaceOrigin;
     GrSwizzle fSwizzle;
 };
 
diff --git a/src/gpu/GrTextureResolveRenderTask.cpp b/src/gpu/GrTextureResolveRenderTask.cpp
index e12bbc8..8c326d3 100644
--- a/src/gpu/GrTextureResolveRenderTask.cpp
+++ b/src/gpu/GrTextureResolveRenderTask.cpp
@@ -17,14 +17,14 @@
 GrTextureResolveRenderTask::~GrTextureResolveRenderTask() {
     for (const auto& resolve : fResolves) {
         // Ensure the proxy doesn't keep hold of a dangling back pointer.
-        resolve.fProxy->setLastRenderTask(nullptr);
+        resolve.fProxyView.proxy()->setLastRenderTask(nullptr);
     }
 }
 
 void GrTextureResolveRenderTask::addProxy(
-        sk_sp<GrSurfaceProxy> proxyHolder, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
-    fResolves.emplace_back(std::move(proxyHolder), flags);
-    GrSurfaceProxy* proxy = fResolves.back().fProxy.get();
+        GrSurfaceProxyView proxyView, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
+    fResolves.emplace_back(std::move(proxyView), flags);
+    GrSurfaceProxy* proxy = fResolves.back().fProxyView.proxy();
 
     // Ensure the last render task that operated on the proxy is closed. That's where msaa and
     // mipmaps should have been marked dirty.
@@ -58,7 +58,7 @@
     // manipulate the resolve proxies.
     auto fakeOp = alloc->curOp();
     for (const auto& resolve : fResolves) {
-        alloc->addInterval(resolve.fProxy.get(), fakeOp, fakeOp,
+        alloc->addInterval(resolve.fProxyView.proxy(), fakeOp, fakeOp,
                            GrResourceAllocator::ActualUse::kYes);
     }
     alloc->incOps();
@@ -68,10 +68,11 @@
     // Resolve all msaa back-to-back, before regenerating mipmaps.
     for (const auto& resolve : fResolves) {
         if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) {
+            GrSurfaceProxy* proxy = resolve.fProxyView.proxy();
             // peekRenderTarget might be null if there was an instantiation error.
-            if (GrRenderTarget* renderTarget = resolve.fProxy->peekRenderTarget()) {
+            if (GrRenderTarget* renderTarget = proxy->peekRenderTarget()) {
                 flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect,
-                                                       resolve.fProxy->origin(),
+                                                       resolve.fProxyView.origin(),
                                                        GrGpu::ForExternalIO::kNo);
             }
         }
@@ -80,7 +81,7 @@
     for (const auto& resolve : fResolves) {
         if (GrSurfaceProxy::ResolveFlags::kMipMaps & resolve.fFlags) {
             // peekTexture might be null if there was an instantiation error.
-            GrTexture* texture = resolve.fProxy->peekTexture();
+            GrTexture* texture = resolve.fProxyView.proxy()->peekTexture();
             if (texture && texture->texturePriv().mipMapsAreDirty()) {
                 flushState->gpu()->regenerateMipMapLevels(texture);
                 SkASSERT(!texture->texturePriv().mipMapsAreDirty());
@@ -94,7 +95,7 @@
 #ifdef SK_DEBUG
 void GrTextureResolveRenderTask::visitProxies_debugOnly(const VisitSurfaceProxyFunc& fn) const {
     for (const auto& resolve : fResolves) {
-        fn(resolve.fProxy.get(), GrMipMapped::kNo);
+        fn(resolve.fProxyView.proxy(), GrMipMapped::kNo);
     }
 }
 #endif
diff --git a/src/gpu/GrTextureResolveRenderTask.h b/src/gpu/GrTextureResolveRenderTask.h
index 48fea39..1a3aed0 100644
--- a/src/gpu/GrTextureResolveRenderTask.h
+++ b/src/gpu/GrTextureResolveRenderTask.h
@@ -12,14 +12,15 @@
 
 class GrTextureResolveRenderTask final : public GrRenderTask {
 public:
-    GrTextureResolveRenderTask() : GrRenderTask(nullptr) {}
+    GrTextureResolveRenderTask() : GrRenderTask() {}
     ~GrTextureResolveRenderTask() override;
 
-    void addProxy(sk_sp<GrSurfaceProxy>, GrSurfaceProxy::ResolveFlags, const GrCaps&);
+    void addProxy(GrSurfaceProxyView proxyView, GrSurfaceProxy::ResolveFlags, const GrCaps&);
 
 private:
     bool onIsUsed(GrSurfaceProxy* proxy) const override {
-        SkASSERT(proxy != fTarget.get());  // This case should be handled by GrRenderTask.
+        // This case should be handled by GrRenderTask.
+        SkASSERT(proxy != fTargetView.proxy());
         return false;
     }
     void handleInternalAllocationFailure() override {
@@ -38,9 +39,9 @@
 #endif
 
     struct Resolve {
-        Resolve(sk_sp<GrSurfaceProxy> proxy, GrSurfaceProxy::ResolveFlags flags)
-                : fProxy(std::move(proxy)), fFlags(flags) {}
-        sk_sp<GrSurfaceProxy> fProxy;
+        Resolve(GrSurfaceProxyView proxyView, GrSurfaceProxy::ResolveFlags flags)
+                : fProxyView(std::move(proxyView)), fFlags(flags) {}
+        GrSurfaceProxyView fProxyView;
         GrSurfaceProxy::ResolveFlags fFlags;
         SkIRect fMSAAResolveRect;
     };
diff --git a/src/gpu/GrTransferFromRenderTask.h b/src/gpu/GrTransferFromRenderTask.h
index 40e89da..d8f6c12 100644
--- a/src/gpu/GrTransferFromRenderTask.h
+++ b/src/gpu/GrTransferFromRenderTask.h
@@ -18,7 +18,7 @@
                              GrColorType dstColorType,
                              sk_sp<GrGpuBuffer> dstBuffer,
                              size_t dstOffset)
-            : GrRenderTask(nullptr)
+            : GrRenderTask()
             , fSrcProxy(std::move(srcProxy))
             , fSrcRect(srcRect)
             , fSurfaceColorType(surfaceColorType)
@@ -28,7 +28,7 @@
 
 private:
     bool onIsUsed(GrSurfaceProxy* proxy) const override {
-        SkASSERT(!fTarget);
+        SkASSERT(!fTargetView.proxy());
         return proxy == fSrcProxy.get();
     }
     // If fSrcProxy is uninstantiated at flush time we simply will skip doing the transfer.
diff --git a/src/gpu/GrWaitRenderTask.cpp b/src/gpu/GrWaitRenderTask.cpp
index a09a9a6..2d057fa 100644
--- a/src/gpu/GrWaitRenderTask.cpp
+++ b/src/gpu/GrWaitRenderTask.cpp
@@ -14,8 +14,8 @@
 void GrWaitRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
     // This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so
     // fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that
-    // we manipulate fTarget.
-    alloc->addInterval(fTarget.get(), alloc->curOp(), alloc->curOp(),
+    // we manipulate fTargetView's proxy.
+    alloc->addInterval(fTargetView.proxy(), alloc->curOp(), alloc->curOp(),
                        GrResourceAllocator::ActualUse::kYes);
     alloc->incOps();
 }
diff --git a/src/gpu/GrWaitRenderTask.h b/src/gpu/GrWaitRenderTask.h
index fc736e1..d3683f2 100644
--- a/src/gpu/GrWaitRenderTask.h
+++ b/src/gpu/GrWaitRenderTask.h
@@ -13,15 +13,17 @@
 
 class GrWaitRenderTask final : public GrRenderTask {
 public:
-    GrWaitRenderTask(sk_sp<GrSurfaceProxy> proxy, std::unique_ptr<sk_sp<GrSemaphore>[]> semaphores,
+    GrWaitRenderTask(GrSurfaceProxyView surfaceView,
+                     std::unique_ptr<sk_sp<GrSemaphore>[]> semaphores,
                      int numSemaphores)
-            : GrRenderTask(std::move(proxy))
+            : GrRenderTask(std::move(surfaceView))
             , fSemaphores(std::move(semaphores))
             , fNumSemaphores(numSemaphores){}
 
 private:
     bool onIsUsed(GrSurfaceProxy* proxy) const override {
-        SkASSERT(proxy != fTarget.get());  // This case should be handled by GrRenderTask.
+        // This case should be handled by GrRenderTask.
+        SkASSERT(proxy != fTargetView.proxy());
         return false;
     }
     void handleInternalAllocationFailure() override {}