Refactor to separate backend object lifecycle and GpuResource budget decision

Refactor GrGpuResource to contain two different pieces of state:
 a) instance is budgeted or not budgeted
 b) instance references wrapped backend objects or not

The "object lifecycle" was also attached to backend object
handles (ids), which made the code a bit unclear. Backend objects
would be associated with GrGpuResource::LifeCycle, even though
GrGpuResource::LifeCycle refers to the GpuResource, and individual
backend objects in one GpuResource might be governed with different
"lifecycle".

Mark the budgeted/not budgeted with SkBudgeted::kYes, SkBudgeted::kNo.
This was previously GrGpuResource::kCached_LifeCycle,
GrGpuResource::kUncached_LifeCycle.

Mark the "references wrapped object" with boolean. This was previously
GrGpuResource::kBorrowed_LifeCycle,
GrGpuResource::kAdopted_LifeCycle for GrGpuResource.

Associate the backend object ownership status with
GrBackendObjectOwnership for the backend object handles.

The resource type leaf constuctors, such has GrGLTexture or
GrGLTextureRenderTarget take "budgeted" parameter. This parameter
is passed to GrGpuResource::registerWithCache().

The resource type intermediary constructors, such as GrGLTexture
constructors for class GrGLTextureRenderTarget do not take "budgeted"
parameters, intermediary construtors do not call registerWithCache.

Removes the need for tagging GrGpuResource -derived subclass
constructors with "Derived" parameter.

Makes instances that wrap backend objects be registered with
a new function GrGpuResource::registerWithCacheWrapped().

Removes "budgeted" parameter from classes such as StencilAttahment, as
they are always cached and never wrap any external backend objects.

Removes the use of concept "external" from the member function names.
The API refers to the objects as "wrapped", so make all related
functions use the term consistently.

No change in functionality. Resources referencing wrapped objects are
always inserted to the cache with budget decision kNo.

BUG=594928
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1862043002

Review URL: https://codereview.chromium.org/1862043002
diff --git a/src/gpu/gl/GrGLBuffer.cpp b/src/gpu/gl/GrGLBuffer.cpp
index 24fd592..37ce273 100644
--- a/src/gpu/gl/GrGLBuffer.cpp
+++ b/src/gpu/gl/GrGLBuffer.cpp
@@ -128,7 +128,7 @@
         }
     }
     VALIDATE();
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 inline GrGLGpu* GrGLBuffer::glGpu() const {
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 3a7f531..d259d2f 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -649,13 +649,10 @@
         return nullptr;
     }
 
-    switch (ownership) {
-        case kAdopt_GrWrapOwnership:
-            idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
-            break;
-        case kBorrow_GrWrapOwnership:
-            idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
-            break;
+    if (kAdopt_GrWrapOwnership == ownership) {
+        idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
+    } else {
+        idDesc.fOwnership = GrBackendObjectOwnership::kBorrowed;
     }
 
     surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
@@ -676,13 +673,12 @@
     GrGLTexture* texture = nullptr;
     if (renderTarget) {
         GrGLRenderTarget::IDDesc rtIDDesc;
-        if (!this->createRenderTargetObjects(surfDesc, GrGpuResource::kUncached_LifeCycle,
-                                             idDesc.fInfo, &rtIDDesc)) {
+        if (!this->createRenderTargetObjects(surfDesc, idDesc.fInfo, &rtIDDesc)) {
             return nullptr;
         }
-        texture = new GrGLTextureRenderTarget(this, surfDesc, idDesc, rtIDDesc);
+        texture = GrGLTextureRenderTarget::CreateWrapped(this, surfDesc, idDesc, rtIDDesc);
     } else {
-        texture = new GrGLTexture(this, surfDesc, idDesc);
+        texture = GrGLTexture::CreateWrapped(this, surfDesc, idDesc);
     }
     if (nullptr == texture) {
         return nullptr;
@@ -697,13 +693,10 @@
     idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle);
     idDesc.fMSColorRenderbufferID = 0;
     idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
-    switch (ownership) {
-        case kAdopt_GrWrapOwnership:
-            idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
-            break;
-        case kBorrow_GrWrapOwnership:
-            idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
-            break;
+    if (kAdopt_GrWrapOwnership == ownership) {
+        idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kOwned;
+    } else {
+        idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kBorrowed;
     }
     idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig;
 
@@ -765,8 +758,7 @@
     }
 
     GrGLRenderTarget::IDDesc rtIDDesc;
-    if (!this->createRenderTargetObjects(surfDesc, GrGpuResource::kUncached_LifeCycle,
-                                         texInfo, &rtIDDesc)) {
+    if (!this->createRenderTargetObjects(surfDesc, texInfo, &rtIDDesc)) {
         return nullptr;
     }
     return GrGLRenderTarget::CreateWrapped(this, surfDesc, rtIDDesc, 0);
@@ -1487,13 +1479,12 @@
 }
 
 bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
-                                        GrGpuResource::LifeCycle lifeCycle,
                                         const GrGLTextureInfo& texInfo,
                                         GrGLRenderTarget::IDDesc* idDesc) {
     idDesc->fMSColorRenderbufferID = 0;
     idDesc->fRTFBOID = 0;
+    idDesc->fRTFBOOwnership = GrBackendObjectOwnership::kOwned;
     idDesc->fTexFBOID = 0;
-    idDesc->fLifeCycle = lifeCycle;
     idDesc->fSampleConfig = (GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType() &&
                             desc.fSampleCnt > 0) ? GrRenderTarget::kStencil_SampleConfig :
                                                    GrRenderTarget::kUnified_SampleConfig;
@@ -1605,12 +1596,11 @@
 }
 #endif
 
-static GrGLTexture::IDDesc generate_gl_texture(const GrGLInterface* interface,
-                                               GrGpuResource::LifeCycle lifeCycle) {
+static GrGLTexture::IDDesc generate_gl_texture(const GrGLInterface* interface) {
     GrGLTexture::IDDesc idDesc;
     idDesc.fInfo.fID = 0;
     GR_GL_CALL(interface, GenTextures(1, &idDesc.fInfo.fID));
-    idDesc.fLifeCycle = lifeCycle;
+    idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
     // When we create the texture, we only
     // create GL_TEXTURE_2D at the moment.
     // External clients can do something different.
@@ -1645,7 +1635,7 @@
 }
 
 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
-                                    GrGpuResource::LifeCycle lifeCycle,
+                                    SkBudgeted budgeted,
                                     const SkTArray<GrMipLevel>& texels) {
     // We fail if the MSAA was requested and is not available.
     if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt) {
@@ -1656,7 +1646,7 @@
     bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
 
     GrGLTexture::IDDesc idDesc;
-    idDesc.fLifeCycle = lifeCycle;
+    idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
     GrGLTexture::TexParams initialTexParams;
     if (!this->createTextureImpl(desc, &idDesc.fInfo, renderTarget, &initialTexParams, texels)) {
         return return_null_texture();
@@ -1668,17 +1658,17 @@
         GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0));
         GrGLRenderTarget::IDDesc rtIDDesc;
 
-        if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fInfo, &rtIDDesc)) {
+        if (!this->createRenderTargetObjects(desc, idDesc.fInfo, &rtIDDesc)) {
             GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID));
             return return_null_texture();
         }
-        tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc);
+        tex = new GrGLTextureRenderTarget(this, budgeted, desc, idDesc, rtIDDesc);
     } else {
         bool wasMipMapDataProvided = false;
         if (texels.count() > 1) {
             wasMipMapDataProvided = true;
         }
-        tex = new GrGLTexture(this, desc, idDesc, wasMipMapDataProvided);
+        tex = new GrGLTexture(this, budgeted, desc, idDesc, wasMipMapDataProvided);
     }
     tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
 #ifdef TRACE_TEXTURE_CREATION
@@ -1689,14 +1679,14 @@
 }
 
 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc,
-                                              GrGpuResource::LifeCycle lifeCycle,
+                                              SkBudgeted budgeted,
                                               const SkTArray<GrMipLevel>& texels) {
     // Make sure that we're not flipping Y.
     if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
         return return_null_texture();
     }
 
-    GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface(), lifeCycle);
+    GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface());
     if (!idDesc.fInfo.fID) {
         return return_null_texture();
     }
@@ -1713,7 +1703,7 @@
     }
 
     GrGLTexture* tex;
-    tex = new GrGLTexture(this, desc, idDesc);
+    tex = new GrGLTexture(this, budgeted, desc, idDesc);
     tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
 #ifdef TRACE_TEXTURE_CREATION
     SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n",
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 00ceb85..c6f0f22 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -126,10 +126,10 @@
 
     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override;
 
-    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
+    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                const SkTArray<GrMipLevel>& texels) override;
     GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
-                                         GrGpuResource::LifeCycle lifeCycle,
+                                         SkBudgeted budgeted,
                                          const SkTArray<GrMipLevel>& texels) override;
 
     GrBuffer* onCreateBuffer(size_t size, GrBufferType intendedType, GrAccessPattern,
@@ -347,8 +347,8 @@
                                  int left = 0, int top = 0,
                                  int width = -1, int height = -1);
 
-    bool createRenderTargetObjects(const GrSurfaceDesc&, GrGpuResource::LifeCycle lifeCycle,
-                                   const GrGLTextureInfo& texInfo, GrGLRenderTarget::IDDesc*);
+    bool createRenderTargetObjects(const GrSurfaceDesc&, const GrGLTextureInfo& texInfo,
+                                   GrGLRenderTarget::IDDesc*);
 
     enum TempFBOTarget {
         kSrc_TempFBOTarget,
diff --git a/src/gpu/gl/GrGLPath.cpp b/src/gpu/gl/GrGLPath.cpp
index 4600655..ed5a31d 100644
--- a/src/gpu/gl/GrGLPath.cpp
+++ b/src/gpu/gl/GrGLPath.cpp
@@ -330,11 +330,11 @@
         }
     }
 
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 void GrGLPath::onRelease() {
-    if (0 != fPathID && this->shouldFreeResources()) {
+    if (0 != fPathID) {
         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 cc660ed..6ed7bcc 100644
--- a/src/gpu/gl/GrGLPathRange.cpp
+++ b/src/gpu/gl/GrGLPathRange.cpp
@@ -16,7 +16,7 @@
       fBasePathID(gpu->glPathRendering()->genPaths(this->getNumPaths())),
       fGpuMemorySize(0) {
     this->init();
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 GrGLPathRange::GrGLPathRange(GrGLGpu* gpu,
@@ -29,7 +29,7 @@
       fBasePathID(basePathID),
       fGpuMemorySize(gpuMemorySize) {
     this->init();
-    this->registerWithCache();
+    this->registerWithCache(SkBudgeted::kYes);
 }
 
 void GrGLPathRange::init() {
@@ -101,7 +101,7 @@
 void GrGLPathRange::onRelease() {
     SkASSERT(this->getGpu());
 
-    if (0 != fBasePathID && this->shouldFreeResources()) {
+    if (0 != fBasePathID) {
         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 b77ec4b..3c27535 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -7,29 +7,31 @@
 
 #include "GrGLRenderTarget.h"
 
-#include "GrRenderTargetPriv.h"
 #include "GrGLGpu.h"
 #include "GrGLUtil.h"
+#include "GrGpuResourcePriv.h"
+#include "GrRenderTargetPriv.h"
 #include "SkTraceMemoryDump.h"
 
 #define GPUGL static_cast<GrGLGpu*>(this->getGpu())
 #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
 
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
+// Constructor for wrapped render targets.
 GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
                                    const GrSurfaceDesc& desc,
                                    const IDDesc& idDesc,
                                    GrGLStencilAttachment* stencil)
-    : GrSurface(gpu, idDesc.fLifeCycle, desc)
-    , INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig, stencil) {
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, idDesc.fSampleConfig, stencil) {
     this->init(desc, idDesc);
-    this->registerWithCache();
+    this->registerWithCacheWrapped();
 }
 
-GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
-                                   Derived)
-    : GrSurface(gpu, idDesc.fLifeCycle, desc)
-    , INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig) {
+GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc,
+                                   const IDDesc& idDesc)
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, idDesc.fSampleConfig) {
     this->init(desc, idDesc);
 }
 
@@ -37,7 +39,7 @@
     fRTFBOID                = idDesc.fRTFBOID;
     fTexFBOID               = idDesc.fTexFBOID;
     fMSColorRenderbufferID  = idDesc.fMSColorRenderbufferID;
-    fRTLifecycle            = idDesc.fLifeCycle;
+    fRTFBOOwnership         = idDesc.fRTFBOOwnership;
 
     fViewport.fLeft   = 0;
     fViewport.fBottom = 0;
@@ -127,7 +129,7 @@
 }
 
 void GrGLRenderTarget::onRelease() {
-    if (kBorrowed_LifeCycle != fRTLifecycle) {
+    if (GrBackendObjectOwnership::kBorrowed != fRTFBOOwnership) {
         if (fTexFBOID) {
             GL_CALL(DeleteFramebuffers(1, &fTexFBOID));
         }
@@ -156,6 +158,13 @@
     return static_cast<GrGLGpu*>(this->getGpu());
 }
 
+bool GrGLRenderTarget::canAttemptStencilAttachment() const {
+    // When we have not created the FBO ID we do not attempt to modify its attachments.
+    // Direct GrGLRenderTarget instances are always created with CreateWrapped.
+    SkASSERT(this->resourcePriv().refsWrappedObjects());
+    return false;
+}
+
 void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
     // Don't log the backing texture's contribution to the memory size. This will be handled by the
     // texture object.
diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h
index d1365ef..edf35a1 100644
--- a/src/gpu/gl/GrGLRenderTarget.h
+++ b/src/gpu/gl/GrGLRenderTarget.h
@@ -24,9 +24,9 @@
 
     struct IDDesc {
         GrGLuint                     fRTFBOID;
+        GrBackendObjectOwnership     fRTFBOOwnership;
         GrGLuint                     fTexFBOID;
         GrGLuint                     fMSColorRenderbufferID;
-        GrGpuResource::LifeCycle     fLifeCycle;
         GrRenderTarget::SampleConfig fSampleConfig;
     };
 
@@ -61,21 +61,15 @@
 
     GrBackendObject getRenderTargetHandle() const override { return fRTFBOID; }
 
-    /** When we don't own the FBO ID we don't attempt to modify its attachments. */
-    bool canAttemptStencilAttachment() const override {
-        return kCached_LifeCycle == fRTLifecycle || kUncached_LifeCycle == fRTLifecycle;
-    }
+    bool canAttemptStencilAttachment() const override;
 
     // GrGLRenderTarget overrides dumpMemoryStatistics so it can log its texture and renderbuffer
     // components seperately.
     void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
 
 protected:
-    // The public constructor registers this object with the cache. However, only the most derived
-    // class should register with the cache. This constructor does not do the registration and
-    // rather moves that burden onto the derived class.
-    enum Derived { kDerived };
-    GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, Derived);
+    // Constructor for subclasses.
+    GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
 
     void init(const GrSurfaceDesc&, const IDDesc&);
 
@@ -86,8 +80,7 @@
     size_t onGpuMemorySize() const override;
 
 private:
-    // This ctor is used only for creating wrapped render targets and is only called for the static
-    // create function CreateWrapped(...).
+    // Constructor for instances wrapping backend objects.
     GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, GrGLStencilAttachment*);
 
     GrGLGpu* getGLGpu() const;
@@ -103,9 +96,7 @@
     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.
-    LifeCycle   fRTLifecycle;
+    GrBackendObjectOwnership fRTFBOOwnership;
 
     // 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
diff --git a/src/gpu/gl/GrGLStencilAttachment.cpp b/src/gpu/gl/GrGLStencilAttachment.cpp
index 15e531b..aa813ed 100644
--- a/src/gpu/gl/GrGLStencilAttachment.cpp
+++ b/src/gpu/gl/GrGLStencilAttachment.cpp
@@ -19,7 +19,7 @@
 }
 
 void GrGLStencilAttachment::onRelease() {
-    if (0 != fRenderbufferID && this->shouldFreeResources()) {
+    if (0 != fRenderbufferID) {
         GrGLGpu* gpuGL = (GrGLGpu*) this->getGpu();
         const GrGLInterface* gl = gpuGL->glInterface();
         GR_GL_CALL(gl, DeleteRenderbuffers(1, &fRenderbufferID));
diff --git a/src/gpu/gl/GrGLStencilAttachment.h b/src/gpu/gl/GrGLStencilAttachment.h
index 3b89a5a..f578bf8 100644
--- a/src/gpu/gl/GrGLStencilAttachment.h
+++ b/src/gpu/gl/GrGLStencilAttachment.h
@@ -24,20 +24,19 @@
     };
 
     struct IDDesc {
-        IDDesc() : fRenderbufferID(0), fLifeCycle(kCached_LifeCycle) {}
+        IDDesc() : fRenderbufferID(0) {}
         GrGLuint fRenderbufferID;
-        GrGpuResource::LifeCycle fLifeCycle;
     };
 
     GrGLStencilAttachment(GrGpu* gpu,
-                      const IDDesc& idDesc,
-                      int width, int height,
-                      int sampleCnt,
-                      const Format& format)
-        : GrStencilAttachment(gpu, idDesc.fLifeCycle, width, height, format.fStencilBits, sampleCnt)
+                          const IDDesc& idDesc,
+                          int width, int height,
+                          int sampleCnt,
+                          const Format& format)
+        : GrStencilAttachment(gpu, width, height, format.fStencilBits, sampleCnt)
         , fFormat(format)
         , fRenderbufferID(idDesc.fRenderbufferID) {
-        this->registerWithCache();
+        this->registerWithCache(SkBudgeted::kYes);
     }
 
     GrGLuint renderbufferID() const {
diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp
index ea02274..6c8f901 100644
--- a/src/gpu/gl/GrGLTexture.cpp
+++ b/src/gpu/gl/GrGLTexture.cpp
@@ -26,24 +26,33 @@
 }
 
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
-GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
-    : GrSurface(gpu, idDesc.fLifeCycle, desc)
-    , INHERITED(gpu, idDesc.fLifeCycle, desc, sampler_type(idDesc, gpu), false) {
+GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
+                         const IDDesc& idDesc)
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, sampler_type(idDesc, gpu), false) {
     this->init(desc, idDesc);
-    this->registerWithCache();
+    this->registerWithCache(budgeted);
 }
 
-GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
+GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
+                         const IDDesc& idDesc,
                          bool wasMipMapDataProvided)
-    : GrSurface(gpu, idDesc.fLifeCycle, desc)
-    , INHERITED(gpu, idDesc.fLifeCycle, desc, sampler_type(idDesc, gpu), wasMipMapDataProvided) {
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, sampler_type(idDesc, gpu), wasMipMapDataProvided) {
     this->init(desc, idDesc);
-    this->registerWithCache();
+    this->registerWithCache(budgeted);
 }
 
-GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc, Derived)
-    : GrSurface(gpu, idDesc.fLifeCycle, desc)
-    , INHERITED(gpu, idDesc.fLifeCycle, desc, sampler_type(idDesc, gpu), false) {
+GrGLTexture::GrGLTexture(GrGLGpu* gpu, Wrapped, const GrSurfaceDesc& desc, const IDDesc& idDesc)
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, sampler_type(idDesc, gpu), false) {
+    this->init(desc, idDesc);
+    this->registerWithCacheWrapped();
+}
+
+GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
+    : GrSurface(gpu, desc)
+    , INHERITED(gpu, desc, sampler_type(idDesc, gpu), false) {
     this->init(desc, idDesc);
 }
 
@@ -52,12 +61,12 @@
     fTexParams.invalidate();
     fTexParamsTimestamp = GrGpu::kExpiredTimestamp;
     fInfo = idDesc.fInfo;
-    fTextureIDLifecycle = idDesc.fLifeCycle;
+    fTextureIDOwnership = idDesc.fOwnership;
 }
 
 void GrGLTexture::onRelease() {
     if (fInfo.fID) {
-        if (GrGpuResource::kBorrowed_LifeCycle != fTextureIDLifecycle) {
+        if (GrBackendObjectOwnership::kBorrowed != fTextureIDOwnership) {
             GL_CALL(DeleteTextures(1, &fInfo.fID));
         }
         fInfo.fID = 0;
@@ -86,3 +95,9 @@
     traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture",
                                       texture_id.c_str());
 }
+
+GrGLTexture* GrGLTexture::CreateWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
+                                        const IDDesc& idDesc) {
+    return new GrGLTexture(gpu, kWrapped, desc, idDesc);
+}
+
diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h
index 6ee8dcf..05d26c8 100644
--- a/src/gpu/gl/GrGLTexture.h
+++ b/src/gpu/gl/GrGLTexture.h
@@ -16,7 +16,6 @@
 class GrGLGpu;
 
 class GrGLTexture : public GrTexture {
-
 public:
     struct TexParams {
         GrGLenum fMinFilter;
@@ -31,11 +30,11 @@
 
     struct IDDesc {
         GrGLTextureInfo             fInfo;
-        GrGpuResource::LifeCycle    fLifeCycle;
+        GrBackendObjectOwnership    fOwnership;
     };
-
-    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
-    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, bool wasMipMapDataProvided);
+    GrGLTexture(GrGLGpu*, SkBudgeted, const GrSurfaceDesc&, const IDDesc&);
+    GrGLTexture(GrGLGpu*, SkBudgeted, const GrSurfaceDesc&, const IDDesc&,
+                bool wasMipMapDataProvided);
 
     GrBackendObject getTextureHandle() const override;
 
@@ -57,12 +56,14 @@
 
     GrGLenum target() const { return fInfo.fTarget; }
 
+    static GrGLTexture* CreateWrapped(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
 protected:
-    // The public constructor registers this object with the cache. However, only the most derived
-    // class should register with the cache. This constructor does not do the registration and
-    // rather moves that burden onto the derived class.
-    enum Derived { kDerived };
-    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, Derived);
+    // Constructor for subclasses.
+    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
+
+    enum Wrapped { kWrapped };
+    // Constructor for instances wrapping backend objects.
+    GrGLTexture(GrGLGpu*, Wrapped, const GrSurfaceDesc&, const IDDesc&);
 
     void init(const GrSurfaceDesc&, const IDDesc&);
 
@@ -77,10 +78,7 @@
     // Holds the texture target and ID. A pointer to this may be shared to external clients for
     // direct interaction with the GL object.
     GrGLTextureInfo                 fInfo;
-
-    // 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.
-    LifeCycle                       fTextureIDLifecycle;
+    GrBackendObjectOwnership        fTextureIDOwnership;
 
     typedef GrTexture INHERITED;
 };
diff --git a/src/gpu/gl/GrGLTextureRenderTarget.cpp b/src/gpu/gl/GrGLTextureRenderTarget.cpp
index b6068a4..1fa0a21 100644
--- a/src/gpu/gl/GrGLTextureRenderTarget.cpp
+++ b/src/gpu/gl/GrGLTextureRenderTarget.cpp
@@ -37,3 +37,16 @@
   traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture",
                                     texture_id.c_str());
 }
+
+bool GrGLTextureRenderTarget::canAttemptStencilAttachment() const {
+    // The RT FBO of GrGLTextureRenderTarget is never created from a
+    // wrapped FBO.
+    return true;
+}
+
+GrGLTextureRenderTarget* GrGLTextureRenderTarget::CreateWrapped(GrGLGpu* gpu,
+                                                                const GrSurfaceDesc& desc,
+                                                                const GrGLTexture::IDDesc& texIDDesc,
+                                                                const GrGLRenderTarget::IDDesc& rtIDDesc) {
+    return new GrGLTextureRenderTarget(gpu, desc, texIDDesc, rtIDDesc);
+}
diff --git a/src/gpu/gl/GrGLTextureRenderTarget.h b/src/gpu/gl/GrGLTextureRenderTarget.h
index 02db8bc..0826cf3 100644
--- a/src/gpu/gl/GrGLTextureRenderTarget.h
+++ b/src/gpu/gl/GrGLTextureRenderTarget.h
@@ -26,17 +26,23 @@
     // We're virtually derived from GrSurface (via both GrGLTexture and GrGLRenderTarget) so its
     // constructor must be explicitly called.
     GrGLTextureRenderTarget(GrGLGpu* gpu,
+                            SkBudgeted budgeted,
                             const GrSurfaceDesc& desc,
                             const GrGLTexture::IDDesc& texIDDesc,
                             const GrGLRenderTarget::IDDesc& rtIDDesc)
-        : GrSurface(gpu, texIDDesc.fLifeCycle, desc)
-        , GrGLTexture(gpu, desc, texIDDesc, GrGLTexture::kDerived)
-        , GrGLRenderTarget(gpu, desc, rtIDDesc, GrGLRenderTarget::kDerived) {
-        this->registerWithCache();
+        : GrSurface(gpu, desc)
+        , GrGLTexture(gpu, desc, texIDDesc)
+        , GrGLRenderTarget(gpu, desc, rtIDDesc) {
+        this->registerWithCache(budgeted);
     }
 
+    bool canAttemptStencilAttachment() const override;
+
     void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
 
+    static GrGLTextureRenderTarget* CreateWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
+                                                  const GrGLTexture::IDDesc& texIDDesc,
+                                                  const GrGLRenderTarget::IDDesc& rtIDDesc);
 protected:
     void onAbandon() override {
         GrGLRenderTarget::onAbandon();
@@ -49,6 +55,17 @@
     }
 
 private:
+    // Constructor for instances wrapping backend objects.
+    GrGLTextureRenderTarget(GrGLGpu* gpu,
+                            const GrSurfaceDesc& desc,
+                            const GrGLTexture::IDDesc& texIDDesc,
+                            const GrGLRenderTarget::IDDesc& rtIDDesc)
+        : GrSurface(gpu, desc)
+        , GrGLTexture(gpu, desc, texIDDesc)
+        , GrGLRenderTarget(gpu, desc, rtIDDesc) {
+        this->registerWithCacheWrapped();
+    }
+
     // GrGLRenderTarget accounts for the texture's memory and any MSAA renderbuffer's memory.
     size_t onGpuMemorySize() const override {
         return GrGLRenderTarget::onGpuMemorySize();