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
get_resource_cache(GrGpu * gpu)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
GrGpuResource(GrGpu * gpu,LifeCycle lifeCycle)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
registerWithCache()31 void GrGpuResource::registerWithCache() {
32 get_resource_cache(fGpu)->resourceAccess().insertResource(this);
33 }
34
~GrGpuResource()35 GrGpuResource::~GrGpuResource() {
36 // The cache should have released or destroyed this resource.
37 SkASSERT(this->wasDestroyed());
38 }
39
release()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
abandon()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
dumpMemoryStatistics(SkTraceMemoryDump * traceMemoryDump) const59 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
setCustomData(const SkData * data)76 const SkData* GrGpuResource::setCustomData(const SkData* data) {
77 SkSafeRef(data);
78 fData.reset(data);
79 return data;
80 }
81
getContext() const82 const GrContext* GrGpuResource::getContext() const {
83 if (fGpu) {
84 return fGpu->getContext();
85 } else {
86 return nullptr;
87 }
88 }
89
getContext()90 GrContext* GrGpuResource::getContext() {
91 if (fGpu) {
92 return fGpu->getContext();
93 } else {
94 return nullptr;
95 }
96 }
97
didChangeGpuMemorySize() const98 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
removeUniqueKey()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
setUniqueKey(const GrUniqueKey & key)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
notifyAllCntsAreZero(CntType lastCntTypeToReachZero) const133 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
notifyRefCountIsZero() const149 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
setScratchKey(const GrScratchKey & scratchKey)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
removeScratchKey()178 void GrGpuResource::removeScratchKey() {
179 if (!this->wasDestroyed() && fScratchKey.isValid()) {
180 get_resource_cache(fGpu)->resourceAccess().willRemoveScratchKey(this);
181 fScratchKey.reset();
182 }
183 }
184
makeBudgeted()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
makeUnbudgeted()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
CreateUniqueID()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