1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #include "GrGpuResource.h" 10 #include "GrContext.h" 11 #include "GrResourceCache.h" 12 #include "GrGpu.h" 13 #include "GrGpuResourcePriv.h" 14 #include "SkTraceMemoryDump.h" 15 16 static inline GrResourceCache* get_resource_cache(GrGpu* gpu) { 17 SkASSERT(gpu); 18 SkASSERT(gpu->getContext()); 19 SkASSERT(gpu->getContext()->getResourceCache()); 20 return gpu->getContext()->getResourceCache(); 21 } 22 23 GrGpuResource::GrGpuResource(GrGpu* gpu, LifeCycle lifeCycle) 24 : fGpu(gpu) 25 , fGpuMemorySize(kInvalidGpuMemorySize) 26 , fLifeCycle(lifeCycle) 27 , fUniqueID(CreateUniqueID()) { 28 SkDEBUGCODE(fCacheArrayIndex = -1); 29 } 30 31 void GrGpuResource::registerWithCache() { 32 get_resource_cache(fGpu)->resourceAccess().insertResource(this); 33 } 34 35 GrGpuResource::~GrGpuResource() { 36 // The cache should have released or destroyed this resource. 37 SkASSERT(this->wasDestroyed()); 38 } 39 40 void GrGpuResource::release() { 41 SkASSERT(fGpu); 42 this->onRelease(); 43 get_resource_cache(fGpu)->resourceAccess().removeResource(this); 44 fGpu = nullptr; 45 fGpuMemorySize = 0; 46 } 47 48 void GrGpuResource::abandon() { 49 if (this->wasDestroyed()) { 50 return; 51 } 52 SkASSERT(fGpu); 53 this->onAbandon(); 54 get_resource_cache(fGpu)->resourceAccess().removeResource(this); 55 fGpu = nullptr; 56 fGpuMemorySize = 0; 57 } 58 59 void GrGpuResource::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { 60 // Dump resource as "skia/gpu_resources/resource_#". 61 SkString dumpName("skia/gpu_resources/resource_"); 62 dumpName.appendS32(this->getUniqueID()); 63 64 traceMemoryDump->dumpNumericValue(dumpName.c_str(), "size", "bytes", this->gpuMemorySize()); 65 66 if (this->isPurgeable()) { 67 traceMemoryDump->dumpNumericValue(dumpName.c_str(), "purgeable_size", "bytes", 68 this->gpuMemorySize()); 69 } 70 71 // Call setMemoryBacking to allow sub-classes with implementation specific backings (such as GL 72 // objects) to provide additional information. 73 this->setMemoryBacking(traceMemoryDump, dumpName); 74 } 75 76 const SkData* GrGpuResource::setCustomData(const SkData* data) { 77 SkSafeRef(data); 78 fData.reset(data); 79 return data; 80 } 81 82 const GrContext* GrGpuResource::getContext() const { 83 if (fGpu) { 84 return fGpu->getContext(); 85 } else { 86 return nullptr; 87 } 88 } 89 90 GrContext* GrGpuResource::getContext() { 91 if (fGpu) { 92 return fGpu->getContext(); 93 } else { 94 return nullptr; 95 } 96 } 97 98 void GrGpuResource::didChangeGpuMemorySize() const { 99 if (this->wasDestroyed()) { 100 return; 101 } 102 103 size_t oldSize = fGpuMemorySize; 104 SkASSERT(kInvalidGpuMemorySize != oldSize); 105 fGpuMemorySize = kInvalidGpuMemorySize; 106 get_resource_cache(fGpu)->resourceAccess().didChangeGpuMemorySize(this, oldSize); 107 } 108 109 void GrGpuResource::removeUniqueKey() { 110 if (this->wasDestroyed()) { 111 return; 112 } 113 SkASSERT(fUniqueKey.isValid()); 114 get_resource_cache(fGpu)->resourceAccess().removeUniqueKey(this); 115 } 116 117 void GrGpuResource::setUniqueKey(const GrUniqueKey& key) { 118 SkASSERT(this->internalHasRef()); 119 SkASSERT(key.isValid()); 120 121 // Wrapped and uncached resources can never have a unique key. 122 if (SkBudgeted::kNo == this->resourcePriv().isBudgeted()) { 123 return; 124 } 125 126 if (this->wasDestroyed()) { 127 return; 128 } 129 130 get_resource_cache(fGpu)->resourceAccess().changeUniqueKey(this, key); 131 } 132 133 void GrGpuResource::notifyAllCntsAreZero(CntType lastCntTypeToReachZero) const { 134 if (this->wasDestroyed()) { 135 // We've already been removed from the cache. Goodbye cruel world! 136 delete this; 137 return; 138 } 139 140 // We should have already handled this fully in notifyRefCntIsZero(). 141 SkASSERT(kRef_CntType != lastCntTypeToReachZero); 142 143 GrGpuResource* mutableThis = const_cast<GrGpuResource*>(this); 144 static const uint32_t kFlag = 145 GrResourceCache::ResourceAccess::kAllCntsReachedZero_RefNotificationFlag; 146 get_resource_cache(fGpu)->resourceAccess().notifyCntReachedZero(mutableThis, kFlag); 147 } 148 149 bool GrGpuResource::notifyRefCountIsZero() const { 150 if (this->wasDestroyed()) { 151 // handle this in notifyAllCntsAreZero(). 152 return true; 153 } 154 155 GrGpuResource* mutableThis = const_cast<GrGpuResource*>(this); 156 uint32_t flags = 157 GrResourceCache::ResourceAccess::kRefCntReachedZero_RefNotificationFlag; 158 if (!this->internalHasPendingIO()) { 159 flags |= GrResourceCache::ResourceAccess::kAllCntsReachedZero_RefNotificationFlag; 160 } 161 get_resource_cache(fGpu)->resourceAccess().notifyCntReachedZero(mutableThis, flags); 162 163 // There is no need to call our notifyAllCntsAreZero function at this point since we already 164 // told the cache about the state of cnts. 165 return false; 166 } 167 168 void GrGpuResource::setScratchKey(const GrScratchKey& scratchKey) { 169 SkASSERT(!fScratchKey.isValid()); 170 SkASSERT(scratchKey.isValid()); 171 // Wrapped resources can never have a scratch key. 172 if (this->cacheAccess().isExternal()) { 173 return; 174 } 175 fScratchKey = scratchKey; 176 } 177 178 void GrGpuResource::removeScratchKey() { 179 if (!this->wasDestroyed() && fScratchKey.isValid()) { 180 get_resource_cache(fGpu)->resourceAccess().willRemoveScratchKey(this); 181 fScratchKey.reset(); 182 } 183 } 184 185 void GrGpuResource::makeBudgeted() { 186 if (!this->wasDestroyed() && GrGpuResource::kUncached_LifeCycle == fLifeCycle) { 187 fLifeCycle = kCached_LifeCycle; 188 get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this); 189 } 190 } 191 192 void GrGpuResource::makeUnbudgeted() { 193 if (!this->wasDestroyed() && GrGpuResource::kCached_LifeCycle == fLifeCycle && 194 !fUniqueKey.isValid()) { 195 fLifeCycle = kUncached_LifeCycle; 196 get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this); 197 } 198 } 199 200 uint32_t GrGpuResource::CreateUniqueID() { 201 static int32_t gUniqueID = SK_InvalidUniqueID; 202 uint32_t id; 203 do { 204 id = static_cast<uint32_t>(sk_atomic_inc(&gUniqueID) + 1); 205 } while (id == SK_InvalidUniqueID); 206 return id; 207 } 208