Make SkImage_Gpu be deferred (take 2)

This CL removes the GrTexture-based ctor forcing everyone to create deferred SkImage_Gpus.

relanding of: https://skia-review.googlesource.com/c/6680/ (Make SkImage_Gpu be deferred)

split out into:
https://skia-review.googlesource.com/c/9106/ (Remove atlas creation from GrResourceProvider)

Change-Id: I834ede430b9706cf9b675bdfdddf1c8c624c2f14
Reviewed-on: https://skia-review.googlesource.com/9965
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index b610c9c..fdbbf82 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -8,14 +8,15 @@
 #include "SkSurface_Gpu.h"
 
 #include "GrContextPriv.h"
+#include "GrRenderTargetContextPriv.h"
 #include "GrResourceProvider.h"
+
 #include "SkCanvas.h"
 #include "SkColorSpace_Base.h"
 #include "SkGpuDevice.h"
 #include "SkImage_Base.h"
 #include "SkImage_Gpu.h"
 #include "SkImagePriv.h"
-#include "GrRenderTargetContextPriv.h"
 #include "SkSurface_Base.h"
 
 #if SK_SUPPORT_GPU
@@ -23,6 +24,7 @@
 SkSurface_Gpu::SkSurface_Gpu(sk_sp<SkGpuDevice> device)
     : INHERITED(device->width(), device->height(), &device->surfaceProps())
     , fDevice(std::move(device)) {
+    SkASSERT(fDevice->accessRenderTargetContext()->asSurfaceProxy()->priv().isExact());
 }
 
 SkSurface_Gpu::~SkSurface_Gpu() {
@@ -91,38 +93,45 @@
 
     GrContext* ctx = fDevice->context();
 
-    GrSurfaceProxy* srcProxy = rtc->asSurfaceProxy();
-    sk_sp<GrSurfaceContext> copyCtx;
+    if (!rtc->asSurfaceProxy()) {
+        return nullptr;
+    }
+
+    SkBudgeted budgeted = rtc->asSurfaceProxy()->isBudgeted();
+
+    sk_sp<GrTextureProxy> srcProxy = rtc->asTextureProxyRef();
     // If the original render target is a buffer originally created by the client, then we don't
     // want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid
     // copy-on-write.
     if (!srcProxy || rtc->priv().refsWrappedObjects()) {
+        // MDB TODO: replace this with GrSurfaceProxy::Copy?
         GrSurfaceDesc desc = rtc->desc();
         desc.fFlags = desc.fFlags & ~kRenderTarget_GrSurfaceFlag;
 
-        copyCtx = ctx->contextPriv().makeDeferredSurfaceContext(desc,
+        sk_sp<GrSurfaceContext> copyCtx = ctx->contextPriv().makeDeferredSurfaceContext(
+                                                                desc,
                                                                 SkBackingFit::kExact,
-                                                                srcProxy->isBudgeted());
+                                                                budgeted);
         if (!copyCtx) {
             return nullptr;
         }
 
-        if (!copyCtx->copy(srcProxy)) {
+        if (!copyCtx->copy(rtc->asSurfaceProxy())) {
             return nullptr;
         }
 
-        srcProxy = copyCtx->asSurfaceProxy();
+        srcProxy = copyCtx->asTextureProxyRef();
     }
 
-    // TODO: add proxy-backed SkImage_Gpu
-    GrTexture* tex = srcProxy->instantiate(ctx->resourceProvider())->asTexture();
-
     const SkImageInfo info = fDevice->imageInfo();
     sk_sp<SkImage> image;
-    if (tex) {
-        image = sk_make_sp<SkImage_Gpu>(kNeedNewImageUniqueID,
-                                        info.alphaType(), sk_ref_sp(tex),
-                                        sk_ref_sp(info.colorSpace()), srcProxy->isBudgeted());
+    if (srcProxy) {
+        // The renderTargetContext coming out of SkGpuDevice should always be exact and the
+        // above copy creates a kExact surfaceContext.
+        SkASSERT(srcProxy->priv().isExact());
+        image = sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID,
+                                        info.alphaType(), std::move(srcProxy),
+                                        info.refColorSpace(), budgeted);
     }
     return image;
 }