Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Side by Side Diff: cc/resources/tile_manager.cc

Issue 14689004: Re-land: cc: Cancel and re-prioritize worker pool tasks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: keep image cache check Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 ResourceProvider* resource_provider, 128 ResourceProvider* resource_provider,
129 scoped_ptr<RasterWorkerPool> raster_worker_pool, 129 scoped_ptr<RasterWorkerPool> raster_worker_pool,
130 size_t num_raster_threads, 130 size_t num_raster_threads,
131 bool use_color_estimator, 131 bool use_color_estimator,
132 RenderingStatsInstrumentation* rendering_stats_instrumentation, 132 RenderingStatsInstrumentation* rendering_stats_instrumentation,
133 bool use_map_image) 133 bool use_map_image)
134 : client_(client), 134 : client_(client),
135 resource_pool_(ResourcePool::Create(resource_provider)), 135 resource_pool_(ResourcePool::Create(resource_provider)),
136 raster_worker_pool_(raster_worker_pool.Pass()), 136 raster_worker_pool_(raster_worker_pool.Pass()),
137 manage_tiles_pending_(false), 137 manage_tiles_pending_(false),
138 manage_tiles_call_count_(0),
139 bytes_pending_upload_(0), 138 bytes_pending_upload_(0),
140 has_performed_uploads_since_last_flush_(false), 139 has_performed_uploads_since_last_flush_(false),
141 ever_exceeded_memory_budget_(false), 140 ever_exceeded_memory_budget_(false),
142 rendering_stats_instrumentation_(rendering_stats_instrumentation), 141 rendering_stats_instrumentation_(rendering_stats_instrumentation),
143 use_color_estimator_(use_color_estimator), 142 use_color_estimator_(use_color_estimator),
144 did_initialize_visible_tile_(false), 143 did_initialize_visible_tile_(false),
145 pending_tasks_(0),
146 max_pending_tasks_(kMaxNumPendingTasksPerThread * num_raster_threads) { 144 max_pending_tasks_(kMaxNumPendingTasksPerThread * num_raster_threads) {
147 raster_worker_pool_->SetClient(this); 145 raster_worker_pool_->SetClient(this);
148 } 146 }
149 147
150 TileManager::~TileManager() { 148 TileManager::~TileManager() {
151 // Reset global state and manage. This should cause 149 // Reset global state and manage. This should cause
152 // our memory usage to drop to zero. 150 // our memory usage to drop to zero.
153 global_state_ = GlobalStateThatImpactsTilePriority(); 151 global_state_ = GlobalStateThatImpactsTilePriority();
154 AssignGpuMemoryToTiles(); 152 AssignGpuMemoryToTiles();
155 // This should finish all pending tasks and release any uninitialized 153 // This should finish all pending tasks and release any uninitialized
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 TRACE_EVENT0("cc", "TileManager::SortTiles"); 300 TRACE_EVENT0("cc", "TileManager::SortTiles");
303 301
304 // Sort by bin, resolution and time until needed. 302 // Sort by bin, resolution and time until needed.
305 std::sort(tiles_.begin(), tiles_.end(), BinComparator()); 303 std::sort(tiles_.begin(), tiles_.end(), BinComparator());
306 } 304 }
307 305
308 void TileManager::ManageTiles() { 306 void TileManager::ManageTiles() {
309 TRACE_EVENT0("cc", "TileManager::ManageTiles"); 307 TRACE_EVENT0("cc", "TileManager::ManageTiles");
310 308
311 manage_tiles_pending_ = false; 309 manage_tiles_pending_ = false;
312 ++manage_tiles_call_count_;
313 310
314 AssignBinsToTiles(); 311 AssignBinsToTiles();
315 SortTiles(); 312 SortTiles();
316 AssignGpuMemoryToTiles(); 313 AssignGpuMemoryToTiles();
317 314
318 TRACE_EVENT_INSTANT1( 315 TRACE_EVENT_INSTANT1(
319 "cc", "DidManage", TRACE_EVENT_SCOPE_THREAD, 316 "cc", "DidManage", TRACE_EVENT_SCOPE_THREAD,
320 "state", TracedValue::FromValue(BasicStateAsValue().release())); 317 "state", TracedValue::FromValue(BasicStateAsValue().release()));
321 318
322 // Finally, kick the rasterizer. 319 // Finally, schedule rasterizer tasks.
323 DispatchMoreTasks(); 320 ScheduleTasks();
324 } 321 }
325 322
326 void TileManager::CheckForCompletedTileUploads() { 323 void TileManager::CheckForCompletedTileUploads() {
327 while (!tiles_with_pending_upload_.empty()) { 324 while (!tiles_with_pending_upload_.empty()) {
328 Tile* tile = tiles_with_pending_upload_.front(); 325 Tile* tile = tiles_with_pending_upload_.front();
329 DCHECK(tile->tile_version().resource_); 326 DCHECK(tile->tile_version().resource_);
330 327
331 // Set pixel tasks complete in the order they are posted. 328 // Set pixel tasks complete in the order they are posted.
332 if (!resource_pool_->resource_provider()->DidSetPixelsComplete( 329 if (!resource_pool_->resource_provider()->DidSetPixelsComplete(
333 tile->tile_version().resource_->id())) { 330 tile->tile_version().resource_->id())) {
334 break; 331 break;
335 } 332 }
336 333
337 // It's now safe to release the pixel buffer. 334 // It's now safe to release the pixel buffer.
338 resource_pool_->resource_provider()->ReleasePixelBuffer( 335 resource_pool_->resource_provider()->ReleasePixelBuffer(
339 tile->tile_version().resource_->id()); 336 tile->tile_version().resource_->id());
340 337
341 bytes_pending_upload_ -= tile->bytes_consumed_if_allocated(); 338 bytes_pending_upload_ -= tile->bytes_consumed_if_allocated();
342 bool was_forced = tile->tile_version().forced_upload_; 339 bool was_forced = tile->tile_version().forced_upload_;
343 // Reset forced_upload_ since we now got the upload completed notification. 340 // Reset forced_upload_ since we now got the upload completed notification.
344 tile->tile_version().forced_upload_ = false; 341 tile->tile_version().forced_upload_ = false;
345 tile->tile_version().memory_state_ = USING_RELEASABLE_MEMORY; 342 tile->tile_version().memory_state_ = USING_RELEASABLE_MEMORY;
346 if (!was_forced) 343 if (!was_forced)
347 DidFinishTileInitialization(tile); 344 DidFinishTileInitialization(tile);
348 345
349 tiles_with_pending_upload_.pop(); 346 tiles_with_pending_upload_.pop();
350 } 347 }
351 348
352 DispatchMoreTasks(); 349 ScheduleTasks();
353 } 350 }
354 351
355 void TileManager::AbortPendingTileUploads() { 352 void TileManager::AbortPendingTileUploads() {
356 while (!tiles_with_pending_upload_.empty()) { 353 while (!tiles_with_pending_upload_.empty()) {
357 Tile* tile = tiles_with_pending_upload_.front(); 354 Tile* tile = tiles_with_pending_upload_.front();
358 DCHECK(tile->tile_version().resource_); 355 DCHECK(tile->tile_version().resource_);
359 356
360 resource_pool_->resource_provider()->AbortSetPixels( 357 resource_pool_->resource_provider()->AbortSetPixels(
361 tile->tile_version().resource_->id()); 358 tile->tile_version().resource_->id());
362 resource_pool_->resource_provider()->ReleasePixelBuffer( 359 resource_pool_->resource_provider()->ReleasePixelBuffer(
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 tiles_that_need_to_be_initialized_for_activation_.insert(tile); 459 tiles_that_need_to_be_initialized_for_activation_.insert(tile);
463 } 460 }
464 461
465 void TileManager::DidFinishDispatchingWorkerPoolCompletionCallbacks() { 462 void TileManager::DidFinishDispatchingWorkerPoolCompletionCallbacks() {
466 // If a flush is needed, do it now before starting to dispatch more tasks. 463 // If a flush is needed, do it now before starting to dispatch more tasks.
467 if (has_performed_uploads_since_last_flush_) { 464 if (has_performed_uploads_since_last_flush_) {
468 resource_pool_->resource_provider()->ShallowFlushIfSupported(); 465 resource_pool_->resource_provider()->ShallowFlushIfSupported();
469 has_performed_uploads_since_last_flush_ = false; 466 has_performed_uploads_since_last_flush_ = false;
470 } 467 }
471 468
472 DispatchMoreTasks(); 469 ScheduleTasks();
473 } 470 }
474 471
475 void TileManager::AssignGpuMemoryToTiles() { 472 void TileManager::AssignGpuMemoryToTiles() {
476 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); 473 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles");
477 size_t unreleasable_bytes = 0; 474 size_t unreleasable_bytes = 0;
478 475
479 // Now give memory out to the tiles until we're out, and build 476 // Now give memory out to the tiles until we're out, and build
480 // the needs-to-be-rasterized queue. 477 // the needs-to-be-rasterized queue.
481 tiles_that_need_to_be_rasterized_.clear(); 478 tiles_that_need_to_be_rasterized_.clear();
482 tiles_that_need_to_be_initialized_for_activation_.clear(); 479 tiles_that_need_to_be_initialized_for_activation_.clear();
483 480
484 // By clearing the tiles_that_need_to_be_rasterized_ vector list 481 // By clearing the tiles_that_need_to_be_rasterized_ vector list
485 // above we move all tiles currently waiting for raster to idle state. 482 // above we move all tiles currently waiting for raster to idle state.
486 // Some memory cannot be released. We figure out how much in this 483 // Some memory cannot be released. We figure out how much in this
487 // loop as well. 484 // loop.
488 for (TileVector::const_iterator it = tiles_.begin(); 485 for (TileVector::const_iterator it = tiles_.begin();
489 it != tiles_.end(); 486 it != tiles_.end();
490 ++it) { 487 ++it) {
491 const Tile* tile = *it; 488 const Tile* tile = *it;
492 if (tile->tile_version().memory_state_ == USING_UNRELEASABLE_MEMORY) 489 if (tile->tile_version().memory_state_ == USING_UNRELEASABLE_MEMORY)
493 unreleasable_bytes += tile->bytes_consumed_if_allocated(); 490 unreleasable_bytes += tile->bytes_consumed_if_allocated();
494 } 491 }
495 492
496 // Global state's memory limit can decrease, causing 493 // Global state's memory limit can decrease, causing
497 // it to be less than unreleasable_bytes 494 // it to be less than unreleasable_bytes
498 size_t bytes_allocatable = 495 size_t bytes_allocatable =
499 global_state_.memory_limit_in_bytes > unreleasable_bytes ? 496 global_state_.memory_limit_in_bytes > unreleasable_bytes ?
500 global_state_.memory_limit_in_bytes - unreleasable_bytes : 497 global_state_.memory_limit_in_bytes - unreleasable_bytes :
501 0; 498 0;
502 size_t bytes_that_exceeded_memory_budget_in_now_bin = 0; 499 size_t bytes_that_exceeded_memory_budget_in_now_bin = 0;
503 size_t bytes_left = bytes_allocatable; 500 size_t bytes_left = bytes_allocatable;
504 size_t bytes_oom_in_now_bin_on_pending_tree = 0; 501 size_t bytes_oom_in_now_bin_on_pending_tree = 0;
505 TileVector tiles_requiring_memory_but_oomed; 502 TileVector tiles_requiring_memory_but_oomed;
503 bool higher_priority_tile_oomed = false;
506 for (TileVector::iterator it = tiles_.begin(); 504 for (TileVector::iterator it = tiles_.begin();
507 it != tiles_.end(); 505 it != tiles_.end();
508 ++it) { 506 ++it) {
509 Tile* tile = *it; 507 Tile* tile = *it;
510 ManagedTileState& mts = tile->managed_state(); 508 ManagedTileState& mts = tile->managed_state();
511 ManagedTileState::TileVersion& tile_version = tile->tile_version(); 509 ManagedTileState::TileVersion& tile_version = tile->tile_version();
512 510
513 // If this tile doesn't need a resource, then nothing to do. 511 // If this tile doesn't need a resource, then nothing to do.
514 if (!tile_version.requires_resource()) 512 if (!tile_version.requires_resource())
515 continue; 513 continue;
516 514
517 // If the memory is unreleasable, then we do not need to do anything. 515 size_t tile_bytes = tile->bytes_consumed_if_allocated();
518 if (tile_version.memory_state_ == USING_UNRELEASABLE_MEMORY) { 516 // Memory is already reserved for tile with unreleasable memory
519 if (tile->required_for_activation()) { 517 // so adding it to |tiles_that_need_to_be_rasterized_| doesn't
520 AddRequiredTileForActivation(tile); 518 // affect bytes_allocatable.
521 // If after rasterizing, this tile has become required or the client has 519 if (tile_version.memory_state_ == USING_UNRELEASABLE_MEMORY)
522 // changed its mind about forcing tiles, do that now. 520 tile_bytes = 0;
523 if (!tile->tile_version().forced_upload_ && 521
524 client_->ShouldForceTileUploadsRequiredForActivationToComplete()) { 522 // If the tile is not needed, free it up.
525 ForceTileUploadToComplete(tile); 523 if (mts.is_in_never_bin_on_both_trees()) {
526 } 524 if (tile_version.memory_state_ != USING_UNRELEASABLE_MEMORY) {
525 FreeResourcesForTile(tile);
526 tile_version.memory_state_ = NOT_ALLOWED_TO_USE_MEMORY;
527 } 527 }
528 continue; 528 continue;
529 } 529 }
530 530
531 size_t tile_bytes = tile->bytes_consumed_if_allocated();
532 // If the tile is not needed, free it up.
533 if (mts.is_in_never_bin_on_both_trees()) {
534 FreeResourcesForTile(tile);
535 tile_version.memory_state_ = NOT_ALLOWED_TO_USE_MEMORY;
536 continue;
537 }
538 // Tile is OOM. 531 // Tile is OOM.
539 if (tile_bytes > bytes_left) { 532 if (tile_bytes > bytes_left) {
540 FreeResourcesForTile(tile);
541 tile->tile_version().set_rasterize_on_demand(); 533 tile->tile_version().set_rasterize_on_demand();
542 if (mts.tree_bin[PENDING_TREE] == NOW_BIN) { 534 if (mts.tree_bin[PENDING_TREE] == NOW_BIN) {
543 tiles_requiring_memory_but_oomed.push_back(tile); 535 tiles_requiring_memory_but_oomed.push_back(tile);
544 bytes_oom_in_now_bin_on_pending_tree += tile_bytes; 536 bytes_oom_in_now_bin_on_pending_tree += tile_bytes;
545 } 537 }
538 FreeResourcesForTile(tile);
539 higher_priority_tile_oomed = true;
546 continue; 540 continue;
547 } 541 }
542
548 tile_version.set_use_resource(); 543 tile_version.set_use_resource();
549 bytes_left -= tile_bytes; 544 bytes_left -= tile_bytes;
550 if (!tile_version.resource_ && 545
551 tile_version.memory_state_ == CAN_USE_MEMORY) { 546 // Tile shouldn't be rasterized if we've failed to assign
547 // gpu memory to a higher priority tile. This is important for
548 // two reasons:
549 // 1. Tile size should not impact raster priority.
550 // 2. Tile with unreleasable memory could otherwise incorrectly
551 // be added as it's not affected by |bytes_allocatable|.
552 if (higher_priority_tile_oomed)
553 continue;
554
555 if (!tile_version.resource_)
552 tiles_that_need_to_be_rasterized_.push_back(tile); 556 tiles_that_need_to_be_rasterized_.push_back(tile);
553 } 557
554 if (!tile_version.resource_ && tile->required_for_activation()) 558 if (!tile_version.resource_ && tile->required_for_activation())
555 AddRequiredTileForActivation(tile); 559 AddRequiredTileForActivation(tile);
560
561 if (tile_version.memory_state_ == USING_UNRELEASABLE_MEMORY &&
562 tile->required_for_activation()) {
563 // If after rasterizing, this tile has become required or the client has
564 // changed its mind about forcing tiles, do that now.
565 if (!tile->tile_version().forced_upload_ &&
566 client_->ShouldForceTileUploadsRequiredForActivationToComplete()) {
567 ForceTileUploadToComplete(tile);
568 }
569 }
556 } 570 }
557 571
558 // In OOM situation, we iterate tiles_, remove the memory for active tree 572 // In OOM situation, we iterate tiles_, remove the memory for active tree
559 // and not the now bin. And give them to bytes_oom_in_now_bin_on_pending_tree 573 // and not the now bin. And give them to bytes_oom_in_now_bin_on_pending_tree
560 if (!tiles_requiring_memory_but_oomed.empty()) { 574 if (!tiles_requiring_memory_but_oomed.empty()) {
561 size_t bytes_freed = 0; 575 size_t bytes_freed = 0;
562 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { 576 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
563 Tile* tile = *it; 577 Tile* tile = *it;
564 ManagedTileState& mts = tile->managed_state(); 578 ManagedTileState& mts = tile->managed_state();
565 ManagedTileState::TileVersion& tile_version = tile->tile_version(); 579 ManagedTileState::TileVersion& tile_version = tile->tile_version();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 "budget", global_state_.memory_limit_in_bytes, 618 "budget", global_state_.memory_limit_in_bytes,
605 "over", bytes_that_exceeded_memory_budget_in_now_bin); 619 "over", bytes_that_exceeded_memory_budget_in_now_bin);
606 } 620 }
607 memory_stats_from_last_assign_.total_budget_in_bytes = 621 memory_stats_from_last_assign_.total_budget_in_bytes =
608 global_state_.memory_limit_in_bytes; 622 global_state_.memory_limit_in_bytes;
609 memory_stats_from_last_assign_.bytes_allocated = 623 memory_stats_from_last_assign_.bytes_allocated =
610 bytes_allocatable - bytes_left; 624 bytes_allocatable - bytes_left;
611 memory_stats_from_last_assign_.bytes_unreleasable = unreleasable_bytes; 625 memory_stats_from_last_assign_.bytes_unreleasable = unreleasable_bytes;
612 memory_stats_from_last_assign_.bytes_over = 626 memory_stats_from_last_assign_.bytes_over =
613 bytes_that_exceeded_memory_budget_in_now_bin; 627 bytes_that_exceeded_memory_budget_in_now_bin;
614
615 // Reverse two tiles_that_need_* vectors such that pop_back gets
616 // the highest priority tile.
617 std::reverse(
618 tiles_that_need_to_be_rasterized_.begin(),
619 tiles_that_need_to_be_rasterized_.end());
620 } 628 }
621 629
622 void TileManager::FreeResourcesForTile(Tile* tile) { 630 void TileManager::FreeResourcesForTile(Tile* tile) {
623 DCHECK(tile->tile_version().memory_state_ != USING_UNRELEASABLE_MEMORY); 631 DCHECK_NE(USING_UNRELEASABLE_MEMORY, tile->tile_version().memory_state_);
624 if (tile->tile_version().resource_) { 632 if (tile->tile_version().resource_) {
625 resource_pool_->ReleaseResource( 633 resource_pool_->ReleaseResource(
626 tile->tile_version().resource_.Pass()); 634 tile->tile_version().resource_.Pass());
627 } 635 }
628 tile->tile_version().memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; 636 tile->tile_version().memory_state_ = NOT_ALLOWED_TO_USE_MEMORY;
629 } 637 }
630 638
631 bool TileManager::CanDispatchRasterTask(Tile* tile) const { 639 void TileManager::ScheduleTasks() {
632 if (pending_tasks_ >= max_pending_tasks_) 640 TRACE_EVENT0("cc", "TileManager::ScheduleTasks");
633 return false; 641 RasterWorkerPool::Task::Queue tasks;
634 size_t new_bytes_pending = bytes_pending_upload_;
635 new_bytes_pending += tile->bytes_consumed_if_allocated();
636 return new_bytes_pending <= kMaxPendingUploadBytes &&
637 tiles_with_pending_upload_.size() < kMaxPendingUploads;
638 }
639 642
640 void TileManager::DispatchMoreTasks() { 643 size_t bytes_pending_upload = bytes_pending_upload_;
641 TileVector tiles_with_image_decoding_tasks; 644 unsigned pending_tasks = 0;
642 645
643 // Process all tiles in the need_to_be_rasterized queue: 646 // Build a new task queue containing all task currently needed. Tasks
644 // 1. Dispatch image decode tasks. 647 // are added in order of priority, highest priority task first.
645 // 2. If the image decode isn't done, save the tile for later processing. 648 for (TileVector::iterator it = tiles_that_need_to_be_rasterized_.begin();
646 // 3. Attempt to dispatch a raster task, or break out of the loop. 649 it != tiles_that_need_to_be_rasterized_.end();
647 while (!tiles_that_need_to_be_rasterized_.empty()) { 650 ++it) {
648 Tile* tile = tiles_that_need_to_be_rasterized_.back(); 651 Tile* tile = *it;
652 ManagedTileState& mts = tile->managed_state();
649 653
650 DCHECK(tile->tile_version().requires_resource()); 654 // Skip tile if determined to not require resource.
655 if (!tile->tile_version().requires_resource())
656 continue;
651 657
652 if (DispatchImageDecodeTasksForTile(tile)) { 658 // Skip tile if already rasterized.
653 tiles_with_image_decoding_tasks.push_back(tile); 659 if (tile->tile_version().resource_)
654 } else if (!CanDispatchRasterTask(tile)) { 660 continue;
655 break; 661
656 } else { 662 // TODO(reveman): Remove throttling based on max pending tasks.
657 DispatchOneRasterTask(tile); 663 if (pending_tasks >= max_pending_tasks_)
658 } 664 break;
659 tiles_that_need_to_be_rasterized_.pop_back(); 665
666 // TODO(reveman): Remove throttling based on max pending uploads.
667 if (tiles_with_pending_upload_.size() >= kMaxPendingUploads)
668 break;
669
670 // TODO(reveman): Throttle based on shared memory usage rather
671 // than bytes pending upload.
672 size_t new_bytes_pending = bytes_pending_upload;
673 new_bytes_pending += tile->bytes_consumed_if_allocated();
674 if (new_bytes_pending > kMaxPendingUploadBytes)
675 break;
676 bytes_pending_upload = new_bytes_pending;
677
678 // Create raster task for this tile if necessary.
679 if (mts.raster_task.is_null())
680 mts.raster_task = CreateRasterTask(tile);
681
682 // Finally append raster task.
683 tasks.Append(mts.raster_task);
684 pending_tasks++;
660 } 685 }
661 686
662 // Put the saved tiles back into the queue. The order is reversed 687 if (!tasks.empty()) {
663 // to preserve original ordering. 688 RasterWorkerPool::Task root(&tasks);
664 tiles_that_need_to_be_rasterized_.insert( 689
665 tiles_that_need_to_be_rasterized_.end(), 690 // Schedule running of tasks in |task_schedule|. This replaces any
666 tiles_with_image_decoding_tasks.rbegin(), 691 // previously scheduled tasks and effectively cancels any tasks
667 tiles_with_image_decoding_tasks.rend()); 692 // not present in |task_schedule|.
693 raster_worker_pool_->ScheduleTasks(&root);
694 } else {
695 raster_worker_pool_->ScheduleTasks(NULL);
696 }
668 697
669 if (did_initialize_visible_tile_) { 698 if (did_initialize_visible_tile_) {
670 did_initialize_visible_tile_ = false; 699 did_initialize_visible_tile_ = false;
671 client_->DidInitializeVisibleTile(); 700 client_->DidInitializeVisibleTile();
672 } 701 }
673 } 702 }
674 703
675 bool TileManager::DispatchImageDecodeTasksForTile(Tile* tile) { 704 RasterWorkerPool::Task TileManager::CreateImageDecodeTask(
676 TRACE_EVENT0("cc", "TileManager::DispatchImageDecodeTasksForTile"); 705 Tile* tile, skia::LazyPixelRef* pixel_ref) {
677 ManagedTileState& mts = tile->managed_state(); 706 TRACE_EVENT0("cc", "TileManager::CreateImageDecodeTask");
678 bool pending_decode_tasks = false;
679 707
708 return RasterWorkerPool::Task(
709 base::Bind(&TileManager::RunImageDecodeTask,
710 pixel_ref,
711 tile->layer_id(),
712 rendering_stats_instrumentation_),
713 base::Bind(&TileManager::OnImageDecodeTaskCompleted,
714 base::Unretained(this),
715 make_scoped_refptr(tile),
716 pixel_ref->getGenerationID()));
717 }
718
719 void TileManager::OnImageDecodeTaskCompleted(scoped_refptr<Tile> tile,
720 uint32_t pixel_ref_id,
721 bool was_cancelled) {
722 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted");
723 DCHECK(pending_decode_tasks_.find(pixel_ref_id) !=
724 pending_decode_tasks_.end());
725 pending_decode_tasks_.erase(pixel_ref_id);
726 }
727
728 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata(
729 const Tile& tile) const {
730 RasterTaskMetadata metadata;
731 const ManagedTileState& mts = tile.managed_state();
732 metadata.is_tile_in_pending_tree_now_bin =
733 mts.tree_bin[PENDING_TREE] == NOW_BIN;
734 metadata.tile_resolution = mts.resolution;
735 metadata.layer_id = tile.layer_id();
736 metadata.tile_id = &tile;
737 metadata.source_frame_number = tile.source_frame_number();
738 return metadata;
739 }
740
741 RasterWorkerPool::Task TileManager::CreateRasterTask(Tile* tile) {
742 TRACE_EVENT0("cc", "TileManager::CreateRasterTask");
743
744 scoped_ptr<ResourcePool::Resource> resource =
745 resource_pool_->AcquireResource(
746 tile->tile_size_.size(),
747 tile->tile_version().resource_format_);
748 resource_pool_->resource_provider()->AcquirePixelBuffer(resource->id());
749
750 DCHECK_EQ(CAN_USE_MEMORY, tile->tile_version().memory_state_);
751 tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY;
752
753 PicturePileImpl::Analysis* analysis = new PicturePileImpl::Analysis;
754
755 // MapPixelBuffer() returns NULL if context was lost at the time
756 // AcquirePixelBuffer() was called. For simplicity we still create
757 // a raster task that is essentially a noop in these situations.
758 uint8* buffer = resource_pool_->resource_provider()->MapPixelBuffer(
759 resource->id());
760
761 // Create image decode schedule that his tile depends on.
762 RasterWorkerPool::Task::Queue decode_tasks;
680 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(), 763 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(),
681 tile->contents_scale(), 764 tile->contents_scale(),
682 tile->picture_pile()); 765 tile->picture_pile());
683 iter; ++iter) { 766 iter; ++iter) {
684 skia::LazyPixelRef* pixel_ref = *iter; 767 skia::LazyPixelRef* pixel_ref = *iter;
685 uint32_t id = pixel_ref->getGenerationID(); 768 uint32_t id = pixel_ref->getGenerationID();
686 769
687 // Check if image has already been decoded. 770 // Append existing image decode task if available.
688 if (mts.decoded_pixel_refs.find(id) != mts.decoded_pixel_refs.end()) 771 PixelRefMap::iterator decode_task_it = pending_decode_tasks_.find(id);
689 continue; 772 if (decode_task_it != pending_decode_tasks_.end()) {
690 773 decode_tasks.Append(decode_task_it->second);
691 // Check if decode task is already pending.
692 if (pending_decode_tasks_.find(id) != pending_decode_tasks_.end()) {
693 pending_decode_tasks = true;
694 continue; 774 continue;
695 } 775 }
696 776
697 // TODO(qinmin): passing correct image size to PrepareToDecode(). 777 // TODO(qinmin): passing correct image size to PrepareToDecode().
698 if (pixel_ref->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) { 778 if (pixel_ref->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) {
699 rendering_stats_instrumentation_->IncrementDeferredImageCacheHitCount(); 779 rendering_stats_instrumentation_->IncrementDeferredImageCacheHitCount();
700 mts.decoded_pixel_refs.insert(id);
701 continue; 780 continue;
702 } 781 }
703 782
704 if (pending_tasks_ >= max_pending_tasks_) 783 // Create and append new image decode task for this pixel ref.
705 break; 784 RasterWorkerPool::Task decode_task = CreateImageDecodeTask(
706 785 tile, pixel_ref);
707 DispatchOneImageDecodeTask(tile, pixel_ref); 786 decode_tasks.Append(decode_task);
708 pending_decode_tasks = true; 787 pending_decode_tasks_[id] = decode_task;
709 } 788 }
710 789
711 return pending_decode_tasks; 790 return RasterWorkerPool::PictureTask(
712 }
713
714 void TileManager::DispatchOneImageDecodeTask(
715 scoped_refptr<Tile> tile, skia::LazyPixelRef* pixel_ref) {
716 TRACE_EVENT0("cc", "TileManager::DispatchOneImageDecodeTask");
717 uint32_t pixel_ref_id = pixel_ref->getGenerationID();
718 DCHECK(pending_decode_tasks_.end() ==
719 pending_decode_tasks_.find(pixel_ref_id));
720 pending_decode_tasks_.insert(pixel_ref_id);
721
722 raster_worker_pool_->PostTaskAndReply(
723 base::Bind(&TileManager::RunImageDecodeTask,
724 pixel_ref,
725 tile->layer_id(),
726 rendering_stats_instrumentation_),
727 base::Bind(&TileManager::OnImageDecodeTaskCompleted,
728 base::Unretained(this),
729 tile,
730 pixel_ref_id));
731 pending_tasks_++;
732 }
733
734 void TileManager::OnImageDecodeTaskCompleted(
735 scoped_refptr<Tile> tile, uint32_t pixel_ref_id) {
736 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted");
737 ManagedTileState& mts = tile->managed_state();
738 mts.decoded_pixel_refs.insert(pixel_ref_id);
739 pending_decode_tasks_.erase(pixel_ref_id);
740 pending_tasks_--;
741 }
742
743 scoped_ptr<ResourcePool::Resource> TileManager::PrepareTileForRaster(
744 Tile* tile) {
745 scoped_ptr<ResourcePool::Resource> resource = resource_pool_->AcquireResource(
746 tile->tile_size_.size(),
747 tile->tile_version().resource_format_);
748 resource_pool_->resource_provider()->AcquirePixelBuffer(resource->id());
749
750 tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY;
751
752 return resource.Pass();
753 }
754
755 void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) {
756 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask");
757 scoped_ptr<ResourcePool::Resource> resource = PrepareTileForRaster(tile);
758 ResourceProvider::ResourceId resource_id = resource->id();
759 PicturePileImpl::Analysis* analysis = new PicturePileImpl::Analysis;
760
761 // MapPixelBuffer() returns NULL if context was lost at the time
762 // AcquirePixelBuffer() was called. For simplicity we still post
763 // a raster task that is essentially a noop in these situations.
764 uint8* buffer = resource_pool_->resource_provider()->MapPixelBuffer(
765 resource_id);
766
767 // skia requires that our buffer be 4-byte aligned
768 CHECK(!(reinterpret_cast<intptr_t>(buffer) & 3));
769
770 raster_worker_pool_->PostRasterTaskAndReply(
771 tile->picture_pile(), 791 tile->picture_pile(),
772 base::Bind(&TileManager::RunAnalyzeAndRasterTask, 792 base::Bind(&TileManager::RunAnalyzeAndRasterTask,
773 base::Bind(&TileManager::RunAnalyzeTask, 793 base::Bind(&TileManager::RunAnalyzeTask,
774 analysis, 794 analysis,
775 tile->content_rect(), 795 tile->content_rect(),
776 tile->contents_scale(), 796 tile->contents_scale(),
777 use_color_estimator_, 797 use_color_estimator_,
778 GetRasterTaskMetadata(*tile), 798 GetRasterTaskMetadata(*tile),
779 rendering_stats_instrumentation_), 799 rendering_stats_instrumentation_),
780 base::Bind(&TileManager::RunRasterTask, 800 base::Bind(&TileManager::RunRasterTask,
781 buffer, 801 buffer,
782 analysis, 802 analysis,
783 tile->content_rect(), 803 tile->content_rect(),
784 tile->contents_scale(), 804 tile->contents_scale(),
785 GetRasterTaskMetadata(*tile), 805 GetRasterTaskMetadata(*tile),
786 rendering_stats_instrumentation_)), 806 rendering_stats_instrumentation_)),
787 base::Bind(&TileManager::OnRasterTaskCompleted, 807 base::Bind(&TileManager::OnRasterTaskCompleted,
788 base::Unretained(this), 808 base::Unretained(this),
789 tile, 809 make_scoped_refptr(tile),
790 base::Passed(&resource), 810 base::Passed(&resource),
791 base::Owned(analysis), 811 base::Owned(analysis)),
792 manage_tiles_call_count_)); 812 &decode_tasks);
793 pending_tasks_++;
794 }
795
796 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata(
797 const Tile& tile) const {
798 RasterTaskMetadata metadata;
799 const ManagedTileState& mts = tile.managed_state();
800 metadata.is_tile_in_pending_tree_now_bin =
801 mts.tree_bin[PENDING_TREE] == NOW_BIN;
802 metadata.tile_resolution = mts.resolution;
803 metadata.layer_id = tile.layer_id();
804 metadata.tile_id = &tile;
805 metadata.source_frame_number = tile.source_frame_number();
806 return metadata;
807 } 813 }
808 814
809 void TileManager::OnRasterTaskCompleted( 815 void TileManager::OnRasterTaskCompleted(
810 scoped_refptr<Tile> tile, 816 scoped_refptr<Tile> tile,
811 scoped_ptr<ResourcePool::Resource> resource, 817 scoped_ptr<ResourcePool::Resource> resource,
812 PicturePileImpl::Analysis* analysis, 818 PicturePileImpl::Analysis* analysis,
813 int manage_tiles_call_count_when_dispatched) { 819 bool was_cancelled) {
814 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); 820 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted");
815 821
816 pending_tasks_--; 822 ManagedTileState& mts = tile->managed_state();
823 DCHECK(!mts.raster_task.is_null());
824 mts.raster_task.Reset();
825
826 // Tile resources can't be freed until upload has completed.
827 DCHECK_EQ(USING_UNRELEASABLE_MEMORY, tile->tile_version().memory_state_);
817 828
818 // Release raster resources. 829 // Release raster resources.
819 resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id()); 830 resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id());
820 831
821 tile->tile_version().memory_state_ = USING_RELEASABLE_MEMORY; 832 if (was_cancelled) {
833 tile->tile_version().memory_state_ = CAN_USE_MEMORY;
834 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id());
835 resource_pool_->ReleaseResource(resource.Pass());
836 return;
837 }
822 838
823 ManagedTileState& managed_tile_state = tile->managed_state(); 839 mts.picture_pile_analysis = *analysis;
824 managed_tile_state.picture_pile_analysis = *analysis; 840 mts.picture_pile_analyzed = true;
825 managed_tile_state.picture_pile_analyzed = true;
826 841
827 if (analysis->is_solid_color) { 842 if (analysis->is_solid_color) {
828 tile->tile_version().set_solid_color(analysis->solid_color); 843 tile->tile_version().set_solid_color(analysis->solid_color);
829 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); 844 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id());
830 resource_pool_->ReleaseResource(resource.Pass()); 845 resource_pool_->ReleaseResource(resource.Pass());
831 DidFinishTileInitialization(tile); 846 DidFinishTileInitialization(tile);
832 return; 847 return;
833 } 848 }
834 849
835 // Tile can be freed after the completion of the raster task. Call 850 resource_pool_->resource_provider()->BeginSetPixels(resource->id());
836 // AssignGpuMemoryToTiles() to re-assign gpu memory to highest priority 851 has_performed_uploads_since_last_flush_ = true;
837 // tiles if ManageTiles() was called since task was dispatched. The result
838 // of this could be that this tile is no longer allowed to use gpu
839 // memory and in that case we need to abort initialization and free all
840 // associated resources before calling DispatchMoreTasks().
841 if (manage_tiles_call_count_when_dispatched != manage_tiles_call_count_)
842 AssignGpuMemoryToTiles();
843 852
844 // Finish resource initialization we're still using memory. 853 tile->tile_version().resource_ = resource.Pass();
845 if (tile->tile_version().memory_state_ == USING_RELEASABLE_MEMORY) {
846 // Tile resources can't be freed until upload has completed.
847 tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY;
848 854
849 resource_pool_->resource_provider()->BeginSetPixels(resource->id()); 855 bytes_pending_upload_ += tile->bytes_consumed_if_allocated();
850 has_performed_uploads_since_last_flush_ = true; 856 tiles_with_pending_upload_.push(tile);
851 857
852 tile->tile_version().resource_ = resource.Pass(); 858 if (tile->required_for_activation() &&
853 859 client_->ShouldForceTileUploadsRequiredForActivationToComplete())
854 bytes_pending_upload_ += tile->bytes_consumed_if_allocated(); 860 ForceTileUploadToComplete(tile);
855 tiles_with_pending_upload_.push(tile);
856
857 if (tile->required_for_activation() &&
858 client_->ShouldForceTileUploadsRequiredForActivationToComplete())
859 ForceTileUploadToComplete(tile);
860 } else {
861 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id());
862 resource_pool_->ReleaseResource(resource.Pass());
863 }
864 } 861 }
865 862
866 void TileManager::DidFinishTileInitialization(Tile* tile) { 863 void TileManager::DidFinishTileInitialization(Tile* tile) {
867 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0) 864 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0)
868 did_initialize_visible_tile_ = true; 865 did_initialize_visible_tile_ = true;
869 if (tile->required_for_activation()) { 866 if (tile->required_for_activation()) {
870 // It's possible that a tile required for activation is not in this list 867 // It's possible that a tile required for activation is not in this list
871 // if it was marked as being required after being dispatched for 868 // if it was marked as being required after being dispatched for
872 // rasterization but before AssignGPUMemory was called again. 869 // rasterization but before AssignGPUMemory was called again.
873 tiles_that_need_to_be_initialized_for_activation_.erase(tile); 870 tiles_that_need_to_be_initialized_for_activation_.erase(tile);
874 } 871 }
875 } 872 }
876 873
877 void TileManager::DidTileTreeBinChange(Tile* tile, 874 void TileManager::DidTileTreeBinChange(Tile* tile,
878 TileManagerBin new_tree_bin, 875 TileManagerBin new_tree_bin,
879 WhichTree tree) { 876 WhichTree tree) {
880 ManagedTileState& mts = tile->managed_state(); 877 ManagedTileState& mts = tile->managed_state();
881 mts.tree_bin[tree] = new_tree_bin; 878 mts.tree_bin[tree] = new_tree_bin;
882 } 879 }
883 880
884 // static 881 // static
882 void TileManager::RunImageDecodeTask(
883 skia::LazyPixelRef* pixel_ref,
884 int layer_id,
885 RenderingStatsInstrumentation* stats_instrumentation) {
886 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask");
887 devtools_instrumentation::ScopedLayerTask image_decode_task(
888 devtools_instrumentation::kImageDecodeTask, layer_id);
889 base::TimeTicks start_time = stats_instrumentation->StartRecording();
890 pixel_ref->Decode();
891 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
892 stats_instrumentation->AddDeferredImageDecode(duration);
893 }
894
895 // static
885 void TileManager::RunAnalyzeAndRasterTask( 896 void TileManager::RunAnalyzeAndRasterTask(
886 const RasterWorkerPool::RasterCallback& analyze_task, 897 const RasterWorkerPool::PictureTask::Callback& analyze_task,
887 const RasterWorkerPool::RasterCallback& raster_task, 898 const RasterWorkerPool::PictureTask::Callback& raster_task,
888 PicturePileImpl* picture_pile) { 899 PicturePileImpl* picture_pile) {
889 analyze_task.Run(picture_pile); 900 analyze_task.Run(picture_pile);
890 raster_task.Run(picture_pile); 901 raster_task.Run(picture_pile);
891 } 902 }
892 903
893 // static 904 // static
894 void TileManager::RunAnalyzeTask( 905 void TileManager::RunAnalyzeTask(
895 PicturePileImpl::Analysis* analysis, 906 PicturePileImpl::Analysis* analysis,
896 gfx::Rect rect, 907 gfx::Rect rect,
897 float contents_scale, 908 float contents_scale,
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 "Renderer4.PictureRasterTimeUS", 984 "Renderer4.PictureRasterTimeUS",
974 raster_stats.total_rasterize_time.InMicroseconds(), 985 raster_stats.total_rasterize_time.InMicroseconds(),
975 0, 986 0,
976 100000, 987 100000,
977 100); 988 100);
978 } else { 989 } else {
979 picture_pile->RasterToBitmap(&canvas, rect, contents_scale, NULL); 990 picture_pile->RasterToBitmap(&canvas, rect, contents_scale, NULL);
980 } 991 }
981 } 992 }
982 993
983 // static
984 void TileManager::RunImageDecodeTask(
985 skia::LazyPixelRef* pixel_ref,
986 int layer_id,
987 RenderingStatsInstrumentation* stats_instrumentation) {
988 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask");
989 devtools_instrumentation::ScopedLayerTask image_decode_task(
990 devtools_instrumentation::kImageDecodeTask, layer_id);
991 base::TimeTicks start_time = stats_instrumentation->StartRecording();
992 pixel_ref->Decode();
993 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
994 stats_instrumentation->AddDeferredImageDecode(duration);
995 }
996
997 } // namespace cc 994 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698