Chromium Code Reviews| 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 "cc/prioritized_resource_manager.h" | 5 #include "cc/prioritized_resource_manager.h" |
| 6 | 6 |
| 7 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "cc/prioritized_resource.h" | 9 #include "cc/prioritized_resource.h" |
| 10 #include "cc/priority_calculator.h" | 10 #include "cc/priority_calculator.h" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 , m_memoryVisibleLastPushedBytes(0) | 29 , m_memoryVisibleLastPushedBytes(0) |
| 30 , m_memoryVisibleAndNearbyLastPushedBytes(0) | 30 , m_memoryVisibleAndNearbyLastPushedBytes(0) |
| 31 { | 31 { |
| 32 } | 32 } |
| 33 | 33 |
| 34 PrioritizedResourceManager::~PrioritizedResourceManager() | 34 PrioritizedResourceManager::~PrioritizedResourceManager() |
| 35 { | 35 { |
| 36 while (m_textures.size() > 0) | 36 while (m_textures.size() > 0) |
| 37 unregisterTexture(*m_textures.begin()); | 37 unregisterTexture(*m_textures.begin()); |
| 38 | 38 |
| 39 deleteAllEvictedBackings(); | 39 unlinkAndClearEvictedBackings(); |
| 40 DCHECK(m_evictedBackings.empty()); | 40 DCHECK(m_evictedBackings.empty()); |
| 41 | 41 |
| 42 // Each remaining backing is a leaked opengl texture. There should be none. | 42 // Each remaining backing is a leaked opengl texture. There should be none. |
| 43 DCHECK(m_backings.empty()); | 43 DCHECK(m_backings.empty()); |
| 44 } | 44 } |
| 45 | 45 |
| 46 size_t PrioritizedResourceManager::memoryVisibleBytes() const | 46 size_t PrioritizedResourceManager::memoryVisibleBytes() const |
| 47 { | 47 { |
| 48 DCHECK(m_proxy->isImplThread()); | 48 DCHECK(m_proxy->isImplThread()); |
| 49 return m_memoryVisibleLastPushedBytes; | 49 return m_memoryVisibleLastPushedBytes; |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 299 break; | 299 break; |
| 300 wastedMemory += (*it)->bytes(); | 300 wastedMemory += (*it)->bytes(); |
| 301 } | 301 } |
| 302 size_t tenPercentOfMemory = m_memoryAvailableBytes / 10; | 302 size_t tenPercentOfMemory = m_memoryAvailableBytes / 10; |
| 303 if (wastedMemory > tenPercentOfMemory) | 303 if (wastedMemory > tenPercentOfMemory) |
| 304 evictBackingsToReduceMemory(memoryUseBytes() - (wastedMemory - tenPercen tOfMemory), | 304 evictBackingsToReduceMemory(memoryUseBytes() - (wastedMemory - tenPercen tOfMemory), |
| 305 PriorityCalculator::allowEverythingCutoff(), | 305 PriorityCalculator::allowEverythingCutoff(), |
| 306 EvictOnlyRecyclable, | 306 EvictOnlyRecyclable, |
| 307 UnlinkBackings, | 307 UnlinkBackings, |
| 308 resourceProvider); | 308 resourceProvider); |
| 309 | |
| 310 // Unlink all evicted backings | |
| 311 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi ctedBackings.end(); ++it) { | |
| 312 if ((*it)->owner()) | |
| 313 (*it)->owner()->unlink(); | |
| 314 } | |
| 315 | |
| 316 // And clear the list of evicted backings | |
| 317 deleteAllEvictedBackings(); | |
| 318 } | 309 } |
| 319 | 310 |
| 320 void PrioritizedResourceManager::clearAllMemory(ResourceProvider* resourceProvid er) | 311 void PrioritizedResourceManager::clearAllMemory(ResourceProvider* resourceProvid er) |
| 321 { | 312 { |
| 322 DCHECK(m_proxy->isImplThread() && m_proxy->isMainThreadBlocked()); | 313 DCHECK(m_proxy->isImplThread() && m_proxy->isMainThreadBlocked()); |
| 323 DCHECK(resourceProvider); | 314 DCHECK(resourceProvider); |
| 324 evictBackingsToReduceMemory(0, | 315 evictBackingsToReduceMemory(0, |
| 325 PriorityCalculator::allowEverythingCutoff(), | 316 PriorityCalculator::allowEverythingCutoff(), |
| 326 EvictAnything, | 317 EvictAnything, |
| 327 DoNotUnlinkBackings, | 318 DoNotUnlinkBackings, |
| 328 resourceProvider); | 319 resourceProvider); |
| 329 } | 320 } |
| 330 | 321 |
| 331 bool PrioritizedResourceManager::reduceMemoryOnImplThread(size_t limitBytes, int priorityCutoff, ResourceProvider* resourceProvider) | 322 bool PrioritizedResourceManager::reduceMemoryOnImplThread(size_t limitBytes, int priorityCutoff, ResourceProvider* resourceProvider) |
| 332 { | 323 { |
| 333 DCHECK(m_proxy->isImplThread()); | 324 DCHECK(m_proxy->isImplThread()); |
| 334 DCHECK(resourceProvider); | 325 DCHECK(resourceProvider); |
| 335 // If we are in the process of uploading a new frame then the backings at th e very end of | 326 // If we are in the process of uploading a new frame then the backings at th e very end of |
| 336 // the list are not sorted by priority. Sort them before doing the eviction. | 327 // the list are not sorted by priority. Sort them before doing the eviction. |
| 337 if (m_backingsTailNotSorted) | 328 if (m_backingsTailNotSorted) |
| 338 sortBackings(); | 329 sortBackings(); |
| 339 return evictBackingsToReduceMemory(limitBytes, | 330 return evictBackingsToReduceMemory(limitBytes, |
| 340 priorityCutoff, | 331 priorityCutoff, |
| 341 EvictAnything, | 332 EvictAnything, |
| 342 DoNotUnlinkBackings, | 333 DoNotUnlinkBackings, |
| 343 resourceProvider); | 334 resourceProvider); |
| 344 } | 335 } |
| 345 | 336 |
| 346 void PrioritizedResourceManager::getEvictedBackings(BackingList& evictedBackings ) | 337 void PrioritizedResourceManager::unlinkAndClearEvictedBackings() |
| 347 { | |
| 348 DCHECK(m_proxy->isImplThread()); | |
| 349 evictedBackings.clear(); | |
| 350 evictedBackings.insert(evictedBackings.begin(), m_evictedBackings.begin(), m _evictedBackings.end()); | |
| 351 for (BackingList::const_iterator it = evictedBackings.begin(); it != evicted Backings.end(); ++it) { | |
| 352 PrioritizedResource::Backing* backing = (*it); | |
| 353 CHECK(!backing->m_inMainThreadEvictedList); | |
| 354 backing->m_inMainThreadEvictedList = true; | |
| 355 } | |
| 356 } | |
| 357 | |
| 358 void PrioritizedResourceManager::unlinkEvictedBackings(const BackingList& evicte dBackings) | |
| 359 { | 338 { |
| 360 DCHECK(m_proxy->isMainThread()); | 339 DCHECK(m_proxy->isMainThread()); |
| 361 for (BackingList::const_iterator it = evictedBackings.begin(); it != evicted Backings.end(); ++it) { | 340 base::AutoLock scoped_lock(m_evictedBackingsLock); |
| 362 PrioritizedResource::Backing* backing = (*it); | |
| 363 CHECK(backing->m_inMainThreadEvictedList); | |
| 364 backing->m_inMainThreadEvictedList = false; | |
| 365 if (backing->owner()) { | |
| 366 CHECK(backing->owner()->backing()); | |
| 367 CHECK(backing->owner()->backing() == backing); | |
| 368 backing->owner()->unlink(); | |
| 369 } | |
| 370 } | |
| 371 } | |
| 372 | |
| 373 void PrioritizedResourceManager::deleteAllEvictedBackings() | |
| 374 { | |
| 375 DCHECK(m_proxy->isMainThread() || (m_proxy->isImplThread() && m_proxy->isMai nThreadBlocked())); | |
| 376 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi ctedBackings.end(); ++it) { | 341 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi ctedBackings.end(); ++it) { |
| 377 PrioritizedResource::Backing* backing = (*it); | 342 PrioritizedResource::Backing* backing = (*it); |
| 378 CHECK(!backing->owner()); | 343 if (backing->owner()) |
| 344 backing->owner()->unlink(); | |
| 379 delete backing; | 345 delete backing; |
| 380 } | 346 } |
| 381 m_evictedBackings.clear(); | 347 m_evictedBackings.clear(); |
| 382 } | 348 } |
| 383 | 349 |
| 384 bool PrioritizedResourceManager::linkedEvictedBackingsExist() const | 350 bool PrioritizedResourceManager::linkedEvictedBackingsExist() |
|
piman
2012/11/29 22:34:11
nit: you can keep this const by making m_evictedBa
ccameron
2012/11/30 00:02:17
Good idea. Done.
| |
| 385 { | 351 { |
| 352 DCHECK(m_proxy->isImplThread() && m_proxy->isMainThreadBlocked()); | |
| 353 base::AutoLock scoped_lock(m_evictedBackingsLock); | |
| 386 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi ctedBackings.end(); ++it) { | 354 for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evi ctedBackings.end(); ++it) { |
| 387 if ((*it)->owner()) | 355 if ((*it)->owner()) |
| 388 return true; | 356 return true; |
| 389 } | 357 } |
| 390 return false; | 358 return false; |
| 391 } | 359 } |
| 392 | 360 |
| 393 void PrioritizedResourceManager::registerTexture(PrioritizedResource* texture) | 361 void PrioritizedResourceManager::registerTexture(PrioritizedResource* texture) |
| 394 { | 362 { |
| 395 DCHECK(m_proxy->isMainThread()); | 363 DCHECK(m_proxy->isMainThread()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 439 DCHECK(!m_backings.empty()); | 407 DCHECK(!m_backings.empty()); |
| 440 PrioritizedResource::Backing* backing = m_backings.front(); | 408 PrioritizedResource::Backing* backing = m_backings.front(); |
| 441 | 409 |
| 442 // Note that we create a backing and its resource at the same time, but we | 410 // Note that we create a backing and its resource at the same time, but we |
| 443 // delete the backing structure and its resource in two steps. This is becau se | 411 // delete the backing structure and its resource in two steps. This is becau se |
| 444 // we can delete the resource while the main thread is running, but we canno t | 412 // we can delete the resource while the main thread is running, but we canno t |
| 445 // unlink backings while the main thread is running. | 413 // unlink backings while the main thread is running. |
| 446 backing->deleteResource(resourceProvider); | 414 backing->deleteResource(resourceProvider); |
| 447 m_memoryUseBytes -= backing->bytes(); | 415 m_memoryUseBytes -= backing->bytes(); |
| 448 m_backings.pop_front(); | 416 m_backings.pop_front(); |
| 417 base::AutoLock scoped_lock(m_evictedBackingsLock); | |
| 449 m_evictedBackings.push_back(backing); | 418 m_evictedBackings.push_back(backing); |
| 450 } | 419 } |
| 451 | 420 |
| 452 void PrioritizedResourceManager::assertInvariants() | 421 void PrioritizedResourceManager::assertInvariants() |
| 453 { | 422 { |
| 454 #ifndef NDEBUG | 423 #ifndef NDEBUG |
| 455 DCHECK(m_proxy->isImplThread() && m_proxy->isMainThreadBlocked()); | 424 DCHECK(m_proxy->isImplThread() && m_proxy->isMainThreadBlocked()); |
| 456 | 425 |
| 457 // If we hit any of these asserts, there is a bug in this class. To see | 426 // If we hit any of these asserts, there is a bug in this class. To see |
| 458 // where the bug is, call this function at the beginning and end of | 427 // where the bug is, call this function at the beginning and end of |
| 459 // every public function. | 428 // every public function. |
| 460 | 429 |
| 461 // Backings/textures must be doubly-linked and only to other backings/textur es in this manager. | 430 // Backings/textures must be doubly-linked and only to other backings/textur es in this manager. |
| 462 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { | 431 for (BackingList::iterator it = m_backings.begin(); it != m_backings.end(); ++it) { |
| 463 if ((*it)->owner()) { | 432 if ((*it)->owner()) { |
| 464 DCHECK(ContainsKey(m_textures, (*it)->owner())); | 433 DCHECK(ContainsKey(m_textures, (*it)->owner())); |
| 465 DCHECK((*it)->owner()->backing() == (*it)); | 434 DCHECK((*it)->owner()->backing() == (*it)); |
| 466 } | 435 } |
| 467 } | 436 } |
| 468 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); + +it) { | 437 for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); + +it) { |
| 469 PrioritizedResource* texture = (*it); | 438 PrioritizedResource* texture = (*it); |
| 470 PrioritizedResource::Backing* backing = texture->backing(); | 439 PrioritizedResource::Backing* backing = texture->backing(); |
| 440 base::AutoLock scoped_lock(m_evictedBackingsLock); | |
| 471 if (backing) { | 441 if (backing) { |
| 472 if (backing->resourceHasBeenDeleted()) { | 442 if (backing->resourceHasBeenDeleted()) { |
| 473 DCHECK(std::find(m_backings.begin(), m_backings.end(), backing) == m_backings.end()); | 443 DCHECK(std::find(m_backings.begin(), m_backings.end(), backing) == m_backings.end()); |
| 474 DCHECK(std::find(m_evictedBackings.begin(), m_evictedBackings.en d(), backing) != m_evictedBackings.end()); | 444 DCHECK(std::find(m_evictedBackings.begin(), m_evictedBackings.en d(), backing) != m_evictedBackings.end()); |
| 475 } else { | 445 } else { |
| 476 DCHECK(std::find(m_backings.begin(), m_backings.end(), backing) != m_backings.end()); | 446 DCHECK(std::find(m_backings.begin(), m_backings.end(), backing) != m_backings.end()); |
| 477 DCHECK(std::find(m_evictedBackings.begin(), m_evictedBackings.en d(), backing) == m_evictedBackings.end()); | 447 DCHECK(std::find(m_evictedBackings.begin(), m_evictedBackings.en d(), backing) == m_evictedBackings.end()); |
| 478 } | 448 } |
| 479 DCHECK(backing->owner() == texture); | 449 DCHECK(backing->owner() == texture); |
| 480 } | 450 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 499 } | 469 } |
| 500 #endif | 470 #endif |
| 501 } | 471 } |
| 502 | 472 |
| 503 const Proxy* PrioritizedResourceManager::proxyForDebug() const | 473 const Proxy* PrioritizedResourceManager::proxyForDebug() const |
| 504 { | 474 { |
| 505 return m_proxy; | 475 return m_proxy; |
| 506 } | 476 } |
| 507 | 477 |
| 508 } // namespace cc | 478 } // namespace cc |
| OLD | NEW |