OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 | 6 |
7 #include "CCPrioritizedTextureManager.h" | 7 #include "CCPrioritizedTextureManager.h" |
8 | 8 |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "CCPrioritizedTexture.h" | 10 #include "CCPrioritizedTexture.h" |
11 #include "CCPriorityCalculator.h" | 11 #include "CCPriorityCalculator.h" |
12 #include "CCProxy.h" | 12 #include "CCProxy.h" |
13 #include "TraceEvent.h" | 13 #include "TraceEvent.h" |
14 #include <algorithm> | 14 #include <algorithm> |
15 | 15 |
16 using namespace std; | 16 using namespace std; |
17 | 17 |
18 namespace cc { | 18 namespace cc { |
19 | 19 |
20 CCPrioritizedTextureManager::CCPrioritizedTextureManager(size_t maxMemoryLimitBy
tes, int, int pool) | 20 PrioritizedTextureManager::PrioritizedTextureManager(size_t maxMemoryLimitBytes,
int, int pool) |
21 : m_maxMemoryLimitBytes(maxMemoryLimitBytes) | 21 : m_maxMemoryLimitBytes(maxMemoryLimitBytes) |
22 , m_memoryUseBytes(0) | 22 , m_memoryUseBytes(0) |
23 , m_memoryAboveCutoffBytes(0) | 23 , m_memoryAboveCutoffBytes(0) |
24 , m_memoryAvailableBytes(0) | 24 , m_memoryAvailableBytes(0) |
25 , m_pool(pool) | 25 , m_pool(pool) |
26 , m_backingsTailNotSorted(false) | 26 , m_backingsTailNotSorted(false) |
27 { | 27 { |
28 } | 28 } |
29 | 29 |
30 CCPrioritizedTextureManager::~CCPrioritizedTextureManager() | 30 PrioritizedTextureManager::~PrioritizedTextureManager() |
31 { | 31 { |
32 while (m_textures.size() > 0) | 32 while (m_textures.size() > 0) |
33 unregisterTexture(*m_textures.begin()); | 33 unregisterTexture(*m_textures.begin()); |
34 | 34 |
35 deleteUnlinkedEvictedBackings(); | 35 deleteUnlinkedEvictedBackings(); |
36 ASSERT(m_evictedBackings.empty()); | 36 ASSERT(m_evictedBackings.empty()); |
37 | 37 |
38 // Each remaining backing is a leaked opengl texture. There should be none. | 38 // Each remaining backing is a leaked opengl texture. There should be none. |
39 ASSERT(m_backings.empty()); | 39 ASSERT(m_backings.empty()); |
40 } | 40 } |
41 | 41 |
42 void CCPrioritizedTextureManager::prioritizeTextures() | 42 void PrioritizedTextureManager::prioritizeTextures() |
43 { | 43 { |
44 TRACE_EVENT0("cc", "CCPrioritizedTextureManager::prioritizeTextures"); | 44 TRACE_EVENT0("cc", "PrioritizedTextureManager::prioritizeTextures"); |
45 ASSERT(CCProxy::isMainThread()); | 45 ASSERT(Proxy::isMainThread()); |
46 | 46 |
47 // Sorting textures in this function could be replaced by a slightly | 47 // Sorting textures in this function could be replaced by a slightly |
48 // modified O(n) quick-select to partition textures rather than | 48 // modified O(n) quick-select to partition textures rather than |
49 // sort them (if performance of the sort becomes an issue). | 49 // sort them (if performance of the sort becomes an issue). |
50 | 50 |
51 TextureVector& sortedTextures = m_tempTextureVector; | 51 TextureVector& sortedTextures = m_tempTextureVector; |
52 sortedTextures.clear(); | 52 sortedTextures.clear(); |
53 | 53 |
54 // Copy all textures into a vector and sort them. | 54 // Copy all textures into a vector and sort them. |
55 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) | 55 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) |
56 sortedTextures.append(*it); | 56 sortedTextures.append(*it); |
57 std::sort(sortedTextures.begin(), sortedTextures.end(), compareTextures); | 57 std::sort(sortedTextures.begin(), sortedTextures.end(), compareTextures); |
58 | 58 |
59 m_memoryAvailableBytes = m_maxMemoryLimitBytes; | 59 m_memoryAvailableBytes = m_maxMemoryLimitBytes; |
60 m_priorityCutoff = CCPriorityCalculator::lowestPriority(); | 60 m_priorityCutoff = PriorityCalculator::lowestPriority(); |
61 size_t memoryBytes = 0; | 61 size_t memoryBytes = 0; |
62 for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextur
es.end(); ++it) { | 62 for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextur
es.end(); ++it) { |
63 if ((*it)->requestPriority() == CCPriorityCalculator::lowestPriority()) | 63 if ((*it)->requestPriority() == PriorityCalculator::lowestPriority()) |
64 break; | 64 break; |
65 | 65 |
66 if ((*it)->isSelfManaged()) { | 66 if ((*it)->isSelfManaged()) { |
67 // Account for self-managed memory immediately by reducing the memor
y | 67 // Account for self-managed memory immediately by reducing the memor
y |
68 // available (since it never gets acquired). | 68 // available (since it never gets acquired). |
69 size_t newMemoryBytes = memoryBytes + (*it)->bytes(); | 69 size_t newMemoryBytes = memoryBytes + (*it)->bytes(); |
70 if (newMemoryBytes > m_memoryAvailableBytes) { | 70 if (newMemoryBytes > m_memoryAvailableBytes) { |
71 m_priorityCutoff = (*it)->requestPriority(); | 71 m_priorityCutoff = (*it)->requestPriority(); |
72 m_memoryAvailableBytes = memoryBytes; | 72 m_memoryAvailableBytes = memoryBytes; |
73 break; | 73 break; |
74 } | 74 } |
75 m_memoryAvailableBytes -= (*it)->bytes(); | 75 m_memoryAvailableBytes -= (*it)->bytes(); |
76 } else { | 76 } else { |
77 size_t newMemoryBytes = memoryBytes + (*it)->bytes(); | 77 size_t newMemoryBytes = memoryBytes + (*it)->bytes(); |
78 if (newMemoryBytes > m_memoryAvailableBytes) { | 78 if (newMemoryBytes > m_memoryAvailableBytes) { |
79 m_priorityCutoff = (*it)->requestPriority(); | 79 m_priorityCutoff = (*it)->requestPriority(); |
80 break; | 80 break; |
81 } | 81 } |
82 memoryBytes = newMemoryBytes; | 82 memoryBytes = newMemoryBytes; |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 // Only allow textures if they are higher than the cutoff. All textures | 86 // Only allow textures if they are higher than the cutoff. All textures |
87 // of the same priority are accepted or rejected together, rather than | 87 // of the same priority are accepted or rejected together, rather than |
88 // being partially allowed randomly. | 88 // being partially allowed randomly. |
89 m_memoryAboveCutoffBytes = 0; | 89 m_memoryAboveCutoffBytes = 0; |
90 for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextur
es.end(); ++it) { | 90 for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextur
es.end(); ++it) { |
91 bool isAbovePriorityCutoff = CCPriorityCalculator::priorityIsHigher((*it
)->requestPriority(), m_priorityCutoff); | 91 bool isAbovePriorityCutoff = PriorityCalculator::priorityIsHigher((*it)-
>requestPriority(), m_priorityCutoff); |
92 (*it)->setAbovePriorityCutoff(isAbovePriorityCutoff); | 92 (*it)->setAbovePriorityCutoff(isAbovePriorityCutoff); |
93 if (isAbovePriorityCutoff && !(*it)->isSelfManaged()) | 93 if (isAbovePriorityCutoff && !(*it)->isSelfManaged()) |
94 m_memoryAboveCutoffBytes += (*it)->bytes(); | 94 m_memoryAboveCutoffBytes += (*it)->bytes(); |
95 } | 95 } |
96 sortedTextures.clear(); | 96 sortedTextures.clear(); |
97 | 97 |
98 ASSERT(m_memoryAboveCutoffBytes <= m_memoryAvailableBytes); | 98 ASSERT(m_memoryAboveCutoffBytes <= m_memoryAvailableBytes); |
99 ASSERT(memoryAboveCutoffBytes() <= maxMemoryLimitBytes()); | 99 ASSERT(memoryAboveCutoffBytes() <= maxMemoryLimitBytes()); |
100 } | 100 } |
101 | 101 |
102 void CCPrioritizedTextureManager::pushTexturePrioritiesToBackings() | 102 void PrioritizedTextureManager::pushTexturePrioritiesToBackings() |
103 { | 103 { |
104 TRACE_EVENT0("cc", "CCPrioritizedTextureManager::pushTexturePrioritiesToBack
ings"); | 104 TRACE_EVENT0("cc", "PrioritizedTextureManager::pushTexturePrioritiesToBackin
gs"); |
105 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 105 ASSERT(Proxy::isImplThread() && Proxy::isMainThreadBlocked()); |
106 | 106 |
107 assertInvariants(); | 107 assertInvariants(); |
108 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) | 108 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) |
109 (*it)->updatePriority(); | 109 (*it)->updatePriority(); |
110 sortBackings(); | 110 sortBackings(); |
111 assertInvariants(); | 111 assertInvariants(); |
112 } | 112 } |
113 | 113 |
114 void CCPrioritizedTextureManager::updateBackingsInDrawingImplTree() | 114 void PrioritizedTextureManager::updateBackingsInDrawingImplTree() |
115 { | 115 { |
116 TRACE_EVENT0("cc", "CCPrioritizedTextureManager::updateBackingsInDrawingImpl
Tree"); | 116 TRACE_EVENT0("cc", "PrioritizedTextureManager::updateBackingsInDrawingImplTr
ee"); |
117 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 117 ASSERT(Proxy::isImplThread() && Proxy::isMainThreadBlocked()); |
118 | 118 |
119 assertInvariants(); | 119 assertInvariants(); |
120 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) { | 120 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) { |
121 CCPrioritizedTexture::Backing* backing = (*it); | 121 PrioritizedTexture::Backing* backing = (*it); |
122 backing->updateInDrawingImplTree(); | 122 backing->updateInDrawingImplTree(); |
123 } | 123 } |
124 sortBackings(); | 124 sortBackings(); |
125 assertInvariants(); | 125 assertInvariants(); |
126 } | 126 } |
127 | 127 |
128 void CCPrioritizedTextureManager::sortBackings() | 128 void PrioritizedTextureManager::sortBackings() |
129 { | 129 { |
130 TRACE_EVENT0("cc", "CCPrioritizedTextureManager::sortBackings"); | 130 TRACE_EVENT0("cc", "PrioritizedTextureManager::sortBackings"); |
131 ASSERT(CCProxy::isImplThread()); | 131 ASSERT(Proxy::isImplThread()); |
132 | 132 |
133 // Put backings in eviction/recycling order. | 133 // Put backings in eviction/recycling order. |
134 m_backings.sort(compareBackings); | 134 m_backings.sort(compareBackings); |
135 m_backingsTailNotSorted = false; | 135 m_backingsTailNotSorted = false; |
136 } | 136 } |
137 | 137 |
138 void CCPrioritizedTextureManager::clearPriorities() | 138 void PrioritizedTextureManager::clearPriorities() |
139 { | 139 { |
140 ASSERT(CCProxy::isMainThread()); | 140 ASSERT(Proxy::isMainThread()); |
141 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) { | 141 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) { |
142 // FIXME: We should remove this and just set all priorities to | 142 // FIXME: We should remove this and just set all priorities to |
143 // CCPriorityCalculator::lowestPriority() once we have priorities | 143 // PriorityCalculator::lowestPriority() once we have priorities |
144 // for all textures (we can't currently calculate distances for | 144 // for all textures (we can't currently calculate distances for |
145 // off-screen textures). | 145 // off-screen textures). |
146 (*it)->setRequestPriority(CCPriorityCalculator::lingeringPriority((*it)-
>requestPriority())); | 146 (*it)->setRequestPriority(PriorityCalculator::lingeringPriority((*it)->r
equestPriority())); |
147 } | 147 } |
148 } | 148 } |
149 | 149 |
150 bool CCPrioritizedTextureManager::requestLate(CCPrioritizedTexture* texture) | 150 bool PrioritizedTextureManager::requestLate(PrioritizedTexture* texture) |
151 { | 151 { |
152 ASSERT(CCProxy::isMainThread()); | 152 ASSERT(Proxy::isMainThread()); |
153 | 153 |
154 // This is already above cutoff, so don't double count it's memory below. | 154 // This is already above cutoff, so don't double count it's memory below. |
155 if (texture->isAbovePriorityCutoff()) | 155 if (texture->isAbovePriorityCutoff()) |
156 return true; | 156 return true; |
157 | 157 |
158 if (CCPriorityCalculator::priorityIsLower(texture->requestPriority(), m_prio
rityCutoff)) | 158 if (PriorityCalculator::priorityIsLower(texture->requestPriority(), m_priori
tyCutoff)) |
159 return false; | 159 return false; |
160 | 160 |
161 size_t newMemoryBytes = m_memoryAboveCutoffBytes + texture->bytes(); | 161 size_t newMemoryBytes = m_memoryAboveCutoffBytes + texture->bytes(); |
162 if (newMemoryBytes > m_memoryAvailableBytes) | 162 if (newMemoryBytes > m_memoryAvailableBytes) |
163 return false; | 163 return false; |
164 | 164 |
165 m_memoryAboveCutoffBytes = newMemoryBytes; | 165 m_memoryAboveCutoffBytes = newMemoryBytes; |
166 texture->setAbovePriorityCutoff(true); | 166 texture->setAbovePriorityCutoff(true); |
167 return true; | 167 return true; |
168 } | 168 } |
169 | 169 |
170 void CCPrioritizedTextureManager::acquireBackingTextureIfNeeded(CCPrioritizedTex
ture* texture, CCResourceProvider* resourceProvider) | 170 void PrioritizedTextureManager::acquireBackingTextureIfNeeded(PrioritizedTexture
* texture, ResourceProvider* resourceProvider) |
171 { | 171 { |
172 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 172 ASSERT(Proxy::isImplThread() && Proxy::isMainThreadBlocked()); |
173 ASSERT(!texture->isSelfManaged()); | 173 ASSERT(!texture->isSelfManaged()); |
174 ASSERT(texture->isAbovePriorityCutoff()); | 174 ASSERT(texture->isAbovePriorityCutoff()); |
175 if (texture->backing() || !texture->isAbovePriorityCutoff()) | 175 if (texture->backing() || !texture->isAbovePriorityCutoff()) |
176 return; | 176 return; |
177 | 177 |
178 // Find a backing below, by either recycling or allocating. | 178 // Find a backing below, by either recycling or allocating. |
179 CCPrioritizedTexture::Backing* backing = 0; | 179 PrioritizedTexture::Backing* backing = 0; |
180 | 180 |
181 // First try to recycle | 181 // First try to recycle |
182 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) { | 182 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) { |
183 if (!(*it)->canBeRecycled()) | 183 if (!(*it)->canBeRecycled()) |
184 break; | 184 break; |
185 if ((*it)->size() == texture->size() && (*it)->format() == texture->form
at()) { | 185 if ((*it)->size() == texture->size() && (*it)->format() == texture->form
at()) { |
186 backing = (*it); | 186 backing = (*it); |
187 m_backings.erase(it); | 187 m_backings.erase(it); |
188 break; | 188 break; |
189 } | 189 } |
(...skipping 10 matching lines...) Expand all Loading... |
200 if (backing->owner()) | 200 if (backing->owner()) |
201 backing->owner()->unlink(); | 201 backing->owner()->unlink(); |
202 texture->link(backing); | 202 texture->link(backing); |
203 m_backings.push_back(backing); | 203 m_backings.push_back(backing); |
204 m_backingsTailNotSorted = true; | 204 m_backingsTailNotSorted = true; |
205 | 205 |
206 // Update the backing's priority from its new owner. | 206 // Update the backing's priority from its new owner. |
207 backing->updatePriority(); | 207 backing->updatePriority(); |
208 } | 208 } |
209 | 209 |
210 bool CCPrioritizedTextureManager::evictBackingsToReduceMemory(size_t limitBytes,
EvictionPriorityPolicy evictionPolicy, CCResourceProvider* resourceProvider) | 210 bool PrioritizedTextureManager::evictBackingsToReduceMemory(size_t limitBytes, E
victionPriorityPolicy evictionPolicy, ResourceProvider* resourceProvider) |
211 { | 211 { |
212 ASSERT(CCProxy::isImplThread()); | 212 ASSERT(Proxy::isImplThread()); |
213 if (memoryUseBytes() <= limitBytes) | 213 if (memoryUseBytes() <= limitBytes) |
214 return false; | 214 return false; |
215 | 215 |
216 // Destroy backings until we are below the limit, | 216 // Destroy backings until we are below the limit, |
217 // or until all backings remaining are above the cutoff. | 217 // or until all backings remaining are above the cutoff. |
218 while (memoryUseBytes() > limitBytes && m_backings.size() > 0) { | 218 while (memoryUseBytes() > limitBytes && m_backings.size() > 0) { |
219 CCPrioritizedTexture::Backing* backing = m_backings.front(); | 219 PrioritizedTexture::Backing* backing = m_backings.front(); |
220 if (evictionPolicy == RespectManagerPriorityCutoff) | 220 if (evictionPolicy == RespectManagerPriorityCutoff) |
221 if (backing->wasAbovePriorityCutoffAtLastPriorityUpdate()) | 221 if (backing->wasAbovePriorityCutoffAtLastPriorityUpdate()) |
222 break; | 222 break; |
223 evictFirstBackingResource(resourceProvider); | 223 evictFirstBackingResource(resourceProvider); |
224 } | 224 } |
225 return true; | 225 return true; |
226 } | 226 } |
227 | 227 |
228 void CCPrioritizedTextureManager::reduceMemory(CCResourceProvider* resourceProvi
der) | 228 void PrioritizedTextureManager::reduceMemory(ResourceProvider* resourceProvider) |
229 { | 229 { |
230 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 230 ASSERT(Proxy::isImplThread() && Proxy::isMainThreadBlocked()); |
231 | 231 |
232 evictBackingsToReduceMemory(m_memoryAvailableBytes, RespectManagerPriorityCu
toff, resourceProvider); | 232 evictBackingsToReduceMemory(m_memoryAvailableBytes, RespectManagerPriorityCu
toff, resourceProvider); |
233 ASSERT(memoryUseBytes() <= maxMemoryLimitBytes()); | 233 ASSERT(memoryUseBytes() <= maxMemoryLimitBytes()); |
234 | 234 |
235 // We currently collect backings from deleted textures for later recycling. | 235 // We currently collect backings from deleted textures for later recycling. |
236 // However, if we do that forever we will always use the max limit even if | 236 // However, if we do that forever we will always use the max limit even if |
237 // we really need very little memory. This should probably be solved by redu
cing the | 237 // we really need very little memory. This should probably be solved by redu
cing the |
238 // limit externally, but until then this just does some "clean up" of unused | 238 // limit externally, but until then this just does some "clean up" of unused |
239 // backing textures (any more than 10%). | 239 // backing textures (any more than 10%). |
240 size_t wastedMemory = 0; | 240 size_t wastedMemory = 0; |
241 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) { | 241 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) { |
242 if ((*it)->owner()) | 242 if ((*it)->owner()) |
243 break; | 243 break; |
244 wastedMemory += (*it)->bytes(); | 244 wastedMemory += (*it)->bytes(); |
245 } | 245 } |
246 size_t tenPercentOfMemory = m_memoryAvailableBytes / 10; | 246 size_t tenPercentOfMemory = m_memoryAvailableBytes / 10; |
247 if (wastedMemory > tenPercentOfMemory) | 247 if (wastedMemory > tenPercentOfMemory) |
248 evictBackingsToReduceMemory(memoryUseBytes() - (wastedMemory - tenPercen
tOfMemory), RespectManagerPriorityCutoff, resourceProvider); | 248 evictBackingsToReduceMemory(memoryUseBytes() - (wastedMemory - tenPercen
tOfMemory), RespectManagerPriorityCutoff, resourceProvider); |
249 | 249 |
250 // Unlink all evicted backings | 250 // Unlink all evicted backings |
251 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi
ctedBackings.end(); ++it) { | 251 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi
ctedBackings.end(); ++it) { |
252 if ((*it)->owner()) | 252 if ((*it)->owner()) |
253 (*it)->owner()->unlink(); | 253 (*it)->owner()->unlink(); |
254 } | 254 } |
255 | 255 |
256 // And clear the list of evicted backings | 256 // And clear the list of evicted backings |
257 deleteUnlinkedEvictedBackings(); | 257 deleteUnlinkedEvictedBackings(); |
258 } | 258 } |
259 | 259 |
260 void CCPrioritizedTextureManager::clearAllMemory(CCResourceProvider* resourcePro
vider) | 260 void PrioritizedTextureManager::clearAllMemory(ResourceProvider* resourceProvide
r) |
261 { | 261 { |
262 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 262 ASSERT(Proxy::isImplThread() && Proxy::isMainThreadBlocked()); |
263 ASSERT(resourceProvider); | 263 ASSERT(resourceProvider); |
264 evictBackingsToReduceMemory(0, DoNotRespectManagerPriorityCutoff, resourcePr
ovider); | 264 evictBackingsToReduceMemory(0, DoNotRespectManagerPriorityCutoff, resourcePr
ovider); |
265 } | 265 } |
266 | 266 |
267 bool CCPrioritizedTextureManager::reduceMemoryOnImplThread(size_t limitBytes, CC
ResourceProvider* resourceProvider) | 267 bool PrioritizedTextureManager::reduceMemoryOnImplThread(size_t limitBytes, Reso
urceProvider* resourceProvider) |
268 { | 268 { |
269 ASSERT(CCProxy::isImplThread()); | 269 ASSERT(Proxy::isImplThread()); |
270 ASSERT(resourceProvider); | 270 ASSERT(resourceProvider); |
271 // If we are in the process of uploading a new frame then the backings at th
e very end of | 271 // If we are in the process of uploading a new frame then the backings at th
e very end of |
272 // the list are not sorted by priority. Sort them before doing the eviction. | 272 // the list are not sorted by priority. Sort them before doing the eviction. |
273 if (m_backingsTailNotSorted) | 273 if (m_backingsTailNotSorted) |
274 sortBackings(); | 274 sortBackings(); |
275 return evictBackingsToReduceMemory(limitBytes, DoNotRespectManagerPriorityCu
toff, resourceProvider); | 275 return evictBackingsToReduceMemory(limitBytes, DoNotRespectManagerPriorityCu
toff, resourceProvider); |
276 } | 276 } |
277 | 277 |
278 void CCPrioritizedTextureManager::getEvictedBackings(BackingList& evictedBacking
s) | 278 void PrioritizedTextureManager::getEvictedBackings(BackingList& evictedBackings) |
279 { | 279 { |
280 ASSERT(CCProxy::isImplThread()); | 280 ASSERT(Proxy::isImplThread()); |
281 evictedBackings.clear(); | 281 evictedBackings.clear(); |
282 evictedBackings.insert(evictedBackings.begin(), m_evictedBackings.begin(), m
_evictedBackings.end()); | 282 evictedBackings.insert(evictedBackings.begin(), m_evictedBackings.begin(), m
_evictedBackings.end()); |
283 } | 283 } |
284 | 284 |
285 void CCPrioritizedTextureManager::unlinkEvictedBackings(const BackingList& evict
edBackings) | 285 void PrioritizedTextureManager::unlinkEvictedBackings(const BackingList& evicted
Backings) |
286 { | 286 { |
287 ASSERT(CCProxy::isMainThread()); | 287 ASSERT(Proxy::isMainThread()); |
288 for (BackingList::const_iterator it = evictedBackings.begin(); it != evicted
Backings.end(); ++it) { | 288 for (BackingList::const_iterator it = evictedBackings.begin(); it != evicted
Backings.end(); ++it) { |
289 CCPrioritizedTexture::Backing* backing = (*it); | 289 PrioritizedTexture::Backing* backing = (*it); |
290 if (backing->owner()) | 290 if (backing->owner()) |
291 backing->owner()->unlink(); | 291 backing->owner()->unlink(); |
292 } | 292 } |
293 } | 293 } |
294 | 294 |
295 void CCPrioritizedTextureManager::deleteUnlinkedEvictedBackings() | 295 void PrioritizedTextureManager::deleteUnlinkedEvictedBackings() |
296 { | 296 { |
297 ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMai
nThreadBlocked())); | 297 ASSERT(Proxy::isMainThread() || (Proxy::isImplThread() && Proxy::isMainThrea
dBlocked())); |
298 BackingList newEvictedBackings; | 298 BackingList newEvictedBackings; |
299 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi
ctedBackings.end(); ++it) { | 299 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi
ctedBackings.end(); ++it) { |
300 CCPrioritizedTexture::Backing* backing = (*it); | 300 PrioritizedTexture::Backing* backing = (*it); |
301 if (backing->owner()) | 301 if (backing->owner()) |
302 newEvictedBackings.push_back(backing); | 302 newEvictedBackings.push_back(backing); |
303 else | 303 else |
304 delete backing; | 304 delete backing; |
305 } | 305 } |
306 m_evictedBackings.swap(newEvictedBackings); | 306 m_evictedBackings.swap(newEvictedBackings); |
307 } | 307 } |
308 | 308 |
309 bool CCPrioritizedTextureManager::linkedEvictedBackingsExist() const | 309 bool PrioritizedTextureManager::linkedEvictedBackingsExist() const |
310 { | 310 { |
311 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi
ctedBackings.end(); ++it) { | 311 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi
ctedBackings.end(); ++it) { |
312 if ((*it)->owner()) | 312 if ((*it)->owner()) |
313 return true; | 313 return true; |
314 } | 314 } |
315 return false; | 315 return false; |
316 } | 316 } |
317 | 317 |
318 void CCPrioritizedTextureManager::registerTexture(CCPrioritizedTexture* texture) | 318 void PrioritizedTextureManager::registerTexture(PrioritizedTexture* texture) |
319 { | 319 { |
320 ASSERT(CCProxy::isMainThread()); | 320 ASSERT(Proxy::isMainThread()); |
321 ASSERT(texture); | 321 ASSERT(texture); |
322 ASSERT(!texture->textureManager()); | 322 ASSERT(!texture->textureManager()); |
323 ASSERT(!texture->backing()); | 323 ASSERT(!texture->backing()); |
324 ASSERT(!ContainsKey(m_textures, texture)); | 324 ASSERT(!ContainsKey(m_textures, texture)); |
325 | 325 |
326 texture->setManagerInternal(this); | 326 texture->setManagerInternal(this); |
327 m_textures.insert(texture); | 327 m_textures.insert(texture); |
328 | 328 |
329 } | 329 } |
330 | 330 |
331 void CCPrioritizedTextureManager::unregisterTexture(CCPrioritizedTexture* textur
e) | 331 void PrioritizedTextureManager::unregisterTexture(PrioritizedTexture* texture) |
332 { | 332 { |
333 ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMai
nThreadBlocked())); | 333 ASSERT(Proxy::isMainThread() || (Proxy::isImplThread() && Proxy::isMainThrea
dBlocked())); |
334 ASSERT(texture); | 334 ASSERT(texture); |
335 ASSERT(ContainsKey(m_textures, texture)); | 335 ASSERT(ContainsKey(m_textures, texture)); |
336 | 336 |
337 returnBackingTexture(texture); | 337 returnBackingTexture(texture); |
338 texture->setManagerInternal(0); | 338 texture->setManagerInternal(0); |
339 m_textures.erase(texture); | 339 m_textures.erase(texture); |
340 texture->setAbovePriorityCutoff(false); | 340 texture->setAbovePriorityCutoff(false); |
341 } | 341 } |
342 | 342 |
343 void CCPrioritizedTextureManager::returnBackingTexture(CCPrioritizedTexture* tex
ture) | 343 void PrioritizedTextureManager::returnBackingTexture(PrioritizedTexture* texture
) |
344 { | 344 { |
345 ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMai
nThreadBlocked())); | 345 ASSERT(Proxy::isMainThread() || (Proxy::isImplThread() && Proxy::isMainThrea
dBlocked())); |
346 if (texture->backing()) | 346 if (texture->backing()) |
347 texture->unlink(); | 347 texture->unlink(); |
348 } | 348 } |
349 | 349 |
350 CCPrioritizedTexture::Backing* CCPrioritizedTextureManager::createBacking(IntSiz
e size, GC3Denum format, CCResourceProvider* resourceProvider) | 350 PrioritizedTexture::Backing* PrioritizedTextureManager::createBacking(IntSize si
ze, GC3Denum format, ResourceProvider* resourceProvider) |
351 { | 351 { |
352 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 352 ASSERT(Proxy::isImplThread() && Proxy::isMainThreadBlocked()); |
353 ASSERT(resourceProvider); | 353 ASSERT(resourceProvider); |
354 CCResourceProvider::ResourceId resourceId = resourceProvider->createResource
(m_pool, size, format, CCResourceProvider::TextureUsageAny); | 354 ResourceProvider::ResourceId resourceId = resourceProvider->createResource(m
_pool, size, format, ResourceProvider::TextureUsageAny); |
355 CCPrioritizedTexture::Backing* backing = new CCPrioritizedTexture::Backing(r
esourceId, resourceProvider, size, format); | 355 PrioritizedTexture::Backing* backing = new PrioritizedTexture::Backing(resou
rceId, resourceProvider, size, format); |
356 m_memoryUseBytes += backing->bytes(); | 356 m_memoryUseBytes += backing->bytes(); |
357 return backing; | 357 return backing; |
358 } | 358 } |
359 | 359 |
360 void CCPrioritizedTextureManager::evictFirstBackingResource(CCResourceProvider*
resourceProvider) | 360 void PrioritizedTextureManager::evictFirstBackingResource(ResourceProvider* reso
urceProvider) |
361 { | 361 { |
362 ASSERT(CCProxy::isImplThread()); | 362 ASSERT(Proxy::isImplThread()); |
363 ASSERT(resourceProvider); | 363 ASSERT(resourceProvider); |
364 ASSERT(!m_backings.empty()); | 364 ASSERT(!m_backings.empty()); |
365 CCPrioritizedTexture::Backing* backing = m_backings.front(); | 365 PrioritizedTexture::Backing* backing = m_backings.front(); |
366 | 366 |
367 // Note that we create a backing and its resource at the same time, but we | 367 // Note that we create a backing and its resource at the same time, but we |
368 // delete the backing structure and its resource in two steps. This is becau
se | 368 // delete the backing structure and its resource in two steps. This is becau
se |
369 // we can delete the resource while the main thread is running, but we canno
t | 369 // we can delete the resource while the main thread is running, but we canno
t |
370 // unlink backings while the main thread is running. | 370 // unlink backings while the main thread is running. |
371 backing->deleteResource(resourceProvider); | 371 backing->deleteResource(resourceProvider); |
372 m_memoryUseBytes -= backing->bytes(); | 372 m_memoryUseBytes -= backing->bytes(); |
373 m_backings.pop_front(); | 373 m_backings.pop_front(); |
374 m_evictedBackings.push_back(backing); | 374 m_evictedBackings.push_back(backing); |
375 } | 375 } |
376 | 376 |
377 void CCPrioritizedTextureManager::assertInvariants() | 377 void PrioritizedTextureManager::assertInvariants() |
378 { | 378 { |
379 #if !ASSERT_DISABLED | 379 #if !ASSERT_DISABLED |
380 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 380 ASSERT(Proxy::isImplThread() && Proxy::isMainThreadBlocked()); |
381 | 381 |
382 // If we hit any of these asserts, there is a bug in this class. To see | 382 // If we hit any of these asserts, there is a bug in this class. To see |
383 // where the bug is, call this function at the beginning and end of | 383 // where the bug is, call this function at the beginning and end of |
384 // every public function. | 384 // every public function. |
385 | 385 |
386 // Backings/textures must be doubly-linked and only to other backings/textur
es in this manager. | 386 // Backings/textures must be doubly-linked and only to other backings/textur
es in this manager. |
387 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) { | 387 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) { |
388 if ((*it)->owner()) { | 388 if ((*it)->owner()) { |
389 ASSERT(ContainsKey(m_textures, (*it)->owner())); | 389 ASSERT(ContainsKey(m_textures, (*it)->owner())); |
390 ASSERT((*it)->owner()->backing() == (*it)); | 390 ASSERT((*it)->owner()->backing() == (*it)); |
391 } | 391 } |
392 } | 392 } |
393 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) { | 393 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) { |
394 CCPrioritizedTexture* texture = (*it); | 394 PrioritizedTexture* texture = (*it); |
395 CCPrioritizedTexture::Backing* backing = texture->backing(); | 395 PrioritizedTexture::Backing* backing = texture->backing(); |
396 if (backing) { | 396 if (backing) { |
397 if (backing->resourceHasBeenDeleted()) { | 397 if (backing->resourceHasBeenDeleted()) { |
398 ASSERT(std::find(m_backings.begin(), m_backings.end(), backing)
== m_backings.end()); | 398 ASSERT(std::find(m_backings.begin(), m_backings.end(), backing)
== m_backings.end()); |
399 ASSERT(std::find(m_evictedBackings.begin(), m_evictedBackings.en
d(), backing) != m_evictedBackings.end()); | 399 ASSERT(std::find(m_evictedBackings.begin(), m_evictedBackings.en
d(), backing) != m_evictedBackings.end()); |
400 } else { | 400 } else { |
401 ASSERT(std::find(m_backings.begin(), m_backings.end(), backing)
!= m_backings.end()); | 401 ASSERT(std::find(m_backings.begin(), m_backings.end(), backing)
!= m_backings.end()); |
402 ASSERT(std::find(m_evictedBackings.begin(), m_evictedBackings.en
d(), backing) == m_evictedBackings.end()); | 402 ASSERT(std::find(m_evictedBackings.begin(), m_evictedBackings.en
d(), backing) == m_evictedBackings.end()); |
403 } | 403 } |
404 ASSERT(backing->owner() == texture); | 404 ASSERT(backing->owner() == texture); |
405 } | 405 } |
406 } | 406 } |
407 | 407 |
408 // At all times, backings that can be evicted must always come before | 408 // At all times, backings that can be evicted must always come before |
409 // backings that can't be evicted in the backing texture list (otherwise | 409 // backings that can't be evicted in the backing texture list (otherwise |
410 // reduceMemory will not find all textures available for eviction/recycling)
. | 410 // reduceMemory will not find all textures available for eviction/recycling)
. |
411 bool reachedUnrecyclable = false; | 411 bool reachedUnrecyclable = false; |
412 CCPrioritizedTexture::Backing* previous_backing = NULL; | 412 PrioritizedTexture::Backing* previous_backing = NULL; |
413 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) { | 413 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end();
++it) { |
414 CCPrioritizedTexture::Backing* backing = *it; | 414 PrioritizedTexture::Backing* backing = *it; |
415 if (previous_backing && (!m_backingsTailNotSorted || !backing->wasAboveP
riorityCutoffAtLastPriorityUpdate())) | 415 if (previous_backing && (!m_backingsTailNotSorted || !backing->wasAboveP
riorityCutoffAtLastPriorityUpdate())) |
416 ASSERT(compareBackings(previous_backing, backing)); | 416 ASSERT(compareBackings(previous_backing, backing)); |
417 if (!backing->canBeRecycled()) | 417 if (!backing->canBeRecycled()) |
418 reachedUnrecyclable = true; | 418 reachedUnrecyclable = true; |
419 if (reachedUnrecyclable) | 419 if (reachedUnrecyclable) |
420 ASSERT(!backing->canBeRecycled()); | 420 ASSERT(!backing->canBeRecycled()); |
421 else | 421 else |
422 ASSERT(backing->canBeRecycled()); | 422 ASSERT(backing->canBeRecycled()); |
423 previous_backing = backing; | 423 previous_backing = backing; |
424 } | 424 } |
425 #endif | 425 #endif |
426 } | 426 } |
427 | 427 |
428 } // namespace cc | 428 } // namespace cc |
OLD | NEW |