| 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 "CCPrioritizedTexture.h" | 9 #include "CCPrioritizedTexture.h" |
| 10 #include "CCPriorityCalculator.h" | 10 #include "CCPriorityCalculator.h" |
| 11 #include "CCProxy.h" | 11 #include "CCProxy.h" |
| 12 #include "TraceEvent.h" | 12 #include "TraceEvent.h" |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 | 14 |
| 15 using namespace std; | 15 using namespace std; |
| 16 | 16 |
| 17 namespace cc { | 17 namespace cc { |
| 18 | 18 |
| 19 CCPrioritizedTextureManager::CCPrioritizedTextureManager(size_t maxMemoryLimitBy
tes, int, int pool) | 19 CCPrioritizedTextureManager::CCPrioritizedTextureManager(size_t maxMemoryLimitBy
tes, int, int pool) |
| 20 : m_maxMemoryLimitBytes(maxMemoryLimitBytes) | 20 : m_maxMemoryLimitBytes(maxMemoryLimitBytes) |
| 21 , m_memoryUseBytes(0) | 21 , m_memoryUseBytes(0) |
| 22 , m_memoryAboveCutoffBytes(0) | 22 , m_memoryAboveCutoffBytes(0) |
| 23 , m_memoryAvailableBytes(0) | 23 , m_memoryAvailableBytes(0) |
| 24 , m_pool(pool) | 24 , m_pool(pool) |
| 25 , m_needsUpdateBackingsPrioritites(false) |
| 25 { | 26 { |
| 26 } | 27 } |
| 27 | 28 |
| 28 CCPrioritizedTextureManager::~CCPrioritizedTextureManager() | 29 CCPrioritizedTextureManager::~CCPrioritizedTextureManager() |
| 29 { | 30 { |
| 30 while (m_textures.size() > 0) | 31 while (m_textures.size() > 0) |
| 31 unregisterTexture(*m_textures.begin()); | 32 unregisterTexture(*m_textures.begin()); |
| 32 | 33 |
| 33 // Each remaining backing is a leaked opengl texture. We don't have the reso
urceProvider | 34 deleteEvictedBackings(); |
| 34 // to delete the textures at this time so clearMemory() needs to be called b
efore this. | 35 |
| 35 while (m_backings.size() > 0) | 36 // Each remaining backing is a leaked opengl texture. There should be none. |
| 36 destroyBacking(*m_backings.begin(), 0); | 37 ASSERT(m_backings.isEmpty()); |
| 37 } | 38 } |
| 38 | 39 |
| 39 void CCPrioritizedTextureManager::prioritizeTextures() | 40 void CCPrioritizedTextureManager::prioritizeTextures() |
| 40 { | 41 { |
| 41 TRACE_EVENT0("cc", "CCPrioritizedTextureManager::prioritizeTextures"); | 42 TRACE_EVENT0("cc", "CCPrioritizedTextureManager::prioritizeTextures"); |
| 42 ASSERT(CCProxy::isMainThread()); | 43 ASSERT(CCProxy::isMainThread()); |
| 43 | 44 |
| 44 #if !ASSERT_DISABLED | |
| 45 assertInvariants(); | |
| 46 #endif | |
| 47 | |
| 48 // Sorting textures in this function could be replaced by a slightly | 45 // Sorting textures in this function could be replaced by a slightly |
| 49 // modified O(n) quick-select to partition textures rather than | 46 // modified O(n) quick-select to partition textures rather than |
| 50 // sort them (if performance of the sort becomes an issue). | 47 // sort them (if performance of the sort becomes an issue). |
| 51 | 48 |
| 52 TextureVector& sortedTextures = m_tempTextureVector; | 49 TextureVector& sortedTextures = m_tempTextureVector; |
| 53 BackingVector& sortedBackings = m_tempBackingVector; | |
| 54 sortedTextures.clear(); | 50 sortedTextures.clear(); |
| 55 sortedBackings.clear(); | |
| 56 | 51 |
| 57 // Copy all textures into a vector and sort them. | 52 // Copy all textures into a vector and sort them. |
| 58 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) | 53 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) |
| 59 sortedTextures.append(*it); | 54 sortedTextures.append(*it); |
| 60 std::sort(sortedTextures.begin(), sortedTextures.end(), compareTextures); | 55 std::sort(sortedTextures.begin(), sortedTextures.end(), compareTextures); |
| 61 | 56 |
| 62 m_memoryAvailableBytes = m_maxMemoryLimitBytes; | 57 m_memoryAvailableBytes = m_maxMemoryLimitBytes; |
| 63 m_priorityCutoff = CCPriorityCalculator::lowestPriority(); | 58 m_priorityCutoff = CCPriorityCalculator::lowestPriority(); |
| 64 size_t memoryBytes = 0; | 59 size_t memoryBytes = 0; |
| 65 for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextur
es.end(); ++it) { | 60 for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextur
es.end(); ++it) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 89 // Only allow textures if they are higher than the cutoff. All textures | 84 // Only allow textures if they are higher than the cutoff. All textures |
| 90 // of the same priority are accepted or rejected together, rather than | 85 // of the same priority are accepted or rejected together, rather than |
| 91 // being partially allowed randomly. | 86 // being partially allowed randomly. |
| 92 m_memoryAboveCutoffBytes = 0; | 87 m_memoryAboveCutoffBytes = 0; |
| 93 for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextur
es.end(); ++it) { | 88 for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextur
es.end(); ++it) { |
| 94 bool isAbovePriorityCutoff = CCPriorityCalculator::priorityIsHigher((*it
)->requestPriority(), m_priorityCutoff); | 89 bool isAbovePriorityCutoff = CCPriorityCalculator::priorityIsHigher((*it
)->requestPriority(), m_priorityCutoff); |
| 95 (*it)->setAbovePriorityCutoff(isAbovePriorityCutoff); | 90 (*it)->setAbovePriorityCutoff(isAbovePriorityCutoff); |
| 96 if (isAbovePriorityCutoff && !(*it)->isSelfManaged()) | 91 if (isAbovePriorityCutoff && !(*it)->isSelfManaged()) |
| 97 m_memoryAboveCutoffBytes += (*it)->bytes(); | 92 m_memoryAboveCutoffBytes += (*it)->bytes(); |
| 98 } | 93 } |
| 94 sortedTextures.clear(); |
| 95 |
| 96 m_needsUpdateBackingsPrioritites = true; |
| 97 |
| 99 ASSERT(m_memoryAboveCutoffBytes <= m_memoryAvailableBytes); | 98 ASSERT(m_memoryAboveCutoffBytes <= m_memoryAvailableBytes); |
| 99 ASSERT(memoryAboveCutoffBytes() <= maxMemoryLimitBytes()); |
| 100 } |
| 100 | 101 |
| 101 // Put backings in eviction/recycling order. | 102 void CCPrioritizedTextureManager::updateBackingsPriorities() |
| 102 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) | 103 { |
| 104 TRACE_EVENT0("cc", "CCPrioritizedTextureManager::updateBackingsPriorities"); |
| 105 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); |
| 106 |
| 107 if (!m_needsUpdateBackingsPrioritites) |
| 108 return; |
| 109 |
| 110 #if !ASSERT_DISABLED |
| 111 assertInvariants(); |
| 112 #endif |
| 113 |
| 114 // Update backings' priorities and put backings in eviction/recycling order. |
| 115 BackingVector& sortedBackings = m_tempBackingVector; |
| 116 sortedBackings.clear(); |
| 117 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { |
| 118 (*it)->updatePriority(); |
| 103 sortedBackings.append(*it); | 119 sortedBackings.append(*it); |
| 120 } |
| 104 std::sort(sortedBackings.begin(), sortedBackings.end(), compareBackings); | 121 std::sort(sortedBackings.begin(), sortedBackings.end(), compareBackings); |
| 105 | 122 |
| 106 for (BackingVector::iterator it = sortedBackings.begin(); it != sortedBackin
gs.end(); ++it) { | 123 for (BackingVector::iterator it = sortedBackings.begin(); it != sortedBackin
gs.end(); ++it) { |
| 107 m_backings.remove(*it); | 124 m_backings.remove(*it); |
| 108 m_backings.add(*it); | 125 m_backings.add(*it); |
| 109 } | 126 } |
| 110 | |
| 111 sortedTextures.clear(); | |
| 112 sortedBackings.clear(); | 127 sortedBackings.clear(); |
| 128 m_needsUpdateBackingsPrioritites = false; |
| 113 | 129 |
| 114 #if !ASSERT_DISABLED | 130 #if !ASSERT_DISABLED |
| 115 assertInvariants(); | 131 assertInvariants(); |
| 116 ASSERT(memoryAboveCutoffBytes() <= maxMemoryLimitBytes()); | |
| 117 #endif | 132 #endif |
| 118 } | 133 } |
| 119 | 134 |
| 120 void CCPrioritizedTextureManager::clearPriorities() | 135 void CCPrioritizedTextureManager::clearPriorities() |
| 121 { | 136 { |
| 122 ASSERT(CCProxy::isMainThread()); | 137 ASSERT(CCProxy::isMainThread()); |
| 123 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) { | 138 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) { |
| 124 // FIXME: We should remove this and just set all priorities to | 139 // FIXME: We should remove this and just set all priorities to |
| 125 // CCPriorityCalculator::lowestPriority() once we have priorities | 140 // CCPriorityCalculator::lowestPriority() once we have priorities |
| 126 // for all textures (we can't currently calculate distances for | 141 // for all textures (we can't currently calculate distances for |
| (...skipping 12 matching lines...) Expand all Loading... |
| 139 | 154 |
| 140 if (CCPriorityCalculator::priorityIsLower(texture->requestPriority(), m_prio
rityCutoff)) | 155 if (CCPriorityCalculator::priorityIsLower(texture->requestPriority(), m_prio
rityCutoff)) |
| 141 return false; | 156 return false; |
| 142 | 157 |
| 143 size_t newMemoryBytes = m_memoryAboveCutoffBytes + texture->bytes(); | 158 size_t newMemoryBytes = m_memoryAboveCutoffBytes + texture->bytes(); |
| 144 if (newMemoryBytes > m_memoryAvailableBytes) | 159 if (newMemoryBytes > m_memoryAvailableBytes) |
| 145 return false; | 160 return false; |
| 146 | 161 |
| 147 m_memoryAboveCutoffBytes = newMemoryBytes; | 162 m_memoryAboveCutoffBytes = newMemoryBytes; |
| 148 texture->setAbovePriorityCutoff(true); | 163 texture->setAbovePriorityCutoff(true); |
| 149 if (texture->backing()) { | 164 m_needsUpdateBackingsPrioritites = true; |
| 150 m_backings.remove(texture->backing()); | |
| 151 m_backings.add(texture->backing()); | |
| 152 } | |
| 153 return true; | 165 return true; |
| 154 } | 166 } |
| 155 | 167 |
| 156 void CCPrioritizedTextureManager::acquireBackingTextureIfNeeded(CCPrioritizedTex
ture* texture, CCResourceProvider* resourceProvider) | 168 void CCPrioritizedTextureManager::acquireBackingTextureIfNeeded(CCPrioritizedTex
ture* texture, CCResourceProvider* resourceProvider) |
| 157 { | 169 { |
| 158 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 170 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); |
| 159 ASSERT(!texture->isSelfManaged()); | 171 ASSERT(!texture->isSelfManaged()); |
| 160 ASSERT(texture->isAbovePriorityCutoff()); | 172 ASSERT(texture->isAbovePriorityCutoff()); |
| 161 if (texture->backing() || !texture->isAbovePriorityCutoff()) | 173 if (texture->backing() || !texture->isAbovePriorityCutoff()) |
| 162 return; | 174 return; |
| 163 | 175 |
| 176 // Make sure that the backings list is up to date and sorted before traversi
ng it. |
| 177 updateBackingsPriorities(); |
| 178 |
| 164 // Find a backing below, by either recycling or allocating. | 179 // Find a backing below, by either recycling or allocating. |
| 165 CCPrioritizedTexture::Backing* backing = 0; | 180 CCPrioritizedTexture::Backing* backing = 0; |
| 166 | 181 |
| 167 // First try to recycle | 182 // First try to recycle |
| 168 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { | 183 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { |
| 169 if ((*it)->owner() && (*it)->owner()->isAbovePriorityCutoff()) | 184 if ((*it)->hadOwnerAtLastPriorityUpdate() && (*it)->wasAbovePriorityCuto
ffAtLastPriorityUpdate()) |
| 170 break; | 185 break; |
| 171 if ((*it)->size() == texture->size() && (*it)->format() == texture->form
at()) { | 186 if ((*it)->size() == texture->size() && (*it)->format() == texture->form
at()) { |
| 172 backing = (*it); | 187 backing = (*it); |
| 173 break; | 188 break; |
| 174 } | 189 } |
| 175 } | 190 } |
| 176 | 191 |
| 177 // Otherwise reduce memory and just allocate a new backing texures. | 192 // Otherwise reduce memory and just allocate a new backing texures. |
| 178 if (!backing) { | 193 if (!backing) { |
| 179 reduceMemory(m_memoryAvailableBytes - texture->bytes(), resourceProvider
); | 194 evictBackingsToReduceMemory(m_memoryAvailableBytes - texture->bytes(), R
espectManagerPriorityCutoff, resourceProvider); |
| 180 backing = createBacking(texture->size(), texture->format(), resourceProv
ider); | 195 backing = createBacking(texture->size(), texture->format(), resourceProv
ider); |
| 181 } | 196 } |
| 182 | 197 |
| 183 // Move the used backing texture to the end of the eviction list. | 198 // Move the used backing texture to the end of the eviction list. |
| 184 if (backing->owner()) | 199 if (backing->owner()) |
| 185 backing->owner()->unlink(); | 200 backing->owner()->unlink(); |
| 186 texture->link(backing); | 201 texture->link(backing); |
| 187 m_backings.remove(backing); | 202 m_backings.remove(backing); |
| 188 m_backings.add(backing); | 203 m_backings.add(backing); |
| 204 |
| 205 // Update the backing's priority from its new owner. |
| 206 backing->updatePriority(); |
| 189 } | 207 } |
| 190 | 208 |
| 191 void CCPrioritizedTextureManager::reduceMemory(size_t limitBytes, CCResourceProv
ider* resourceProvider) | 209 void CCPrioritizedTextureManager::evictBackingsToReduceMemory(size_t limitBytes,
EvictionPriorityPolicy evictionPolicy, CCResourceProvider* resourceProvider) |
| 192 { | 210 { |
| 193 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 211 ASSERT(CCProxy::isImplThread()); |
| 194 if (memoryUseBytes() <= limitBytes) | 212 if (memoryUseBytes() <= limitBytes) |
| 195 return; | 213 return; |
| 214 |
| 196 // Destroy backings until we are below the limit, | 215 // Destroy backings until we are below the limit, |
| 197 // or until all backings remaining are above the cutoff. | 216 // or until all backings remaining are above the cutoff. |
| 198 while (memoryUseBytes() > limitBytes && m_backings.size() > 0) { | 217 while (memoryUseBytes() > limitBytes && m_backings.size() > 0) { |
| 199 BackingSet::iterator it = m_backings.begin(); | 218 CCPrioritizedTexture::Backing* backing = *m_backings.begin(); |
| 200 if ((*it)->owner() && (*it)->owner()->isAbovePriorityCutoff()) | 219 if (evictionPolicy == RespectManagerPriorityCutoff) |
| 201 break; | 220 if (backing->hadOwnerAtLastPriorityUpdate() && backing->wasAbovePrio
rityCutoffAtLastPriorityUpdate()) |
| 202 destroyBacking((*it), resourceProvider); | 221 break; |
| 222 evictBackingResource(backing, resourceProvider); |
| 203 } | 223 } |
| 204 } | 224 } |
| 205 | 225 |
| 206 void CCPrioritizedTextureManager::reduceMemory(CCResourceProvider* resourceProvi
der) | 226 void CCPrioritizedTextureManager::reduceMemory(CCResourceProvider* resourceProvi
der) |
| 207 { | 227 { |
| 208 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 228 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); |
| 209 reduceMemory(m_memoryAvailableBytes, resourceProvider); | 229 |
| 230 // Make sure that the backings list is up to date and sorted before traversi
ng it. |
| 231 updateBackingsPriorities(); |
| 232 |
| 233 evictBackingsToReduceMemory(m_memoryAvailableBytes, RespectManagerPriorityCu
toff, resourceProvider); |
| 210 ASSERT(memoryUseBytes() <= maxMemoryLimitBytes()); | 234 ASSERT(memoryUseBytes() <= maxMemoryLimitBytes()); |
| 211 | 235 |
| 212 // We currently collect backings from deleted textures for later recycling. | 236 // We currently collect backings from deleted textures for later recycling. |
| 213 // However, if we do that forever we will always use the max limit even if | 237 // However, if we do that forever we will always use the max limit even if |
| 214 // we really need very little memory. This should probably be solved by redu
cing the | 238 // we really need very little memory. This should probably be solved by redu
cing the |
| 215 // limit externally, but until then this just does some "clean up" of unused | 239 // limit externally, but until then this just does some "clean up" of unused |
| 216 // backing textures (any more than 10%). | 240 // backing textures (any more than 10%). |
| 217 size_t wastedMemory = 0; | 241 size_t wastedMemory = 0; |
| 218 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { | 242 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { |
| 219 if ((*it)->owner()) | 243 if ((*it)->owner()) |
| 220 break; | 244 break; |
| 221 wastedMemory += (*it)->bytes(); | 245 wastedMemory += (*it)->bytes(); |
| 222 } | 246 } |
| 223 size_t tenPercentOfMemory = m_memoryAvailableBytes / 10; | 247 size_t tenPercentOfMemory = m_memoryAvailableBytes / 10; |
| 224 if (wastedMemory <= tenPercentOfMemory) | 248 if (wastedMemory > tenPercentOfMemory) |
| 225 return; | 249 evictBackingsToReduceMemory(memoryUseBytes() - (wastedMemory - tenPercen
tOfMemory), RespectManagerPriorityCutoff, resourceProvider); |
| 226 reduceMemory(memoryUseBytes() - (wastedMemory - tenPercentOfMemory), resourc
eProvider); | 250 |
| 251 deleteEvictedBackings(); |
| 227 } | 252 } |
| 228 | 253 |
| 229 void CCPrioritizedTextureManager::clearAllMemory(CCResourceProvider* resourcePro
vider) | 254 void CCPrioritizedTextureManager::clearAllMemory(CCResourceProvider* resourcePro
vider) |
| 230 { | 255 { |
| 231 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 256 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); |
| 232 ASSERT(resourceProvider); | 257 ASSERT(resourceProvider); |
| 233 // Unlink and destroy all backing textures. | 258 evictBackingsToReduceMemory(0, DoNotRespectManagerPriorityCutoff, resourcePr
ovider); |
| 234 while (m_backings.size() > 0) { | 259 deleteEvictedBackings(); |
| 235 BackingSet::iterator it = m_backings.begin(); | 260 } |
| 236 if ((*it)->owner()) | 261 |
| 237 (*it)->owner()->unlink(); | 262 void CCPrioritizedTextureManager::reduceMemoryOnImplThread(size_t limitBytes, CC
ResourceProvider* resourceProvider) |
| 238 destroyBacking((*it), resourceProvider); | 263 { |
| 264 ASSERT(CCProxy::isImplThread()); |
| 265 ASSERT(resourceProvider); |
| 266 |
| 267 evictBackingsToReduceMemory(limitBytes, DoNotRespectManagerPriorityCutoff, r
esourceProvider); |
| 268 |
| 269 // Deleting just some (not all) resources is not supported yet because we do
not clear |
| 270 // only the deleted resources from the texture upload queues (rather, we cle
ar all uploads). |
| 271 // Make sure that if we evict all resources. |
| 272 ASSERT(m_backings.isEmpty()); |
| 273 } |
| 274 |
| 275 void CCPrioritizedTextureManager::getEvictedBackings(BackingVector& evictedBacki
ngs) |
| 276 { |
| 277 ASSERT(CCProxy::isImplThread()); |
| 278 evictedBackings.clear(); |
| 279 evictedBackings.append(m_evictedBackings); |
| 280 } |
| 281 |
| 282 void CCPrioritizedTextureManager::unlinkEvictedBackings(const BackingVector& evi
ctedBackings) |
| 283 { |
| 284 ASSERT(CCProxy::isMainThread()); |
| 285 for (BackingVector::const_iterator it = evictedBackings.begin(); it != evict
edBackings.end(); ++it) { |
| 286 CCPrioritizedTexture::Backing* backing = (*it); |
| 287 if (backing->owner()) |
| 288 backing->owner()->unlink(); |
| 239 } | 289 } |
| 240 } | 290 } |
| 241 | 291 |
| 242 void CCPrioritizedTextureManager::unlinkAllBackings() | 292 bool CCPrioritizedTextureManager::deleteEvictedBackings() |
| 243 { | 293 { |
| 244 ASSERT(CCProxy::isMainThread()); | 294 ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMai
nThreadBlocked())); |
| 245 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) | 295 bool linkedEvictedBackingsExisted = false; |
| 246 if ((*it)->owner()) | 296 for (BackingVector::const_iterator it = m_evictedBackings.begin(); it != m_e
victedBackings.end(); ++it) { |
| 247 (*it)->owner()->unlink(); | 297 CCPrioritizedTexture::Backing* backing = (*it); |
| 248 } | 298 if (backing->owner()) { |
| 249 | 299 linkedEvictedBackingsExisted = true; |
| 250 void CCPrioritizedTextureManager::deleteAllUnlinkedBackings() | 300 backing->owner()->unlink(); |
| 251 { | 301 } |
| 252 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 302 delete backing; |
| 253 BackingVector backingsToDelete; | 303 } |
| 254 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) | 304 m_evictedBackings.clear(); |
| 255 if (!(*it)->owner()) | 305 return linkedEvictedBackingsExisted; |
| 256 backingsToDelete.append((*it)); | |
| 257 | |
| 258 for (BackingVector::iterator it = backingsToDelete.begin(); it != backingsTo
Delete.end(); ++it) | |
| 259 destroyBacking((*it), 0); | |
| 260 } | 306 } |
| 261 | 307 |
| 262 void CCPrioritizedTextureManager::registerTexture(CCPrioritizedTexture* texture) | 308 void CCPrioritizedTextureManager::registerTexture(CCPrioritizedTexture* texture) |
| 263 { | 309 { |
| 264 ASSERT(CCProxy::isMainThread()); | 310 ASSERT(CCProxy::isMainThread()); |
| 265 ASSERT(texture); | 311 ASSERT(texture); |
| 266 ASSERT(!texture->textureManager()); | 312 ASSERT(!texture->textureManager()); |
| 267 ASSERT(!texture->backing()); | 313 ASSERT(!texture->backing()); |
| 268 ASSERT(m_textures.find(texture) == m_textures.end()); | 314 ASSERT(m_textures.find(texture) == m_textures.end()); |
| 269 | 315 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 281 returnBackingTexture(texture); | 327 returnBackingTexture(texture); |
| 282 texture->setManagerInternal(0); | 328 texture->setManagerInternal(0); |
| 283 m_textures.remove(texture); | 329 m_textures.remove(texture); |
| 284 texture->setAbovePriorityCutoff(false); | 330 texture->setAbovePriorityCutoff(false); |
| 285 } | 331 } |
| 286 | 332 |
| 287 void CCPrioritizedTextureManager::returnBackingTexture(CCPrioritizedTexture* tex
ture) | 333 void CCPrioritizedTextureManager::returnBackingTexture(CCPrioritizedTexture* tex
ture) |
| 288 { | 334 { |
| 289 ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMai
nThreadBlocked())); | 335 ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMai
nThreadBlocked())); |
| 290 if (texture->backing()) { | 336 if (texture->backing()) { |
| 291 // Move the backing texture to the front for eviction/recycling and unli
nk it. | |
| 292 m_backings.remove(texture->backing()); | |
| 293 m_backings.insertBefore(m_backings.begin(), texture->backing()); | |
| 294 texture->unlink(); | 337 texture->unlink(); |
| 338 m_needsUpdateBackingsPrioritites = true; |
| 295 } | 339 } |
| 296 } | 340 } |
| 297 | 341 |
| 298 CCPrioritizedTexture::Backing* CCPrioritizedTextureManager::createBacking(IntSiz
e size, GC3Denum format, CCResourceProvider* resourceProvider) | 342 CCPrioritizedTexture::Backing* CCPrioritizedTextureManager::createBacking(IntSiz
e size, GC3Denum format, CCResourceProvider* resourceProvider) |
| 299 { | 343 { |
| 300 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | 344 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); |
| 301 ASSERT(resourceProvider); | 345 ASSERT(resourceProvider); |
| 302 CCResourceProvider::ResourceId resourceId = resourceProvider->createResource
(m_pool, size, format, CCResourceProvider::TextureUsageAny); | 346 CCResourceProvider::ResourceId resourceId = resourceProvider->createResource
(m_pool, size, format, CCResourceProvider::TextureUsageAny); |
| 303 CCPrioritizedTexture::Backing* backing = new CCPrioritizedTexture::Backing(r
esourceId, size, format); | 347 CCPrioritizedTexture::Backing* backing = new CCPrioritizedTexture::Backing(r
esourceId, size, format); |
| 304 m_memoryUseBytes += backing->bytes(); | 348 m_memoryUseBytes += backing->bytes(); |
| 305 // Put backing texture at the front for eviction, since it isn't in use yet. | 349 // Put backing texture at the front for eviction, since it isn't in use yet. |
| 306 m_backings.insertBefore(m_backings.begin(), backing); | 350 m_backings.insertBefore(m_backings.begin(), backing); |
| 307 return backing; | 351 return backing; |
| 308 } | 352 } |
| 309 | 353 |
| 310 void CCPrioritizedTextureManager::destroyBacking(CCPrioritizedTexture::Backing*
backing, CCResourceProvider* resourceProvider) | 354 void CCPrioritizedTextureManager::evictBackingResource(CCPrioritizedTexture::Bac
king* backing, CCResourceProvider* resourceProvider) |
| 311 { | 355 { |
| 356 ASSERT(CCProxy::isImplThread()); |
| 312 ASSERT(backing); | 357 ASSERT(backing); |
| 313 ASSERT(!backing->owner() || !backing->owner()->isAbovePriorityCutoff()); | 358 ASSERT(resourceProvider); |
| 314 ASSERT(!backing->owner() || !backing->owner()->isSelfManaged()); | |
| 315 ASSERT(m_backings.find(backing) != m_backings.end()); | 359 ASSERT(m_backings.find(backing) != m_backings.end()); |
| 316 | 360 |
| 317 if (resourceProvider) | 361 resourceProvider->deleteResource(backing->id()); |
| 318 resourceProvider->deleteResource(backing->id()); | 362 backing->setId(0); |
| 319 if (backing->owner()) | |
| 320 backing->owner()->unlink(); | |
| 321 m_memoryUseBytes -= backing->bytes(); | 363 m_memoryUseBytes -= backing->bytes(); |
| 322 m_backings.remove(backing); | 364 m_backings.remove(backing); |
| 323 | 365 m_evictedBackings.append(backing); |
| 324 delete backing; | |
| 325 } | 366 } |
| 326 | 367 |
| 327 | |
| 328 #if !ASSERT_DISABLED | 368 #if !ASSERT_DISABLED |
| 329 void CCPrioritizedTextureManager::assertInvariants() | 369 void CCPrioritizedTextureManager::assertInvariants() |
| 330 { | 370 { |
| 331 ASSERT(CCProxy::isMainThread()); | 371 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); |
| 332 | 372 |
| 333 // If we hit any of these asserts, there is a bug in this class. To see | 373 // If we hit any of these asserts, there is a bug in this class. To see |
| 334 // where the bug is, call this function at the beginning and end of | 374 // where the bug is, call this function at the beginning and end of |
| 335 // every public function. | 375 // every public function. |
| 336 | 376 |
| 337 // Backings/textures must be doubly-linked and only to other backings/textur
es in this manager. | 377 // Backings/textures must be doubly-linked and only to other backings/textur
es in this manager. |
| 338 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { | 378 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { |
| 339 if ((*it)->owner()) { | 379 if ((*it)->owner()) { |
| 340 ASSERT(m_textures.find((*it)->owner()) != m_textures.end()); | 380 ASSERT(m_textures.find((*it)->owner()) != m_textures.end()); |
| 341 ASSERT((*it)->owner()->backing() == (*it)); | 381 ASSERT((*it)->owner()->backing() == (*it)); |
| 342 } | 382 } |
| 343 } | 383 } |
| 344 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) { | 384 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) { |
| 345 if ((*it)->backing()) { | 385 if ((*it)->backing()) { |
| 346 ASSERT(m_backings.find((*it)->backing()) != m_backings.end()); | 386 ASSERT(m_backings.find((*it)->backing()) != m_backings.end()); |
| 347 ASSERT((*it)->backing()->owner() == (*it)); | 387 ASSERT((*it)->backing()->owner() == (*it)); |
| 348 } | 388 } |
| 349 } | 389 } |
| 350 | 390 |
| 351 // At all times, backings that can be evicted must always come before | 391 // At all times, backings that can be evicted must always come before |
| 352 // backings that can't be evicted in the backing texture list (otherwise | 392 // backings that can't be evicted in the backing texture list (otherwise |
| 353 // reduceMemory will not find all textures available for eviction/recycling)
. | 393 // reduceMemory will not find all textures available for eviction/recycling)
. |
| 354 bool reachedProtected = false; | 394 bool reachedOwned = false; |
| 395 bool reachedAboveCutoff = false; |
| 355 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { | 396 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { |
| 356 if ((*it)->owner() && (*it)->owner()->isAbovePriorityCutoff()) | 397 if ((*it)->hadOwnerAtLastPriorityUpdate()) |
| 357 reachedProtected = true; | 398 reachedOwned = true; |
| 358 if (reachedProtected) | 399 if ((*it)->wasAbovePriorityCutoffAtLastPriorityUpdate()) |
| 359 ASSERT((*it)->owner() && (*it)->owner()->isAbovePriorityCutoff()); | 400 reachedAboveCutoff = true; |
| 401 if (reachedOwned) |
| 402 ASSERT((*it)->hadOwnerAtLastPriorityUpdate()); |
| 403 if (reachedAboveCutoff) { |
| 404 ASSERT((*it)->hadOwnerAtLastPriorityUpdate() && (*it)->wasAbovePrior
ityCutoffAtLastPriorityUpdate()); |
| 405 ASSERT(reachedOwned); |
| 406 } |
| 360 } | 407 } |
| 361 } | 408 } |
| 362 #endif | 409 #endif |
| 363 | 410 |
| 364 | 411 |
| 365 } // namespace cc | 412 } // namespace cc |
| OLD | NEW |