| 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 | 
|---|