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

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: move alignment check to RP 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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698