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/resources/tile_manager.h" | 5 #include "cc/resources/tile_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 task_runner_.get(), | 233 task_runner_.get(), |
234 base::Bind(&TileManager::CheckIfReadyToActivate, | 234 base::Bind(&TileManager::CheckIfReadyToActivate, |
235 base::Unretained(this))), | 235 base::Unretained(this))), |
236 ready_to_draw_check_notifier_( | 236 ready_to_draw_check_notifier_( |
237 task_runner_.get(), | 237 task_runner_.get(), |
238 base::Bind(&TileManager::CheckIfReadyToDraw, base::Unretained(this))), | 238 base::Bind(&TileManager::CheckIfReadyToDraw, base::Unretained(this))), |
239 more_tiles_need_prepare_check_notifier_( | 239 more_tiles_need_prepare_check_notifier_( |
240 task_runner_.get(), | 240 task_runner_.get(), |
241 base::Bind(&TileManager::CheckIfMoreTilesNeedToBePrepared, | 241 base::Bind(&TileManager::CheckIfMoreTilesNeedToBePrepared, |
242 base::Unretained(this))), | 242 base::Unretained(this))), |
243 eviction_priority_queue_is_up_to_date_(false), | |
244 did_notify_ready_to_activate_(false), | 243 did_notify_ready_to_activate_(false), |
245 did_notify_ready_to_draw_(false) { | 244 did_notify_ready_to_draw_(false) { |
246 tile_task_runner_->SetClient(this); | 245 tile_task_runner_->SetClient(this); |
247 } | 246 } |
248 | 247 |
249 TileManager::~TileManager() { | 248 TileManager::~TileManager() { |
250 // Reset global state and manage. This should cause | 249 // Reset global state and manage. This should cause |
251 // our memory usage to drop to zero. | 250 // our memory usage to drop to zero. |
252 global_state_ = GlobalStateThatImpactsTilePriority(); | 251 global_state_ = GlobalStateThatImpactsTilePriority(); |
253 | 252 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 AssignGpuMemoryToTiles(&raster_priority_queue, scheduled_raster_task_limit_, | 366 AssignGpuMemoryToTiles(&raster_priority_queue, scheduled_raster_task_limit_, |
368 &tiles_that_need_to_be_rasterized); | 367 &tiles_that_need_to_be_rasterized); |
369 | 368 |
370 // Schedule tile tasks. | 369 // Schedule tile tasks. |
371 ScheduleTasks(tiles_that_need_to_be_rasterized); | 370 ScheduleTasks(tiles_that_need_to_be_rasterized); |
372 | 371 |
373 did_notify_ready_to_activate_ = false; | 372 did_notify_ready_to_activate_ = false; |
374 did_notify_ready_to_draw_ = false; | 373 did_notify_ready_to_draw_ = false; |
375 } else { | 374 } else { |
376 if (global_state_.hard_memory_limit_in_bytes == 0) { | 375 if (global_state_.hard_memory_limit_in_bytes == 0) { |
377 // TODO(vmpstr): Add a function to unconditionally create an eviction | |
378 // queue and guard the rest of the calls sites with this flag, instead of | |
379 // clearing here and building, which is a bit awkward. | |
380 eviction_priority_queue_is_up_to_date_ = false; | |
381 resource_pool_->CheckBusyResources(false); | 376 resource_pool_->CheckBusyResources(false); |
382 MemoryUsage memory_limit(0, 0); | 377 MemoryUsage memory_limit(0, 0); |
383 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), | 378 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), |
384 resource_pool_->acquired_resource_count()); | 379 resource_pool_->acquired_resource_count()); |
385 FreeTileResourcesUntilUsageIsWithinLimit(memory_limit, &memory_usage); | 380 FreeTileResourcesUntilUsageIsWithinLimit(memory_limit, &memory_usage); |
381 eviction_priority_queue_.reset(); | |
386 } | 382 } |
387 | 383 |
388 did_notify_ready_to_activate_ = false; | 384 did_notify_ready_to_activate_ = false; |
389 did_notify_ready_to_draw_ = false; | 385 did_notify_ready_to_draw_ = false; |
390 ready_to_activate_notifier_.Schedule(); | 386 ready_to_activate_notifier_.Schedule(); |
391 ready_to_draw_notifier_.Schedule(); | 387 ready_to_draw_notifier_.Schedule(); |
392 } | 388 } |
393 | 389 |
394 TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD, | 390 TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD, |
395 "state", BasicStateAsValue()); | 391 "state", BasicStateAsValue()); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 | 482 |
487 void TileManager::BasicStateAsValueInto(base::debug::TracedValue* state) const { | 483 void TileManager::BasicStateAsValueInto(base::debug::TracedValue* state) const { |
488 state->SetInteger("tile_count", tiles_.size()); | 484 state->SetInteger("tile_count", tiles_.size()); |
489 state->SetBoolean("did_oom_on_last_assign", did_oom_on_last_assign_); | 485 state->SetBoolean("did_oom_on_last_assign", did_oom_on_last_assign_); |
490 state->BeginDictionary("global_state"); | 486 state->BeginDictionary("global_state"); |
491 global_state_.AsValueInto(state); | 487 global_state_.AsValueInto(state); |
492 state->EndDictionary(); | 488 state->EndDictionary(); |
493 } | 489 } |
494 | 490 |
495 void TileManager::RebuildEvictionQueueIfNeeded() { | 491 void TileManager::RebuildEvictionQueueIfNeeded() { |
496 TRACE_EVENT1("cc", | 492 TRACE_EVENT0("cc", "TileManager::RebuildEvictionQueueIfNeeded"); |
497 "TileManager::RebuildEvictionQueueIfNeeded", | 493 if (eviction_priority_queue_) |
498 "eviction_priority_queue_is_up_to_date", | |
499 eviction_priority_queue_is_up_to_date_); | |
500 if (eviction_priority_queue_is_up_to_date_) | |
501 return; | 494 return; |
502 | 495 |
503 eviction_priority_queue_.Reset(); | 496 eviction_priority_queue_ = |
504 client_->BuildEvictionQueue(&eviction_priority_queue_, | 497 client_->BuildEvictionQueue(global_state_.tree_priority); |
505 global_state_.tree_priority); | |
506 eviction_priority_queue_is_up_to_date_ = true; | |
507 } | 498 } |
508 | 499 |
509 bool TileManager::FreeTileResourcesUntilUsageIsWithinLimit( | 500 bool TileManager::FreeTileResourcesUntilUsageIsWithinLimit( |
510 const MemoryUsage& limit, | 501 const MemoryUsage& limit, |
511 MemoryUsage* usage) { | 502 MemoryUsage* usage) { |
512 while (usage->Exceeds(limit)) { | 503 while (usage->Exceeds(limit)) { |
513 RebuildEvictionQueueIfNeeded(); | 504 RebuildEvictionQueueIfNeeded(); |
514 if (eviction_priority_queue_.IsEmpty()) | 505 if (eviction_priority_queue_->IsEmpty()) |
515 return false; | 506 return false; |
516 | 507 |
517 Tile* tile = eviction_priority_queue_.Top(); | 508 Tile* tile = eviction_priority_queue_->Top(); |
518 *usage -= MemoryUsage::FromTile(tile); | 509 *usage -= MemoryUsage::FromTile(tile); |
519 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); | 510 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); |
520 eviction_priority_queue_.Pop(); | 511 eviction_priority_queue_->Pop(); |
521 } | 512 } |
522 return true; | 513 return true; |
523 } | 514 } |
524 | 515 |
525 bool TileManager::FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( | 516 bool TileManager::FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( |
526 const MemoryUsage& limit, | 517 const MemoryUsage& limit, |
527 const TilePriority& other_priority, | 518 const TilePriority& other_priority, |
528 MemoryUsage* usage) { | 519 MemoryUsage* usage) { |
529 while (usage->Exceeds(limit)) { | 520 while (usage->Exceeds(limit)) { |
530 RebuildEvictionQueueIfNeeded(); | 521 RebuildEvictionQueueIfNeeded(); |
531 if (eviction_priority_queue_.IsEmpty()) | 522 if (eviction_priority_queue_->IsEmpty()) |
532 return false; | 523 return false; |
533 | 524 |
534 Tile* tile = eviction_priority_queue_.Top(); | 525 Tile* tile = eviction_priority_queue_->Top(); |
535 if (!other_priority.IsHigherPriorityThan(tile->combined_priority())) | 526 if (!other_priority.IsHigherPriorityThan(tile->combined_priority())) |
536 return false; | 527 return false; |
537 | 528 |
538 *usage -= MemoryUsage::FromTile(tile); | 529 *usage -= MemoryUsage::FromTile(tile); |
539 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); | 530 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); |
540 eviction_priority_queue_.Pop(); | 531 eviction_priority_queue_->Pop(); |
541 } | 532 } |
542 return true; | 533 return true; |
543 } | 534 } |
544 | 535 |
545 bool TileManager::TilePriorityViolatesMemoryPolicy( | 536 bool TileManager::TilePriorityViolatesMemoryPolicy( |
546 const TilePriority& priority) { | 537 const TilePriority& priority) { |
547 switch (global_state_.memory_limit_policy) { | 538 switch (global_state_.memory_limit_policy) { |
548 case ALLOW_NOTHING: | 539 case ALLOW_NOTHING: |
549 return true; | 540 return true; |
550 case ALLOW_ABSOLUTE_MINIMUM: | 541 case ALLOW_ABSOLUTE_MINIMUM: |
(...skipping 26 matching lines...) Expand all Loading... | |
577 all_tiles_that_need_to_be_rasterized_are_scheduled_ = true; | 568 all_tiles_that_need_to_be_rasterized_are_scheduled_ = true; |
578 bool had_enough_memory_to_schedule_tiles_needed_now = true; | 569 bool had_enough_memory_to_schedule_tiles_needed_now = true; |
579 | 570 |
580 MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes, | 571 MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes, |
581 global_state_.num_resources_limit); | 572 global_state_.num_resources_limit); |
582 MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes, | 573 MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes, |
583 global_state_.num_resources_limit); | 574 global_state_.num_resources_limit); |
584 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), | 575 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), |
585 resource_pool_->acquired_resource_count()); | 576 resource_pool_->acquired_resource_count()); |
586 | 577 |
587 eviction_priority_queue_is_up_to_date_ = false; | 578 DCHECK(!eviction_priority_queue_); |
588 for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) { | 579 for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) { |
589 Tile* tile = raster_priority_queue->Top(); | 580 Tile* tile = raster_priority_queue->Top(); |
590 TilePriority priority = tile->combined_priority(); | 581 TilePriority priority = tile->combined_priority(); |
591 | 582 |
592 if (TilePriorityViolatesMemoryPolicy(priority)) { | 583 if (TilePriorityViolatesMemoryPolicy(priority)) { |
593 TRACE_EVENT_INSTANT0( | 584 TRACE_EVENT_INSTANT0( |
594 "cc", "TileManager::AssignGpuMemory tile violates memory policy", | 585 "cc", "TileManager::AssignGpuMemory tile violates memory policy", |
595 TRACE_EVENT_SCOPE_THREAD); | 586 TRACE_EVENT_SCOPE_THREAD); |
596 break; | 587 break; |
597 } | 588 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
642 | 633 |
643 memory_usage += memory_required_by_tile_to_be_scheduled; | 634 memory_usage += memory_required_by_tile_to_be_scheduled; |
644 tiles_that_need_to_be_rasterized->push_back(tile); | 635 tiles_that_need_to_be_rasterized->push_back(tile); |
645 } | 636 } |
646 | 637 |
647 // Note that we should try and further reduce memory in case the above loop | 638 // Note that we should try and further reduce memory in case the above loop |
648 // didn't reduce memory. This ensures that we always release as many resources | 639 // didn't reduce memory. This ensures that we always release as many resources |
649 // as possible to stay within the memory limit. | 640 // as possible to stay within the memory limit. |
650 FreeTileResourcesUntilUsageIsWithinLimit(hard_memory_limit, &memory_usage); | 641 FreeTileResourcesUntilUsageIsWithinLimit(hard_memory_limit, &memory_usage); |
651 | 642 |
643 eviction_priority_queue_.reset(); | |
danakj
2015/01/22 23:12:23
Can you explain this? There's a DCHECK above that
vmpstr
2015/01/22 23:45:03
Since creating an eviction queue might be expensiv
| |
644 | |
652 UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget", | 645 UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget", |
653 !had_enough_memory_to_schedule_tiles_needed_now); | 646 !had_enough_memory_to_schedule_tiles_needed_now); |
654 did_oom_on_last_assign_ = !had_enough_memory_to_schedule_tiles_needed_now; | 647 did_oom_on_last_assign_ = !had_enough_memory_to_schedule_tiles_needed_now; |
655 | 648 |
656 memory_stats_from_last_assign_.total_budget_in_bytes = | 649 memory_stats_from_last_assign_.total_budget_in_bytes = |
657 global_state_.hard_memory_limit_in_bytes; | 650 global_state_.hard_memory_limit_in_bytes; |
658 memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes(); | 651 memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes(); |
659 memory_stats_from_last_assign_.had_enough_memory = | 652 memory_stats_from_last_assign_.had_enough_memory = |
660 had_enough_memory_to_schedule_tiles_needed_now; | 653 had_enough_memory_to_schedule_tiles_needed_now; |
661 | 654 |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1043 result -= other; | 1036 result -= other; |
1044 return result; | 1037 return result; |
1045 } | 1038 } |
1046 | 1039 |
1047 bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const { | 1040 bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const { |
1048 return memory_bytes_ > limit.memory_bytes_ || | 1041 return memory_bytes_ > limit.memory_bytes_ || |
1049 resource_count_ > limit.resource_count_; | 1042 resource_count_ > limit.resource_count_; |
1050 } | 1043 } |
1051 | 1044 |
1052 } // namespace cc | 1045 } // namespace cc |
OLD | NEW |