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 "GrResourceCache.h"
11 #include "GrGpu.h"
12 #include "GrGpuResourcePriv.h"
13 
get_resource_cache(GrGpu * gpu)14 static inline GrResourceCache* get_resource_cache(GrGpu* gpu) {
15     SkASSERT(gpu);
16     SkASSERT(gpu->getContext());
17     SkASSERT(gpu->getContext()->getResourceCache());
18     return gpu->getContext()->getResourceCache();
19 }
20 
GrGpuResource(GrGpu * gpu,LifeCycle lifeCycle)21 GrGpuResource::GrGpuResource(GrGpu* gpu, LifeCycle lifeCycle)
22     : fGpu(gpu)
23     , fGpuMemorySize(kInvalidGpuMemorySize)
24     , fLifeCycle(lifeCycle)
25     , fUniqueID(CreateUniqueID()) {
26     SkDEBUGCODE(fCacheArrayIndex = -1);
27 }
28 
registerWithCache()29 void GrGpuResource::registerWithCache() {
30     get_resource_cache(fGpu)->resourceAccess().insertResource(this);
31 }
32 
~GrGpuResource()33 GrGpuResource::~GrGpuResource() {
34     // The cache should have released or destroyed this resource.
35     SkASSERT(this->wasDestroyed());
36 }
37 
release()38 void GrGpuResource::release() {
39     SkASSERT(fGpu);
40     this->onRelease();
41     get_resource_cache(fGpu)->resourceAccess().removeResource(this);
42     fGpu = NULL;
43     fGpuMemorySize = 0;
44 }
45 
abandon()46 void GrGpuResource::abandon() {
47     SkASSERT(fGpu);
48     this->onAbandon();
49     get_resource_cache(fGpu)->resourceAccess().removeResource(this);
50     fGpu = NULL;
51     fGpuMemorySize = 0;
52 }
53 
setCustomData(const SkData * data)54 const SkData* GrGpuResource::setCustomData(const SkData* data) {
55     SkSafeRef(data);
56     fData.reset(data);
57     return data;
58 }
59 
getContext() const60 const GrContext* GrGpuResource::getContext() const {
61     if (fGpu) {
62         return fGpu->getContext();
63     } else {
64         return NULL;
65     }
66 }
67 
getContext()68 GrContext* GrGpuResource::getContext() {
69     if (fGpu) {
70         return fGpu->getContext();
71     } else {
72         return NULL;
73     }
74 }
75 
didChangeGpuMemorySize() const76 void GrGpuResource::didChangeGpuMemorySize() const {
77     if (this->wasDestroyed()) {
78         return;
79     }
80 
81     size_t oldSize = fGpuMemorySize;
82     SkASSERT(kInvalidGpuMemorySize != oldSize);
83     fGpuMemorySize = kInvalidGpuMemorySize;
84     get_resource_cache(fGpu)->resourceAccess().didChangeGpuMemorySize(this, oldSize);
85 }
86 
removeUniqueKey()87 void GrGpuResource::removeUniqueKey() {
88     SkASSERT(fUniqueKey.isValid());
89     get_resource_cache(fGpu)->resourceAccess().removeUniqueKey(this);
90 }
91 
setUniqueKey(const GrUniqueKey & key)92 void GrGpuResource::setUniqueKey(const GrUniqueKey& key) {
93     SkASSERT(this->internalHasRef());
94     SkASSERT(key.isValid());
95 
96     // Wrapped and uncached resources can never have a unique key.
97     if (!this->resourcePriv().isBudgeted()) {
98         return;
99     }
100 
101     if (this->wasDestroyed()) {
102         return;
103     }
104 
105     get_resource_cache(fGpu)->resourceAccess().changeUniqueKey(this, key);
106 }
107 
notifyAllCntsAreZero(CntType lastCntTypeToReachZero) const108 void GrGpuResource::notifyAllCntsAreZero(CntType lastCntTypeToReachZero) const {
109     if (this->wasDestroyed()) {
110         // We've already been removed from the cache. Goodbye cruel world!
111         SkDELETE(this);
112         return;
113     }
114 
115     // We should have already handled this fully in notifyRefCntIsZero().
116     SkASSERT(kRef_CntType != lastCntTypeToReachZero);
117 
118     GrGpuResource* mutableThis = const_cast<GrGpuResource*>(this);
119     static const uint32_t kFlag =
120         GrResourceCache::ResourceAccess::kAllCntsReachedZero_RefNotificationFlag;
121     get_resource_cache(fGpu)->resourceAccess().notifyCntReachedZero(mutableThis, kFlag);
122 }
123 
notifyRefCountIsZero() const124 bool GrGpuResource::notifyRefCountIsZero() const {
125     if (this->wasDestroyed()) {
126         // handle this in notifyAllCntsAreZero().
127         return true;
128     }
129 
130     GrGpuResource* mutableThis = const_cast<GrGpuResource*>(this);
131     uint32_t flags =
132         GrResourceCache::ResourceAccess::kRefCntReachedZero_RefNotificationFlag;
133     if (!this->internalHasPendingIO()) {
134         flags |= GrResourceCache::ResourceAccess::kAllCntsReachedZero_RefNotificationFlag;
135     }
136     get_resource_cache(fGpu)->resourceAccess().notifyCntReachedZero(mutableThis, flags);
137 
138     // There is no need to call our notifyAllCntsAreZero function at this point since we already
139     // told the cache about the state of cnts.
140     return false;
141 }
142 
setScratchKey(const GrScratchKey & scratchKey)143 void GrGpuResource::setScratchKey(const GrScratchKey& scratchKey) {
144     SkASSERT(!fScratchKey.isValid());
145     SkASSERT(scratchKey.isValid());
146     // Wrapped resources can never have a scratch key.
147     if (this->isWrapped()) {
148         return;
149     }
150     fScratchKey = scratchKey;
151 }
152 
removeScratchKey()153 void GrGpuResource::removeScratchKey() {
154     if (!this->wasDestroyed() && fScratchKey.isValid()) {
155         get_resource_cache(fGpu)->resourceAccess().willRemoveScratchKey(this);
156         fScratchKey.reset();
157     }
158 }
159 
makeBudgeted()160 void GrGpuResource::makeBudgeted() {
161     if (GrGpuResource::kUncached_LifeCycle == fLifeCycle) {
162         fLifeCycle = kCached_LifeCycle;
163         get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
164     }
165 }
166 
makeUnbudgeted()167 void GrGpuResource::makeUnbudgeted() {
168     if (GrGpuResource::kCached_LifeCycle == fLifeCycle && !fUniqueKey.isValid()) {
169         fLifeCycle = kUncached_LifeCycle;
170         get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
171     }
172 }
173 
CreateUniqueID()174 uint32_t GrGpuResource::CreateUniqueID() {
175     static int32_t gUniqueID = SK_InvalidUniqueID;
176     uint32_t id;
177     do {
178         id = static_cast<uint32_t>(sk_atomic_inc(&gUniqueID) + 1);
179     } while (id == SK_InvalidUniqueID);
180     return id;
181 }
182