Add support for creating texture backed images where Skia will delete the texture.

Review URL: https://codereview.chromium.org/1187523005
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index a6e9654..d46d09d 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -175,9 +175,9 @@
     }
 }
 
-GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc) {
+GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc, GrWrapOwnership ownership) {
     this->handleDirtyContext();
-    GrTexture* tex = this->onWrapBackendTexture(desc);
+    GrTexture* tex = this->onWrapBackendTexture(desc, ownership);
     if (NULL == tex) {
         return NULL;
     }
@@ -191,9 +191,10 @@
     }
 }
 
-GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
+GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc,
+                                               GrWrapOwnership ownership) {
     this->handleDirtyContext();
-    return this->onWrapBackendRenderTarget(desc);
+    return this->onWrapBackendRenderTarget(desc, ownership);
 }
 
 GrVertexBuffer* GrGpu::createVertexBuffer(size_t size, bool dynamic) {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 8d483d1..3bb84a4 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -97,12 +97,12 @@
     /**
      * Implements GrContext::wrapBackendTexture
      */
-    GrTexture* wrapBackendTexture(const GrBackendTextureDesc&);
+    GrTexture* wrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership);
 
     /**
      * Implements GrContext::wrapBackendTexture
      */
-    GrRenderTarget* wrapBackendRenderTarget(const GrBackendRenderTargetDesc&);
+    GrRenderTarget* wrapBackendRenderTarget(const GrBackendRenderTargetDesc&, GrWrapOwnership);
 
     /**
      * Creates a vertex buffer.
@@ -401,8 +401,9 @@
     virtual GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
                                                  GrGpuResource::LifeCycle lifeCycle,
                                                  const void* srcData) = 0;
-    virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) = 0;
-    virtual GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) = 0;
+    virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) = 0;
+    virtual GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&,
+                                                      GrWrapOwnership) = 0;
     virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) = 0;
     virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) = 0;
 
diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp
index c2d9362..49212df 100644
--- a/src/gpu/GrGpuResource.cpp
+++ b/src/gpu/GrGpuResource.cpp
@@ -145,7 +145,7 @@
     SkASSERT(!fScratchKey.isValid());
     SkASSERT(scratchKey.isValid());
     // Wrapped resources can never have a scratch key.
-    if (this->isWrapped()) {
+    if (this->cacheAccess().isExternal()) {
         return;
     }
     fScratchKey = scratchKey;
diff --git a/src/gpu/GrGpuResourceCacheAccess.h b/src/gpu/GrGpuResourceCacheAccess.h
index 4f38fc6..611d43b 100644
--- a/src/gpu/GrGpuResourceCacheAccess.h
+++ b/src/gpu/GrGpuResourceCacheAccess.h
@@ -33,7 +33,19 @@
     /**
      * Is the resource object wrapping an externally allocated GPU resource?
      */
-    bool isWrapped() const { return GrGpuResource::kWrapped_LifeCycle == fResource->fLifeCycle; }
+    bool isExternal() const { return fResource->isExternal(); }
+
+    /**
+     * Is the resource object wrapping an externally allocated GPU resource that Skia has not taken
+     * ownership of.
+     */
+    bool isBorrowed() const { return GrGpuResource::kBorrowed_LifeCycle == fResource->fLifeCycle; }
+
+    /**
+     * Is the resource object wrapping an externally allocated GPU resource that Skia has taken
+     * ownership of.
+     */
+    bool isAdopted() const { return GrGpuResource::kAdopted_LifeCycle == fResource->fLifeCycle; }
  
     /**
      * Called by the cache to delete the resource under normal circumstances.
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index ae9c68f..88128ac 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -146,7 +146,7 @@
 #endif
     }
     if (resource->resourcePriv().getScratchKey().isValid()) {
-        SkASSERT(!resource->cacheAccess().isWrapped());
+        SkASSERT(!resource->cacheAccess().isExternal());
         fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource);
     }
 
@@ -369,7 +369,7 @@
 
     if (!resource->resourcePriv().isBudgeted()) {
         // Check whether this resource could still be used as a scratch resource.
-        if (!resource->cacheAccess().isWrapped() &&
+        if (!resource->cacheAccess().isExternal() &&
             resource->resourcePriv().getScratchKey().isValid()) {
             // We won't purge an existing resource to make room for this one.
             if (fBudgetedCount < fMaxCount &&
@@ -645,19 +645,19 @@
                 SkASSERT(!resource->getUniqueKey().isValid());
                 ++fScratch;
                 SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getScratchKey()));
-                SkASSERT(!resource->cacheAccess().isWrapped());
+                SkASSERT(!resource->cacheAccess().isExternal());
             } else if (resource->resourcePriv().getScratchKey().isValid()) {
                 SkASSERT(!resource->resourcePriv().isBudgeted() ||
                          resource->getUniqueKey().isValid());
                 ++fCouldBeScratch;
                 SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getScratchKey()));
-                SkASSERT(!resource->cacheAccess().isWrapped());
+                SkASSERT(!resource->cacheAccess().isExternal());
             }
             const GrUniqueKey& uniqueKey = resource->getUniqueKey();
             if (uniqueKey.isValid()) {
                 ++fContent;
                 SkASSERT(fUniqueHash->find(uniqueKey) == resource);
-                SkASSERT(!resource->cacheAccess().isWrapped());
+                SkASSERT(!resource->cacheAccess().isExternal());
                 SkASSERT(resource->resourcePriv().isBudgeted());
             }
 
diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp
index 7a754bc..470bc58 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -79,17 +79,25 @@
 
     struct Stats {
         int fScratch;
-        int fWrapped;
+        int fExternal;
+        int fBorrowed;
+        int fAdopted;
         size_t fUnbudgetedSize;
 
-        Stats() : fScratch(0), fWrapped(0), fUnbudgetedSize(0) {}
+        Stats() : fScratch(0), fExternal(0), fBorrowed(0), fAdopted(0), fUnbudgetedSize(0) {}
 
         void update(GrGpuResource* resource) {
             if (resource->cacheAccess().isScratch()) {
                 ++fScratch;
             }
-            if (resource->cacheAccess().isWrapped()) {
-                ++fWrapped;
+            if (resource->cacheAccess().isExternal()) {
+                ++fExternal;
+            }
+            if (resource->cacheAccess().isBorrowed()) {
+                ++fBorrowed;
+            }
+            if (resource->cacheAccess().isAdopted()) {
+                ++fAdopted;
             }
             if (!resource->resourcePriv().isBudgeted()) {
                 fUnbudgetedSize += resource->gpuMemorySize();
@@ -111,9 +119,9 @@
 
     out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
     out->appendf("\t\tEntry Count: current %d"
-                 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
-                 this->getResourceCount(), fBudgetedCount, stats.fWrapped, locked, stats.fScratch,
-                 countUtilization, fHighWaterCount);
+                 " (%d budgeted, %d external(%d borrowed, %d adopted), %d locked, %d scratch %.2g%% full), high %d\n",
+                 this->getResourceCount(), fBudgetedCount, stats.fExternal, stats.fBorrowed,
+                 stats.fAdopted, locked, stats.fScratch, countUtilization, fHighWaterCount);
     out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
                  SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
                  SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
@@ -179,9 +187,11 @@
         return NULL;
     }
 
-    GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) override { return NULL; }
+    GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&,
+                                    GrWrapOwnership) override { return NULL; }
 
-    GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) override {
+    GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&,
+                                              GrWrapOwnership) override {
         return NULL;
     }
 
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index e954c5e..b760757 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -81,7 +81,7 @@
     : INHERITED(gpu, lifeCycle, desc)
     , fMipMapsStatus(kNotAllocated_MipMapsStatus) {
 
-    if (kWrapped_LifeCycle != lifeCycle && !GrPixelConfigIsCompressed(desc.fConfig)) {
+    if (!this->isExternal() && !GrPixelConfigIsCompressed(desc.fConfig)) {
         GrScratchKey key;
         GrTexturePriv::ComputeScratchKey(desc, &key);
         this->setScratchKey(key);
diff --git a/src/gpu/GrTextureProvider.cpp b/src/gpu/GrTextureProvider.cpp
index c195398..cfa6994 100644
--- a/src/gpu/GrTextureProvider.cpp
+++ b/src/gpu/GrTextureProvider.cpp
@@ -107,15 +107,17 @@
     return NULL;
 }
 
-GrTexture* GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc) {
+GrTexture* GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc,
+                                                 GrWrapOwnership ownership) {
     if (this->isAbandoned()) {
         return NULL;
     }
-    return fGpu->wrapBackendTexture(desc);
+    return fGpu->wrapBackendTexture(desc, ownership);
 }
 
 GrRenderTarget* GrTextureProvider::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
-    return this->isAbandoned() ? NULL : fGpu->wrapBackendRenderTarget(desc);
+    return this->isAbandoned() ? NULL : fGpu->wrapBackendRenderTarget(desc,
+                                                                      kBorrow_GrWrapOwnership);
 }
 
 void GrTextureProvider::assignUniqueKeyToResource(const GrUniqueKey& key, GrGpuResource* resource) {
diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp
index 6296f6e..86f3eb5 100644
--- a/src/gpu/gl/GrGLAssembleInterface.cpp
+++ b/src/gpu/gl/GrGLAssembleInterface.cpp
@@ -150,6 +150,7 @@
     GET_PROC(GenQueries);
     GET_PROC(GenTextures);
     GET_PROC(GetUniformLocation);
+    GET_PROC(IsTexture);
     GET_PROC(LineWidth);
     GET_PROC(LinkProgram);
     GET_PROC(MapBuffer);
@@ -553,6 +554,7 @@
     GET_PROC(GetString);
     GET_PROC(GetStringi);
     GET_PROC(GetUniformLocation);
+    GET_PROC(IsTexture);
     GET_PROC(LineWidth);
     GET_PROC(LinkProgram);
     GET_PROC(PixelStorei);
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 625299d..d0fa81d 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -452,7 +452,8 @@
     }
 }
 
-GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc) {
+GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
+                                         GrWrapOwnership ownership) {
     if (!this->configToGLFormats(desc.fConfig, false, NULL, NULL, NULL)) {
         return NULL;
     }
@@ -470,7 +471,15 @@
     GrSurfaceDesc surfDesc;
 
     idDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle);
-    idDesc.fLifeCycle = GrGpuResource::kWrapped_LifeCycle;
+    
+    switch (ownership) {
+        case kAdopt_GrWrapOwnership:
+            idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
+            break;
+        case kBorrow_GrWrapOwnership:
+            idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
+            break;
+    }    
 
     // next line relies on GrBackendTextureDesc's flags matching GrTexture's
     surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
@@ -507,12 +516,20 @@
     return texture;
 }
 
-GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc) {
+GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc,
+                                                   GrWrapOwnership ownership) {
     GrGLRenderTarget::IDDesc idDesc;
     idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle);
     idDesc.fMSColorRenderbufferID = 0;
     idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
-    idDesc.fLifeCycle = GrGpuResource::kWrapped_LifeCycle;
+    switch (ownership) {
+        case kAdopt_GrWrapOwnership:
+            idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
+            break;
+        case kBorrow_GrWrapOwnership:
+            idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
+            break;
+    }    
 
     GrSurfaceDesc desc;
     desc.fConfig = wrapDesc.fConfig;
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 6f7add6..98d0ffc 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -126,8 +126,9 @@
                                          const void* srcData) override;
     GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) override;
     GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) override;
-    GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) override;
-    GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) override;
+    GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) override;
+    GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&,
+                                              GrWrapOwnership) override;
     bool createStencilAttachmentForRenderTarget(GrRenderTarget* rt, int width, int height) override;
     bool attachStencilAttachmentToRenderTarget(GrStencilAttachment* sb,
                                                GrRenderTarget* rt) override;
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index 29a092a..9158f25 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -152,6 +152,9 @@
         NULL == fFunctions.fGetShaderiv ||
         NULL == fFunctions.fGetString ||
         NULL == fFunctions.fGetUniformLocation ||
+#if 0 //  Not included in Chrome yet
+        NULL == fFunctions.fIsTexture ||
+#endif
         NULL == fFunctions.fLinkProgram ||
         NULL == fFunctions.fLineWidth ||
         NULL == fFunctions.fPixelStorei ||
diff --git a/src/gpu/gl/GrGLPath.cpp b/src/gpu/gl/GrGLPath.cpp
index 80c6356..0b35a70 100644
--- a/src/gpu/gl/GrGLPath.cpp
+++ b/src/gpu/gl/GrGLPath.cpp
@@ -214,7 +214,7 @@
 }
 
 void GrGLPath::onRelease() {
-    if (0 != fPathID && !this->isWrapped()) {
+    if (0 != fPathID && this->shouldFreeResources()) {
         static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fPathID, 1);
         fPathID = 0;
     }
diff --git a/src/gpu/gl/GrGLPathRange.cpp b/src/gpu/gl/GrGLPathRange.cpp
index b577d89..071fa42 100644
--- a/src/gpu/gl/GrGLPathRange.cpp
+++ b/src/gpu/gl/GrGLPathRange.cpp
@@ -89,7 +89,7 @@
 void GrGLPathRange::onRelease() {
     SkASSERT(this->getGpu());
 
-    if (0 != fBasePathID && !this->isWrapped()) {
+    if (0 != fBasePathID && this->shouldFreeResources()) {
         static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fBasePathID,
                                                                               this->getNumPaths());
         fBasePathID = 0;
diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp
index a89022e..e93c5c1 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -31,7 +31,7 @@
     fRTFBOID                = idDesc.fRTFBOID;
     fTexFBOID               = idDesc.fTexFBOID;
     fMSColorRenderbufferID  = idDesc.fMSColorRenderbufferID;
-    fIsWrapped              = kWrapped_LifeCycle == idDesc.fLifeCycle;
+    fRTLifecycle            = idDesc.fLifeCycle;
 
     fViewport.fLeft   = 0;
     fViewport.fBottom = 0;
@@ -59,7 +59,7 @@
 }
 
 void GrGLRenderTarget::onRelease() {
-    if (!fIsWrapped) {
+    if (kBorrowed_LifeCycle != fRTLifecycle) {
         if (fTexFBOID) {
             GL_CALL(DeleteFramebuffers(1, &fTexFBOID));
         }
@@ -73,7 +73,6 @@
     fRTFBOID                = 0;
     fTexFBOID               = 0;
     fMSColorRenderbufferID  = 0;
-    fIsWrapped              = false;
     INHERITED::onRelease();
 }
 
@@ -81,6 +80,5 @@
     fRTFBOID                = 0;
     fTexFBOID               = 0;
     fMSColorRenderbufferID  = 0;
-    fIsWrapped              = false;
     INHERITED::onAbandon();
 }
diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h
index 32c7d4f..2113a80 100644
--- a/src/gpu/gl/GrGLRenderTarget.h
+++ b/src/gpu/gl/GrGLRenderTarget.h
@@ -56,7 +56,9 @@
     }
 
     /** When we don't own the FBO ID we don't attempt to modify its attachments. */
-    bool canAttemptStencilAttachment() const override { return !fIsWrapped; }
+    bool canAttemptStencilAttachment() const override {
+        return kCached_LifeCycle == fRTLifecycle || kUncached_LifeCycle == fRTLifecycle;
+    }
 
 protected:
     // The public constructor registers this object with the cache. However, only the most derived
@@ -74,22 +76,22 @@
     size_t onGpuMemorySize() const override;
 
 private:
-    GrGLuint      fRTFBOID;
-    GrGLuint      fTexFBOID;
-    GrGLuint      fMSColorRenderbufferID;
+    GrGLuint    fRTFBOID;
+    GrGLuint    fTexFBOID;
+    GrGLuint    fMSColorRenderbufferID;
 
     // We track this separately from GrGpuResource because this may be both a texture and a render
     // target, and the texture may be wrapped while the render target is not.
-    bool fIsWrapped;
+    LifeCycle   fRTLifecycle;
 
     // when we switch to this render target we want to set the viewport to
     // only render to content area (as opposed to the whole allocation) and
     // we want the rendering to be at top left (GL has origin in bottom left)
-    GrGLIRect fViewport;
+    GrGLIRect   fViewport;
 
     // onGpuMemorySize() needs to know the VRAM footprint of the FBO(s). However, abandon and
     // release zero out the IDs and the cache needs to know the size even after those actions.
-    size_t fGpuMemorySize;
+    size_t      fGpuMemorySize;
 
     typedef GrRenderTarget INHERITED;
 };
diff --git a/src/gpu/gl/GrGLStencilAttachment.cpp b/src/gpu/gl/GrGLStencilAttachment.cpp
index 4ea08c8..d72729d 100644
--- a/src/gpu/gl/GrGLStencilAttachment.cpp
+++ b/src/gpu/gl/GrGLStencilAttachment.cpp
@@ -18,7 +18,7 @@
 }
 
 void GrGLStencilAttachment::onRelease() {
-    if (0 != fRenderbufferID && !this->isWrapped()) {
+    if (0 != fRenderbufferID && this->shouldFreeResources()) {
         GrGLGpu* gpuGL = (GrGLGpu*) this->getGpu();
         const GrGLInterface* gl = gpuGL->glInterface();
         GR_GL_CALL(gl, DeleteRenderbuffers(1, &fRenderbufferID));
diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp
index faa9f35..f855e54 100644
--- a/src/gpu/gl/GrGLTexture.cpp
+++ b/src/gpu/gl/GrGLTexture.cpp
@@ -30,23 +30,21 @@
     fTexParams.invalidate();
     fTexParamsTimestamp = GrGpu::kExpiredTimestamp;
     fTextureID = idDesc.fTextureID;
-    fIsWrapped = kWrapped_LifeCycle == idDesc.fLifeCycle;
+    fTextureIDLifecycle = idDesc.fLifeCycle;
 }
 
 void GrGLTexture::onRelease() {
     if (fTextureID) {
-        if (!fIsWrapped) {
+        if (GrGpuResource::kBorrowed_LifeCycle != fTextureIDLifecycle) {
             GL_CALL(DeleteTextures(1, &fTextureID));
         }
         fTextureID = 0;
-        fIsWrapped = false;
     }
     INHERITED::onRelease();
 }
 
 void GrGLTexture::onAbandon() {
     fTextureID = 0;
-    fIsWrapped = false;
     INHERITED::onAbandon();
 }
 
diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h
index de3cf3f..06a229e 100644
--- a/src/gpu/gl/GrGLTexture.h
+++ b/src/gpu/gl/GrGLTexture.h
@@ -71,7 +71,7 @@
 
     // We track this separately from GrGpuResource because this may be both a texture and a render
     // target, and the texture may be wrapped while the render target is not.
-    bool fIsWrapped;
+    LifeCycle                       fTextureIDLifecycle;
 
     typedef GrTexture INHERITED;
 };
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 4e563a0..5202557 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -209,6 +209,10 @@
     return NULL;
 }
 
+SkImage* SkImage::NewFromAdoptedTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType) {
+    return NULL;
+}
+
 SkImage* SkImage::NewFromTextureCopy(GrContext*, const GrBackendTextureDesc&, SkAlphaType) {
     return NULL;
 }
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index dfb8f92..281f762 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -114,16 +114,27 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-SkImage* SkImage::NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc, SkAlphaType at) {
+static SkImage* new_wrapped_texture_common(GrContext* ctx, const GrBackendTextureDesc& desc,
+                                           SkAlphaType at, GrWrapOwnership ownership) {
     if (desc.fWidth <= 0 || desc.fHeight <= 0) {
         return NULL;
     }
-    SkAutoTUnref<GrTexture> tex(ctx->textureProvider()->wrapBackendTexture(desc));
+    SkAutoTUnref<GrTexture> tex(ctx->textureProvider()->wrapBackendTexture(desc, ownership));
     if (!tex) {
         return NULL;
     }
     const SkSurface::Budgeted budgeted = SkSurface::kNo_Budgeted;
     return SkNEW_ARGS(SkImage_Gpu, (desc.fWidth, desc.fHeight, at, tex, 0, budgeted));
+
+}
+
+SkImage* SkImage::NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc, SkAlphaType at) {
+    return new_wrapped_texture_common(ctx, desc, at, kBorrow_GrWrapOwnership);
+}
+
+SkImage* SkImage::NewFromAdoptedTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
+                                        SkAlphaType at) {
+    return new_wrapped_texture_common(ctx, desc, at, kAdopt_GrWrapOwnership);
 }
 
 SkImage* SkImage::NewFromTextureCopy(GrContext* ctx, const GrBackendTextureDesc& srcDesc,
@@ -134,7 +145,8 @@
     if (srcDesc.fWidth <= 0 || srcDesc.fHeight <= 0) {
         return NULL;
     }
-    SkAutoTUnref<GrTexture> src(ctx->textureProvider()->wrapBackendTexture(srcDesc));
+    SkAutoTUnref<GrTexture> src(ctx->textureProvider()->wrapBackendTexture(
+        srcDesc, kBorrow_GrWrapOwnership));
     if (!src) {
         return NULL;
     }
@@ -199,9 +211,12 @@
     vDesc.fWidth = yuvSizes[2].fWidth;
     vDesc.fHeight = yuvSizes[2].fHeight;
 
-    SkAutoTUnref<GrTexture> yTex(ctx->textureProvider()->wrapBackendTexture(yDesc));
-    SkAutoTUnref<GrTexture> uTex(ctx->textureProvider()->wrapBackendTexture(uDesc));
-    SkAutoTUnref<GrTexture> vTex(ctx->textureProvider()->wrapBackendTexture(vDesc));
+    SkAutoTUnref<GrTexture> yTex(ctx->textureProvider()->wrapBackendTexture(
+        yDesc, kBorrow_GrWrapOwnership));
+    SkAutoTUnref<GrTexture> uTex(ctx->textureProvider()->wrapBackendTexture(
+        uDesc, kBorrow_GrWrapOwnership));
+    SkAutoTUnref<GrTexture> vTex(ctx->textureProvider()->wrapBackendTexture(
+        vDesc, kBorrow_GrWrapOwnership));
     if (!yTex || !uTex || !vTex) {
         return NULL;
     }
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 20fcbf3..0db3e8c 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -109,7 +109,8 @@
     if (!SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
         return NULL;
     }
-    SkAutoTUnref<GrSurface> surface(context->textureProvider()->wrapBackendTexture(desc));
+    SkAutoTUnref<GrSurface> surface(context->textureProvider()->wrapBackendTexture(desc,
+                                    kBorrow_GrWrapOwnership));
     if (!surface) {
         return NULL;
     }