| 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 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 | 322 |
| 323 // When OOM, keep re-assigning memory until we reach a steady state | 323 // When OOM, keep re-assigning memory until we reach a steady state |
| 324 // where top-priority tiles are initialized. | 324 // where top-priority tiles are initialized. |
| 325 if (all_tiles_that_need_to_be_rasterized_are_scheduled_ && | 325 if (all_tiles_that_need_to_be_rasterized_are_scheduled_ && |
| 326 !memory_usage_above_limit) | 326 !memory_usage_above_limit) |
| 327 return; | 327 return; |
| 328 | 328 |
| 329 rasterizer_->CheckForCompletedTasks(); | 329 rasterizer_->CheckForCompletedTasks(); |
| 330 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 330 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| 331 | 331 |
| 332 client_->BuildRasterQueue(&raster_priority_queue_, |
| 333 global_state_.tree_priority); |
| 332 TileVector tiles_that_need_to_be_rasterized; | 334 TileVector tiles_that_need_to_be_rasterized; |
| 333 AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized); | 335 AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized, |
| 336 scheduled_raster_task_limit_); |
| 337 raster_priority_queue_.Reset(); |
| 334 | 338 |
| 335 // |tiles_that_need_to_be_rasterized| will be empty when we reach a | 339 // |tiles_that_need_to_be_rasterized| will be empty when we reach a |
| 336 // steady memory state. Keep scheduling tasks until we reach this state. | 340 // steady memory state. Keep scheduling tasks until we reach this state. |
| 337 if (!tiles_that_need_to_be_rasterized.empty()) { | 341 if (!tiles_that_need_to_be_rasterized.empty()) { |
| 338 ScheduleTasks(tiles_that_need_to_be_rasterized); | 342 ScheduleTasks(tiles_that_need_to_be_rasterized); |
| 339 return; | 343 return; |
| 340 } | 344 } |
| 341 | 345 |
| 342 FreeResourcesForReleasedTiles(); | 346 FreeResourcesForReleasedTiles(); |
| 343 | 347 |
| 344 resource_pool_->ReduceResourceUsage(); | 348 resource_pool_->ReduceResourceUsage(); |
| 345 | 349 |
| 346 // We don't reserve memory for required-for-activation tiles during | 350 // We don't reserve memory for required-for-activation tiles during |
| 347 // accelerated gestures, so we just postpone activation when we don't | 351 // accelerated gestures, so we just postpone activation when we don't |
| 348 // have these tiles, and activate after the accelerated gesture. | 352 // have these tiles, and activate after the accelerated gesture. |
| 349 // Likewise if we don't allow any tiles (as is the case when we're | 353 // Likewise if we don't allow any tiles (as is the case when we're |
| 350 // invisible), if we have tiles that aren't ready, then we shouldn't | 354 // invisible), if we have tiles that aren't ready, then we shouldn't |
| 351 // activate as activation can cause checkerboards. | 355 // activate as activation can cause checkerboards. |
| 352 bool allow_rasterize_on_demand = | 356 bool allow_rasterize_on_demand = |
| 353 global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY && | 357 global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY && |
| 354 global_state_.memory_limit_policy != ALLOW_NOTHING; | 358 global_state_.memory_limit_policy != ALLOW_NOTHING; |
| 355 | 359 |
| 356 // Use on-demand raster for any required-for-activation tiles that have | 360 // Use on-demand raster for any required-for-activation tiles that have |
| 357 // not | 361 // not been been assigned memory after reaching a steady memory |
| 358 // been been assigned memory after reaching a steady memory state. This | 362 // state. This ensures that we activate even when OOM. Note that we have |
| 359 // ensures that we activate even when OOM. Note that we have to rebuilt | 363 // to rebuilt the queue in case the last AssignGpuMemoryToTiles evicted |
| 360 // the | 364 // some tiles that would otherwise not be picked up by the old raster |
| 361 // queue in case the last AssignGpuMemoryToTiles evicted some tiles that | 365 // queue. |
| 362 // would otherwise not be picked up by the old raster queue. | |
| 363 client_->BuildRasterQueue(&raster_priority_queue_, | 366 client_->BuildRasterQueue(&raster_priority_queue_, |
| 364 global_state_.tree_priority); | 367 global_state_.tree_priority); |
| 365 bool ready_to_activate = true; | 368 bool ready_to_activate = true; |
| 366 while (!raster_priority_queue_.IsEmpty()) { | 369 while (!raster_priority_queue_.IsEmpty()) { |
| 367 Tile* tile = raster_priority_queue_.Top(); | 370 Tile* tile = raster_priority_queue_.Top(); |
| 368 ManagedTileState& mts = tile->managed_state(); | 371 ManagedTileState& mts = tile->managed_state(); |
| 369 | 372 |
| 370 if (tile->required_for_activation() && !mts.draw_info.IsReadyToDraw()) { | 373 if (tile->required_for_activation() && !mts.draw_info.IsReadyToDraw()) { |
| 371 // If we can't raster on demand, give up early (and don't activate). | 374 // If we can't raster on demand, give up early (and don't activate). |
| 372 if (!allow_rasterize_on_demand) { | 375 if (!allow_rasterize_on_demand) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 391 ready_to_activate_check_notifier_.Schedule(); | 394 ready_to_activate_check_notifier_.Schedule(); |
| 392 return; | 395 return; |
| 393 case REQUIRED_FOR_DRAW: | 396 case REQUIRED_FOR_DRAW: |
| 394 ready_to_draw_check_notifier_.Schedule(); | 397 ready_to_draw_check_notifier_.Schedule(); |
| 395 return; | 398 return; |
| 396 } | 399 } |
| 397 | 400 |
| 398 NOTREACHED(); | 401 NOTREACHED(); |
| 399 } | 402 } |
| 400 | 403 |
| 404 void TileManager::RasterizeTiles( |
| 405 const GlobalStateThatImpactsTilePriority& state) { |
| 406 TRACE_EVENT0("cc", "TileManager::RasterizeTiles"); |
| 407 |
| 408 global_state_ = state; |
| 409 |
| 410 FreeResourcesForReleasedTiles(); |
| 411 CleanUpReleasedTiles(); |
| 412 |
| 413 client_->BuildRasterQueue(&raster_priority_queue_, |
| 414 global_state_.tree_priority); |
| 415 TileVector tiles_that_need_to_be_rasterized; |
| 416 AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized, |
| 417 std::numeric_limits<size_t>::max()); |
| 418 |
| 419 // Build a new task queue containing all task currently needed. |
| 420 raster_queue_.Reset(); |
| 421 for (auto& tile : tiles_that_need_to_be_rasterized) { |
| 422 ManagedTileState& mts = tile->managed_state(); |
| 423 |
| 424 if (!mts.raster_task.get()) |
| 425 mts.raster_task = CreateRasterTask(tile); |
| 426 |
| 427 TaskSetCollection task_sets; |
| 428 if (tile->required_for_draw()) |
| 429 task_sets.set(REQUIRED_FOR_DRAW); |
| 430 task_sets.set(ALL); |
| 431 raster_queue_.items.push_back( |
| 432 RasterTaskQueue::Item(mts.raster_task.get(), task_sets)); |
| 433 } |
| 434 |
| 435 // We must reduce the amount of unused resoruces before calling |
| 436 // RunTasks to prevent usage from rising above limits. |
| 437 resource_pool_->ReduceResourceUsage(); |
| 438 |
| 439 // Run and complete all raster task synchronously. |
| 440 rasterizer_->RunTasks(&raster_queue_); |
| 441 |
| 442 // Use on-demand raster for any tiles that have not been been assigned |
| 443 // memory. This ensures that we draw even when OOM. |
| 444 while (!raster_priority_queue_.IsEmpty()) { |
| 445 Tile* tile = raster_priority_queue_.Top(); |
| 446 ManagedTileState& mts = tile->managed_state(); |
| 447 |
| 448 if (!mts.draw_info.IsReadyToDraw()) { |
| 449 mts.draw_info.set_rasterize_on_demand(); |
| 450 client_->NotifyTileStateChanged(tile); |
| 451 } |
| 452 raster_priority_queue_.Pop(); |
| 453 } |
| 454 raster_priority_queue_.Reset(); |
| 455 |
| 456 if (IsReadyToDraw()) |
| 457 client_->NotifyReadyToDraw(); |
| 458 |
| 459 TRACE_EVENT_INSTANT1("cc", "DidRasterize", TRACE_EVENT_SCOPE_THREAD, "state", |
| 460 BasicStateAsValue()); |
| 461 |
| 462 TRACE_COUNTER_ID1("cc", "unused_memory_bytes", this, |
| 463 resource_pool_->total_memory_usage_bytes() - |
| 464 resource_pool_->acquired_memory_usage_bytes()); |
| 465 } |
| 466 |
| 401 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { | 467 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { |
| 402 TRACE_EVENT0("cc", "TileManager::ManageTiles"); | 468 TRACE_EVENT0("cc", "TileManager::ManageTiles"); |
| 403 | 469 |
| 404 global_state_ = state; | 470 global_state_ = state; |
| 405 | 471 |
| 406 // We need to call CheckForCompletedTasks() once in-between each call | 472 // We need to call CheckForCompletedTasks() once in-between each call |
| 407 // to ScheduleTasks() to prevent canceled tasks from being scheduled. | 473 // to ScheduleTasks() to prevent canceled tasks from being scheduled. |
| 408 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { | 474 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { |
| 409 rasterizer_->CheckForCompletedTasks(); | 475 rasterizer_->CheckForCompletedTasks(); |
| 410 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 476 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| 411 } | 477 } |
| 412 | 478 |
| 413 FreeResourcesForReleasedTiles(); | 479 FreeResourcesForReleasedTiles(); |
| 414 CleanUpReleasedTiles(); | 480 CleanUpReleasedTiles(); |
| 415 | 481 |
| 482 client_->BuildRasterQueue(&raster_priority_queue_, |
| 483 global_state_.tree_priority); |
| 416 TileVector tiles_that_need_to_be_rasterized; | 484 TileVector tiles_that_need_to_be_rasterized; |
| 417 AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized); | 485 AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized, |
| 486 scheduled_raster_task_limit_); |
| 487 raster_priority_queue_.Reset(); |
| 418 | 488 |
| 419 // Finally, schedule rasterizer tasks. | 489 // Finally, schedule rasterizer tasks. |
| 420 ScheduleTasks(tiles_that_need_to_be_rasterized); | 490 ScheduleTasks(tiles_that_need_to_be_rasterized); |
| 421 | 491 |
| 422 TRACE_EVENT_INSTANT1("cc", | 492 TRACE_EVENT_INSTANT1("cc", |
| 423 "DidManage", | 493 "DidManage", |
| 424 TRACE_EVENT_SCOPE_THREAD, | 494 TRACE_EVENT_SCOPE_THREAD, |
| 425 "state", | 495 "state", |
| 426 BasicStateAsValue()); | 496 BasicStateAsValue()); |
| 427 | 497 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 return priority.priority_bin > TilePriority::SOON; | 594 return priority.priority_bin > TilePriority::SOON; |
| 525 case ALLOW_ANYTHING: | 595 case ALLOW_ANYTHING: |
| 526 return priority.distance_to_visible == | 596 return priority.distance_to_visible == |
| 527 std::numeric_limits<float>::infinity(); | 597 std::numeric_limits<float>::infinity(); |
| 528 } | 598 } |
| 529 NOTREACHED(); | 599 NOTREACHED(); |
| 530 return true; | 600 return true; |
| 531 } | 601 } |
| 532 | 602 |
| 533 void TileManager::AssignGpuMemoryToTiles( | 603 void TileManager::AssignGpuMemoryToTiles( |
| 534 TileVector* tiles_that_need_to_be_rasterized) { | 604 TileVector* tiles_that_need_to_be_rasterized, |
| 605 size_t scheduled_raster_task_limit) { |
| 535 TRACE_EVENT_BEGIN0("cc", "TileManager::AssignGpuMemoryToTiles"); | 606 TRACE_EVENT_BEGIN0("cc", "TileManager::AssignGpuMemoryToTiles"); |
| 536 | 607 |
| 537 // Maintain the list of released resources that can potentially be re-used | 608 // Maintain the list of released resources that can potentially be re-used |
| 538 // or deleted. | 609 // or deleted. |
| 539 // If this operation becomes expensive too, only do this after some | 610 // If this operation becomes expensive too, only do this after some |
| 540 // resource(s) was returned. Note that in that case, one also need to | 611 // resource(s) was returned. Note that in that case, one also need to |
| 541 // invalidate when releasing some resource from the pool. | 612 // invalidate when releasing some resource from the pool. |
| 542 resource_pool_->CheckBusyResources(false); | 613 resource_pool_->CheckBusyResources(false); |
| 543 | 614 |
| 544 // Now give memory out to the tiles until we're out, and build | 615 // Now give memory out to the tiles until we're out, and build |
| 545 // the needs-to-be-rasterized queue. | 616 // the needs-to-be-rasterized queue. |
| 546 unsigned schedule_priority = 1u; | 617 unsigned schedule_priority = 1u; |
| 547 all_tiles_that_need_to_be_rasterized_are_scheduled_ = true; | 618 all_tiles_that_need_to_be_rasterized_are_scheduled_ = true; |
| 548 bool had_enough_memory_to_schedule_tiles_needed_now = true; | 619 bool had_enough_memory_to_schedule_tiles_needed_now = true; |
| 549 | 620 |
| 550 MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes, | 621 MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes, |
| 551 global_state_.num_resources_limit); | 622 global_state_.num_resources_limit); |
| 552 MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes, | 623 MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes, |
| 553 global_state_.num_resources_limit); | 624 global_state_.num_resources_limit); |
| 554 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), | 625 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), |
| 555 resource_pool_->acquired_resource_count()); | 626 resource_pool_->acquired_resource_count()); |
| 556 | 627 |
| 557 eviction_priority_queue_is_up_to_date_ = false; | 628 eviction_priority_queue_is_up_to_date_ = false; |
| 558 client_->BuildRasterQueue(&raster_priority_queue_, | |
| 559 global_state_.tree_priority); | |
| 560 | 629 |
| 561 while (!raster_priority_queue_.IsEmpty()) { | 630 while (!raster_priority_queue_.IsEmpty()) { |
| 562 Tile* tile = raster_priority_queue_.Top(); | 631 Tile* tile = raster_priority_queue_.Top(); |
| 563 TilePriority priority = tile->combined_priority(); | 632 TilePriority priority = tile->combined_priority(); |
| 564 | 633 |
| 565 if (TilePriorityViolatesMemoryPolicy(priority)) { | 634 if (TilePriorityViolatesMemoryPolicy(priority)) { |
| 566 TRACE_EVENT_INSTANT0( | 635 TRACE_EVENT_INSTANT0( |
| 567 "cc", | 636 "cc", |
| 568 "TileManager::AssignGpuMemory tile violates memory policy", | 637 "TileManager::AssignGpuMemory tile violates memory policy", |
| 569 TRACE_EVENT_SCOPE_THREAD); | 638 TRACE_EVENT_SCOPE_THREAD); |
| 570 break; | 639 break; |
| 571 } | 640 } |
| 572 | 641 |
| 573 // We won't be able to schedule this tile, so break out early. | 642 // We won't be able to schedule this tile, so break out early. |
| 574 if (tiles_that_need_to_be_rasterized->size() >= | 643 if (tiles_that_need_to_be_rasterized->size() >= |
| 575 scheduled_raster_task_limit_) { | 644 scheduled_raster_task_limit) { |
| 576 all_tiles_that_need_to_be_rasterized_are_scheduled_ = false; | 645 all_tiles_that_need_to_be_rasterized_are_scheduled_ = false; |
| 577 break; | 646 break; |
| 578 } | 647 } |
| 579 | 648 |
| 580 ManagedTileState& mts = tile->managed_state(); | 649 ManagedTileState& mts = tile->managed_state(); |
| 581 mts.scheduled_priority = schedule_priority++; | 650 mts.scheduled_priority = schedule_priority++; |
| 582 mts.resolution = priority.resolution; | 651 mts.resolution = priority.resolution; |
| 583 | 652 |
| 584 DCHECK(mts.draw_info.mode() == | 653 DCHECK(mts.draw_info.mode() == |
| 585 ManagedTileState::DrawInfo::PICTURE_PILE_MODE || | 654 ManagedTileState::DrawInfo::PICTURE_PILE_MODE || |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget", | 699 UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget", |
| 631 !had_enough_memory_to_schedule_tiles_needed_now); | 700 !had_enough_memory_to_schedule_tiles_needed_now); |
| 632 did_oom_on_last_assign_ = !had_enough_memory_to_schedule_tiles_needed_now; | 701 did_oom_on_last_assign_ = !had_enough_memory_to_schedule_tiles_needed_now; |
| 633 | 702 |
| 634 memory_stats_from_last_assign_.total_budget_in_bytes = | 703 memory_stats_from_last_assign_.total_budget_in_bytes = |
| 635 global_state_.hard_memory_limit_in_bytes; | 704 global_state_.hard_memory_limit_in_bytes; |
| 636 memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes(); | 705 memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes(); |
| 637 memory_stats_from_last_assign_.had_enough_memory = | 706 memory_stats_from_last_assign_.had_enough_memory = |
| 638 had_enough_memory_to_schedule_tiles_needed_now; | 707 had_enough_memory_to_schedule_tiles_needed_now; |
| 639 | 708 |
| 640 raster_priority_queue_.Reset(); | |
| 641 | |
| 642 TRACE_EVENT_END2("cc", | 709 TRACE_EVENT_END2("cc", |
| 643 "TileManager::AssignGpuMemoryToTiles", | 710 "TileManager::AssignGpuMemoryToTiles", |
| 644 "all_tiles_that_need_to_be_rasterized_are_scheduled", | 711 "all_tiles_that_need_to_be_rasterized_are_scheduled", |
| 645 all_tiles_that_need_to_be_rasterized_are_scheduled_, | 712 all_tiles_that_need_to_be_rasterized_are_scheduled_, |
| 646 "had_enough_memory_to_schedule_tiles_needed_now", | 713 "had_enough_memory_to_schedule_tiles_needed_now", |
| 647 had_enough_memory_to_schedule_tiles_needed_now); | 714 had_enough_memory_to_schedule_tiles_needed_now); |
| 648 } | 715 } |
| 649 | 716 |
| 650 void TileManager::FreeResourcesForTile(Tile* tile) { | 717 void TileManager::FreeResourcesForTile(Tile* tile) { |
| 651 ManagedTileState& mts = tile->managed_state(); | 718 ManagedTileState& mts = tile->managed_state(); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 result -= other; | 1007 result -= other; |
| 941 return result; | 1008 return result; |
| 942 } | 1009 } |
| 943 | 1010 |
| 944 bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const { | 1011 bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const { |
| 945 return memory_bytes_ > limit.memory_bytes_ || | 1012 return memory_bytes_ > limit.memory_bytes_ || |
| 946 resource_count_ > limit.resource_count_; | 1013 resource_count_ > limit.resource_count_; |
| 947 } | 1014 } |
| 948 | 1015 |
| 949 } // namespace cc | 1016 } // namespace cc |
| OLD | NEW |