| 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 <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 TileManagerClient* client, | 126 TileManagerClient* client, |
| 127 ResourceProvider* resource_provider, | 127 ResourceProvider* resource_provider, |
| 128 scoped_ptr<RasterWorkerPool> raster_worker_pool, | 128 scoped_ptr<RasterWorkerPool> raster_worker_pool, |
| 129 size_t num_raster_threads, | 129 size_t num_raster_threads, |
| 130 bool use_color_estimator, | 130 bool use_color_estimator, |
| 131 RenderingStatsInstrumentation* rendering_stats_instrumentation) | 131 RenderingStatsInstrumentation* rendering_stats_instrumentation) |
| 132 : client_(client), | 132 : client_(client), |
| 133 resource_pool_(ResourcePool::Create(resource_provider)), | 133 resource_pool_(ResourcePool::Create(resource_provider)), |
| 134 raster_worker_pool_(raster_worker_pool.Pass()), | 134 raster_worker_pool_(raster_worker_pool.Pass()), |
| 135 manage_tiles_pending_(false), | 135 manage_tiles_pending_(false), |
| 136 manage_tiles_call_count_(0), | |
| 137 bytes_pending_upload_(0), | 136 bytes_pending_upload_(0), |
| 138 has_performed_uploads_since_last_flush_(false), | 137 has_performed_uploads_since_last_flush_(false), |
| 139 ever_exceeded_memory_budget_(false), | 138 ever_exceeded_memory_budget_(false), |
| 140 rendering_stats_instrumentation_(rendering_stats_instrumentation), | 139 rendering_stats_instrumentation_(rendering_stats_instrumentation), |
| 141 use_color_estimator_(use_color_estimator), | 140 use_color_estimator_(use_color_estimator), |
| 142 did_initialize_visible_tile_(false), | 141 did_initialize_visible_tile_(false), |
| 143 pending_tasks_(0), | |
| 144 max_pending_tasks_(kMaxNumPendingTasksPerThread * num_raster_threads) { | 142 max_pending_tasks_(kMaxNumPendingTasksPerThread * num_raster_threads) { |
| 145 raster_worker_pool_->SetClient(this); | 143 raster_worker_pool_->SetClient(this); |
| 146 } | 144 } |
| 147 | 145 |
| 148 TileManager::~TileManager() { | 146 TileManager::~TileManager() { |
| 149 // Reset global state and manage. This should cause | 147 // Reset global state and manage. This should cause |
| 150 // our memory usage to drop to zero. | 148 // our memory usage to drop to zero. |
| 151 global_state_ = GlobalStateThatImpactsTilePriority(); | 149 global_state_ = GlobalStateThatImpactsTilePriority(); |
| 152 AssignGpuMemoryToTiles(); | 150 AssignGpuMemoryToTiles(); |
| 153 // This should finish all pending tasks and release any uninitialized | 151 // This should finish all pending tasks and release any uninitialized |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 | 294 |
| 297 // Sort by bin, resolution and time until needed. | 295 // Sort by bin, resolution and time until needed. |
| 298 std::sort(tiles_.begin(), tiles_.end(), BinComparator()); | 296 std::sort(tiles_.begin(), tiles_.end(), BinComparator()); |
| 299 } | 297 } |
| 300 | 298 |
| 301 void TileManager::ManageTiles() { | 299 void TileManager::ManageTiles() { |
| 302 TRACE_EVENT0("cc", "TileManager::ManageTiles"); | 300 TRACE_EVENT0("cc", "TileManager::ManageTiles"); |
| 303 TRACE_COUNTER_ID1("cc", "TileCount", this, tiles_.size()); | 301 TRACE_COUNTER_ID1("cc", "TileCount", this, tiles_.size()); |
| 304 | 302 |
| 305 manage_tiles_pending_ = false; | 303 manage_tiles_pending_ = false; |
| 306 ++manage_tiles_call_count_; | |
| 307 | 304 |
| 308 AssignBinsToTiles(); | 305 AssignBinsToTiles(); |
| 309 SortTiles(); | 306 SortTiles(); |
| 310 AssignGpuMemoryToTiles(); | 307 AssignGpuMemoryToTiles(); |
| 311 | 308 |
| 312 TRACE_EVENT_INSTANT1( | 309 TRACE_EVENT_INSTANT1( |
| 313 "cc", "DidManage", TRACE_EVENT_SCOPE_THREAD, | 310 "cc", "DidManage", TRACE_EVENT_SCOPE_THREAD, |
| 314 "state", TracedValue::FromValue(BasicStateAsValue().release())); | 311 "state", TracedValue::FromValue(BasicStateAsValue().release())); |
| 315 | 312 |
| 316 // Finally, kick the rasterizer. | 313 // Finally, schedule rasterizer tasks. |
| 317 DispatchMoreTasks(); | 314 ScheduleTasks(); |
| 318 } | 315 } |
| 319 | 316 |
| 320 void TileManager::CheckForCompletedTileUploads() { | 317 void TileManager::CheckForCompletedTileUploads() { |
| 321 while (!tiles_with_pending_upload_.empty()) { | 318 while (!tiles_with_pending_upload_.empty()) { |
| 322 Tile* tile = tiles_with_pending_upload_.front(); | 319 Tile* tile = tiles_with_pending_upload_.front(); |
| 323 DCHECK(tile->drawing_info().resource_); | 320 DCHECK(tile->drawing_info().resource_); |
| 324 | 321 |
| 325 // Set pixel tasks complete in the order they are posted. | 322 // Set pixel tasks complete in the order they are posted. |
| 326 if (!resource_pool_->resource_provider()->DidSetPixelsComplete( | 323 if (!resource_pool_->resource_provider()->DidSetPixelsComplete( |
| 327 tile->drawing_info().resource_->id())) { | 324 tile->drawing_info().resource_->id())) { |
| 328 break; | 325 break; |
| 329 } | 326 } |
| 330 | 327 |
| 331 // It's now safe to release the pixel buffer. | 328 // It's now safe to release the pixel buffer. |
| 332 resource_pool_->resource_provider()->ReleasePixelBuffer( | 329 resource_pool_->resource_provider()->ReleasePixelBuffer( |
| 333 tile->drawing_info().resource_->id()); | 330 tile->drawing_info().resource_->id()); |
| 334 | 331 |
| 335 bytes_pending_upload_ -= tile->bytes_consumed_if_allocated(); | 332 bytes_pending_upload_ -= tile->bytes_consumed_if_allocated(); |
| 336 // Reset forced_upload_ since we now got the upload completed notification. | 333 // Reset forced_upload_ since we now got the upload completed notification. |
| 337 tile->drawing_info().forced_upload_ = false; | 334 tile->drawing_info().forced_upload_ = false; |
| 338 tile->drawing_info().memory_state_ = USING_RELEASABLE_MEMORY; | 335 tile->drawing_info().memory_state_ = USING_RELEASABLE_MEMORY; |
| 339 DidFinishTileInitialization(tile); | 336 DidFinishTileInitialization(tile); |
| 340 | 337 |
| 341 tiles_with_pending_upload_.pop(); | 338 tiles_with_pending_upload_.pop(); |
| 342 } | 339 } |
| 343 | 340 |
| 344 DispatchMoreTasks(); | 341 ScheduleTasks(); |
| 345 } | 342 } |
| 346 | 343 |
| 347 void TileManager::AbortPendingTileUploads() { | 344 void TileManager::AbortPendingTileUploads() { |
| 348 while (!tiles_with_pending_upload_.empty()) { | 345 while (!tiles_with_pending_upload_.empty()) { |
| 349 Tile* tile = tiles_with_pending_upload_.front(); | 346 Tile* tile = tiles_with_pending_upload_.front(); |
| 350 DCHECK(tile->drawing_info().resource_); | 347 DCHECK(tile->drawing_info().resource_); |
| 351 | 348 |
| 352 resource_pool_->resource_provider()->AbortSetPixels( | 349 resource_pool_->resource_provider()->AbortSetPixels( |
| 353 tile->drawing_info().resource_->id()); | 350 tile->drawing_info().resource_->id()); |
| 354 resource_pool_->resource_provider()->ReleasePixelBuffer( | 351 resource_pool_->resource_provider()->ReleasePixelBuffer( |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 return requirements.PassAs<base::Value>(); | 442 return requirements.PassAs<base::Value>(); |
| 446 } | 443 } |
| 447 | 444 |
| 448 void TileManager::DidFinishDispatchingWorkerPoolCompletionCallbacks() { | 445 void TileManager::DidFinishDispatchingWorkerPoolCompletionCallbacks() { |
| 449 // If a flush is needed, do it now before starting to dispatch more tasks. | 446 // If a flush is needed, do it now before starting to dispatch more tasks. |
| 450 if (has_performed_uploads_since_last_flush_) { | 447 if (has_performed_uploads_since_last_flush_) { |
| 451 resource_pool_->resource_provider()->ShallowFlushIfSupported(); | 448 resource_pool_->resource_provider()->ShallowFlushIfSupported(); |
| 452 has_performed_uploads_since_last_flush_ = false; | 449 has_performed_uploads_since_last_flush_ = false; |
| 453 } | 450 } |
| 454 | 451 |
| 455 DispatchMoreTasks(); | 452 ScheduleTasks(); |
| 456 } | 453 } |
| 457 | 454 |
| 458 void TileManager::AssignGpuMemoryToTiles() { | 455 void TileManager::AssignGpuMemoryToTiles() { |
| 459 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); | 456 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); |
| 460 size_t unreleasable_bytes = 0; | 457 size_t unreleasable_bytes = 0; |
| 461 | 458 |
| 462 // Now give memory out to the tiles until we're out, and build | 459 // Now give memory out to the tiles until we're out, and build |
| 463 // the needs-to-be-rasterized queue. | 460 // the needs-to-be-rasterized queue. |
| 464 tiles_that_need_to_be_rasterized_.clear(); | 461 tiles_that_need_to_be_rasterized_.clear(); |
| 465 | 462 |
| 466 // By clearing the tiles_that_need_to_be_rasterized_ vector list | 463 // By clearing the tiles_that_need_to_be_rasterized_ vector list |
| 467 // above we move all tiles currently waiting for raster to idle state. | 464 // above we move all tiles currently waiting for raster to idle state. |
| 468 // Some memory cannot be released. We figure out how much in this | 465 // Some memory cannot be released. We figure out how much in this |
| 469 // loop as well. | 466 // loop. |
| 470 for (TileVector::const_iterator it = tiles_.begin(); | 467 for (TileVector::const_iterator it = tiles_.begin(); |
| 471 it != tiles_.end(); | 468 it != tiles_.end(); |
| 472 ++it) { | 469 ++it) { |
| 473 const Tile* tile = *it; | 470 const Tile* tile = *it; |
| 474 if (tile->drawing_info().memory_state_ == USING_UNRELEASABLE_MEMORY) | 471 if (tile->drawing_info().memory_state_ == USING_UNRELEASABLE_MEMORY) |
| 475 unreleasable_bytes += tile->bytes_consumed_if_allocated(); | 472 unreleasable_bytes += tile->bytes_consumed_if_allocated(); |
| 476 } | 473 } |
| 477 | 474 |
| 478 // Global state's memory limit can decrease, causing | 475 // Global state's memory limit can decrease, causing |
| 479 // it to be less than unreleasable_bytes | 476 // it to be less than unreleasable_bytes |
| 480 size_t bytes_allocatable = | 477 size_t bytes_allocatable = |
| 481 global_state_.memory_limit_in_bytes > unreleasable_bytes ? | 478 global_state_.memory_limit_in_bytes > unreleasable_bytes ? |
| 482 global_state_.memory_limit_in_bytes - unreleasable_bytes : | 479 global_state_.memory_limit_in_bytes - unreleasable_bytes : |
| 483 0; | 480 0; |
| 484 size_t bytes_that_exceeded_memory_budget_in_now_bin = 0; | 481 size_t bytes_that_exceeded_memory_budget_in_now_bin = 0; |
| 485 size_t bytes_left = bytes_allocatable; | 482 size_t bytes_left = bytes_allocatable; |
| 486 size_t bytes_oom_in_now_bin_on_pending_tree = 0; | 483 size_t bytes_oom_in_now_bin_on_pending_tree = 0; |
| 487 TileVector tiles_requiring_memory_but_oomed; | 484 TileVector tiles_requiring_memory_but_oomed; |
| 485 bool higher_priority_tile_oomed = false; |
| 488 for (TileVector::iterator it = tiles_.begin(); | 486 for (TileVector::iterator it = tiles_.begin(); |
| 489 it != tiles_.end(); | 487 it != tiles_.end(); |
| 490 ++it) { | 488 ++it) { |
| 491 Tile* tile = *it; | 489 Tile* tile = *it; |
| 492 ManagedTileState& mts = tile->managed_state(); | 490 ManagedTileState& mts = tile->managed_state(); |
| 493 ManagedTileState::DrawingInfo& drawing_info = tile->drawing_info(); | 491 ManagedTileState::DrawingInfo& drawing_info = tile->drawing_info(); |
| 494 | 492 |
| 495 // If this tile doesn't need a resource, or if the memory | 493 // If this tile doesn't need a resource, then we do not need |
| 496 // is unreleasable, then we do not need to do anything. | 494 // to do anything. |
| 497 if (!drawing_info.requires_resource() || | 495 if (!drawing_info.requires_resource()) |
| 498 drawing_info.memory_state_ == USING_UNRELEASABLE_MEMORY) { | 496 continue; |
| 497 |
| 498 size_t tile_bytes = tile->bytes_consumed_if_allocated(); |
| 499 // Memory is already reserved for tile with unreleasable memory |
| 500 // so adding it to |tiles_that_need_to_be_rasterized_| doesn't |
| 501 // affect bytes_allocatable. |
| 502 if (drawing_info.memory_state_ == USING_UNRELEASABLE_MEMORY) |
| 503 tile_bytes = 0; |
| 504 |
| 505 // If the tile is not needed, free it up. |
| 506 if (mts.is_in_never_bin_on_both_trees()) { |
| 507 if (drawing_info.memory_state_ != USING_UNRELEASABLE_MEMORY) { |
| 508 FreeResourcesForTile(tile); |
| 509 drawing_info.memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; |
| 510 } |
| 499 continue; | 511 continue; |
| 500 } | 512 } |
| 501 | 513 |
| 502 size_t tile_bytes = tile->bytes_consumed_if_allocated(); | |
| 503 // If the tile is not needed, free it up. | |
| 504 if (mts.is_in_never_bin_on_both_trees()) { | |
| 505 FreeResourcesForTile(tile); | |
| 506 drawing_info.memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; | |
| 507 continue; | |
| 508 } | |
| 509 // Tile is OOM. | 514 // Tile is OOM. |
| 510 if (tile_bytes > bytes_left) { | 515 if (tile_bytes > bytes_left) { |
| 511 FreeResourcesForTile(tile); | |
| 512 tile->drawing_info().set_rasterize_on_demand(); | 516 tile->drawing_info().set_rasterize_on_demand(); |
| 513 if (mts.tree_bin[PENDING_TREE] == NOW_BIN) { | 517 if (mts.tree_bin[PENDING_TREE] == NOW_BIN) { |
| 514 tiles_requiring_memory_but_oomed.push_back(tile); | 518 tiles_requiring_memory_but_oomed.push_back(tile); |
| 515 bytes_oom_in_now_bin_on_pending_tree += tile_bytes; | 519 bytes_oom_in_now_bin_on_pending_tree += tile_bytes; |
| 516 } | 520 } |
| 521 FreeResourcesForTile(tile); |
| 522 higher_priority_tile_oomed = true; |
| 517 continue; | 523 continue; |
| 518 } | 524 } |
| 525 |
| 519 drawing_info.set_use_resource(); | 526 drawing_info.set_use_resource(); |
| 520 bytes_left -= tile_bytes; | 527 bytes_left -= tile_bytes; |
| 521 if (!drawing_info.resource_ && | 528 |
| 522 drawing_info.memory_state_ == CAN_USE_MEMORY) { | 529 // Tile shouldn't be rasterized if we've failed to assign |
| 530 // gpu memory to a higher priority tile. This is important for |
| 531 // two reasons: |
| 532 // 1. Tile size should not impact raster priority. |
| 533 // 2. Tile with unreleasable memory could otherwise incorrectly |
| 534 // be added as it's not affected by |bytes_allocatable|. |
| 535 if (higher_priority_tile_oomed) |
| 536 continue; |
| 537 |
| 538 if (!drawing_info.resource_) |
| 523 tiles_that_need_to_be_rasterized_.push_back(tile); | 539 tiles_that_need_to_be_rasterized_.push_back(tile); |
| 524 } | |
| 525 } | 540 } |
| 526 | 541 |
| 527 // In OOM situation, we iterate tiles_, remove the memory for active tree | 542 // In OOM situation, we iterate tiles_, remove the memory for active tree |
| 528 // and not the now bin. And give them to bytes_oom_in_now_bin_on_pending_tree | 543 // and not the now bin. And give them to bytes_oom_in_now_bin_on_pending_tree |
| 529 if (!tiles_requiring_memory_but_oomed.empty()) { | 544 if (!tiles_requiring_memory_but_oomed.empty()) { |
| 530 size_t bytes_freed = 0; | 545 size_t bytes_freed = 0; |
| 531 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 546 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| 532 Tile* tile = *it; | 547 Tile* tile = *it; |
| 533 ManagedTileState& mts = tile->managed_state(); | 548 ManagedTileState& mts = tile->managed_state(); |
| 534 ManagedTileState::DrawingInfo& drawing_info = tile->drawing_info(); | 549 ManagedTileState::DrawingInfo& drawing_info = tile->drawing_info(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 "budget", global_state_.memory_limit_in_bytes, | 585 "budget", global_state_.memory_limit_in_bytes, |
| 571 "over", bytes_that_exceeded_memory_budget_in_now_bin); | 586 "over", bytes_that_exceeded_memory_budget_in_now_bin); |
| 572 } | 587 } |
| 573 memory_stats_from_last_assign_.total_budget_in_bytes = | 588 memory_stats_from_last_assign_.total_budget_in_bytes = |
| 574 global_state_.memory_limit_in_bytes; | 589 global_state_.memory_limit_in_bytes; |
| 575 memory_stats_from_last_assign_.bytes_allocated = | 590 memory_stats_from_last_assign_.bytes_allocated = |
| 576 bytes_allocatable - bytes_left; | 591 bytes_allocatable - bytes_left; |
| 577 memory_stats_from_last_assign_.bytes_unreleasable = unreleasable_bytes; | 592 memory_stats_from_last_assign_.bytes_unreleasable = unreleasable_bytes; |
| 578 memory_stats_from_last_assign_.bytes_over = | 593 memory_stats_from_last_assign_.bytes_over = |
| 579 bytes_that_exceeded_memory_budget_in_now_bin; | 594 bytes_that_exceeded_memory_budget_in_now_bin; |
| 580 | |
| 581 // Reverse two tiles_that_need_* vectors such that pop_back gets | |
| 582 // the highest priority tile. | |
| 583 std::reverse( | |
| 584 tiles_that_need_to_be_rasterized_.begin(), | |
| 585 tiles_that_need_to_be_rasterized_.end()); | |
| 586 } | 595 } |
| 587 | 596 |
| 588 void TileManager::FreeResourcesForTile(Tile* tile) { | 597 void TileManager::FreeResourcesForTile(Tile* tile) { |
| 589 DCHECK(tile->drawing_info().memory_state_ != USING_UNRELEASABLE_MEMORY); | 598 DCHECK_NE(USING_UNRELEASABLE_MEMORY, tile->drawing_info().memory_state_); |
| 590 if (tile->drawing_info().resource_) { | 599 if (tile->drawing_info().resource_) { |
| 591 resource_pool_->ReleaseResource( | 600 resource_pool_->ReleaseResource( |
| 592 tile->drawing_info().resource_.Pass()); | 601 tile->drawing_info().resource_.Pass()); |
| 593 } | 602 } |
| 594 tile->drawing_info().memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; | 603 tile->drawing_info().memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; |
| 595 } | 604 } |
| 596 | 605 |
| 597 bool TileManager::CanDispatchRasterTask(Tile* tile) const { | 606 void TileManager::ScheduleTasks() { |
| 598 if (pending_tasks_ >= max_pending_tasks_) | 607 TRACE_EVENT0("cc", "TileManager::ScheduleTasks"); |
| 599 return false; | 608 RasterWorkerPool::Task::Schedule task_schedule; |
| 600 size_t new_bytes_pending = bytes_pending_upload_; | |
| 601 new_bytes_pending += tile->bytes_consumed_if_allocated(); | |
| 602 return new_bytes_pending <= kMaxPendingUploadBytes && | |
| 603 tiles_with_pending_upload_.size() < kMaxPendingUploads; | |
| 604 } | |
| 605 | 609 |
| 606 void TileManager::DispatchMoreTasks() { | 610 size_t bytes_pending_upload = bytes_pending_upload_; |
| 607 TileVector tiles_with_image_decoding_tasks; | 611 unsigned pending_tasks = 0; |
| 608 | 612 |
| 609 // Process all tiles in the need_to_be_rasterized queue: | 613 // Build a new task schedule containing all task currently needed. Tasks |
| 610 // 1. Dispatch image decode tasks. | 614 // are added in order of priority, highest priority task first. |
| 611 // 2. If the image decode isn't done, save the tile for later processing. | 615 for (TileVector::iterator it = tiles_that_need_to_be_rasterized_.begin(); |
| 612 // 3. Attempt to dispatch a raster task, or break out of the loop. | 616 it != tiles_that_need_to_be_rasterized_.end(); |
| 613 while (!tiles_that_need_to_be_rasterized_.empty()) { | 617 ++it) { |
| 614 Tile* tile = tiles_that_need_to_be_rasterized_.back(); | 618 Tile* tile = *it; |
| 619 ManagedTileState& mts = tile->managed_state(); |
| 615 | 620 |
| 616 DCHECK(tile->drawing_info().requires_resource()); | 621 // Skip tile if determined to not require resource. |
| 622 if (!tile->drawing_info().requires_resource()) |
| 623 continue; |
| 617 | 624 |
| 618 if (DispatchImageDecodeTasksForTile(tile)) { | 625 // Skip tile if already rasterized. |
| 619 tiles_with_image_decoding_tasks.push_back(tile); | 626 if (tile->drawing_info().resource_) |
| 620 } else if (!CanDispatchRasterTask(tile)) { | 627 continue; |
| 621 break; | 628 |
| 622 } else { | 629 // TODO(reveman): Remove throttling based on max pending tasks. |
| 623 DispatchOneRasterTask(tile); | 630 if (pending_tasks >= max_pending_tasks_) |
| 631 break; |
| 632 |
| 633 // TODO(reveman): Remove throttling based on max pending uploads. |
| 634 if (tiles_with_pending_upload_.size() >= kMaxPendingUploads) |
| 635 break; |
| 636 |
| 637 // TODO(reveman): Throttle based on shared memory usage rather |
| 638 // than bytes pending upload. |
| 639 size_t new_bytes_pending = bytes_pending_upload; |
| 640 new_bytes_pending += tile->bytes_consumed_if_allocated(); |
| 641 if (new_bytes_pending > kMaxPendingUploadBytes) |
| 642 break; |
| 643 bytes_pending_upload = new_bytes_pending; |
| 644 |
| 645 // Create image decode schedule that his tile depends on. |
| 646 RasterWorkerPool::Task::Schedule decode_task_schedule; |
| 647 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(), |
| 648 tile->contents_scale(), |
| 649 tile->picture_pile()); |
| 650 iter; ++iter) { |
| 651 skia::LazyPixelRef* pixel_ref = *iter; |
| 652 uint32_t id = pixel_ref->getGenerationID(); |
| 653 |
| 654 // Append existing image decode task if available. |
| 655 PixelRefMap::iterator decode_task_it = pending_decode_tasks_.find(id); |
| 656 if (decode_task_it != pending_decode_tasks_.end()) { |
| 657 decode_task_schedule.Append(decode_task_it->second); |
| 658 continue; |
| 659 } |
| 660 |
| 661 // Create and append new image decode task for this pixel ref. |
| 662 RasterWorkerPool::Task decode_task = CreateImageDecodeTask( |
| 663 tile, pixel_ref); |
| 664 decode_task_schedule.Append(decode_task); |
| 665 pending_decode_tasks_[id] = decode_task; |
| 624 } | 666 } |
| 625 tiles_that_need_to_be_rasterized_.pop_back(); | 667 |
| 668 // Create raster task for this tile if necessary. |
| 669 if (mts.raster_task.is_null()) |
| 670 mts.raster_task = CreateRasterTask(tile); |
| 671 |
| 672 // Finally append raster task and image decode dependencies for tile. |
| 673 task_schedule.AppendWithDependencies( |
| 674 mts.raster_task, &decode_task_schedule); |
| 675 pending_tasks++; |
| 626 } | 676 } |
| 627 | 677 |
| 628 // Put the saved tiles back into the queue. The order is reversed | 678 // Schedule running of tasks in |task_schedule|. This replaces any |
| 629 // to preserve original ordering. | 679 // previously scheduled tasks and effectively cancels any tasks |
| 630 tiles_that_need_to_be_rasterized_.insert( | 680 // not present in |task_schedule|. |
| 631 tiles_that_need_to_be_rasterized_.end(), | 681 raster_worker_pool_->ScheduleTasks(&task_schedule); |
| 632 tiles_with_image_decoding_tasks.rbegin(), | |
| 633 tiles_with_image_decoding_tasks.rend()); | |
| 634 | 682 |
| 635 if (did_initialize_visible_tile_) { | 683 if (did_initialize_visible_tile_) { |
| 636 did_initialize_visible_tile_ = false; | 684 did_initialize_visible_tile_ = false; |
| 637 client_->DidInitializeVisibleTile(); | 685 client_->DidInitializeVisibleTile(); |
| 638 } | 686 } |
| 639 } | 687 } |
| 640 | 688 |
| 641 bool TileManager::DispatchImageDecodeTasksForTile(Tile* tile) { | 689 RasterWorkerPool::Task TileManager::CreateImageDecodeTask( |
| 642 TRACE_EVENT0("cc", "TileManager::DispatchImageDecodeTasksForTile"); | 690 Tile* tile, skia::LazyPixelRef* pixel_ref) { |
| 643 ManagedTileState& mts = tile->managed_state(); | 691 TRACE_EVENT0("cc", "TileManager::CreateImageDecodeTask"); |
| 644 bool pending_decode_tasks = false; | |
| 645 | 692 |
| 646 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(), | 693 return RasterWorkerPool::Task( |
| 647 tile->contents_scale(), | |
| 648 tile->picture_pile()); | |
| 649 iter; ++iter) { | |
| 650 skia::LazyPixelRef* pixel_ref = *iter; | |
| 651 uint32_t id = pixel_ref->getGenerationID(); | |
| 652 | |
| 653 // Check if image has already been decoded. | |
| 654 if (mts.decoded_pixel_refs.find(id) != mts.decoded_pixel_refs.end()) | |
| 655 continue; | |
| 656 | |
| 657 // Check if decode task is already pending. | |
| 658 if (pending_decode_tasks_.find(id) != pending_decode_tasks_.end()) { | |
| 659 pending_decode_tasks = true; | |
| 660 continue; | |
| 661 } | |
| 662 | |
| 663 // TODO(qinmin): passing correct image size to PrepareToDecode(). | |
| 664 if (pixel_ref->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) { | |
| 665 rendering_stats_instrumentation_->IncrementDeferredImageCacheHitCount(); | |
| 666 mts.decoded_pixel_refs.insert(id); | |
| 667 continue; | |
| 668 } | |
| 669 | |
| 670 if (pending_tasks_ >= max_pending_tasks_) | |
| 671 break; | |
| 672 | |
| 673 DispatchOneImageDecodeTask(tile, pixel_ref); | |
| 674 pending_decode_tasks = true; | |
| 675 } | |
| 676 | |
| 677 return pending_decode_tasks; | |
| 678 } | |
| 679 | |
| 680 void TileManager::DispatchOneImageDecodeTask( | |
| 681 scoped_refptr<Tile> tile, skia::LazyPixelRef* pixel_ref) { | |
| 682 TRACE_EVENT0("cc", "TileManager::DispatchOneImageDecodeTask"); | |
| 683 uint32_t pixel_ref_id = pixel_ref->getGenerationID(); | |
| 684 DCHECK(pending_decode_tasks_.end() == | |
| 685 pending_decode_tasks_.find(pixel_ref_id)); | |
| 686 pending_decode_tasks_.insert(pixel_ref_id); | |
| 687 | |
| 688 raster_worker_pool_->PostTaskAndReply( | |
| 689 base::Bind(&TileManager::RunImageDecodeTask, | 694 base::Bind(&TileManager::RunImageDecodeTask, |
| 690 pixel_ref, | 695 pixel_ref, |
| 691 tile->layer_id(), | 696 tile->layer_id(), |
| 692 rendering_stats_instrumentation_), | 697 rendering_stats_instrumentation_), |
| 693 base::Bind(&TileManager::OnImageDecodeTaskCompleted, | 698 base::Bind(&TileManager::OnImageDecodeTaskCompleted, |
| 694 base::Unretained(this), | 699 base::Unretained(this), |
| 695 tile, | 700 make_scoped_refptr(tile), |
| 696 pixel_ref_id)); | 701 pixel_ref->getGenerationID())); |
| 697 pending_tasks_++; | |
| 698 } | 702 } |
| 699 | 703 |
| 700 void TileManager::OnImageDecodeTaskCompleted( | 704 void TileManager::OnImageDecodeTaskCompleted(scoped_refptr<Tile> tile, |
| 701 scoped_refptr<Tile> tile, uint32_t pixel_ref_id) { | 705 uint32_t pixel_ref_id, |
| 706 bool was_cancelled) { |
| 702 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted"); | 707 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted"); |
| 703 ManagedTileState& mts = tile->managed_state(); | 708 DCHECK(pending_decode_tasks_.find(pixel_ref_id) != |
| 704 mts.decoded_pixel_refs.insert(pixel_ref_id); | 709 pending_decode_tasks_.end()); |
| 705 pending_decode_tasks_.erase(pixel_ref_id); | 710 pending_decode_tasks_.erase(pixel_ref_id); |
| 706 pending_tasks_--; | |
| 707 } | 711 } |
| 708 | 712 |
| 709 scoped_ptr<ResourcePool::Resource> TileManager::PrepareTileForRaster( | 713 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata( |
| 710 Tile* tile) { | 714 const Tile& tile) const { |
| 711 scoped_ptr<ResourcePool::Resource> resource = resource_pool_->AcquireResource( | 715 RasterTaskMetadata metadata; |
| 712 tile->tile_size_.size(), | 716 const ManagedTileState& mts = tile.managed_state(); |
| 713 tile->drawing_info().resource_format_); | 717 metadata.is_tile_in_pending_tree_now_bin = |
| 718 mts.tree_bin[PENDING_TREE] == NOW_BIN; |
| 719 metadata.tile_resolution = mts.resolution; |
| 720 metadata.layer_id = tile.layer_id(); |
| 721 metadata.tile_id = &tile; |
| 722 metadata.source_frame_number = tile.source_frame_number(); |
| 723 return metadata; |
| 724 } |
| 725 |
| 726 RasterWorkerPool::Task TileManager::CreateRasterTask(Tile* tile) { |
| 727 TRACE_EVENT0("cc", "TileManager::CreateRasterTask"); |
| 728 |
| 729 scoped_ptr<ResourcePool::Resource> resource = |
| 730 resource_pool_->AcquireResource( |
| 731 tile->tile_size_.size(), |
| 732 tile->drawing_info().resource_format_); |
| 714 resource_pool_->resource_provider()->AcquirePixelBuffer(resource->id()); | 733 resource_pool_->resource_provider()->AcquirePixelBuffer(resource->id()); |
| 715 | 734 |
| 735 DCHECK_EQ(CAN_USE_MEMORY, tile->drawing_info().memory_state_); |
| 716 tile->drawing_info().memory_state_ = USING_UNRELEASABLE_MEMORY; | 736 tile->drawing_info().memory_state_ = USING_UNRELEASABLE_MEMORY; |
| 717 | 737 |
| 718 return resource.Pass(); | |
| 719 } | |
| 720 | |
| 721 void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { | |
| 722 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); | |
| 723 scoped_ptr<ResourcePool::Resource> resource = PrepareTileForRaster(tile); | |
| 724 ResourceProvider::ResourceId resource_id = resource->id(); | |
| 725 PicturePileImpl::Analysis* analysis = new PicturePileImpl::Analysis; | 738 PicturePileImpl::Analysis* analysis = new PicturePileImpl::Analysis; |
| 726 | 739 |
| 727 // MapPixelBuffer() returns NULL if context was lost at the time | 740 // MapPixelBuffer() returns NULL if context was lost at the time |
| 728 // AcquirePixelBuffer() was called. For simplicity we still post | 741 // AcquirePixelBuffer() was called. For simplicity we still create |
| 729 // a raster task that is essentially a noop in these situations. | 742 // a raster task that is essentially a noop in these situations. |
| 730 uint8* buffer = resource_pool_->resource_provider()->MapPixelBuffer( | 743 uint8* buffer = resource_pool_->resource_provider()->MapPixelBuffer( |
| 731 resource_id); | 744 resource->id()); |
| 732 | 745 |
| 733 // skia requires that our buffer be 4-byte aligned | 746 return RasterWorkerPool::PictureTask( |
| 734 CHECK(!(reinterpret_cast<intptr_t>(buffer) & 3)); | |
| 735 | |
| 736 raster_worker_pool_->PostRasterTaskAndReply( | |
| 737 tile->picture_pile(), | 747 tile->picture_pile(), |
| 738 base::Bind(&TileManager::RunAnalyzeAndRasterTask, | 748 base::Bind(&TileManager::RunAnalyzeAndRasterTask, |
| 739 base::Bind(&TileManager::RunAnalyzeTask, | 749 base::Bind(&TileManager::RunAnalyzeTask, |
| 740 analysis, | 750 analysis, |
| 741 tile->content_rect(), | 751 tile->content_rect(), |
| 742 tile->contents_scale(), | 752 tile->contents_scale(), |
| 743 use_color_estimator_, | 753 use_color_estimator_, |
| 744 GetRasterTaskMetadata(*tile), | 754 GetRasterTaskMetadata(*tile), |
| 745 rendering_stats_instrumentation_), | 755 rendering_stats_instrumentation_), |
| 746 base::Bind(&TileManager::RunRasterTask, | 756 base::Bind(&TileManager::RunRasterTask, |
| 747 buffer, | 757 buffer, |
| 748 analysis, | 758 analysis, |
| 749 tile->content_rect(), | 759 tile->content_rect(), |
| 750 tile->contents_scale(), | 760 tile->contents_scale(), |
| 751 GetRasterTaskMetadata(*tile), | 761 GetRasterTaskMetadata(*tile), |
| 752 rendering_stats_instrumentation_)), | 762 rendering_stats_instrumentation_)), |
| 753 base::Bind(&TileManager::OnRasterTaskCompleted, | 763 base::Bind(&TileManager::OnRasterTaskCompleted, |
| 754 base::Unretained(this), | 764 base::Unretained(this), |
| 755 tile, | 765 make_scoped_refptr(tile), |
| 756 base::Passed(&resource), | 766 base::Passed(&resource), |
| 757 base::Owned(analysis), | 767 base::Owned(analysis))); |
| 758 manage_tiles_call_count_)); | |
| 759 pending_tasks_++; | |
| 760 } | |
| 761 | |
| 762 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata( | |
| 763 const Tile& tile) const { | |
| 764 RasterTaskMetadata metadata; | |
| 765 const ManagedTileState& mts = tile.managed_state(); | |
| 766 metadata.is_tile_in_pending_tree_now_bin = | |
| 767 mts.tree_bin[PENDING_TREE] == NOW_BIN; | |
| 768 metadata.tile_resolution = mts.resolution; | |
| 769 metadata.layer_id = tile.layer_id(); | |
| 770 metadata.tile_id = &tile; | |
| 771 metadata.source_frame_number = tile.source_frame_number(); | |
| 772 return metadata; | |
| 773 } | 768 } |
| 774 | 769 |
| 775 void TileManager::OnRasterTaskCompleted( | 770 void TileManager::OnRasterTaskCompleted( |
| 776 scoped_refptr<Tile> tile, | 771 scoped_refptr<Tile> tile, |
| 777 scoped_ptr<ResourcePool::Resource> resource, | 772 scoped_ptr<ResourcePool::Resource> resource, |
| 778 PicturePileImpl::Analysis* analysis, | 773 PicturePileImpl::Analysis* analysis, |
| 779 int manage_tiles_call_count_when_dispatched) { | 774 bool was_cancelled) { |
| 780 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); | 775 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); |
| 781 | 776 |
| 782 pending_tasks_--; | 777 ManagedTileState& mts = tile->managed_state(); |
| 778 DCHECK(!mts.raster_task.is_null()); |
| 779 mts.raster_task.Reset(); |
| 780 |
| 781 // Tile resources can't be freed until upload has completed. |
| 782 DCHECK_EQ(USING_UNRELEASABLE_MEMORY, tile->drawing_info().memory_state_); |
| 783 | 783 |
| 784 // Release raster resources. | 784 // Release raster resources. |
| 785 resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id()); | 785 resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id()); |
| 786 | 786 |
| 787 tile->drawing_info().memory_state_ = USING_RELEASABLE_MEMORY; | 787 if (was_cancelled) { |
| 788 tile->drawing_info().memory_state_ = CAN_USE_MEMORY; |
| 789 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); |
| 790 resource_pool_->ReleaseResource(resource.Pass()); |
| 791 return; |
| 792 } |
| 788 | 793 |
| 789 ManagedTileState& managed_tile_state = tile->managed_state(); | 794 mts.picture_pile_analysis = *analysis; |
| 790 managed_tile_state.picture_pile_analysis = *analysis; | 795 mts.picture_pile_analyzed = true; |
| 791 managed_tile_state.picture_pile_analyzed = true; | |
| 792 | 796 |
| 793 if (analysis->is_solid_color) { | 797 if (analysis->is_solid_color) { |
| 794 tile->drawing_info().set_solid_color(analysis->solid_color); | 798 tile->drawing_info().set_solid_color(analysis->solid_color); |
| 795 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); | 799 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); |
| 796 resource_pool_->ReleaseResource(resource.Pass()); | 800 resource_pool_->ReleaseResource(resource.Pass()); |
| 797 DidFinishTileInitialization(tile); | 801 DidFinishTileInitialization(tile); |
| 798 return; | 802 return; |
| 799 } | 803 } |
| 800 | 804 |
| 801 // Tile can be freed after the completion of the raster task. Call | 805 resource_pool_->resource_provider()->BeginSetPixels(resource->id()); |
| 802 // AssignGpuMemoryToTiles() to re-assign gpu memory to highest priority | 806 has_performed_uploads_since_last_flush_ = true; |
| 803 // tiles if ManageTiles() was called since task was dispatched. The result | |
| 804 // of this could be that this tile is no longer allowed to use gpu | |
| 805 // memory and in that case we need to abort initialization and free all | |
| 806 // associated resources before calling DispatchMoreTasks(). | |
| 807 if (manage_tiles_call_count_when_dispatched != manage_tiles_call_count_) | |
| 808 AssignGpuMemoryToTiles(); | |
| 809 | 807 |
| 810 // Finish resource initialization we're still using memory. | 808 tile->drawing_info().resource_ = resource.Pass(); |
| 811 if (tile->drawing_info().memory_state_ == USING_RELEASABLE_MEMORY) { | |
| 812 // Tile resources can't be freed until upload has completed. | |
| 813 tile->drawing_info().memory_state_ = USING_UNRELEASABLE_MEMORY; | |
| 814 | 809 |
| 815 resource_pool_->resource_provider()->BeginSetPixels(resource->id()); | 810 bytes_pending_upload_ += tile->bytes_consumed_if_allocated(); |
| 816 has_performed_uploads_since_last_flush_ = true; | 811 tiles_with_pending_upload_.push(tile); |
| 817 | |
| 818 tile->drawing_info().resource_ = resource.Pass(); | |
| 819 | |
| 820 bytes_pending_upload_ += tile->bytes_consumed_if_allocated(); | |
| 821 tiles_with_pending_upload_.push(tile); | |
| 822 } else { | |
| 823 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); | |
| 824 resource_pool_->ReleaseResource(resource.Pass()); | |
| 825 } | |
| 826 } | 812 } |
| 827 | 813 |
| 828 void TileManager::DidFinishTileInitialization(Tile* tile) { | 814 void TileManager::DidFinishTileInitialization(Tile* tile) { |
| 829 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0) | 815 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0) |
| 830 did_initialize_visible_tile_ = true; | 816 did_initialize_visible_tile_ = true; |
| 831 } | 817 } |
| 832 | 818 |
| 833 void TileManager::DidTileTreeBinChange(Tile* tile, | 819 void TileManager::DidTileTreeBinChange(Tile* tile, |
| 834 TileManagerBin new_tree_bin, | 820 TileManagerBin new_tree_bin, |
| 835 WhichTree tree) { | 821 WhichTree tree) { |
| 836 ManagedTileState& mts = tile->managed_state(); | 822 ManagedTileState& mts = tile->managed_state(); |
| 837 mts.tree_bin[tree] = new_tree_bin; | 823 mts.tree_bin[tree] = new_tree_bin; |
| 838 } | 824 } |
| 839 | 825 |
| 840 // static | 826 // static |
| 827 void TileManager::RunImageDecodeTask( |
| 828 skia::LazyPixelRef* pixel_ref, |
| 829 int layer_id, |
| 830 RenderingStatsInstrumentation* stats_instrumentation) { |
| 831 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask"); |
| 832 devtools_instrumentation::ScopedImageDecodeTask image_decode_task(layer_id); |
| 833 base::TimeTicks start_time = stats_instrumentation->StartRecording(); |
| 834 pixel_ref->Decode(); |
| 835 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time); |
| 836 stats_instrumentation->AddDeferredImageDecode(duration); |
| 837 } |
| 838 |
| 839 // static |
| 841 void TileManager::RunAnalyzeAndRasterTask( | 840 void TileManager::RunAnalyzeAndRasterTask( |
| 842 const RasterWorkerPool::RasterCallback& analyze_task, | 841 const RasterWorkerPool::PictureTask::Callback& analyze_task, |
| 843 const RasterWorkerPool::RasterCallback& raster_task, | 842 const RasterWorkerPool::PictureTask::Callback& raster_task, |
| 844 PicturePileImpl* picture_pile) { | 843 PicturePileImpl* picture_pile) { |
| 845 analyze_task.Run(picture_pile); | 844 analyze_task.Run(picture_pile); |
| 846 raster_task.Run(picture_pile); | 845 raster_task.Run(picture_pile); |
| 847 } | 846 } |
| 848 | 847 |
| 849 // static | 848 // static |
| 850 void TileManager::RunAnalyzeTask( | 849 void TileManager::RunAnalyzeTask( |
| 851 PicturePileImpl::Analysis* analysis, | 850 PicturePileImpl::Analysis* analysis, |
| 852 gfx::Rect rect, | 851 gfx::Rect rect, |
| 853 float contents_scale, | 852 float contents_scale, |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 "Renderer4.PictureRasterTimeUS", | 929 "Renderer4.PictureRasterTimeUS", |
| 931 raster_stats.total_rasterize_time.InMicroseconds(), | 930 raster_stats.total_rasterize_time.InMicroseconds(), |
| 932 0, | 931 0, |
| 933 100000, | 932 100000, |
| 934 100); | 933 100); |
| 935 } else { | 934 } else { |
| 936 picture_pile->Raster(&canvas, rect, contents_scale, NULL); | 935 picture_pile->Raster(&canvas, rect, contents_scale, NULL); |
| 937 } | 936 } |
| 938 } | 937 } |
| 939 | 938 |
| 940 // static | |
| 941 void TileManager::RunImageDecodeTask( | |
| 942 skia::LazyPixelRef* pixel_ref, | |
| 943 int layer_id, | |
| 944 RenderingStatsInstrumentation* stats_instrumentation) { | |
| 945 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask"); | |
| 946 devtools_instrumentation::ScopedImageDecodeTask image_decode_task(layer_id); | |
| 947 base::TimeTicks start_time = stats_instrumentation->StartRecording(); | |
| 948 pixel_ref->Decode(); | |
| 949 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time); | |
| 950 stats_instrumentation->AddDeferredImageDecode(duration); | |
| 951 } | |
| 952 | |
| 953 } // namespace cc | 939 } // namespace cc |
| OLD | NEW |