Make uncached textures uncached from the get go.
authorbsalomon <bsalomon@google.com>
Wed, 14 Jan 2015 18:42:08 +0000 (10:42 -0800)
committerCommit bot <commit-bot@chromium.org>
Wed, 14 Jan 2015 18:42:08 +0000 (10:42 -0800)
This avoids the problem of a newly created uncached texture causing a purge of cached resources.

BUG=chromium:445885

Review URL: https://codereview.chromium.org/846303002

38 files changed:
bench/GrResourceCacheBench.cpp
include/gpu/GrGpuResource.h
include/gpu/GrRenderTarget.h
include/gpu/GrSurface.h
include/gpu/GrTexture.h
src/gpu/GrAtlas.cpp
src/gpu/GrContext.cpp
src/gpu/GrDistanceFieldTextContext.cpp
src/gpu/GrGeometryBuffer.h
src/gpu/GrGpu.cpp
src/gpu/GrGpu.h
src/gpu/GrGpuResource.cpp
src/gpu/GrGpuResourceCacheAccess.h
src/gpu/GrIndexBuffer.h
src/gpu/GrPath.h
src/gpu/GrPathRange.cpp
src/gpu/GrPathRange.h
src/gpu/GrResourceCache2.cpp
src/gpu/GrStencilBuffer.h
src/gpu/GrTest.cpp
src/gpu/GrTexture.cpp
src/gpu/GrVertexBuffer.h
src/gpu/gl/GrGLBufferImpl.cpp
src/gpu/gl/GrGLBufferImpl.h
src/gpu/gl/GrGLGpu.cpp
src/gpu/gl/GrGLGpu.h
src/gpu/gl/GrGLIndexBuffer.cpp
src/gpu/gl/GrGLPath.cpp
src/gpu/gl/GrGLRenderTarget.cpp
src/gpu/gl/GrGLRenderTarget.h
src/gpu/gl/GrGLStencilBuffer.h
src/gpu/gl/GrGLTexture.cpp
src/gpu/gl/GrGLTexture.h
src/gpu/gl/GrGLTextureRenderTarget.h
src/gpu/gl/GrGLVertexArray.cpp
src/gpu/gl/GrGLVertexBuffer.cpp
tests/GLProgramsTest.cpp
tests/ResourceCacheTest.cpp

index 491823b..2a593c5 100644 (file)
@@ -24,7 +24,7 @@ class BenchResource : public GrGpuResource {
 public:
     SK_DECLARE_INST_COUNT(BenchResource);
     BenchResource (GrGpu* gpu)
-        : INHERITED(gpu, false) {
+        : INHERITED(gpu, kCached_LifeCycle) {
         this->registerWithCache();
     }
 
index 4340f71..44c4ba0 100644 (file)
@@ -125,6 +125,26 @@ class SK_API GrGpuResource : public GrIORef<GrGpuResource> {
 public:
     SK_DECLARE_INST_COUNT(GrGpuResource)
 
+    enum LifeCycle {
+        /**
+         * The resource is cached and owned by Skia. Resources with this status may be kept alive
+         * by the cache as either scratch or content resources even when there are no refs to them.
+         * The cache may release them whenever there are no refs.
+         */
+        kCached_LifeCycle,
+        /**
+         * The resource is uncached. As soon as there are no more refs to it, it is released. Under
+         * the hood the cache may opaquely recycle it as a cached resource.
+         */
+        kUncached_LifeCycle,
+        /**
+         * Similar to uncached, but Skia does not manage the lifetime of the underlying backend
+         * 3D API object(s). The client is responsible for freeing those. Used to inject client-
+         * created GPU resources into Skia (e.g. to render to a client-created texture).
+         */
+        kWrapped_LifeCycle,
+    };
+
     /**
      * Tests whether a object has been abandoned or released. All objects will
      * be in this state after their creating GrContext is destroyed or has
@@ -204,7 +224,7 @@ protected:
     // initialized (i.e. not in a base class constructor).
     void registerWithCache();
 
-    GrGpuResource(GrGpu*, bool isWrapped);
+    GrGpuResource(GrGpu*, LifeCycle);
     virtual ~GrGpuResource();
 
     GrGpu* getGpu() const { return fGpu; }
@@ -216,7 +236,7 @@ protected:
         backend API calls should be made. */
     virtual void onAbandon() { }
 
-    bool isWrapped() const { return SkToBool(kWrapped_Flag & fFlags); }
+    bool isWrapped() const { return kWrapped_LifeCycle == fLifeCycle; }
 
     /**
      * This entry point should be called whenever gpuMemorySize() should report a different size.
@@ -240,7 +260,6 @@ private:
 
     // See comments in CacheAccess.
     bool setContentKey(const GrResourceKey& contentKey);
-    void setBudgeted(bool countsAgainstBudget);
     void notifyIsPurgable() const;
     void removeScratchKey();
 
@@ -257,21 +276,9 @@ private:
     static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
     enum Flags {
         /**
-         * The resource counts against the resource cache's budget.
-         */
-        kBudgeted_Flag      = 0x1,
-
-        /**
-         * This object wraps a GPU object given to us by Skia's client. Skia will not free the
-         * underlying backend API GPU resources when the GrGpuResource is destroyed. This also
-         * implies that kBudgeted_Flag is not set.
-         */
-        kWrapped_Flag       = 0x2,
-
-        /**
          * If set then fContentKey is valid and the resource is cached based on its content.
          */
-        kContentKeySet_Flag = 0x4,
+        kContentKeySet_Flag = 0x1,
     };
 
     GrScratchKey            fScratchKey;
@@ -284,6 +291,7 @@ private:
     mutable size_t          fGpuMemorySize;
 
     uint32_t                fFlags;
+    LifeCycle               fLifeCycle;
     const uint32_t          fUniqueID;
 
     SkAutoTUnref<const SkData> fData;
index 4c771a4..eaae49e 100644 (file)
@@ -109,10 +109,8 @@ public:
     void setStencilBuffer(GrStencilBuffer* stencilBuffer);
 
 protected:
-    GrRenderTarget(GrGpu* gpu,
-                   bool isWrapped,
-                   const GrSurfaceDesc& desc)
-        : INHERITED(gpu, isWrapped, desc)
+    GrRenderTarget(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc)
+        : INHERITED(gpu, lifeCycle, desc)
         , fStencilBuffer(NULL) {
         fResolveRect.setLargestInverted();
     }
index 8f772b3..2b40f9c 100644 (file)
@@ -138,9 +138,9 @@ protected:
     // Provides access to methods that should be public within Skia code.
     friend class GrSurfacePriv;
 
-    GrSurface(GrGpu* gpu, bool isWrapped, const GrSurfaceDesc& desc)
-    : INHERITED(gpu, isWrapped)
-    , fDesc(desc) {
+    GrSurface(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc)
+        : INHERITED(gpu, lifeCycle)
+        , fDesc(desc) {
     }
 
     GrSurfaceDesc fDesc;
index 612fef4..ecc1bb0 100644 (file)
@@ -46,7 +46,7 @@ public:
     inline const GrTexturePriv texturePriv() const;
 
 protected:
-    GrTexture(GrGpu* gpu, bool isWrapped, const GrSurfaceDesc& desc);
+    GrTexture(GrGpu*, LifeCycle, const GrSurfaceDesc&);
 
     void validateDesc() const;
 
index c065dab..7ebdf6e 100644 (file)
@@ -225,7 +225,7 @@ GrPlot* GrAtlas::addToAtlas(ClientPlotUsage* usage,
         desc.fHeight = fBackingTextureSize.height();
         desc.fConfig = fPixelConfig;
 
-        fTexture = fGpu->createTexture(desc, NULL, 0);
+        fTexture = fGpu->createTexture(desc, true, NULL, 0);
         if (NULL == fTexture) {
             return NULL;
         }
index e6fd358..785691d 100755 (executable)
@@ -298,7 +298,7 @@ GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc,
     rtDesc.fWidth  = GrNextPow2(desc.fWidth);
     rtDesc.fHeight = GrNextPow2(desc.fHeight);
 
-    GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
+    GrTexture* texture = fGpu->createTexture(rtDesc, true, NULL, 0);
 
     if (texture) {
         GrDrawState drawState;
@@ -347,7 +347,7 @@ GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc,
 
         size_t stretchedRowBytes = rtDesc.fWidth * bpp;
 
-        texture = fGpu->createTexture(rtDesc, stretchedPixels.get(), stretchedRowBytes);
+        texture = fGpu->createTexture(rtDesc, true, stretchedPixels.get(), stretchedRowBytes);
         SkASSERT(texture);
     }
 
@@ -371,7 +371,7 @@ GrTexture* GrContext::createTexture(const GrTextureParams* params,
                                              srcData, rowBytes,
                                              GrTexturePriv::NeedsBilerp(resourceKey));
     } else {
-        texture = fGpu->createTexture(desc, srcData, rowBytes);
+        texture = fGpu->createTexture(desc, true, srcData, rowBytes);
     }
 
     if (texture) {
@@ -445,7 +445,7 @@ GrTexture* GrContext::refScratchTexture(const GrSurfaceDesc& inDesc, ScratchTexM
         desc.writable()->fFlags = origFlags;
     }
 
-    GrTexture* texture = fGpu->createTexture(*desc, NULL, 0);
+    GrTexture* texture = fGpu->createTexture(*desc, true, NULL, 0);
 #ifdef SK_DEBUG
     GrScratchKey key;
     GrTexturePriv::ComputeScratchKey(*desc, &key);
@@ -464,17 +464,10 @@ void GrContext::OverBudgetCB(void* data) {
 }
 
 
-GrTexture* GrContext::createUncachedTexture(const GrSurfaceDesc& descIn,
+GrTexture* GrContext::createUncachedTexture(const GrSurfaceDesc& desc,
                                             void* srcData,
                                             size_t rowBytes) {
-    GrSurfaceDesc descCopy = descIn;
-    GrTexture* texture = fGpu->createTexture(descCopy, srcData, rowBytes);
-    if (texture) {
-        // TODO: It'd be nice to be able to do this before creation so we don't boot something
-        // out of the cache. We could temporarily boost the cache budget.
-        texture->cacheAccess().setBudgeted(false);
-    }
-    return texture;
+    return fGpu->createTexture(desc, false, srcData, rowBytes);
 }
 
 void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
index 69dcaa7..1480975 100755 (executable)
@@ -188,7 +188,7 @@ static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
         desc.fHeight = height;
         desc.fConfig = kAlpha_8_GrPixelConfig;
 
-        *gammaTexture = context->getGpu()->createTexture(desc, NULL, 0);
+        *gammaTexture = context->getGpu()->createTexture(desc, true, NULL, 0);
         if (NULL == *gammaTexture) {
             return;
         }
index d676183..55d43d7 100644 (file)
@@ -99,8 +99,8 @@ public:
     }
 
 protected:
-    GrGeometryBuffer(GrGpu* gpu, bool isWrapped, size_t gpuMemorySize, bool dynamic, bool cpuBacked)
-        : INHERITED(gpu, isWrapped)
+    GrGeometryBuffer(GrGpu* gpu, size_t gpuMemorySize, bool dynamic, bool cpuBacked)
+        : INHERITED(gpu, kCached_LifeCycle)
         , fMapPtr(NULL)
         , fGpuMemorySize(gpuMemorySize)
         , fDynamic(dynamic)
index 23a7fde..0c60a02 100644 (file)
@@ -34,7 +34,7 @@ void GrGpu::contextAbandoned() {}
 
 ////////////////////////////////////////////////////////////////////////////////
 
-GrTexture* GrGpu::createTexture(const GrSurfaceDesc& desc,
+GrTexture* GrGpu::createTexture(const GrSurfaceDesc& desc, bool budgeted,
                                 const void* srcData, size_t rowBytes) {
     if (!this->caps()->isConfigTexturable(desc.fConfig)) {
         return NULL;
@@ -56,10 +56,10 @@ GrTexture* GrGpu::createTexture(const GrSurfaceDesc& desc,
         }
 
         this->handleDirtyContext();
-        tex = this->onCreateCompressedTexture(desc, srcData);
+        tex = this->onCreateCompressedTexture(desc, budgeted, srcData);
     } else {
         this->handleDirtyContext();
-        tex = this->onCreateTexture(desc, srcData, rowBytes);
+        tex = this->onCreateTexture(desc, budgeted, srcData, rowBytes);
         if (tex &&
             (kRenderTarget_GrSurfaceFlag & desc.fFlags) &&
             !(kNoStencil_GrSurfaceFlag & desc.fFlags)) {
index a657d17..429c9c8 100644 (file)
@@ -90,6 +90,7 @@ public:
      * or render targets can be checked using GrDrawTargetCaps.
      *
      * @param desc        describes the texture to be created.
+     * @param budgeted    does this texture count against the resource cache budget?
      * @param srcData     texel data to load texture. Begins with full-size
      *                    palette data for paletted textures. For compressed
      *                    formats it contains the compressed pixel data. Otherwise,
@@ -101,7 +102,8 @@ public:
      *
      * @return    The texture object if successful, otherwise NULL.
      */
-    GrTexture* createTexture(const GrSurfaceDesc& desc, const void* srcData, size_t rowBytes);
+    GrTexture* createTexture(const GrSurfaceDesc& desc, bool budgeted,
+                             const void* srcData, size_t rowBytes);
 
     /**
      * Implements GrContext::wrapBackendTexture
@@ -423,10 +425,9 @@ private:
     virtual void onResetContext(uint32_t resetBits) = 0;
 
     // overridden by backend-specific derived class to create objects.
-    virtual GrTexture* onCreateTexture(const GrSurfaceDesc& desc,
-                                       const void* srcData,
-                                       size_t rowBytes) = 0;
-    virtual GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
+    virtual GrTexture* onCreateTexture(const GrSurfaceDesc& desc, bool budgeted,
+                                       const void* srcData, size_t rowBytes) = 0;
+    virtual GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, bool budgeted,
                                                  const void* srcData) = 0;
     virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) = 0;
     virtual GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) = 0;
index b2fad0b..a2df7e1 100644 (file)
@@ -18,16 +18,12 @@ static inline GrResourceCache2* get_resource_cache2(GrGpu* gpu) {
     return gpu->getContext()->getResourceCache2();
 }
 
-GrGpuResource::GrGpuResource(GrGpu* gpu, bool isWrapped)
+GrGpuResource::GrGpuResource(GrGpu* gpu, LifeCycle lifeCycle)
     : fGpu(gpu)
     , fGpuMemorySize(kInvalidGpuMemorySize)
+    , fFlags(0)
+    , fLifeCycle(lifeCycle)
     , fUniqueID(CreateUniqueID()) {
-    if (isWrapped) {
-        fFlags = kWrapped_Flag;
-    } else {
-        // By default all non-wrapped resources are budgeted.
-        fFlags = kBudgeted_Flag;
-    }
 }
 
 void GrGpuResource::registerWithCache() {
@@ -146,21 +142,3 @@ uint32_t GrGpuResource::CreateUniqueID() {
     } while (id == SK_InvalidUniqueID);
     return id;
 }
-
-void GrGpuResource::setBudgeted(bool countsAgainstBudget) {
-    // Wrapped resources never count against the budget, nothing to do. No point in changing the
-    // budgeting of destroyed resources.
-    if (this->isWrapped() || this->wasDestroyed()) {
-        return;
-    }
-
-    uint32_t oldFlags = fFlags;
-    if (countsAgainstBudget) {
-        fFlags |= kBudgeted_Flag;
-    } else {
-        fFlags &= ~kBudgeted_Flag;
-    }
-    if (fFlags != oldFlags) {
-        get_resource_cache2(fGpu)->resourceAccess().didChangeBudgetStatus(this);
-    }
-}
index 475317d..0aadb89 100644 (file)
@@ -29,11 +29,6 @@ public:
     }
 
     /**
-     * Changes whether the resource counts against the resource cache budget.
-     */
-    void setBudgeted(bool countsAgainstBudget) { fResource->setBudgeted(countsAgainstBudget); }
-
-    /**
      * Is the resource currently cached as scratch? This means it has a valid scratch key and does
      * not have a content key.
      */
@@ -67,16 +62,12 @@ public:
     /**
      * Is the resource object wrapping an externally allocated GPU resource?
      */
-    bool isWrapped() const { return fResource->isWrapped(); }
+    bool isWrapped() const { return GrGpuResource::kWrapped_LifeCycle == fResource->fLifeCycle; }
 
     /**
      * Does the resource count against the resource budget?
      */
-    bool isBudgeted() const { 
-        bool ret = SkToBool(GrGpuResource::kBudgeted_Flag & fResource->fFlags);
-        SkASSERT(!(ret && fResource->isWrapped()));
-        return ret;
-    }
+    bool isBudgeted() const { return GrGpuResource::kCached_LifeCycle == fResource->fLifeCycle; }
 
     /**
      * Called by the cache to delete the resource under normal circumstances.
index 113b89d..4dfd1c1 100644 (file)
@@ -24,8 +24,8 @@ public:
         return static_cast<int>(this->gpuMemorySize() / (sizeof(uint16_t) * 6));
     }
 protected:
-    GrIndexBuffer(GrGpu* gpu, bool isWrapped, size_t gpuMemorySize, bool dynamic, bool cpuBacked)
-        : INHERITED(gpu, isWrapped, gpuMemorySize, dynamic, cpuBacked) {}
+    GrIndexBuffer(GrGpu* gpu, size_t gpuMemorySize, bool dynamic, bool cpuBacked)
+        : INHERITED(gpu, gpuMemorySize, dynamic, cpuBacked) {}
 private:
     typedef GrGeometryBuffer INHERITED;
 };
index 394db6f..eaa3b40 100644 (file)
@@ -20,8 +20,8 @@ public:
     /**
      * Initialize to a path with a fixed stroke. Stroke must not be hairline.
      */
-    GrPath(GrGpu* gpu, bool isWrapped, const SkPath& skPath, const SkStrokeRec& stroke)
-        : INHERITED(gpu, isWrapped),
+    GrPath(GrGpu* gpu, const SkPath& skPath, const SkStrokeRec& stroke)
+        : INHERITED(gpu, kCached_LifeCycle),
           fSkPath(skPath),
           fStroke(stroke),
           fBounds(skPath.getBounds()) {
index cfe89fe..8bac750 100644 (file)
@@ -15,7 +15,7 @@ enum {
 GrPathRange::GrPathRange(GrGpu* gpu,
                          PathGenerator* pathGenerator,
                          const SkStrokeRec& stroke)
-    : INHERITED(gpu, kIsWrapped),
+    : INHERITED(gpu, kCached_LifeCycle),
       fPathGenerator(SkRef(pathGenerator)),
       fNumPaths(fPathGenerator->getNumPaths()),
       fStroke(stroke) {
@@ -27,7 +27,7 @@ GrPathRange::GrPathRange(GrGpu* gpu,
 GrPathRange::GrPathRange(GrGpu* gpu,
                          int numPaths,
                          const SkStrokeRec& stroke)
-    : INHERITED(gpu, kIsWrapped),
+    : INHERITED(gpu, kCached_LifeCycle),
       fNumPaths(numPaths),
       fStroke(stroke) {
 }
index 014b7ec..86883e3 100644 (file)
@@ -26,8 +26,6 @@ class GrPathRange : public GrGpuResource {
 public:
     SK_DECLARE_INST_COUNT(GrPathRange);
 
-    static const bool kIsWrapped = false;
-
     enum PathIndexType {
         kU8_PathIndexType,   //!< uint8_t
         kU16_PathIndexType,  //!< uint16_t
index 1db96ec..e23f968 100644 (file)
@@ -261,10 +261,9 @@ void GrResourceCache2::notifyPurgable(GrGpuResource* resource) {
     bool noKey = !resource->cacheAccess().isScratch() &&
                  (NULL == resource->cacheAccess().getContentKey());
 
-    // Wrapped resources should never have a key.
-    SkASSERT(noKey || !resource->cacheAccess().isWrapped());
+    // Only cached resources should ever have a key.
+    SkASSERT(noKey || resource->cacheAccess().isBudgeted());
 
-    // And purge if the resource is wrapped
     if (overBudget || noKey) {
         SkDEBUGCODE(int beforeCount = fCount;)
         resource->cacheAccess().release();
@@ -316,7 +315,6 @@ void GrResourceCache2::didChangeBudgetStatus(GrGpuResource* resource) {
     this->validate();
 }
 
-
 void GrResourceCache2::internalPurgeAsNeeded() {
     SkASSERT(!fPurging);
     SkASSERT(!fNewlyPurgableResourceWhilePurging);
index 11ecedd..883a982 100644 (file)
@@ -50,8 +50,8 @@ public:
     static void ComputeKey(int width, int height, int sampleCnt, GrScratchKey* key);
 
 protected:
-    GrStencilBuffer(GrGpu* gpu, bool isWrapped, int width, int height, int bits, int sampleCnt)
-        : GrGpuResource(gpu, isWrapped)
+    GrStencilBuffer(GrGpu* gpu, int width, int height, int bits, int sampleCnt)
+        : GrGpuResource(gpu, kCached_LifeCycle)
         , fWidth(width)
         , fHeight(height)
         , fBits(bits)
index ec31307..d709853 100644 (file)
@@ -87,13 +87,12 @@ public:
 private:
     void onResetContext(uint32_t resetBits) SK_OVERRIDE {}
 
-    GrTexture* onCreateTexture(const GrSurfaceDesc& desc,
-                               const void* srcData,
+    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, bool budgeted, const void* srcData,
                                size_t rowBytes) SK_OVERRIDE {
         return NULL;
     }
 
-    GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
+    GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, bool budgeted,
                                          const void* srcData) SK_OVERRIDE {
         return NULL;
     }
index eb518f5..378e990 100644 (file)
@@ -118,11 +118,11 @@ GrSurfaceOrigin resolve_origin(const GrSurfaceDesc& desc) {
 }
 
 //////////////////////////////////////////////////////////////////////////////
-GrTexture::GrTexture(GrGpu* gpu, bool isWrapped, const GrSurfaceDesc& desc)
-    : INHERITED(gpu, isWrapped, desc)
+GrTexture::GrTexture(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc)
+    : INHERITED(gpu, lifeCycle, desc)
     , fMipMapsStatus(kNotAllocated_MipMapsStatus) {
 
-    if (!isWrapped) {
+    if (kCached_LifeCycle == lifeCycle) {
         GrScratchKey key;
         GrTexturePriv::ComputeScratchKey(desc, &key);
         this->setScratchKey(key);
index c3cf534..3f2ada2 100644 (file)
@@ -15,8 +15,8 @@
 
 class GrVertexBuffer : public GrGeometryBuffer {
 protected:
-    GrVertexBuffer(GrGpu* gpu, bool isWrapped, size_t gpuMemorySize, bool dynamic, bool cpuBacked)
-        : INHERITED(gpu, isWrapped, gpuMemorySize, dynamic, cpuBacked) {}
+    GrVertexBuffer(GrGpu* gpu, size_t gpuMemorySize, bool dynamic, bool cpuBacked)
+        : INHERITED(gpu, gpuMemorySize, dynamic, cpuBacked) {}
 private:
     typedef GrGeometryBuffer INHERITED;
 };
index b65fe5b..5d5ca88 100644 (file)
@@ -41,7 +41,7 @@ void GrGLBufferImpl::release(GrGLGpu* gpu) {
     if (fCPUData) {
         sk_free(fCPUData);
         fCPUData = NULL;
-    } else if (fDesc.fID && !fDesc.fIsWrapped) {
+    } else if (fDesc.fID) {
         GL_CALL(gpu, DeleteBuffers(1, &fDesc.fID));
         if (GR_GL_ARRAY_BUFFER == fBufferType) {
             gpu->notifyVertexBufferDelete(fDesc.fID);
@@ -219,7 +219,6 @@ void GrGLBufferImpl::validate() const {
     SkASSERT(GR_GL_ARRAY_BUFFER == fBufferType || GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType);
     // The following assert isn't valid when the buffer has been abandoned:
     // SkASSERT((0 == fDesc.fID) == (fCPUData));
-    SkASSERT(0 != fDesc.fID || !fDesc.fIsWrapped);
     SkASSERT(NULL == fCPUData || 0 == fGLSizeInBytes);
     SkASSERT(NULL == fMapPtr || fCPUData || fGLSizeInBytes == fDesc.fSizeInBytes);
     SkASSERT(NULL == fCPUData || NULL == fMapPtr || fCPUData == fMapPtr);
index 8617a89..5526ff9 100644 (file)
@@ -20,7 +20,6 @@ class GrGLGpu;
 class GrGLBufferImpl : SkNoncopyable {
 public:
     struct Desc {
-        bool        fIsWrapped;
         GrGLuint    fID;            // set to 0 to indicate buffer is CPU-backed and not a VBO.
         size_t      fSizeInBytes;
         bool        fDynamic;
index b99d30e..182d258 100644 (file)
@@ -377,7 +377,7 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc) {
     GrSurfaceDesc surfDesc;
 
     idDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle);
-    idDesc.fIsWrapped = true;
+    idDesc.fLifeCycle = GrGpuResource::kWrapped_LifeCycle;
 
     // next line relies on GrBackendTextureDesc's flags matching GrTexture's
     surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
@@ -399,7 +399,7 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc) {
     GrGLTexture* texture = NULL;
     if (renderTarget) {
         GrGLRenderTarget::IDDesc rtIDDesc;
-        if (!this->createRenderTargetObjects(surfDesc, idDesc.fTextureID, &rtIDDesc)) {
+        if (!this->createRenderTargetObjects(surfDesc, false, idDesc.fTextureID, &rtIDDesc)) {
             return NULL;
         }
         texture = SkNEW_ARGS(GrGLTextureRenderTarget, (this, surfDesc, idDesc, rtIDDesc));
@@ -418,7 +418,7 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
     idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle);
     idDesc.fMSColorRenderbufferID = 0;
     idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
-    idDesc.fIsWrapped = true;
+    idDesc.fLifeCycle = GrGpuResource::kWrapped_LifeCycle;
 
     GrSurfaceDesc desc;
     desc.fConfig = wrapDesc.fConfig;
@@ -435,10 +435,8 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
         format.fPacked = false;
         format.fStencilBits = wrapDesc.fStencilBits;
         format.fTotalBits = wrapDesc.fStencilBits;
-        static const bool kIsSBWrapped = false;
         GrGLStencilBuffer* sb = SkNEW_ARGS(GrGLStencilBuffer,
                                            (this,
-                                            kIsSBWrapped,
                                             0,
                                             desc.fWidth,
                                             desc.fHeight,
@@ -795,12 +793,13 @@ static bool renderbuffer_storage_msaa(GrGLContext& ctx,
     return (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctx.interface()));;
 }
 
-bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, GrGLuint texID,
+bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted, GrGLuint texID,
                                         GrGLRenderTarget::IDDesc* idDesc) {
     idDesc->fMSColorRenderbufferID = 0;
     idDesc->fRTFBOID = 0;
     idDesc->fTexFBOID = 0;
-    idDesc->fIsWrapped = false;
+    idDesc->fLifeCycle = budgeted ? GrGpuResource::kCached_LifeCycle :
+                                    GrGpuResource::kUncached_LifeCycle;
 
     GrGLenum status;
 
@@ -913,12 +912,10 @@ static size_t as_size_t(int x) {
 }
 #endif
 
-GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& origDesc,
-                                    const void* srcData,
-                                    size_t rowBytes) {
+GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& origDesc, bool budgeted,
+                                    const void* srcData, size_t rowBytes) {
 
     GrSurfaceDesc desc = origDesc;
-    GrGLRenderTarget::IDDesc rtIDDesc;
 
     // Attempt to catch un- or wrongly initialized sample counts;
     SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
@@ -934,11 +931,6 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& origDesc,
     desc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
     desc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
 
-    rtIDDesc.fMSColorRenderbufferID = 0;
-    rtIDDesc.fRTFBOID = 0;
-    rtIDDesc.fTexFBOID = 0;
-    rtIDDesc.fIsWrapped = false;
-
     if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt) {
         //SkDebugf("MSAA RT requested but not supported on this platform.");
         return return_null_texture();
@@ -958,7 +950,8 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& origDesc,
 
     GrGLTexture::IDDesc idDesc;
     GL_CALL(GenTextures(1, &idDesc.fTextureID));
-    idDesc.fIsWrapped = false;
+    idDesc.fLifeCycle = budgeted ? GrGpuResource::kCached_LifeCycle :
+                                   GrGpuResource::kUncached_LifeCycle;
 
     if (!idDesc.fTextureID) {
         return return_null_texture();
@@ -1007,8 +1000,9 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& origDesc,
     if (renderTarget) {
         // unbind the texture from the texture unit before binding it to the frame buffer
         GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0));
+        GrGLRenderTarget::IDDesc rtIDDesc;
 
-        if (!this->createRenderTargetObjects(desc,  idDesc.fTextureID, &rtIDDesc)) {
+        if (!this->createRenderTargetObjects(desc, budgeted, idDesc.fTextureID, &rtIDDesc)) {
             GL_CALL(DeleteTextures(1, &idDesc.fTextureID));
             return return_null_texture();
         }
@@ -1024,7 +1018,8 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& origDesc,
     return tex;
 }
 
-GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& origDesc, const void* srcData) {
+GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& origDesc, bool budgeted,
+                                              const void* srcData) {
 
     if(SkToBool(origDesc.fFlags & kRenderTarget_GrSurfaceFlag) || origDesc.fSampleCnt > 0) {
         return return_null_texture();
@@ -1045,7 +1040,8 @@ GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& origDesc, con
 
     GrGLTexture::IDDesc idDesc;
     GL_CALL(GenTextures(1, &idDesc.fTextureID));
-    idDesc.fIsWrapped = false;
+    idDesc.fLifeCycle = budgeted ? GrGpuResource::kCached_LifeCycle :
+                                   GrGpuResource::kUncached_LifeCycle;
 
     if (!idDesc.fTextureID) {
         return return_null_texture();
@@ -1163,10 +1159,8 @@ bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width,
             // whatever sizes GL gives us. In that case we query for the size.
             GrGLStencilBuffer::Format format = sFmt;
             get_stencil_rb_sizes(this->glInterface(), &format);
-            static const bool kIsWrapped = false;
             SkAutoTUnref<GrStencilBuffer> sb(SkNEW_ARGS(GrGLStencilBuffer,
-                                                  (this, kIsWrapped, sbID, width, height,
-                                                  samples, format)));
+                                                  (this, sbID, width, height, samples, format)));
             if (this->attachStencilBufferToRenderTarget(sb, rt)) {
                 fLastSuccessfulStencilFmtIdx = sIdx;
                 rt->setStencilBuffer(sb);
@@ -1252,7 +1246,6 @@ GrVertexBuffer* GrGLGpu::onCreateVertexBuffer(size_t size, bool dynamic) {
     GrGLVertexBuffer::Desc desc;
     desc.fDynamic = dynamic;
     desc.fSizeInBytes = size;
-    desc.fIsWrapped = false;
 
     if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && desc.fDynamic) {
         desc.fID = 0;
@@ -1285,7 +1278,6 @@ GrIndexBuffer* GrGLGpu::onCreateIndexBuffer(size_t size, bool dynamic) {
     GrGLIndexBuffer::Desc desc;
     desc.fDynamic = dynamic;
     desc.fSizeInBytes = size;
-    desc.fIsWrapped = false;
 
     if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && desc.fDynamic) {
         desc.fID = 0;
index 3809dc7..88cf6f6 100644 (file)
@@ -114,10 +114,9 @@ private:
     // GrGpu overrides
     void onResetContext(uint32_t resetBits) SK_OVERRIDE;
 
-    GrTexture* onCreateTexture(const GrSurfaceDesc& desc,
-                               const void* srcData,
+    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, bool budgeted, const void* srcData,
                                size_t rowBytes) SK_OVERRIDE;
-    GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
+    GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, bool budgeted,
                                          const void* srcData) SK_OVERRIDE;
     GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) SK_OVERRIDE;
     GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) SK_OVERRIDE;
@@ -278,7 +277,8 @@ private:
                                  int left = 0, int top = 0,
                                  int width = -1, int height = -1);
 
-    bool createRenderTargetObjects(const GrSurfaceDesc&, GrGLuint texID, GrGLRenderTarget::IDDesc*);
+    bool createRenderTargetObjects(const GrSurfaceDesc&, bool budgeted, GrGLuint texID, 
+                                   GrGLRenderTarget::IDDesc*);
 
     GrGLuint bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport);
 
index 2d4b9a8..52cf5f8 100644 (file)
@@ -9,7 +9,7 @@
 #include "GrGLGpu.h"
 
 GrGLIndexBuffer::GrGLIndexBuffer(GrGLGpu* gpu, const Desc& desc)
-    : INHERITED(gpu, desc.fIsWrapped, desc.fSizeInBytes, desc.fDynamic, 0 == desc.fID)
+    : INHERITED(gpu, desc.fSizeInBytes, desc.fDynamic, 0 == desc.fID)
     , fImpl(gpu, desc, GR_GL_ELEMENT_ARRAY_BUFFER) {
     this->registerWithCache();
 }
index f5f66b8..6417e68 100644 (file)
@@ -88,8 +88,6 @@ inline void points_to_coords(const SkPoint points[], size_t first_point, size_t
 }
 }
 
-static const bool kIsWrapped = false; // The constructor creates the GL path object.
-
 void GrGLPath::InitPathObject(GrGLGpu* gpu,
                               GrGLuint pathID,
                               const SkPath& skPath,
@@ -184,7 +182,7 @@ void GrGLPath::InitPathObject(GrGLGpu* gpu,
 }
 
 GrGLPath::GrGLPath(GrGLGpu* gpu, const SkPath& path, const SkStrokeRec& stroke)
-    : INHERITED(gpu, kIsWrapped, path, stroke),
+    : INHERITED(gpu, path, stroke),
       fPathID(gpu->glPathRendering()->genPaths(1)) {
 
     InitPathObject(gpu, fPathID, fSkPath, stroke);
index c513b65..3eb2ae0 100644 (file)
 
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
 GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
-    : GrSurface(gpu, idDesc.fIsWrapped, desc)
-    , INHERITED(gpu, idDesc.fIsWrapped, desc) {
+    : GrSurface(gpu, idDesc.fLifeCycle, desc)
+    , INHERITED(gpu, idDesc.fLifeCycle, desc) {
     this->init(desc, idDesc);
     this->registerWithCache();
 }
 
 GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
                                    Derived)
-    : GrSurface(gpu, idDesc.fIsWrapped, desc)
-    , INHERITED(gpu, idDesc.fIsWrapped, desc) {
+    : GrSurface(gpu, idDesc.fLifeCycle, desc)
+    , INHERITED(gpu, idDesc.fLifeCycle, desc) {
     this->init(desc, idDesc);
 }
 
@@ -31,7 +31,7 @@ void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
     fRTFBOID                = idDesc.fRTFBOID;
     fTexFBOID               = idDesc.fTexFBOID;
     fMSColorRenderbufferID  = idDesc.fMSColorRenderbufferID;
-    fIsWrapped              = idDesc.fIsWrapped;
+    fIsWrapped              = kWrapped_LifeCycle == idDesc.fLifeCycle;
 
     fViewport.fLeft   = 0;
     fViewport.fBottom = 0;
index 09de571..ed1e2b3 100644 (file)
@@ -22,10 +22,10 @@ public:
     enum { kUnresolvableFBOID = 0 };
 
     struct IDDesc {
-        GrGLuint         fRTFBOID;
-        GrGLuint         fTexFBOID;
-        GrGLuint         fMSColorRenderbufferID;
-        bool             fIsWrapped;
+        GrGLuint                    fRTFBOID;
+        GrGLuint                    fTexFBOID;
+        GrGLuint                    fMSColorRenderbufferID;
+        GrGpuResource::LifeCycle    fLifeCycle;
     };
 
     GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
index c554091..3bfbafc 100644 (file)
@@ -24,12 +24,11 @@ public:
     };
 
     GrGLStencilBuffer(GrGpu* gpu,
-                      bool isWrapped,
                       GrGLint rbid,
                       int width, int height,
                       int sampleCnt,
                       const Format& format)
-        : GrStencilBuffer(gpu, isWrapped, width, height, format.fStencilBits, sampleCnt)
+        : GrStencilBuffer(gpu, width, height, format.fStencilBits, sampleCnt)
         , fFormat(format)
         , fRenderbufferID(rbid) {
         this->registerWithCache();
index 2f4f49b..faa9f35 100644 (file)
 
 // 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.fIsWrapped, desc)
-    , INHERITED(gpu, idDesc.fIsWrapped, desc) {
+    : GrSurface(gpu, idDesc.fLifeCycle, desc)
+    , INHERITED(gpu, idDesc.fLifeCycle, desc) {
     this->init(desc, idDesc);
     this->registerWithCache();
 }
 
 GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc, Derived)
-    : GrSurface(gpu, idDesc.fIsWrapped, desc)
-    , INHERITED(gpu, idDesc.fIsWrapped, desc) {
+    : GrSurface(gpu, idDesc.fLifeCycle, desc)
+    , INHERITED(gpu, idDesc.fLifeCycle, desc) {
     this->init(desc, idDesc);
 }
 
@@ -30,7 +30,7 @@ void GrGLTexture::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
     fTexParams.invalidate();
     fTexParamsTimestamp = GrGpu::kExpiredTimestamp;
     fTextureID = idDesc.fTextureID;
-    fIsWrapped = idDesc.fIsWrapped;
+    fIsWrapped = kWrapped_LifeCycle == idDesc.fLifeCycle;
 }
 
 void GrGLTexture::onRelease() {
index cc8adeb..c64865f 100644 (file)
@@ -27,8 +27,8 @@ public:
     };
 
     struct IDDesc {
-        GrGLuint        fTextureID;
-        bool            fIsWrapped;
+        GrGLuint                    fTextureID;
+        GrGpuResource::LifeCycle    fLifeCycle;
     };
 
     GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
index af0fde4..e2dd14c 100644 (file)
@@ -28,7 +28,7 @@ public:
                             const GrSurfaceDesc& desc,
                             const GrGLTexture::IDDesc& texIDDesc,
                             const GrGLRenderTarget::IDDesc& rtIDDesc)
-        : GrSurface(gpu, texIDDesc.fIsWrapped, desc)
+        : GrSurface(gpu, texIDDesc.fLifeCycle, desc)
         , GrGLTexture(gpu, desc, texIDDesc, GrGLTexture::kDerived)
         , GrGLRenderTarget(gpu, desc, rtIDDesc, GrGLRenderTarget::kDerived) {
         this->registerWithCache();
index d6cc42a..bb409c6 100644 (file)
@@ -69,7 +69,7 @@ void GrGLAttribArrayState::disableUnusedArrays(const GrGLGpu* gpu, uint64_t used
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 GrGLVertexArray::GrGLVertexArray(GrGLGpu* gpu, GrGLint id, int attribCount)
-    : INHERITED(gpu, false)
+    : INHERITED(gpu, kCached_LifeCycle)
     , fID(id)
     , fAttribArrays(attribCount)
     , fIndexBufferIDIsValid(false) {
index 5691176..61936f2 100644 (file)
@@ -9,7 +9,7 @@
 #include "GrGLGpu.h"
 
 GrGLVertexBuffer::GrGLVertexBuffer(GrGLGpu* gpu, const Desc& desc)
-    : INHERITED(gpu, desc.fIsWrapped, desc.fSizeInBytes, desc.fDynamic, 0 == desc.fID)
+    : INHERITED(gpu, desc.fSizeInBytes, desc.fDynamic, 0 == desc.fID)
     , fImpl(gpu, desc, GR_GL_ARRAY_BUFFER) {
     this->registerWithCache();
 }
index ec18a8c..70b95e0 100644 (file)
@@ -224,12 +224,12 @@ bool GrDrawTarget::programUnitTest(int maxStages) {
     dummyDesc.fConfig = kSkia8888_GrPixelConfig;
     dummyDesc.fWidth = 34;
     dummyDesc.fHeight = 18;
-    SkAutoTUnref<GrTexture> dummyTexture1(gpu->createTexture(dummyDesc, NULL, 0));
+    SkAutoTUnref<GrTexture> dummyTexture1(gpu->createTexture(dummyDesc, false, NULL, 0));
     dummyDesc.fFlags = kNone_GrSurfaceFlags;
     dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
     dummyDesc.fWidth = 16;
     dummyDesc.fHeight = 22;
-    SkAutoTUnref<GrTexture> dummyTexture2(gpu->createTexture(dummyDesc, NULL, 0));
+    SkAutoTUnref<GrTexture> dummyTexture2(gpu->createTexture(dummyDesc, false, NULL, 0));
 
     if (!dummyTexture1 || ! dummyTexture2) {
         SkDebugf("Could not allocate dummy textures");
index a1a594e..8639626 100644 (file)
@@ -66,8 +66,16 @@ class TestResource : public GrGpuResource {
 
 public:
     SK_DECLARE_INST_COUNT(TestResource);
-    TestResource(GrGpu* gpu, bool isWrapped)
-        : INHERITED(gpu, isWrapped)
+    TestResource(GrGpu* gpu, size_t size, GrGpuResource::LifeCycle lifeCycle)
+        : INHERITED(gpu, lifeCycle)
+        , fToDelete(NULL)
+        , fSize(size) {
+        ++fNumAlive;
+        this->registerWithCache();
+    }
+
+    TestResource(GrGpu* gpu, GrGpuResource::LifeCycle lifeCycle)
+        : INHERITED(gpu, lifeCycle)
         , fToDelete(NULL)
         , fSize(kDefaultSize) {
         ++fNumAlive;
@@ -75,7 +83,7 @@ public:
     }
 
     TestResource(GrGpu* gpu)
-        : INHERITED(gpu, false)
+        : INHERITED(gpu, kCached_LifeCycle)
         , fToDelete(NULL)
         , fSize(kDefaultSize) {
         ++fNumAlive;
@@ -83,7 +91,7 @@ public:
     }
 
     TestResource(GrGpu* gpu, const GrScratchKey& scratchKey)
-        : INHERITED(gpu, false)
+        : INHERITED(gpu, kCached_LifeCycle)
         , fToDelete(NULL)
         , fSize(kDefaultSize) {
         this->setScratchKey(scratchKey);
@@ -130,10 +138,10 @@ static void test_no_key(skiatest::Reporter* reporter) {
     SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
 
     // Create a bunch of resources with no keys
-    TestResource* a = new TestResource(context->getGpu());
-    TestResource* b = new TestResource(context->getGpu());
-    TestResource* c = new TestResource(context->getGpu());
-    TestResource* d = new TestResource(context->getGpu());
+    TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
+    TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
+    TestResource* c = SkNEW_ARGS(TestResource, (context->getGpu()));
+    TestResource* d = SkNEW_ARGS(TestResource, (context->getGpu()));
     a->setSize(11);
     b->setSize(12);
     c->setSize(13);
@@ -198,16 +206,17 @@ static void test_budgeting(skiatest::Reporter* reporter) {
     GrResourceKey contentKey(GrCacheID(GrCacheID::GenerateDomain(), keyData), 0);
 
     // Create a scratch, a content, and a wrapped resource
-    TestResource* scratch = new TestResource(context->getGpu(), scratchKey);
+    TestResource* scratch = SkNEW_ARGS(TestResource, (context->getGpu(), scratchKey));
     scratch->setSize(10);
-    TestResource* content = new TestResource(context->getGpu());
-    scratch->setSize(11);
+    TestResource* content = SkNEW_ARGS(TestResource, (context->getGpu()));
+    content->setSize(11);
     REPORTER_ASSERT(reporter, content->cacheAccess().setContentKey(contentKey));
-    TestResource* wrapped = new TestResource(context->getGpu(), true);
-    scratch->setSize(12);
-    TestResource* unbudgeted = new TestResource(context->getGpu());
+    TestResource* wrapped = SkNEW_ARGS(TestResource,
+                                       (context->getGpu(), GrGpuResource::kWrapped_LifeCycle));
+    wrapped->setSize(12);
+    TestResource* unbudgeted = SkNEW_ARGS(TestResource,
+                                          (context->getGpu(), GrGpuResource::kUncached_LifeCycle));
     unbudgeted->setSize(13);
-    unbudgeted->cacheAccess().setBudgeted(false);
 
     // Make sure we can't add a content key to the wrapped resource
     keyData.fData8[0] = 1;
@@ -241,7 +250,7 @@ static void test_budgeting(skiatest::Reporter* reporter) {
                               unbudgeted->gpuMemorySize() == cache2->getResourceBytes());
 
     // Now try freeing the budgeted resources first
-    wrapped = new TestResource(context->getGpu(), true);
+    wrapped = SkNEW_ARGS(TestResource, (context->getGpu(), GrGpuResource::kWrapped_LifeCycle));
     scratch->setSize(12);
     content->unref();
     cache2->purgeAllUnlocked();
@@ -272,6 +281,82 @@ static void test_budgeting(skiatest::Reporter* reporter) {
     REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
 }
 
+static void test_unbudgeted(skiatest::Reporter* reporter) {
+    SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
+    REPORTER_ASSERT(reporter, SkToBool(context));
+    if (NULL == context) {
+        return;
+    }
+    context->setResourceCacheLimits(10, 300);
+    GrResourceCache2* cache2 = context->getResourceCache2();
+    cache2->purgeAllUnlocked();
+    SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
+    SkASSERT(0 == cache2->getBudgetedResourceCount() && 0 == cache2->getBudgetedResourceBytes());
+
+    GrScratchKey scratchKey;
+    make_scratch_key(&scratchKey);
+
+    GrCacheID::Key keyData;
+    memset(&keyData, 0, sizeof(keyData));
+    GrResourceKey contentKey(GrCacheID(GrCacheID::GenerateDomain(), keyData), 0);
+
+    TestResource* scratch;
+    TestResource* content;
+    TestResource* wrapped;
+    TestResource* unbudgeted;
+
+    // A large uncached or wrapped resource shouldn't evict anything.
+    scratch = SkNEW_ARGS(TestResource, (context->getGpu(), scratchKey));
+    scratch->setSize(10);
+    scratch->unref();
+    REPORTER_ASSERT(reporter, 1 == cache2->getResourceCount());
+    REPORTER_ASSERT(reporter, 10 == cache2->getResourceBytes());
+    REPORTER_ASSERT(reporter, 1 == cache2->getBudgetedResourceCount());
+    REPORTER_ASSERT(reporter, 10 == cache2->getBudgetedResourceBytes());
+
+    content = SkNEW_ARGS(TestResource, (context->getGpu()));
+    content->setSize(11);
+    REPORTER_ASSERT(reporter, content->cacheAccess().setContentKey(contentKey));
+    content->unref();
+    REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
+    REPORTER_ASSERT(reporter, 21 == cache2->getResourceBytes());
+    REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
+    REPORTER_ASSERT(reporter, 21 == cache2->getBudgetedResourceBytes());
+
+    size_t large = 2 * cache2->getResourceBytes();
+    unbudgeted = SkNEW_ARGS(TestResource,
+                            (context->getGpu(), large, GrGpuResource::kUncached_LifeCycle));
+    REPORTER_ASSERT(reporter, 3 == cache2->getResourceCount());
+    REPORTER_ASSERT(reporter, 21 + large == cache2->getResourceBytes());
+    REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
+    REPORTER_ASSERT(reporter, 21 == cache2->getBudgetedResourceBytes());
+
+    unbudgeted->unref();
+    REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
+    REPORTER_ASSERT(reporter, 21 == cache2->getResourceBytes());
+    REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
+    REPORTER_ASSERT(reporter, 21 == cache2->getBudgetedResourceBytes());
+
+    wrapped = SkNEW_ARGS(TestResource,
+                         (context->getGpu(), large, GrGpuResource::kWrapped_LifeCycle));
+    REPORTER_ASSERT(reporter, 3 == cache2->getResourceCount());
+    REPORTER_ASSERT(reporter, 21 + large == cache2->getResourceBytes());
+    REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
+    REPORTER_ASSERT(reporter, 21 == cache2->getBudgetedResourceBytes());
+
+    wrapped->unref();
+    REPORTER_ASSERT(reporter, 2 == cache2->getResourceCount());
+    REPORTER_ASSERT(reporter, 21 == cache2->getResourceBytes());
+    REPORTER_ASSERT(reporter, 2 == cache2->getBudgetedResourceCount());
+    REPORTER_ASSERT(reporter, 21 == cache2->getBudgetedResourceBytes());
+
+    cache2->purgeAllUnlocked();
+    REPORTER_ASSERT(reporter, 0 == cache2->getResourceCount());
+    REPORTER_ASSERT(reporter, 0 == cache2->getResourceBytes());
+    REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceCount());
+    REPORTER_ASSERT(reporter, 0 == cache2->getBudgetedResourceBytes());
+}
+
 static void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
     SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
     REPORTER_ASSERT(reporter, SkToBool(context));
@@ -287,8 +372,8 @@ static void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
     make_scratch_key(&scratchKey);
 
     // Create two resources that have the same scratch key.
-    TestResource* a = new TestResource(context->getGpu(), scratchKey);
-    TestResource* b = new TestResource(context->getGpu(), scratchKey);
+    TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu(), scratchKey));
+    TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu(), scratchKey));
     a->setSize(11);
     b->setSize(12);
     // Scratch resources are registered with GrResourceCache2 just by existing. There are 2.
@@ -331,8 +416,8 @@ static void test_remove_scratch_key(skiatest::Reporter* reporter) {
     make_scratch_key(&scratchKey);
 
     // Create two resources that have the same scratch key.
-    TestResource* a = new TestResource(context->getGpu(), scratchKey);
-    TestResource* b = new TestResource(context->getGpu(), scratchKey);
+    TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu(), scratchKey));
+    TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu(), scratchKey));
     a->unref();
     b->unref();
 
@@ -392,8 +477,8 @@ static void test_duplicate_content_key(skiatest::Reporter* reporter) {
     GrResourceKey key(GrCacheID(domain, keyData), 0);
     
     // Create two resources that we will attempt to register with the same content key.
-    TestResource* a = new TestResource(context->getGpu());
-    TestResource* b = new TestResource(context->getGpu());
+    TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
+    TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
     a->setSize(11);
     b->setSize(12);
     
@@ -454,9 +539,9 @@ static void test_purge_invalidated(skiatest::Reporter* reporter) {
     SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
 
     // Add three resources to the cache.
-    TestResource* a = new TestResource(context->getGpu());
-    TestResource* b = new TestResource(context->getGpu());
-    TestResource* c = new TestResource(context->getGpu());
+    TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
+    TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
+    TestResource* c = SkNEW_ARGS(TestResource, (context->getGpu()));
     a->cacheAccess().setContentKey(key1);
     b->cacheAccess().setContentKey(key2);
     c->cacheAccess().setContentKey(key3);
@@ -520,8 +605,8 @@ static void test_cache_chained_purge(skiatest::Reporter* reporter) {
         cache2->purgeAllUnlocked();
         SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
 
-        TestResource* a = new TestResource(context->getGpu());
-        TestResource* b = new TestResource(context->getGpu());
+        TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
+        TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
         a->cacheAccess().setContentKey(key1);
         b->cacheAccess().setContentKey(key2);
 
@@ -574,11 +659,11 @@ static void test_resource_size_changed(skiatest::Reporter* reporter) {
         cache2->purgeAllUnlocked();
         SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
 
-        TestResource* a = new TestResource(context->getGpu());
+        TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
         a->cacheAccess().setContentKey(key1);
         a->unref();
 
-        TestResource* b = new TestResource(context->getGpu());
+        TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
         b->cacheAccess().setContentKey(key2);
         b->unref();
 
@@ -602,12 +687,12 @@ static void test_resource_size_changed(skiatest::Reporter* reporter) {
         cache2->purgeAllUnlocked();
         SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());
 
-        TestResource* a = new TestResource(context->getGpu());
+        TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
         a->setSize(100);
         a->cacheAccess().setContentKey(key1);
         a->unref();
 
-        TestResource* b = new TestResource(context->getGpu());
+        TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
         b->setSize(100);
         b->cacheAccess().setContentKey(key2);
         b->unref();
@@ -719,6 +804,7 @@ DEF_GPUTEST(ResourceCache, reporter, factory) {
     // The below tests create their own mock contexts.
     test_no_key(reporter);
     test_budgeting(reporter);
+    test_unbudgeted(reporter);
     test_duplicate_content_key(reporter);
     test_duplicate_scratch_key(reporter);
     test_remove_scratch_key(reporter);