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