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