Home | History | Annotate | Download | only in gpu
      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