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