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

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: 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) {
485 continue; 482 continue;
486 }
487 483
488 size_t tile_bytes = tile->bytes_consumed_if_allocated(); 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
489 // If the tile is not needed, free it up. 491 // If the tile is not needed, free it up.
490 if (mts.is_in_never_bin_on_both_trees()) { 492 if (mts.is_in_never_bin_on_both_trees()) {
491 FreeResourcesForTile(tile); 493 if (drawing_info.memory_state_ != USING_UNRELEASABLE_MEMORY) {
492 drawing_info.memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; 494 FreeResourcesForTile(tile);
495 drawing_info.memory_state_ = NOT_ALLOWED_TO_USE_MEMORY;
496 }
493 continue; 497 continue;
494 } 498 }
495 // Tile is OOM. 499 // Tile is OOM.
496 if (tile_bytes > bytes_left) { 500 if (tile_bytes > bytes_left) {
497 FreeResourcesForTile(tile);
498 tile->drawing_info().set_rasterize_on_demand(); 501 tile->drawing_info().set_rasterize_on_demand();
499 if (mts.tree_bin[PENDING_TREE] == NOW_BIN) { 502 if (mts.tree_bin[PENDING_TREE] == NOW_BIN) {
500 tiles_requiring_memory_but_oomed.push_back(tile); 503 tiles_requiring_memory_but_oomed.push_back(tile);
501 bytes_oom_in_now_bin_on_pending_tree += tile_bytes; 504 bytes_oom_in_now_bin_on_pending_tree += tile_bytes;
502 } 505 }
506 FreeResourcesForTile(tile);
507 higher_priority_tile_oomed = true;
503 continue; 508 continue;
504 } 509 }
505 drawing_info.set_use_resource(); 510 drawing_info.set_use_resource();
506 bytes_left -= tile_bytes; 511 bytes_left -= tile_bytes;
507 if (!drawing_info.resource_ && 512 // Tile shouldn't be rasterized if we've failed to assign
vmpstr 2013/05/06 18:05:51 If a large tile is OOM, followed by a smaller tile
reveman 2013/05/06 21:36:27 Yes, being assigned memory is not the same as bein
508 drawing_info.memory_state_ == CAN_USE_MEMORY) { 513 // gpu memory to a higher priority tile. This is important for
514 // two reasons:
515 // 1. Tile size should not impact raster priority.
516 // 2. Tile with unreleasable memory could otherwise incorrectly
517 // be added as it's not affected by |bytes_allocatable|.
518 if (!drawing_info.resource_ && !higher_priority_tile_oomed)
509 tiles_that_need_to_be_rasterized_.push_back(tile); 519 tiles_that_need_to_be_rasterized_.push_back(tile);
510 }
511 } 520 }
512 521
513 // In OOM situation, we iterate tiles_, remove the memory for active tree 522 // 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 523 // 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()) { 524 if (!tiles_requiring_memory_but_oomed.empty()) {
516 size_t bytes_freed = 0; 525 size_t bytes_freed = 0;
517 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { 526 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
518 Tile* tile = *it; 527 Tile* tile = *it;
519 ManagedTileState& mts = tile->managed_state(); 528 ManagedTileState& mts = tile->managed_state();
520 ManagedTileState::DrawingInfo& drawing_info = tile->drawing_info(); 529 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, 565 "budget", global_state_.memory_limit_in_bytes,
557 "over", bytes_that_exceeded_memory_budget_in_now_bin); 566 "over", bytes_that_exceeded_memory_budget_in_now_bin);
558 } 567 }
559 memory_stats_from_last_assign_.total_budget_in_bytes = 568 memory_stats_from_last_assign_.total_budget_in_bytes =
560 global_state_.memory_limit_in_bytes; 569 global_state_.memory_limit_in_bytes;
561 memory_stats_from_last_assign_.bytes_allocated = 570 memory_stats_from_last_assign_.bytes_allocated =
562 bytes_allocatable - bytes_left; 571 bytes_allocatable - bytes_left;
563 memory_stats_from_last_assign_.bytes_unreleasable = unreleasable_bytes; 572 memory_stats_from_last_assign_.bytes_unreleasable = unreleasable_bytes;
564 memory_stats_from_last_assign_.bytes_over = 573 memory_stats_from_last_assign_.bytes_over =
565 bytes_that_exceeded_memory_budget_in_now_bin; 574 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 } 575 }
573 576
574 void TileManager::FreeResourcesForTile(Tile* tile) { 577 void TileManager::FreeResourcesForTile(Tile* tile) {
575 DCHECK(tile->drawing_info().memory_state_ != USING_UNRELEASABLE_MEMORY); 578 DCHECK_NE(USING_UNRELEASABLE_MEMORY, tile->drawing_info().memory_state_);
vmpstr 2013/05/06 18:05:51 nit: I kinda prefer the constant to be the second
reveman 2013/05/06 21:36:27 DCHECK_NE is used in both ways throughout chromium
576 if (tile->drawing_info().resource_) { 579 if (tile->drawing_info().resource_) {
577 resource_pool_->ReleaseResource( 580 resource_pool_->ReleaseResource(
578 tile->drawing_info().resource_.Pass()); 581 tile->drawing_info().resource_.Pass());
579 } 582 }
580 tile->drawing_info().memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; 583 tile->drawing_info().memory_state_ = NOT_ALLOWED_TO_USE_MEMORY;
581 } 584 }
582 585
583 bool TileManager::CanDispatchRasterTask(Tile* tile) const { 586 void TileManager::ScheduleTasks() {
584 if (pending_tasks_ >= max_pending_tasks_) 587 TRACE_EVENT0("cc", "TileManager::ScheduleTasks");
585 return false; 588 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 589
592 void TileManager::DispatchMoreTasks() { 590 size_t bytes_pending_upload = bytes_pending_upload_;
593 TileVector tiles_with_image_decoding_tasks; 591 ManagedTileState::PixelRefSet decode_tasks;
594 592
593 // Build a new task queue containing all task currently needed. Tasks
594 // are added to queue in order of priority, highest priority task first.
595 //
595 // Process all tiles in the need_to_be_rasterized queue: 596 // Process all tiles in the need_to_be_rasterized queue:
596 // 1. Dispatch image decode tasks. 597 // 1. Queue image decode tasks for tile.
597 // 2. If the image decode isn't done, save the tile for later processing. 598 // 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. 599 // 3. Attempt to queue a raster task, or break out of the loop.
599 while (!tiles_that_need_to_be_rasterized_.empty()) { 600 for (TileVector::iterator it = tiles_that_need_to_be_rasterized_.begin();
600 Tile* tile = tiles_that_need_to_be_rasterized_.back(); 601 it != tiles_that_need_to_be_rasterized_.end();
602 ++it) {
603 Tile* tile = *it;
601 604
602 DCHECK(tile->drawing_info().requires_resource()); 605 // Skip tile if determined to not require resource.
606 if (!tile->drawing_info().requires_resource())
607 continue;
603 608
604 if (DispatchImageDecodeTasksForTile(tile)) { 609 // Skip tile if already rasterized.
605 tiles_with_image_decoding_tasks.push_back(tile); 610 if (tile->drawing_info().resource_)
606 } else if (!CanDispatchRasterTask(tile)) { 611 continue;
612
613 bool pending_decode_tasks = false;
614 ManagedTileState& mts = tile->managed_state();
615
616 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(),
vmpstr 2013/05/06 18:05:51 Is it possible to refactor this loop into a separa
reveman 2013/05/06 21:36:27 Done.
617 tile->contents_scale(),
618 tile->picture_pile());
619 iter; ++iter) {
620 skia::LazyPixelRef* pixel_ref = *iter;
621 uint32_t id = pixel_ref->getGenerationID();
622
623 // Check if image has already been decoded for this tile.
624 if (mts.decoded_pixel_refs.find(id) != mts.decoded_pixel_refs.end())
625 continue;
626
627 // TODO(qinmin): passing correct image size to PrepareToDecode().
628 if (pixel_ref->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) {
629 rendering_stats_instrumentation_->IncrementDeferredImageCacheHitCount();
630 mts.decoded_pixel_refs.insert(id);
631 continue;
632 }
633
634 pending_decode_tasks = true;
635
636 // TODO(reveman): Remove max pending tasks throttling.
637 if (task_queue.size() >= max_pending_tasks_)
607 break; 638 break;
608 } else { 639
609 DispatchOneRasterTask(tile); 640 // Check if already added to |task_queue|. There should only be
641 // one task per pixel ref.
642 if (decode_tasks.find(id) != decode_tasks.end())
643 continue;
644 decode_tasks.insert(id);
645
646 // Queue existing task if available.
647 PixelRefMap::iterator decode_task_it = pending_decode_tasks_.find(id);
648 if (decode_task_it != pending_decode_tasks_.end()) {
649 task_queue.Append(decode_task_it->second);
650 continue;
651 }
652
653 // Create and queue new image decode task for this pixel ref.
654 RasterWorkerPool::Task decode_task = CreateImageDecodeTask(
655 tile, pixel_ref);
656 task_queue.Append(decode_task);
657 pending_decode_tasks_[id] = decode_task;
610 } 658 }
611 tiles_that_need_to_be_rasterized_.pop_back(); 659
660 // Skip tile if image decode is pending.
661 if (pending_decode_tasks)
662 continue;
663
664 // TODO(reveman): Remove throttling based on max pending tasks.
665 if (task_queue.size() >= max_pending_tasks_)
666 break;
667
668 // TODO(reveman): Remove throttling based on max pending uploads.
669 if (tiles_with_pending_upload_.size() >= kMaxPendingUploads)
670 break;
671
672 // TODO(reveman): Throttle based on shared memory usage rather
673 // than bytes pending upload.
674 size_t new_bytes_pending = bytes_pending_upload;
675 new_bytes_pending += tile->bytes_consumed_if_allocated();
676 if (new_bytes_pending > kMaxPendingUploadBytes)
677 break;
678 bytes_pending_upload = new_bytes_pending;
679
680 // Create raster task for this tile if necessary.
681 if (mts.raster_task.is_null())
682 mts.raster_task = CreateRasterTask(tile);
683
684 // Finally queue raster task for tile.
685 task_queue.Append(mts.raster_task);
612 } 686 }
613 687
614 // Put the saved tiles back into the queue. The order is reversed 688 // Schedule running of tasks in |task_queue|. This replaces any
615 // to preserve original ordering. 689 // previously scheduled tasks and effectively cancels any tasks
vmpstr 2013/05/06 18:05:51 How do we cancel an upload? (or ensure upload cont
reveman 2013/05/06 21:36:27 We can't cancel an upload at the moment but that's
616 tiles_that_need_to_be_rasterized_.insert( 690 // not present in |task_queue|.
617 tiles_that_need_to_be_rasterized_.end(), 691 raster_worker_pool_->ScheduleTasks(&task_queue);
618 tiles_with_image_decoding_tasks.rbegin(),
619 tiles_with_image_decoding_tasks.rend());
620 692
621 if (did_initialize_visible_tile_) { 693 if (did_initialize_visible_tile_) {
622 did_initialize_visible_tile_ = false; 694 did_initialize_visible_tile_ = false;
623 client_->DidInitializeVisibleTile(); 695 client_->DidInitializeVisibleTile();
624 } 696 }
625 } 697 }
626 698
627 bool TileManager::DispatchImageDecodeTasksForTile(Tile* tile) { 699 RasterWorkerPool::Task TileManager::CreateImageDecodeTask(
vmpstr 2013/05/06 18:05:51 I guess my earlier comment is asking to just renam
reveman 2013/05/06 21:36:27 Done.
628 TRACE_EVENT0("cc", "TileManager::DispatchImageDecodeTasksForTile"); 700 Tile* tile, skia::LazyPixelRef* pixel_ref) {
629 ManagedTileState& mts = tile->managed_state(); 701 TRACE_EVENT0("cc", "TileManager::CreateImageDecodeTask");
630 bool pending_decode_tasks = false;
631 702
632 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(), 703 return RasterWorkerPool::Task(
633 tile->contents_scale(),
634 tile->picture_pile());
635 iter; ++iter) {
636 skia::LazyPixelRef* pixel_ref = *iter;
637 uint32_t id = pixel_ref->getGenerationID();
638
639 // Check if image has already been decoded.
640 if (mts.decoded_pixel_refs.find(id) != mts.decoded_pixel_refs.end())
641 continue;
642
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().
650 if (pixel_ref->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) {
651 rendering_stats_instrumentation_->IncrementDeferredImageCacheHitCount();
652 mts.decoded_pixel_refs.insert(id);
653 continue;
654 }
655
656 if (pending_tasks_ >= max_pending_tasks_)
657 break;
658
659 DispatchOneImageDecodeTask(tile, pixel_ref);
660 pending_decode_tasks = true;
661 }
662
663 return pending_decode_tasks;
664 }
665
666 void TileManager::DispatchOneImageDecodeTask(
667 scoped_refptr<Tile> tile, skia::LazyPixelRef* pixel_ref) {
668 TRACE_EVENT0("cc", "TileManager::DispatchOneImageDecodeTask");
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
674 raster_worker_pool_->PostTaskAndReply(
675 base::Bind(&TileManager::RunImageDecodeTask, 704 base::Bind(&TileManager::RunImageDecodeTask,
676 pixel_ref, 705 pixel_ref,
677 rendering_stats_instrumentation_), 706 rendering_stats_instrumentation_),
678 base::Bind(&TileManager::OnImageDecodeTaskCompleted, 707 base::Bind(&TileManager::OnImageDecodeTaskCompleted,
679 base::Unretained(this), 708 base::Unretained(this),
680 tile, 709 make_scoped_refptr(tile),
681 pixel_ref_id)); 710 pixel_ref->getGenerationID()));
682 pending_tasks_++;
683 } 711 }
684 712
685 void TileManager::OnImageDecodeTaskCompleted( 713 void TileManager::OnImageDecodeTaskCompleted(scoped_refptr<Tile> tile,
686 scoped_refptr<Tile> tile, uint32_t pixel_ref_id) { 714 uint32_t pixel_ref_id,
715 bool was_cancelled) {
687 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted"); 716 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted");
717 DCHECK(pending_decode_tasks_.find(pixel_ref_id) !=
718 pending_decode_tasks_.end());
719 pending_decode_tasks_.erase(pixel_ref_id);
720 if (was_cancelled)
721 return;
688 ManagedTileState& mts = tile->managed_state(); 722 ManagedTileState& mts = tile->managed_state();
723 // Note: |decoded_pixel_refs| might already contain |pixel_ref_id| as
724 // the PrepareToDecode() check in ScheduleTasks() could have added it.
689 mts.decoded_pixel_refs.insert(pixel_ref_id); 725 mts.decoded_pixel_refs.insert(pixel_ref_id);
690 pending_decode_tasks_.erase(pixel_ref_id);
691 pending_tasks_--;
692 } 726 }
693 727
694 scoped_ptr<ResourcePool::Resource> TileManager::PrepareTileForRaster( 728 RasterWorkerPool::Task TileManager::CreateRasterTask(Tile* tile) {
695 Tile* tile) { 729 TRACE_EVENT0("cc", "TileManager::CreateRasterTask");
696 scoped_ptr<ResourcePool::Resource> resource = resource_pool_->AcquireResource( 730
697 tile->tile_size_.size(), 731 scoped_ptr<ResourcePool::Resource> resource =
698 tile->drawing_info().resource_format_); 732 resource_pool_->AcquireResource(
733 tile->tile_size_.size(),
734 tile->drawing_info().resource_format_);
699 resource_pool_->resource_provider()->AcquirePixelBuffer(resource->id()); 735 resource_pool_->resource_provider()->AcquirePixelBuffer(resource->id());
700 736
737 DCHECK_EQ(CAN_USE_MEMORY, tile->drawing_info().memory_state_);
701 tile->drawing_info().memory_state_ = USING_UNRELEASABLE_MEMORY; 738 tile->drawing_info().memory_state_ = USING_UNRELEASABLE_MEMORY;
702 739
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; 740 PicturePileImpl::Analysis* analysis = new PicturePileImpl::Analysis;
711 741
712 // MapPixelBuffer() returns NULL if context was lost at the time 742 // MapPixelBuffer() returns NULL if context was lost at the time
713 // AcquirePixelBuffer() was called. For simplicity we still post 743 // AcquirePixelBuffer() was called. For simplicity we still post
714 // a raster task that is essentially a noop in these situations. 744 // a raster task that is essentially a noop in these situations.
715 uint8* buffer = resource_pool_->resource_provider()->MapPixelBuffer( 745 uint8* buffer = resource_pool_->resource_provider()->MapPixelBuffer(
716 resource_id); 746 resource->id());
717 747
718 // skia requires that our buffer be 4-byte aligned 748 // skia requires that our buffer be 4-byte aligned
719 CHECK(!(reinterpret_cast<intptr_t>(buffer) & 3)); 749 CHECK(!(reinterpret_cast<intptr_t>(buffer) & 3));
vmpstr 2013/05/06 18:05:51 I would vote that this moves into MapPixelBuffer,
reveman 2013/05/06 21:36:27 I agree. Moving it RP and closer to the source as
720 750
721 raster_worker_pool_->PostRasterTaskAndReply( 751 return RasterWorkerPool::PictureTask(
722 tile->picture_pile(), 752 tile->picture_pile(),
723 base::Bind(&TileManager::RunAnalyzeAndRasterTask, 753 base::Bind(&TileManager::RunAnalyzeAndRasterTask,
724 base::Bind(&TileManager::RunAnalyzeTask, 754 base::Bind(&TileManager::RunAnalyzeTask,
725 analysis, 755 analysis,
726 tile->content_rect(), 756 tile->content_rect(),
727 tile->contents_scale(), 757 tile->contents_scale(),
728 use_color_estimator_, 758 use_color_estimator_,
729 GetRasterTaskMetadata(*tile), 759 GetRasterTaskMetadata(*tile),
730 rendering_stats_instrumentation_), 760 rendering_stats_instrumentation_),
731 base::Bind(&TileManager::RunRasterTask, 761 base::Bind(&TileManager::RunRasterTask,
732 buffer, 762 buffer,
733 analysis, 763 analysis,
734 tile->content_rect(), 764 tile->content_rect(),
735 tile->contents_scale(), 765 tile->contents_scale(),
736 GetRasterTaskMetadata(*tile), 766 GetRasterTaskMetadata(*tile),
737 rendering_stats_instrumentation_)), 767 rendering_stats_instrumentation_)),
738 base::Bind(&TileManager::OnRasterTaskCompleted, 768 base::Bind(&TileManager::OnRasterTaskCompleted,
739 base::Unretained(this), 769 base::Unretained(this),
740 tile, 770 make_scoped_refptr(tile),
741 base::Passed(&resource), 771 base::Passed(&resource),
742 base::Owned(analysis), 772 base::Owned(analysis)));
743 manage_tiles_call_count_));
744 pending_tasks_++;
745 } 773 }
746 774
747 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata( 775 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata(
748 const Tile& tile) const { 776 const Tile& tile) const {
749 RasterTaskMetadata metadata; 777 RasterTaskMetadata metadata;
750 const ManagedTileState& mts = tile.managed_state(); 778 const ManagedTileState& mts = tile.managed_state();
751 metadata.prediction_benchmarking = prediction_benchmarking_; 779 metadata.prediction_benchmarking = prediction_benchmarking_;
752 metadata.is_tile_in_pending_tree_now_bin = 780 metadata.is_tile_in_pending_tree_now_bin =
753 mts.tree_bin[PENDING_TREE] == NOW_BIN; 781 mts.tree_bin[PENDING_TREE] == NOW_BIN;
754 metadata.tile_resolution = mts.resolution; 782 metadata.tile_resolution = mts.resolution;
755 metadata.layer_id = tile.layer_id(); 783 metadata.layer_id = tile.layer_id();
756 return metadata; 784 return metadata;
757 } 785 }
758 786
759 void TileManager::OnRasterTaskCompleted( 787 void TileManager::OnRasterTaskCompleted(
760 scoped_refptr<Tile> tile, 788 scoped_refptr<Tile> tile,
761 scoped_ptr<ResourcePool::Resource> resource, 789 scoped_ptr<ResourcePool::Resource> resource,
762 PicturePileImpl::Analysis* analysis, 790 PicturePileImpl::Analysis* analysis,
763 int manage_tiles_call_count_when_dispatched) { 791 bool was_cancelled) {
764 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); 792 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted");
765 793
766 pending_tasks_--; 794 ManagedTileState& mts = tile->managed_state();
795 DCHECK(!mts.raster_task.is_null());
796 mts.raster_task.Reset();
797
798 // Tile resources can't be freed until upload has completed.
799 DCHECK_EQ(USING_UNRELEASABLE_MEMORY, tile->drawing_info().memory_state_);
767 800
768 // Release raster resources. 801 // Release raster resources.
769 resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id()); 802 resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id());
770 803
771 tile->drawing_info().memory_state_ = USING_RELEASABLE_MEMORY; 804 if (was_cancelled) {
805 tile->drawing_info().memory_state_ = CAN_USE_MEMORY;
vmpstr 2013/05/06 18:05:51 Why can use memory? I would think that if it was c
reveman 2013/05/06 21:36:27 The tile will always be allowed to use memory at t
806 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id());
807 resource_pool_->ReleaseResource(resource.Pass());
808 return;
809 }
772 810
773 ManagedTileState& managed_tile_state = tile->managed_state(); 811 mts.picture_pile_analysis = *analysis;
774 managed_tile_state.picture_pile_analysis = *analysis; 812 mts.picture_pile_analyzed = true;
775 managed_tile_state.picture_pile_analyzed = true;
776 813
777 if (analysis->is_solid_color) { 814 if (analysis->is_solid_color) {
778 tile->drawing_info().set_solid_color(analysis->solid_color); 815 tile->drawing_info().set_solid_color(analysis->solid_color);
779 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); 816 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id());
780 resource_pool_->ReleaseResource(resource.Pass()); 817 resource_pool_->ReleaseResource(resource.Pass());
781 DidFinishTileInitialization(tile); 818 DidFinishTileInitialization(tile);
782 return; 819 return;
783 } 820 }
784 821
785 // Tile can be freed after the completion of the raster task. Call 822 resource_pool_->resource_provider()->BeginSetPixels(resource->id());
786 // AssignGpuMemoryToTiles() to re-assign gpu memory to highest priority 823 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 824
794 // Finish resource initialization we're still using memory. 825 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 826
799 resource_pool_->resource_provider()->BeginSetPixels(resource->id()); 827 bytes_pending_upload_ += tile->bytes_consumed_if_allocated();
800 has_performed_uploads_since_last_flush_ = true; 828 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 } 829 }
811 830
812 void TileManager::DidFinishTileInitialization(Tile* tile) { 831 void TileManager::DidFinishTileInitialization(Tile* tile) {
813 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0) 832 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0)
814 did_initialize_visible_tile_ = true; 833 did_initialize_visible_tile_ = true;
815 } 834 }
816 835
817 void TileManager::DidTileTreeBinChange(Tile* tile, 836 void TileManager::DidTileTreeBinChange(Tile* tile,
818 TileManagerBin new_tree_bin, 837 TileManagerBin new_tree_bin,
819 WhichTree tree) { 838 WhichTree tree) {
820 ManagedTileState& mts = tile->managed_state(); 839 ManagedTileState& mts = tile->managed_state();
821 mts.tree_bin[tree] = new_tree_bin; 840 mts.tree_bin[tree] = new_tree_bin;
822 } 841 }
823 842
824 // static 843 // static
844 void TileManager::RunImageDecodeTask(
845 skia::LazyPixelRef* pixel_ref,
846 RenderingStatsInstrumentation* stats_instrumentation) {
847 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask");
848 base::TimeTicks start_time = stats_instrumentation->StartRecording();
849 pixel_ref->Decode();
850 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
851 stats_instrumentation->AddDeferredImageDecode(duration);
852 }
853
854 // static
825 void TileManager::RunAnalyzeAndRasterTask( 855 void TileManager::RunAnalyzeAndRasterTask(
826 const RasterWorkerPool::RasterCallback& analyze_task, 856 const RasterWorkerPool::PictureTask::Callback& analyze_task,
827 const RasterWorkerPool::RasterCallback& raster_task, 857 const RasterWorkerPool::PictureTask::Callback& raster_task,
828 PicturePileImpl* picture_pile) { 858 PicturePileImpl* picture_pile) {
829 analyze_task.Run(picture_pile); 859 analyze_task.Run(picture_pile);
830 raster_task.Run(picture_pile); 860 raster_task.Run(picture_pile);
831 } 861 }
832 862
833 // static 863 // static
834 void TileManager::RunAnalyzeTask( 864 void TileManager::RunAnalyzeTask(
835 PicturePileImpl::Analysis* analysis, 865 PicturePileImpl::Analysis* analysis,
836 gfx::Rect rect, 866 gfx::Rect rect,
837 float contents_scale, 867 float contents_scale,
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 raster_stats.total_rasterize_time.InMicroseconds(), 949 raster_stats.total_rasterize_time.InMicroseconds(),
920 0, 950 0,
921 100000, 951 100000,
922 100); 952 100);
923 } else { 953 } else {
924 picture_pile->Raster(&canvas, rect, contents_scale, NULL); 954 picture_pile->Raster(&canvas, rect, contents_scale, NULL);
925 } 955 }
926 } 956 }
927 957
928 // static 958 // 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( 959 void TileManager::RecordSolidColorPredictorResults(
941 const SkPMColor* actual_colors, 960 const SkPMColor* actual_colors,
942 size_t color_count, 961 size_t color_count,
943 bool is_predicted_solid, 962 bool is_predicted_solid,
944 SkPMColor predicted_color) { 963 SkPMColor predicted_color) {
945 DCHECK_GT(color_count, 0u); 964 DCHECK_GT(color_count, 0u);
946 965
947 bool is_actually_solid = true; 966 bool is_actually_solid = true;
948 967
949 SkPMColor actual_color = *actual_colors; 968 SkPMColor actual_color = *actual_colors;
(...skipping 14 matching lines...) Expand all
964 is_predicted_solid && predicted_color != actual_color); 983 is_predicted_solid && predicted_color != actual_color);
965 HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.Accuracy", 984 HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.Accuracy",
966 is_predicted_solid == is_actually_solid && 985 is_predicted_solid == is_actually_solid &&
967 (!is_predicted_solid || predicted_color == actual_color)); 986 (!is_predicted_solid || predicted_color == actual_color));
968 HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.IsCorrectSolid", 987 HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.IsCorrectSolid",
969 is_predicted_solid == is_actually_solid && 988 is_predicted_solid == is_actually_solid &&
970 (is_predicted_solid && predicted_color == actual_color)); 989 (is_predicted_solid && predicted_color == actual_color));
971 } 990 }
972 991
973 } // namespace cc 992 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698