Add a deferred copy surface (take 3)

This CL forces all GrSurface copies to go through a GrSurfaceContext (rather than GrContext).

There is a bit of goofiness going on here until read/writePixels is also consolidated in GrSurfaceContext and a proxy-backed SkImage/SkSurface is added.

This is a reland of https://skia-review.googlesource.com/c/5773/ (Add a deferred copy surface)

Change-Id: Ib8fd96d0569274ef781366eb900ed8ee839ae9bd
Reviewed-on: https://skia-review.googlesource.com/6109
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index de80b68..147cf5c 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -301,25 +301,6 @@
                             uint32_t pixelOpsFlags = 0);
 
     /**
-     * Copies a rectangle of texels from src to dst.
-     * @param dst           the surface to copy to.
-     * @param src           the surface to copy from.
-     * @param srcRect       the rectangle of the src that should be copied.
-     * @param dstPoint      the translation applied when writing the srcRect's pixels to the dst.
-     */
-    bool copySurface(GrSurface* dst,
-                     GrSurface* src,
-                     const SkIRect& srcRect,
-                     const SkIPoint& dstPoint);
-
-    /** Helper that copies the whole surface but fails when the two surfaces are not identically
-        sized. */
-    bool copySurface(GrSurface* dst, GrSurface* src) {
-        return this->copySurface(dst, src, SkIRect::MakeWH(dst->width(), dst->height()),
-                                 SkIPoint::Make(0,0));
-    }
-
-    /**
      * After this returns any pending writes to the surface will have been issued to the backend 3D API.
      */
     void flushSurfaceWrites(GrSurface* surface);
diff --git a/include/gpu/GrRenderTargetContext.h b/include/gpu/GrRenderTargetContext.h
index 864055b..b86b626 100644
--- a/include/gpu/GrRenderTargetContext.h
+++ b/include/gpu/GrRenderTargetContext.h
@@ -50,8 +50,6 @@
 public:
     ~GrRenderTargetContext() override;
 
-    bool copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
-
     // TODO: it is odd that we need both the SkPaint in the following 3 methods.
     // We should extract the text parameters from SkPaint and pass them separately
     // akin to GrStyle (GrTextInfo?)
@@ -469,6 +467,8 @@
                           const SkPath&,
                           const GrStyle&);
 
+    bool onCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
+
     // This entry point allows the GrTextContext-derived classes to add their ops to the GrOpList.
     void addDrawOp(const GrPipelineBuilder&, const GrClip&, sk_sp<GrDrawOp>);
 
diff --git a/include/gpu/GrSurfaceContext.h b/include/gpu/GrSurfaceContext.h
index f966086..a772d19 100644
--- a/include/gpu/GrSurfaceContext.h
+++ b/include/gpu/GrSurfaceContext.h
@@ -8,6 +8,8 @@
 #ifndef GrSurfaceContext_DEFINED
 #define GrSurfaceContext_DEFINED
 
+#include "../private/GrSurfaceProxy.h"
+
 #include "SkRefCnt.h"
 
 class GrAuditTrail;
@@ -28,7 +30,27 @@
 public:
     ~GrSurfaceContext() override {}
 
-    virtual bool copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) = 0;
+    /*
+     * Copy 'src' into the proxy backing this context
+     * @param src       src of pixels
+     * @param srcRect   the subset of 'src' to copy
+     * @param dstPoint  the origin of the 'srcRect' in the destination coordinate space
+     * @return          true if the copy succeeded; false otherwise
+     *
+     * Note: Notionally, 'srcRect' is clipped to 'src's extent with 'dstPoint' being adjusted.
+     *       Then the 'srcRect' offset by 'dstPoint' is clipped against the dst's extent.
+     *       The end result is only valid src pixels and dst pixels will be touched but the copied
+     *       regions will not be shifted.
+     */
+    bool copy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
+        return this->onCopy(src, srcRect, dstPoint);
+    }
+
+    bool copy(GrSurfaceProxy* src) {
+        return this->onCopy(src,
+                            SkIRect::MakeWH(src->width(), src->height()),
+                            SkIPoint::Make(0, 0));
+    }
 
     // TODO: this is virtual b.c. this object doesn't have a pointer to the wrapped GrSurfaceProxy?
     virtual GrSurfaceProxy* asDeferredSurface() = 0;
@@ -55,6 +77,10 @@
     SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
 
 private:
+    virtual bool onCopy(GrSurfaceProxy* src,
+                        const SkIRect& srcRect,
+                        const SkIPoint& dstPoint) = 0;
+
     typedef SkRefCnt INHERITED;
 };
 
diff --git a/include/gpu/GrTextureContext.h b/include/gpu/GrTextureContext.h
index 28fe63d..ef9613f 100644
--- a/include/gpu/GrTextureContext.h
+++ b/include/gpu/GrTextureContext.h
@@ -27,8 +27,6 @@
 public:
     ~GrTextureContext() override;
 
-    bool copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
-
     GrSurfaceProxy* asDeferredSurface() override { return fTextureProxy.get(); }
     GrTextureProxy* asDeferredTexture() override { return fTextureProxy.get(); }
     GrRenderTargetProxy* asDeferredRenderTarget() override;
@@ -44,6 +42,8 @@
 private:
     friend class GrDrawingManager; // for ctor
 
+    bool onCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
+
     GrTextureOpList* getOpList();
 
     GrDrawingManager*            fDrawingManager;
@@ -52,6 +52,8 @@
     // In MDB-mode the GrOpList can be closed by some other renderTargetContext that has picked
     // it up. For this reason, the GrOpList should only ever be accessed via 'getOpList'.
     GrTextureOpList*             fOpList;
+
+    typedef GrSurfaceContext INHERITED;
 };
 
 #endif
diff --git a/include/private/GrRenderTargetProxy.h b/include/private/GrRenderTargetProxy.h
index 83107da..7f026ba 100644
--- a/include/private/GrRenderTargetProxy.h
+++ b/include/private/GrRenderTargetProxy.h
@@ -53,6 +53,9 @@
 
     GrRenderTarget::Flags testingOnly_getFlags() const;
 
+    // TODO: move this to a priv class!
+    bool refsWrappedObjects() const;
+
 protected:
     friend class GrSurfaceProxy;  // for ctors
 
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 731603b..12972c2 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -266,6 +266,20 @@
         return fGpuMemorySize;
     }
 
+    // Helper function that creates a temporary SurfaceContext to perform the copy
+    static sk_sp<GrSurfaceProxy> Copy(GrContext*, GrSurfaceProxy* src,
+                                      SkIRect srcRect, SkBudgeted);
+
+    // Copy the entire 'src'
+    static sk_sp<GrSurfaceProxy> Copy(GrContext* context, GrSurfaceProxy* src,
+                                      SkBudgeted budgeted) {
+        return Copy(context, src, SkIRect::MakeWH(src->width(), src->height()), budgeted);
+    }
+
+    // Test-only entry point - should decrease in use as proxies propagate
+    static sk_sp<GrSurfaceProxy> TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
+                                          GrTexture* srcTexture, SkBudgeted budgeted);
+
     bool isWrapped_ForTesting() const;
 
     SkDEBUGCODE(void validate(GrContext*) const;)