1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkTraceMemoryDump.h" 9cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 10cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 11cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrGpuResource.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrGpuResourcePriv.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrResourceCache.h" 15cb93a386Sopenharmony_ci#include <atomic> 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_cistatic inline GrResourceCache* get_resource_cache(GrGpu* gpu) { 18cb93a386Sopenharmony_ci SkASSERT(gpu); 19cb93a386Sopenharmony_ci SkASSERT(gpu->getContext()); 20cb93a386Sopenharmony_ci SkASSERT(gpu->getContext()->priv().getResourceCache()); 21cb93a386Sopenharmony_ci return gpu->getContext()->priv().getResourceCache(); 22cb93a386Sopenharmony_ci} 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ciGrGpuResource::GrGpuResource(GrGpu* gpu) : fGpu(gpu), fUniqueID(CreateUniqueID()) { 25cb93a386Sopenharmony_ci SkDEBUGCODE(fCacheArrayIndex = -1); 26cb93a386Sopenharmony_ci auto cache = get_resource_cache(fGpu); 27cb93a386Sopenharmony_ci if (cache) { 28cb93a386Sopenharmony_ci fGrResourceTag = cache->resourceAccess().getCurrentGrResourceTag(); 29cb93a386Sopenharmony_ci } 30cb93a386Sopenharmony_ci} 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_civoid GrGpuResource::registerWithCache(SkBudgeted budgeted) { 33cb93a386Sopenharmony_ci SkASSERT(fBudgetedType == GrBudgetedType::kUnbudgetedUncacheable); 34cb93a386Sopenharmony_ci fBudgetedType = budgeted == SkBudgeted::kYes ? GrBudgetedType::kBudgeted 35cb93a386Sopenharmony_ci : GrBudgetedType::kUnbudgetedUncacheable; 36cb93a386Sopenharmony_ci this->computeScratchKey(&fScratchKey); 37cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().insertResource(this); 38cb93a386Sopenharmony_ci} 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_civoid GrGpuResource::registerWithCacheWrapped(GrWrapCacheable wrapType) { 41cb93a386Sopenharmony_ci SkASSERT(fBudgetedType == GrBudgetedType::kUnbudgetedUncacheable); 42cb93a386Sopenharmony_ci // Resources referencing wrapped objects are never budgeted. They may be cached or uncached. 43cb93a386Sopenharmony_ci fBudgetedType = wrapType == GrWrapCacheable::kNo ? GrBudgetedType::kUnbudgetedUncacheable 44cb93a386Sopenharmony_ci : GrBudgetedType::kUnbudgetedCacheable; 45cb93a386Sopenharmony_ci fRefsWrappedObjects = true; 46cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().insertResource(this); 47cb93a386Sopenharmony_ci} 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ciGrGpuResource::~GrGpuResource() { 50cb93a386Sopenharmony_ci // The cache should have released or destroyed this resource. 51cb93a386Sopenharmony_ci SkASSERT(this->wasDestroyed()); 52cb93a386Sopenharmony_ci} 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_civoid GrGpuResource::release() { 55cb93a386Sopenharmony_ci SkASSERT(fGpu); 56cb93a386Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 57cb93a386Sopenharmony_ci if (!fGpu) { 58cb93a386Sopenharmony_ci SkDebugf("OHOS GrGpuResource::release(), fGpu == nullptr"); 59cb93a386Sopenharmony_ci return; 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci this->onRelease(); 62cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().removeResource(this); 63cb93a386Sopenharmony_ci fGpu = nullptr; 64cb93a386Sopenharmony_ci fGpuMemorySize = 0; 65cb93a386Sopenharmony_ci} 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_civoid GrGpuResource::abandon() { 68cb93a386Sopenharmony_ci if (this->wasDestroyed()) { 69cb93a386Sopenharmony_ci return; 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci SkASSERT(fGpu); 72cb93a386Sopenharmony_ci this->onAbandon(); 73cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().removeResource(this); 74cb93a386Sopenharmony_ci fGpu = nullptr; 75cb93a386Sopenharmony_ci fGpuMemorySize = 0; 76cb93a386Sopenharmony_ci} 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_civoid GrGpuResource::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { 79cb93a386Sopenharmony_ci if (this->fRefsWrappedObjects && !traceMemoryDump->shouldDumpWrappedObjects()) { 80cb93a386Sopenharmony_ci return; 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci this->dumpMemoryStatisticsPriv(traceMemoryDump, this->getResourceName(), 84cb93a386Sopenharmony_ci this->getResourceType(), this->gpuMemorySize()); 85cb93a386Sopenharmony_ci} 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_civoid GrGpuResource::dumpMemoryStatisticsPriv(SkTraceMemoryDump* traceMemoryDump, 88cb93a386Sopenharmony_ci const SkString& resourceName, 89cb93a386Sopenharmony_ci const char* type, size_t size) const { 90cb93a386Sopenharmony_ci const char* tag = "Scratch"; 91cb93a386Sopenharmony_ci if (fUniqueKey.isValid()) { 92cb93a386Sopenharmony_ci tag = (fUniqueKey.tag() != nullptr) ? fUniqueKey.tag() : "Other"; 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci traceMemoryDump->dumpNumericValue(resourceName.c_str(), "size", "bytes", size); 96cb93a386Sopenharmony_ci traceMemoryDump->dumpStringValue(resourceName.c_str(), "type", type); 97cb93a386Sopenharmony_ci traceMemoryDump->dumpStringValue(resourceName.c_str(), "category", tag); 98cb93a386Sopenharmony_ci if (this->isPurgeable()) { 99cb93a386Sopenharmony_ci traceMemoryDump->dumpNumericValue(resourceName.c_str(), "purgeable_size", "bytes", size); 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci if (traceMemoryDump->shouldDumpWrappedObjects()) { 102cb93a386Sopenharmony_ci traceMemoryDump->dumpWrappedState(resourceName.c_str(), fRefsWrappedObjects); 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci this->setMemoryBacking(traceMemoryDump, resourceName); 106cb93a386Sopenharmony_ci} 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_cibool GrGpuResource::isPurgeable() const { 109cb93a386Sopenharmony_ci // Resources in the kUnbudgetedCacheable state are never purgeable when they have a unique 110cb93a386Sopenharmony_ci // key. The key must be removed/invalidated to make them purgeable. 111cb93a386Sopenharmony_ci return !this->hasRef() && 112cb93a386Sopenharmony_ci this->hasNoCommandBufferUsages() && 113cb93a386Sopenharmony_ci !(fBudgetedType == GrBudgetedType::kUnbudgetedCacheable && fUniqueKey.isValid()); 114cb93a386Sopenharmony_ci} 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_cibool GrGpuResource::hasRef() const { return this->internalHasRef(); } 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_cibool GrGpuResource::hasNoCommandBufferUsages() const { 119cb93a386Sopenharmony_ci return this->internalHasNoCommandBufferUsages(); 120cb93a386Sopenharmony_ci} 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ciSkString GrGpuResource::getResourceName() const { 123cb93a386Sopenharmony_ci // Dump resource as "skia/gpu_resources/resource_#". 124cb93a386Sopenharmony_ci SkString resourceName("skia/gpu_resources/resource_"); 125cb93a386Sopenharmony_ci resourceName.appendU32(this->uniqueID().asUInt()); 126cb93a386Sopenharmony_ci return resourceName; 127cb93a386Sopenharmony_ci} 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ciconst GrDirectContext* GrGpuResource::getContext() const { 130cb93a386Sopenharmony_ci if (fGpu) { 131cb93a386Sopenharmony_ci return fGpu->getContext(); 132cb93a386Sopenharmony_ci } else { 133cb93a386Sopenharmony_ci return nullptr; 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci} 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_ciGrDirectContext* GrGpuResource::getContext() { 138cb93a386Sopenharmony_ci if (fGpu) { 139cb93a386Sopenharmony_ci return fGpu->getContext(); 140cb93a386Sopenharmony_ci } else { 141cb93a386Sopenharmony_ci return nullptr; 142cb93a386Sopenharmony_ci } 143cb93a386Sopenharmony_ci} 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_civoid GrGpuResource::removeUniqueKey() { 146cb93a386Sopenharmony_ci if (this->wasDestroyed()) { 147cb93a386Sopenharmony_ci return; 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci SkASSERT(fUniqueKey.isValid()); 150cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().removeUniqueKey(this); 151cb93a386Sopenharmony_ci} 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_civoid GrGpuResource::setUniqueKey(const GrUniqueKey& key) { 154cb93a386Sopenharmony_ci SkASSERT(this->internalHasRef()); 155cb93a386Sopenharmony_ci SkASSERT(key.isValid()); 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci // Uncached resources can never have a unique key, unless they're wrapped resources. Wrapped 158cb93a386Sopenharmony_ci // resources are a special case: the unique keys give us a weak ref so that we can reuse the 159cb93a386Sopenharmony_ci // same resource (rather than re-wrapping). When a wrapped resource is no longer referenced, 160cb93a386Sopenharmony_ci // it will always be released - it is never converted to a scratch resource. 161cb93a386Sopenharmony_ci if (this->resourcePriv().budgetedType() != GrBudgetedType::kBudgeted && 162cb93a386Sopenharmony_ci !this->fRefsWrappedObjects) { 163cb93a386Sopenharmony_ci return; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci if (this->wasDestroyed()) { 167cb93a386Sopenharmony_ci return; 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().changeUniqueKey(this, key); 171cb93a386Sopenharmony_ci} 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_civoid GrGpuResource::notifyARefCntIsZero(LastRemovedRef removedRef) const { 174cb93a386Sopenharmony_ci if (this->wasDestroyed()) { 175cb93a386Sopenharmony_ci if (this->hasNoCommandBufferUsages() && !this->hasRef()) { 176cb93a386Sopenharmony_ci // We've already been removed from the cache. Goodbye cruel world! 177cb93a386Sopenharmony_ci delete this; 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci return; 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci GrGpuResource* mutableThis = const_cast<GrGpuResource*>(this); 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().notifyARefCntReachedZero(mutableThis, removedRef); 185cb93a386Sopenharmony_ci} 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_civoid GrGpuResource::removeScratchKey() { 188cb93a386Sopenharmony_ci if (!this->wasDestroyed() && fScratchKey.isValid()) { 189cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().willRemoveScratchKey(this); 190cb93a386Sopenharmony_ci fScratchKey.reset(); 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci} 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_civoid GrGpuResource::makeBudgeted() { 195cb93a386Sopenharmony_ci // We should never make a wrapped resource budgeted. 196cb93a386Sopenharmony_ci SkASSERT(!fRefsWrappedObjects); 197cb93a386Sopenharmony_ci // Only wrapped resources can be in the kUnbudgetedCacheable state. 198cb93a386Sopenharmony_ci SkASSERT(fBudgetedType != GrBudgetedType::kUnbudgetedCacheable); 199cb93a386Sopenharmony_ci if (!this->wasDestroyed() && fBudgetedType == GrBudgetedType::kUnbudgetedUncacheable) { 200cb93a386Sopenharmony_ci // Currently resources referencing wrapped objects are not budgeted. 201cb93a386Sopenharmony_ci fBudgetedType = GrBudgetedType::kBudgeted; 202cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this); 203cb93a386Sopenharmony_ci } 204cb93a386Sopenharmony_ci} 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_civoid GrGpuResource::makeUnbudgeted() { 207cb93a386Sopenharmony_ci if (!this->wasDestroyed() && fBudgetedType == GrBudgetedType::kBudgeted && 208cb93a386Sopenharmony_ci !fUniqueKey.isValid()) { 209cb93a386Sopenharmony_ci fBudgetedType = GrBudgetedType::kUnbudgetedUncacheable; 210cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this); 211cb93a386Sopenharmony_ci } 212cb93a386Sopenharmony_ci} 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_civoid GrGpuResource::userRegisterResource() 215cb93a386Sopenharmony_ci{ 216cb93a386Sopenharmony_ci if (this->wasDestroyed()) { 217cb93a386Sopenharmony_ci return; 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci SkASSERT(!fScratchKey.isValid()); 220cb93a386Sopenharmony_ci SkASSERT(!fUniqueKey.isValid()); 221cb93a386Sopenharmony_ci if (fCacheArrayIndex >= 0 && fBudgetedType == GrBudgetedType::kUnbudgetedUncacheable) { 222cb93a386Sopenharmony_ci this->computeScratchKey(&fScratchKey); 223cb93a386Sopenharmony_ci makeBudgeted(); 224cb93a386Sopenharmony_ci } 225cb93a386Sopenharmony_ci} 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ciuint32_t GrGpuResource::CreateUniqueID() { 228cb93a386Sopenharmony_ci static std::atomic<uint32_t> nextID{1}; 229cb93a386Sopenharmony_ci uint32_t id; 230cb93a386Sopenharmony_ci do { 231cb93a386Sopenharmony_ci id = nextID.fetch_add(1, std::memory_order_relaxed); 232cb93a386Sopenharmony_ci } while (id == SK_InvalidUniqueID); 233cb93a386Sopenharmony_ci return id; 234cb93a386Sopenharmony_ci} 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_civoid GrGpuResource::setResourceTag(const GrGpuResourceTag tag) 237cb93a386Sopenharmony_ci{ 238cb93a386Sopenharmony_ci int32_t pid = fGrResourceTag.fPid; 239cb93a386Sopenharmony_ci fGrResourceTag = tag; 240cb93a386Sopenharmony_ci if (pid == tag.fPid || !fRealAlloc) { 241cb93a386Sopenharmony_ci return; 242cb93a386Sopenharmony_ci } 243cb93a386Sopenharmony_ci size_t size = this->gpuMemorySize(); 244cb93a386Sopenharmony_ci get_resource_cache(fGpu)->resourceAccess().changeByteOfPid(pid, tag.fPid, fRealAllocSize); 245cb93a386Sopenharmony_ci} 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_civoid GrGpuResource::ProxyAccess::ref(GrResourceCache* cache) { 250cb93a386Sopenharmony_ci SkASSERT(cache == fResource->getContext()->priv().getResourceCache()); 251cb93a386Sopenharmony_ci cache->resourceAccess().refResource(fResource); 252cb93a386Sopenharmony_ci} 253