| 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 "TraceEvent.h" | 12 #include "TraceEvent.h" |
| 12 #include <algorithm> | 13 #include <algorithm> |
| 13 | 14 |
| 14 using namespace std; | 15 using namespace std; |
| 15 | 16 |
| 16 namespace WebCore { | 17 namespace WebCore { |
| 17 | 18 |
| 18 CCPrioritizedTextureManager::CCPrioritizedTextureManager(size_t maxMemoryLimitBy
tes, int, int pool) | 19 CCPrioritizedTextureManager::CCPrioritizedTextureManager(size_t maxMemoryLimitBy
tes, int, int pool) |
| 19 : m_maxMemoryLimitBytes(maxMemoryLimitBytes) | 20 : m_maxMemoryLimitBytes(maxMemoryLimitBytes) |
| 20 , m_memoryUseBytes(0) | 21 , m_memoryUseBytes(0) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 31 | 32 |
| 32 // Each remaining backing is a leaked opengl texture. We don't have the reso
urceProvider | 33 // Each remaining backing is a leaked opengl texture. We don't have the reso
urceProvider |
| 33 // to delete the textures at this time so clearMemory() needs to be called b
efore this. | 34 // to delete the textures at this time so clearMemory() needs to be called b
efore this. |
| 34 while (m_backings.size() > 0) | 35 while (m_backings.size() > 0) |
| 35 destroyBacking(*m_backings.begin(), 0); | 36 destroyBacking(*m_backings.begin(), 0); |
| 36 } | 37 } |
| 37 | 38 |
| 38 void CCPrioritizedTextureManager::prioritizeTextures() | 39 void CCPrioritizedTextureManager::prioritizeTextures() |
| 39 { | 40 { |
| 40 TRACE_EVENT0("cc", "CCPrioritizedTextureManager::prioritizeTextures"); | 41 TRACE_EVENT0("cc", "CCPrioritizedTextureManager::prioritizeTextures"); |
| 42 ASSERT(CCProxy::isMainThread()); |
| 41 | 43 |
| 42 #if !ASSERT_DISABLED | 44 #if !ASSERT_DISABLED |
| 43 assertInvariants(); | 45 assertInvariants(); |
| 44 #endif | 46 #endif |
| 45 | 47 |
| 46 // Sorting textures in this function could be replaced by a slightly | 48 // Sorting textures in this function could be replaced by a slightly |
| 47 // modified O(n) quick-select to partition textures rather than | 49 // modified O(n) quick-select to partition textures rather than |
| 48 // sort them (if performance of the sort becomes an issue). | 50 // sort them (if performance of the sort becomes an issue). |
| 49 | 51 |
| 50 TextureVector& sortedTextures = m_tempTextureVector; | 52 TextureVector& sortedTextures = m_tempTextureVector; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 sortedBackings.clear(); | 112 sortedBackings.clear(); |
| 111 | 113 |
| 112 #if !ASSERT_DISABLED | 114 #if !ASSERT_DISABLED |
| 113 assertInvariants(); | 115 assertInvariants(); |
| 114 ASSERT(memoryAboveCutoffBytes() <= maxMemoryLimitBytes()); | 116 ASSERT(memoryAboveCutoffBytes() <= maxMemoryLimitBytes()); |
| 115 #endif | 117 #endif |
| 116 } | 118 } |
| 117 | 119 |
| 118 void CCPrioritizedTextureManager::clearPriorities() | 120 void CCPrioritizedTextureManager::clearPriorities() |
| 119 { | 121 { |
| 122 ASSERT(CCProxy::isMainThread()); |
| 120 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) { | 123 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); +
+it) { |
| 121 // FIXME: We should remove this and just set all priorities to | 124 // FIXME: We should remove this and just set all priorities to |
| 122 // CCPriorityCalculator::lowestPriority() once we have priorities | 125 // CCPriorityCalculator::lowestPriority() once we have priorities |
| 123 // for all textures (we can't currently calculate distances for | 126 // for all textures (we can't currently calculate distances for |
| 124 // off-screen textures). | 127 // off-screen textures). |
| 125 (*it)->setRequestPriority(CCPriorityCalculator::lingeringPriority((*it)-
>requestPriority())); | 128 (*it)->setRequestPriority(CCPriorityCalculator::lingeringPriority((*it)-
>requestPriority())); |
| 126 } | 129 } |
| 127 } | 130 } |
| 128 | 131 |
| 129 bool CCPrioritizedTextureManager::requestLate(CCPrioritizedTexture* texture) | 132 bool CCPrioritizedTextureManager::requestLate(CCPrioritizedTexture* texture) |
| 130 { | 133 { |
| 134 ASSERT(CCProxy::isMainThread()); |
| 135 |
| 131 // This is already above cutoff, so don't double count it's memory below. | 136 // This is already above cutoff, so don't double count it's memory below. |
| 132 if (texture->isAbovePriorityCutoff()) | 137 if (texture->isAbovePriorityCutoff()) |
| 133 return true; | 138 return true; |
| 134 | 139 |
| 135 if (CCPriorityCalculator::priorityIsLower(texture->requestPriority(), m_prio
rityCutoff)) | 140 if (CCPriorityCalculator::priorityIsLower(texture->requestPriority(), m_prio
rityCutoff)) |
| 136 return false; | 141 return false; |
| 137 | 142 |
| 138 size_t newMemoryBytes = m_memoryAboveCutoffBytes + texture->bytes(); | 143 size_t newMemoryBytes = m_memoryAboveCutoffBytes + texture->bytes(); |
| 139 if (newMemoryBytes > m_memoryAvailableBytes) | 144 if (newMemoryBytes > m_memoryAvailableBytes) |
| 140 return false; | 145 return false; |
| 141 | 146 |
| 142 m_memoryAboveCutoffBytes = newMemoryBytes; | 147 m_memoryAboveCutoffBytes = newMemoryBytes; |
| 143 texture->setAbovePriorityCutoff(true); | 148 texture->setAbovePriorityCutoff(true); |
| 144 if (texture->backing()) { | 149 if (texture->backing()) { |
| 145 m_backings.remove(texture->backing()); | 150 m_backings.remove(texture->backing()); |
| 146 m_backings.add(texture->backing()); | 151 m_backings.add(texture->backing()); |
| 147 } | 152 } |
| 148 return true; | 153 return true; |
| 149 } | 154 } |
| 150 | 155 |
| 151 void CCPrioritizedTextureManager::acquireBackingTextureIfNeeded(CCPrioritizedTex
ture* texture, CCResourceProvider* resourceProvider) | 156 void CCPrioritizedTextureManager::acquireBackingTextureIfNeeded(CCPrioritizedTex
ture* texture, CCResourceProvider* resourceProvider) |
| 152 { | 157 { |
| 158 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); |
| 153 ASSERT(!texture->isSelfManaged()); | 159 ASSERT(!texture->isSelfManaged()); |
| 154 ASSERT(texture->isAbovePriorityCutoff()); | 160 ASSERT(texture->isAbovePriorityCutoff()); |
| 155 if (texture->backing() || !texture->isAbovePriorityCutoff()) | 161 if (texture->backing() || !texture->isAbovePriorityCutoff()) |
| 156 return; | 162 return; |
| 157 | 163 |
| 158 // Find a backing below, by either recycling or allocating. | 164 // Find a backing below, by either recycling or allocating. |
| 159 CCPrioritizedTexture::Backing* backing = 0; | 165 CCPrioritizedTexture::Backing* backing = 0; |
| 160 | 166 |
| 161 // First try to recycle | 167 // First try to recycle |
| 162 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { | 168 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 177 // Move the used backing texture to the end of the eviction list. | 183 // Move the used backing texture to the end of the eviction list. |
| 178 if (backing->owner()) | 184 if (backing->owner()) |
| 179 backing->owner()->unlink(); | 185 backing->owner()->unlink(); |
| 180 texture->link(backing); | 186 texture->link(backing); |
| 181 m_backings.remove(backing); | 187 m_backings.remove(backing); |
| 182 m_backings.add(backing); | 188 m_backings.add(backing); |
| 183 } | 189 } |
| 184 | 190 |
| 185 void CCPrioritizedTextureManager::reduceMemory(size_t limitBytes, CCResourceProv
ider* resourceProvider) | 191 void CCPrioritizedTextureManager::reduceMemory(size_t limitBytes, CCResourceProv
ider* resourceProvider) |
| 186 { | 192 { |
| 193 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); |
| 187 if (memoryUseBytes() <= limitBytes) | 194 if (memoryUseBytes() <= limitBytes) |
| 188 return; | 195 return; |
| 189 // Destroy backings until we are below the limit, | 196 // Destroy backings until we are below the limit, |
| 190 // or until all backings remaining are above the cutoff. | 197 // or until all backings remaining are above the cutoff. |
| 191 while (memoryUseBytes() > limitBytes && m_backings.size() > 0) { | 198 while (memoryUseBytes() > limitBytes && m_backings.size() > 0) { |
| 192 BackingSet::iterator it = m_backings.begin(); | 199 BackingSet::iterator it = m_backings.begin(); |
| 193 if ((*it)->owner() && (*it)->owner()->isAbovePriorityCutoff()) | 200 if ((*it)->owner() && (*it)->owner()->isAbovePriorityCutoff()) |
| 194 break; | 201 break; |
| 195 destroyBacking((*it), resourceProvider); | 202 destroyBacking((*it), resourceProvider); |
| 196 } | 203 } |
| 197 } | 204 } |
| 198 | 205 |
| 199 void CCPrioritizedTextureManager::reduceMemory(CCResourceProvider* resourceProvi
der) | 206 void CCPrioritizedTextureManager::reduceMemory(CCResourceProvider* resourceProvi
der) |
| 200 { | 207 { |
| 208 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); |
| 201 reduceMemory(m_memoryAvailableBytes, resourceProvider); | 209 reduceMemory(m_memoryAvailableBytes, resourceProvider); |
| 202 ASSERT(memoryUseBytes() <= maxMemoryLimitBytes()); | 210 ASSERT(memoryUseBytes() <= maxMemoryLimitBytes()); |
| 203 | 211 |
| 204 // We currently collect backings from deleted textures for later recycling. | 212 // We currently collect backings from deleted textures for later recycling. |
| 205 // However, if we do that forever we will always use the max limit even if | 213 // However, if we do that forever we will always use the max limit even if |
| 206 // we really need very little memory. This should probably be solved by redu
cing the | 214 // we really need very little memory. This should probably be solved by redu
cing the |
| 207 // limit externally, but until then this just does some "clean up" of unused | 215 // limit externally, but until then this just does some "clean up" of unused |
| 208 // backing textures (any more than 10%). | 216 // backing textures (any more than 10%). |
| 209 size_t wastedMemory = 0; | 217 size_t wastedMemory = 0; |
| 210 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { | 218 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 232 void CCPrioritizedTextureManager::allBackingTexturesWereDeleted() | 240 void CCPrioritizedTextureManager::allBackingTexturesWereDeleted() |
| 233 { | 241 { |
| 234 // Same as clearAllMemory, except all our textures were already | 242 // Same as clearAllMemory, except all our textures were already |
| 235 // deleted externally, so we don't delete them. Passing no | 243 // deleted externally, so we don't delete them. Passing no |
| 236 // resourceProvider results in leaking the (now invalid) texture ids. | 244 // resourceProvider results in leaking the (now invalid) texture ids. |
| 237 clearAllMemory(0); | 245 clearAllMemory(0); |
| 238 } | 246 } |
| 239 | 247 |
| 240 void CCPrioritizedTextureManager::registerTexture(CCPrioritizedTexture* texture) | 248 void CCPrioritizedTextureManager::registerTexture(CCPrioritizedTexture* texture) |
| 241 { | 249 { |
| 250 ASSERT(CCProxy::isMainThread()); |
| 242 ASSERT(texture); | 251 ASSERT(texture); |
| 243 ASSERT(!texture->textureManager()); | 252 ASSERT(!texture->textureManager()); |
| 244 ASSERT(!texture->backing()); | 253 ASSERT(!texture->backing()); |
| 245 ASSERT(m_textures.find(texture) == m_textures.end()); | 254 ASSERT(m_textures.find(texture) == m_textures.end()); |
| 246 | 255 |
| 247 texture->setManagerInternal(this); | 256 texture->setManagerInternal(this); |
| 248 m_textures.add(texture); | 257 m_textures.add(texture); |
| 249 | 258 |
| 250 } | 259 } |
| 251 | 260 |
| 252 void CCPrioritizedTextureManager::unregisterTexture(CCPrioritizedTexture* textur
e) | 261 void CCPrioritizedTextureManager::unregisterTexture(CCPrioritizedTexture* textur
e) |
| 253 { | 262 { |
| 263 ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMai
nThreadBlocked())); |
| 254 ASSERT(texture); | 264 ASSERT(texture); |
| 255 ASSERT(m_textures.find(texture) != m_textures.end()); | 265 ASSERT(m_textures.find(texture) != m_textures.end()); |
| 256 | 266 |
| 257 returnBackingTexture(texture); | 267 returnBackingTexture(texture); |
| 258 texture->setManagerInternal(0); | 268 texture->setManagerInternal(0); |
| 259 m_textures.remove(texture); | 269 m_textures.remove(texture); |
| 260 texture->setAbovePriorityCutoff(false); | 270 texture->setAbovePriorityCutoff(false); |
| 261 } | 271 } |
| 262 | 272 |
| 263 | |
| 264 void CCPrioritizedTextureManager::returnBackingTexture(CCPrioritizedTexture* tex
ture) | 273 void CCPrioritizedTextureManager::returnBackingTexture(CCPrioritizedTexture* tex
ture) |
| 265 { | 274 { |
| 275 ASSERT(CCProxy::isMainThread() || (CCProxy::isImplThread() && CCProxy::isMai
nThreadBlocked())); |
| 266 if (texture->backing()) { | 276 if (texture->backing()) { |
| 267 // Move the backing texture to the front for eviction/recycling and unli
nk it. | 277 // Move the backing texture to the front for eviction/recycling and unli
nk it. |
| 268 m_backings.remove(texture->backing()); | 278 m_backings.remove(texture->backing()); |
| 269 m_backings.insertBefore(m_backings.begin(), texture->backing()); | 279 m_backings.insertBefore(m_backings.begin(), texture->backing()); |
| 270 texture->unlink(); | 280 texture->unlink(); |
| 271 } | 281 } |
| 272 } | 282 } |
| 273 | 283 |
| 274 CCPrioritizedTexture::Backing* CCPrioritizedTextureManager::createBacking(IntSiz
e size, GC3Denum format, CCResourceProvider* resourceProvider) | 284 CCPrioritizedTexture::Backing* CCPrioritizedTextureManager::createBacking(IntSiz
e size, GC3Denum format, CCResourceProvider* resourceProvider) |
| 275 { | 285 { |
| 286 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); |
| 276 ASSERT(resourceProvider); | 287 ASSERT(resourceProvider); |
| 277 | |
| 278 CCResourceProvider::ResourceId resourceId = resourceProvider->createResource
(m_pool, size, format, CCResourceProvider::TextureUsageAny); | 288 CCResourceProvider::ResourceId resourceId = resourceProvider->createResource
(m_pool, size, format, CCResourceProvider::TextureUsageAny); |
| 279 CCPrioritizedTexture::Backing* backing = new CCPrioritizedTexture::Backing(r
esourceId, size, format); | 289 CCPrioritizedTexture::Backing* backing = new CCPrioritizedTexture::Backing(r
esourceId, size, format); |
| 280 m_memoryUseBytes += backing->bytes(); | 290 m_memoryUseBytes += backing->bytes(); |
| 281 // Put backing texture at the front for eviction, since it isn't in use yet. | 291 // Put backing texture at the front for eviction, since it isn't in use yet. |
| 282 m_backings.insertBefore(m_backings.begin(), backing); | 292 m_backings.insertBefore(m_backings.begin(), backing); |
| 283 return backing; | 293 return backing; |
| 284 } | 294 } |
| 285 | 295 |
| 286 void CCPrioritizedTextureManager::destroyBacking(CCPrioritizedTexture::Backing*
backing, CCResourceProvider* resourceProvider) | 296 void CCPrioritizedTextureManager::destroyBacking(CCPrioritizedTexture::Backing*
backing, CCResourceProvider* resourceProvider) |
| 287 { | 297 { |
| 288 ASSERT(backing); | 298 ASSERT(backing); |
| 289 ASSERT(!backing->owner() || !backing->owner()->isAbovePriorityCutoff()); | 299 ASSERT(!backing->owner() || !backing->owner()->isAbovePriorityCutoff()); |
| 290 ASSERT(!backing->owner() || !backing->owner()->isSelfManaged()); | 300 ASSERT(!backing->owner() || !backing->owner()->isSelfManaged()); |
| 291 ASSERT(m_backings.find(backing) != m_backings.end()); | 301 ASSERT(m_backings.find(backing) != m_backings.end()); |
| 292 | 302 |
| 293 if (resourceProvider) | 303 if (resourceProvider) |
| 294 resourceProvider->deleteResource(backing->id()); | 304 resourceProvider->deleteResource(backing->id()); |
| 295 if (backing->owner()) | 305 if (backing->owner()) |
| 296 backing->owner()->unlink(); | 306 backing->owner()->unlink(); |
| 297 m_memoryUseBytes -= backing->bytes(); | 307 m_memoryUseBytes -= backing->bytes(); |
| 298 m_backings.remove(backing); | 308 m_backings.remove(backing); |
| 299 | 309 |
| 300 delete backing; | 310 delete backing; |
| 301 } | 311 } |
| 302 | 312 |
| 303 | 313 |
| 304 #if !ASSERT_DISABLED | 314 #if !ASSERT_DISABLED |
| 305 void CCPrioritizedTextureManager::assertInvariants() | 315 void CCPrioritizedTextureManager::assertInvariants() |
| 306 { | 316 { |
| 317 ASSERT(CCProxy::isMainThread()); |
| 318 |
| 307 // If we hit any of these asserts, there is a bug in this class. To see | 319 // If we hit any of these asserts, there is a bug in this class. To see |
| 308 // where the bug is, call this function at the beginning and end of | 320 // where the bug is, call this function at the beginning and end of |
| 309 // every public function. | 321 // every public function. |
| 310 | 322 |
| 311 // Backings/textures must be doubly-linked and only to other backings/textur
es in this manager. | 323 // Backings/textures must be doubly-linked and only to other backings/textur
es in this manager. |
| 312 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { | 324 for (BackingSet::iterator it = m_backings.begin(); it != m_backings.end(); +
+it) { |
| 313 if ((*it)->owner()) { | 325 if ((*it)->owner()) { |
| 314 ASSERT(m_textures.find((*it)->owner()) != m_textures.end()); | 326 ASSERT(m_textures.find((*it)->owner()) != m_textures.end()); |
| 315 ASSERT((*it)->owner()->backing() == (*it)); | 327 ASSERT((*it)->owner()->backing() == (*it)); |
| 316 } | 328 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 330 if ((*it)->owner() && (*it)->owner()->isAbovePriorityCutoff()) | 342 if ((*it)->owner() && (*it)->owner()->isAbovePriorityCutoff()) |
| 331 reachedProtected = true; | 343 reachedProtected = true; |
| 332 if (reachedProtected) | 344 if (reachedProtected) |
| 333 ASSERT((*it)->owner() && (*it)->owner()->isAbovePriorityCutoff()); | 345 ASSERT((*it)->owner() && (*it)->owner()->isAbovePriorityCutoff()); |
| 334 } | 346 } |
| 335 } | 347 } |
| 336 #endif | 348 #endif |
| 337 | 349 |
| 338 | 350 |
| 339 } // namespace WebCore | 351 } // namespace WebCore |
| OLD | NEW |