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