Add lazy proxy's for wrapping backend textures

Bug: skia:
Change-Id: I3bb557cefc35312adc9515b5683d2ed747bb4eb3
Reviewed-on: https://skia-review.googlesource.com/96862
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index b07115e..064727e 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -114,15 +114,14 @@
 
     // Must make copies of member variables to capture in the lambda since this image generator may
     // be deleted before we actuallly execute the lambda.
-    GrSurfaceOrigin surfaceOrigin = fSurfaceOrigin;
     sk_sp<GrSemaphore> semaphore = fSemaphore;
     GrBackendTexture backendTexture = fBackendTexture;
     RefHelper* refHelper = fRefHelper;
     refHelper->ref();
 
     sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy(
-            [refHelper, semaphore, backendTexture, surfaceOrigin]
-            (GrResourceProvider* resourceProvider, GrSurfaceOrigin* outOrigin) {
+            [refHelper, semaphore, backendTexture]
+            (GrResourceProvider* resourceProvider, GrSurfaceOrigin* /*outOrigin*/) {
                 if (!resourceProvider) {
                     // If we get here then we never created a texture to pass the refHelper ref off
                     // to. Thus we must unref it ourselves.
@@ -168,7 +167,6 @@
                     tex->setRelease(ReleaseRefHelper_TextureReleaseProc, refHelper);
                 }
 
-                *outOrigin = surfaceOrigin;
                 return tex;
 
             }, desc, mipMapped, SkBackingFit::kExact, SkBudgeted::kNo);
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index c49f6b8..1267750 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -330,17 +330,46 @@
         return nullptr;
     }
 
-    sk_sp<GrTexture> texture(fResourceProvider->wrapBackendTexture(backendTex, ownership));
-    if (!texture) {
-        return nullptr;
-    }
-    if (releaseProc) {
-        texture->setRelease(releaseProc, releaseCtx);
-    }
+    GrSurfaceDesc desc;
+    desc.fOrigin = origin;
+    desc.fWidth = backendTex.width();
+    desc.fHeight = backendTex.height();
+    desc.fConfig = backendTex.config();
+    GrMipMapped mipMapped = backendTex.hasMipMaps() ? GrMipMapped::kYes : GrMipMapped::kNo;
 
-    SkASSERT(!texture->asRenderTarget());   // Strictly a GrTexture
+    sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
+            [backendTex, ownership, releaseProc, releaseCtx]
+            (GrResourceProvider* resourceProvider, GrSurfaceOrigin* /*outOrigin*/) {
+                if (!resourceProvider) {
+                    // This lazy proxy was never initialized. If it has a releaseProc we must call
+                    // it now so that the client knows they can free the underlying backend object.
+                    if (releaseProc) {
+                        releaseProc(releaseCtx);
+                    }
+                    return sk_sp<GrTexture>();
+                }
 
-    return this->createWrapped(std::move(texture), origin);
+                sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(backendTex,
+                                                                            ownership);
+                if (!tex) {
+                    return sk_sp<GrTexture>();
+                }
+                if (releaseProc) {
+                    tex->setRelease(releaseProc, releaseCtx);
+                }
+                SkASSERT(!tex->asRenderTarget());   // Strictly a GrTexture
+                // Make sure we match how we created the proxy with SkBudgeted::kNo
+                SkASSERT(SkBudgeted::kNo == tex->resourcePriv().isBudgeted());
+
+                return tex;
+            }, desc, mipMapped, SkBackingFit::kExact, SkBudgeted::kNo);
+
+    if (fResourceProvider) {
+        // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however,
+        // we're better off instantiating the proxy immediately here.
+        proxy->priv().doLazyInstantiation(fResourceProvider);
+    }
+    return proxy;
 }
 
 sk_sp<GrTextureProxy> GrProxyProvider::createWrappedTextureProxy(const GrBackendTexture& tex,
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 9dadaca..08e4dd3 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -351,7 +351,19 @@
     SkASSERT(fProxy->fLazyInstantiateCallback);
     SkASSERT(!fProxy->fTarget);
 
-    sk_sp<GrTexture> texture = fProxy->fLazyInstantiateCallback(resourceProvider, &fProxy->fOrigin);
+    GrSurfaceOrigin* outOrigin;
+    if (GrSurfaceProxy::LazyState::kPartially == fProxy->lazyInstantiationState()) {
+        // In the partially instantiated case, we set the origin on the SurfaceProxy at creation
+        // time (via a GrSurfaceDesc). In the lambda, the creation of the texture never needs to
+        // know the origin, and it also can't change or have any effect on it. Thus we just pass in
+        // nullptr in this case since it should never be set.
+        outOrigin = nullptr;
+    } else {
+        outOrigin = &fProxy->fOrigin;
+    }
+
+    sk_sp<GrTexture> texture = fProxy->fLazyInstantiateCallback(resourceProvider, outOrigin);
+
 
     // Indicate we are no longer pending lazy instantiation.
     fProxy->fLazyInstantiateCallback = nullptr;
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index fe4c2b9..c00c50d 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -156,6 +156,22 @@
                                                 GrSurfaceOrigin* origin) const {
     SkASSERT(fProxy);
 
+    if (!fContext->contextPriv().resourceProvider() && !fProxy->priv().isInstantiated()) {
+        // This image was created with a DDL context and cannot be instantiated. Thus we return 0
+        // here which is considered invalid for all backends.
+        return 0;
+    }
+
+    if (GrSurfaceProxy::LazyState::kNot != fProxy->lazyInstantiationState()) {
+        SkASSERT(fContext->contextPriv().resourceProvider());
+        fProxy->priv().doLazyInstantiation(fContext->contextPriv().resourceProvider());
+        if (!fProxy->priv().isInstantiated()) {
+            // We failed to instantiate the lazy proxy. Thus we return 0 here which is considered
+            // invalid for all backends.
+            return 0;
+        }
+    }
+
     if (!fProxy->instantiate(fContext->contextPriv().resourceProvider())) {
         return 0;
     }
@@ -335,6 +351,10 @@
 sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
                                                const GrBackendTexture& tex, GrSurfaceOrigin origin,
                                                SkAlphaType at, sk_sp<SkColorSpace> cs) {
+    if (!ctx->contextPriv().resourceProvider()) {
+        // We have a DDL context and we don't support adopted textures for them.
+        return nullptr;
+    }
     return new_wrapped_texture_common(ctx, tex, origin, at, std::move(cs), kAdopt_GrWrapOwnership,
                                       nullptr, nullptr);
 }