123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- /*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/core/SkTraceMemoryDump.h"
- #include "include/gpu/GrContext.h"
- #include "include/gpu/GrGpuResource.h"
- #include "src/gpu/GrContextPriv.h"
- #include "src/gpu/GrGpu.h"
- #include "src/gpu/GrGpuResourcePriv.h"
- #include "src/gpu/GrResourceCache.h"
- #include <atomic>
- static inline GrResourceCache* get_resource_cache(GrGpu* gpu) {
- SkASSERT(gpu);
- SkASSERT(gpu->getContext());
- SkASSERT(gpu->getContext()->priv().getResourceCache());
- return gpu->getContext()->priv().getResourceCache();
- }
- GrGpuResource::GrGpuResource(GrGpu* gpu) : fGpu(gpu), fUniqueID(CreateUniqueID()) {
- SkDEBUGCODE(fCacheArrayIndex = -1);
- }
- void GrGpuResource::registerWithCache(SkBudgeted budgeted) {
- SkASSERT(fBudgetedType == GrBudgetedType::kUnbudgetedUncacheable);
- fBudgetedType = budgeted == SkBudgeted::kYes ? GrBudgetedType::kBudgeted
- : GrBudgetedType::kUnbudgetedUncacheable;
- this->computeScratchKey(&fScratchKey);
- get_resource_cache(fGpu)->resourceAccess().insertResource(this);
- }
- void GrGpuResource::registerWithCacheWrapped(GrWrapCacheable wrapType) {
- SkASSERT(fBudgetedType == GrBudgetedType::kUnbudgetedUncacheable);
- // Resources referencing wrapped objects are never budgeted. They may be cached or uncached.
- fBudgetedType = wrapType == GrWrapCacheable::kNo ? GrBudgetedType::kUnbudgetedUncacheable
- : GrBudgetedType::kUnbudgetedCacheable;
- fRefsWrappedObjects = true;
- get_resource_cache(fGpu)->resourceAccess().insertResource(this);
- }
- GrGpuResource::~GrGpuResource() {
- // The cache should have released or destroyed this resource.
- SkASSERT(this->wasDestroyed());
- }
- void GrGpuResource::release() {
- SkASSERT(fGpu);
- this->onRelease();
- get_resource_cache(fGpu)->resourceAccess().removeResource(this);
- fGpu = nullptr;
- fGpuMemorySize = 0;
- }
- void GrGpuResource::abandon() {
- if (this->wasDestroyed()) {
- return;
- }
- SkASSERT(fGpu);
- this->onAbandon();
- get_resource_cache(fGpu)->resourceAccess().removeResource(this);
- fGpu = nullptr;
- fGpuMemorySize = 0;
- }
- void GrGpuResource::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
- if (this->fRefsWrappedObjects && !traceMemoryDump->shouldDumpWrappedObjects()) {
- return;
- }
- this->dumpMemoryStatisticsPriv(traceMemoryDump, this->getResourceName(),
- this->getResourceType(), this->gpuMemorySize());
- }
- void GrGpuResource::dumpMemoryStatisticsPriv(SkTraceMemoryDump* traceMemoryDump,
- const SkString& resourceName,
- const char* type, size_t size) const {
- const char* tag = "Scratch";
- if (fUniqueKey.isValid()) {
- tag = (fUniqueKey.tag() != nullptr) ? fUniqueKey.tag() : "Other";
- }
- traceMemoryDump->dumpNumericValue(resourceName.c_str(), "size", "bytes", size);
- traceMemoryDump->dumpStringValue(resourceName.c_str(), "type", type);
- traceMemoryDump->dumpStringValue(resourceName.c_str(), "category", tag);
- if (this->isPurgeable()) {
- traceMemoryDump->dumpNumericValue(resourceName.c_str(), "purgeable_size", "bytes", size);
- }
- this->setMemoryBacking(traceMemoryDump, resourceName);
- }
- bool GrGpuResource::isPurgeable() const {
- // Resources in the kUnbudgetedCacheable state are never purgeable when they have a unique
- // key. The key must be removed/invalidated to make them purgeable.
- return !this->hasRefOrPendingIO() &&
- !(fBudgetedType == GrBudgetedType::kUnbudgetedCacheable && fUniqueKey.isValid());
- }
- bool GrGpuResource::hasRefOrPendingIO() const {
- return this->internalHasRef() || this->internalHasPendingIO();
- }
- bool GrGpuResource::hasRef() const { return this->internalHasRef(); }
- SkString GrGpuResource::getResourceName() const {
- // Dump resource as "skia/gpu_resources/resource_#".
- SkString resourceName("skia/gpu_resources/resource_");
- resourceName.appendU32(this->uniqueID().asUInt());
- return resourceName;
- }
- const GrContext* GrGpuResource::getContext() const {
- if (fGpu) {
- return fGpu->getContext();
- } else {
- return nullptr;
- }
- }
- GrContext* GrGpuResource::getContext() {
- if (fGpu) {
- return fGpu->getContext();
- } else {
- return nullptr;
- }
- }
- void GrGpuResource::removeUniqueKey() {
- if (this->wasDestroyed()) {
- return;
- }
- SkASSERT(fUniqueKey.isValid());
- get_resource_cache(fGpu)->resourceAccess().removeUniqueKey(this);
- }
- void GrGpuResource::setUniqueKey(const GrUniqueKey& key) {
- SkASSERT(this->internalHasRef());
- SkASSERT(key.isValid());
- // Uncached resources can never have a unique key, unless they're wrapped resources. Wrapped
- // resources are a special case: the unique keys give us a weak ref so that we can reuse the
- // same resource (rather than re-wrapping). When a wrapped resource is no longer referenced,
- // it will always be released - it is never converted to a scratch resource.
- if (this->resourcePriv().budgetedType() != GrBudgetedType::kBudgeted &&
- !this->fRefsWrappedObjects) {
- return;
- }
- if (this->wasDestroyed()) {
- return;
- }
- get_resource_cache(fGpu)->resourceAccess().changeUniqueKey(this, key);
- }
- void GrGpuResource::notifyAllCntsWillBeZero() const {
- GrGpuResource* mutableThis = const_cast<GrGpuResource*>(this);
- mutableThis->willRemoveLastRefOrPendingIO();
- }
- void GrGpuResource::notifyAllCntsAreZero(CntType lastCntTypeToReachZero) const {
- if (this->wasDestroyed()) {
- // We've already been removed from the cache. Goodbye cruel world!
- delete this;
- return;
- }
- // We should have already handled this fully in notifyRefCntIsZero().
- SkASSERT(kRef_CntType != lastCntTypeToReachZero);
- static const uint32_t kFlag =
- GrResourceCache::ResourceAccess::kAllCntsReachedZero_RefNotificationFlag;
- GrGpuResource* mutableThis = const_cast<GrGpuResource*>(this);
- get_resource_cache(fGpu)->resourceAccess().notifyCntReachedZero(mutableThis, kFlag);
- }
- bool GrGpuResource::notifyRefCountIsZero() const {
- if (this->wasDestroyed()) {
- // handle this in notifyAllCntsAreZero().
- return true;
- }
- GrGpuResource* mutableThis = const_cast<GrGpuResource*>(this);
- uint32_t flags = GrResourceCache::ResourceAccess::kRefCntReachedZero_RefNotificationFlag;
- if (!this->internalHasPendingIO()) {
- flags |= GrResourceCache::ResourceAccess::kAllCntsReachedZero_RefNotificationFlag;
- }
- get_resource_cache(fGpu)->resourceAccess().notifyCntReachedZero(mutableThis, flags);
- // There is no need to call our notifyAllCntsAreZero function at this point since we already
- // told the cache about the state of cnts.
- return false;
- }
- void GrGpuResource::removeScratchKey() {
- if (!this->wasDestroyed() && fScratchKey.isValid()) {
- get_resource_cache(fGpu)->resourceAccess().willRemoveScratchKey(this);
- fScratchKey.reset();
- }
- }
- void GrGpuResource::makeBudgeted() {
- // We should never make a wrapped resource budgeted.
- SkASSERT(!fRefsWrappedObjects);
- // Only wrapped resources can be in the kUnbudgetedCacheable state.
- SkASSERT(fBudgetedType != GrBudgetedType::kUnbudgetedCacheable);
- if (!this->wasDestroyed() && fBudgetedType == GrBudgetedType::kUnbudgetedUncacheable) {
- // Currently resources referencing wrapped objects are not budgeted.
- fBudgetedType = GrBudgetedType::kBudgeted;
- get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
- }
- }
- void GrGpuResource::makeUnbudgeted() {
- if (!this->wasDestroyed() && fBudgetedType == GrBudgetedType::kBudgeted &&
- !fUniqueKey.isValid()) {
- fBudgetedType = GrBudgetedType::kUnbudgetedUncacheable;
- get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
- }
- }
- uint32_t GrGpuResource::CreateUniqueID() {
- static std::atomic<uint32_t> nextID{1};
- uint32_t id;
- do {
- id = nextID++;
- } while (id == SK_InvalidUniqueID);
- return id;
- }
- //////////////////////////////////////////////////////////////////////////////
- void GrGpuResource::ProxyAccess::ref(GrResourceCache* cache) {
- SkASSERT(cache == fResource->getContext()->priv().getResourceCache());
- cache->resourceAccess().refResource(fResource);
- }
|