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

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: Check and prevent worker pool reentrancy during dispatch of completion callbacks Created 7 years, 6 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
« no previous file with comments | « cc/resources/tile_manager.h ('k') | cc/test/fake_tile_manager.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 17 matching lines...) Expand all
380 377
381 // We have to set the memory state to be unreleasable, to ensure 378 // We have to set the memory state to be unreleasable, to ensure
382 // that the tile will not be freed until we get the upload finished 379 // that the tile will not be freed until we get the upload finished
383 // notification. However, setting |forced_upload_| to true makes 380 // notification. However, setting |forced_upload_| to true makes
384 // this tile ready to draw. 381 // this tile ready to draw.
385 tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY; 382 tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY;
386 tile->tile_version().forced_upload_ = true; 383 tile->tile_version().forced_upload_ = true;
387 DidFinishTileInitialization(tile); 384 DidFinishTileInitialization(tile);
388 DCHECK(tile->tile_version().IsReadyToDraw()); 385 DCHECK(tile->tile_version().IsReadyToDraw());
389 } 386 }
390
391 if (did_initialize_visible_tile_) {
392 did_initialize_visible_tile_ = false;
393 client_->DidInitializeVisibleTile();
394 }
395 } 387 }
396 388
397 void TileManager::GetMemoryStats( 389 void TileManager::GetMemoryStats(
398 size_t* memory_required_bytes, 390 size_t* memory_required_bytes,
399 size_t* memory_nice_to_have_bytes, 391 size_t* memory_nice_to_have_bytes,
400 size_t* memory_used_bytes) const { 392 size_t* memory_used_bytes) const {
401 *memory_required_bytes = 0; 393 *memory_required_bytes = 0;
402 *memory_nice_to_have_bytes = 0; 394 *memory_nice_to_have_bytes = 0;
403 *memory_used_bytes = 0; 395 *memory_used_bytes = 0;
404 for (TileVector::const_iterator it = tiles_.begin(); 396 for (TileVector::const_iterator it = tiles_.begin();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 tiles_that_need_to_be_initialized_for_activation_.insert(tile); 454 tiles_that_need_to_be_initialized_for_activation_.insert(tile);
463 } 455 }
464 456
465 void TileManager::DidFinishDispatchingWorkerPoolCompletionCallbacks() { 457 void TileManager::DidFinishDispatchingWorkerPoolCompletionCallbacks() {
466 // If a flush is needed, do it now before starting to dispatch more tasks. 458 // If a flush is needed, do it now before starting to dispatch more tasks.
467 if (has_performed_uploads_since_last_flush_) { 459 if (has_performed_uploads_since_last_flush_) {
468 resource_pool_->resource_provider()->ShallowFlushIfSupported(); 460 resource_pool_->resource_provider()->ShallowFlushIfSupported();
469 has_performed_uploads_since_last_flush_ = false; 461 has_performed_uploads_since_last_flush_ = false;
470 } 462 }
471 463
472 DispatchMoreTasks(); 464 ScheduleTasks();
473 } 465 }
474 466
475 void TileManager::AssignGpuMemoryToTiles() { 467 void TileManager::AssignGpuMemoryToTiles() {
476 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); 468 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles");
477 size_t unreleasable_bytes = 0; 469 size_t unreleasable_bytes = 0;
478 470
479 // Now give memory out to the tiles until we're out, and build 471 // Now give memory out to the tiles until we're out, and build
480 // the needs-to-be-rasterized queue. 472 // the needs-to-be-rasterized queue.
481 tiles_that_need_to_be_rasterized_.clear(); 473 tiles_that_need_to_be_rasterized_.clear();
482 tiles_that_need_to_be_initialized_for_activation_.clear(); 474 tiles_that_need_to_be_initialized_for_activation_.clear();
483 475
484 // By clearing the tiles_that_need_to_be_rasterized_ vector list 476 // By clearing the tiles_that_need_to_be_rasterized_ vector list
485 // above we move all tiles currently waiting for raster to idle state. 477 // 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 478 // Some memory cannot be released. We figure out how much in this
487 // loop as well. 479 // loop.
488 for (TileVector::const_iterator it = tiles_.begin(); 480 for (TileVector::const_iterator it = tiles_.begin();
489 it != tiles_.end(); 481 it != tiles_.end();
490 ++it) { 482 ++it) {
491 const Tile* tile = *it; 483 const Tile* tile = *it;
492 if (tile->tile_version().memory_state_ == USING_UNRELEASABLE_MEMORY) 484 if (tile->tile_version().memory_state_ == USING_UNRELEASABLE_MEMORY)
493 unreleasable_bytes += tile->bytes_consumed_if_allocated(); 485 unreleasable_bytes += tile->bytes_consumed_if_allocated();
494 } 486 }
495 487
496 // Global state's memory limit can decrease, causing 488 // Global state's memory limit can decrease, causing
497 // it to be less than unreleasable_bytes 489 // it to be less than unreleasable_bytes
498 size_t bytes_allocatable = 490 size_t bytes_allocatable =
499 global_state_.memory_limit_in_bytes > unreleasable_bytes ? 491 global_state_.memory_limit_in_bytes > unreleasable_bytes ?
500 global_state_.memory_limit_in_bytes - unreleasable_bytes : 492 global_state_.memory_limit_in_bytes - unreleasable_bytes :
501 0; 493 0;
502 size_t bytes_that_exceeded_memory_budget_in_now_bin = 0; 494 size_t bytes_that_exceeded_memory_budget_in_now_bin = 0;
503 size_t bytes_left = bytes_allocatable; 495 size_t bytes_left = bytes_allocatable;
504 size_t bytes_oom_in_now_bin_on_pending_tree = 0; 496 size_t bytes_oom_in_now_bin_on_pending_tree = 0;
505 TileVector tiles_requiring_memory_but_oomed; 497 TileVector tiles_requiring_memory_but_oomed;
498 bool higher_priority_tile_oomed = false;
506 for (TileVector::iterator it = tiles_.begin(); 499 for (TileVector::iterator it = tiles_.begin();
507 it != tiles_.end(); 500 it != tiles_.end();
508 ++it) { 501 ++it) {
509 Tile* tile = *it; 502 Tile* tile = *it;
510 ManagedTileState& mts = tile->managed_state(); 503 ManagedTileState& mts = tile->managed_state();
511 ManagedTileState::TileVersion& tile_version = tile->tile_version(); 504 ManagedTileState::TileVersion& tile_version = tile->tile_version();
512 505
513 // If this tile doesn't need a resource, then nothing to do. 506 // If this tile doesn't need a resource, then nothing to do.
514 if (!tile_version.requires_resource()) 507 if (!tile_version.requires_resource())
515 continue; 508 continue;
516 509
517 // If the memory is unreleasable, then we do not need to do anything. 510 size_t tile_bytes = tile->bytes_consumed_if_allocated();
518 if (tile_version.memory_state_ == USING_UNRELEASABLE_MEMORY) { 511 // Memory is already reserved for tile with unreleasable memory
519 if (tile->required_for_activation()) { 512 // so adding it to |tiles_that_need_to_be_rasterized_| doesn't
520 AddRequiredTileForActivation(tile); 513 // affect bytes_allocatable.
521 // If after rasterizing, this tile has become required or the client has 514 if (tile_version.memory_state_ == USING_UNRELEASABLE_MEMORY)
522 // changed its mind about forcing tiles, do that now. 515 tile_bytes = 0;
523 if (!tile->tile_version().forced_upload_ && 516
524 client_->ShouldForceTileUploadsRequiredForActivationToComplete()) { 517 // If the tile is not needed, free it up.
525 ForceTileUploadToComplete(tile); 518 if (mts.is_in_never_bin_on_both_trees()) {
526 } 519 if (tile_version.memory_state_ != USING_UNRELEASABLE_MEMORY) {
520 FreeResourcesForTile(tile);
521 tile_version.memory_state_ = NOT_ALLOWED_TO_USE_MEMORY;
527 } 522 }
528 continue; 523 continue;
529 } 524 }
530 525
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. 526 // Tile is OOM.
539 if (tile_bytes > bytes_left) { 527 if (tile_bytes > bytes_left) {
540 FreeResourcesForTile(tile);
541 tile->tile_version().set_rasterize_on_demand(); 528 tile->tile_version().set_rasterize_on_demand();
542 if (mts.tree_bin[PENDING_TREE] == NOW_BIN) { 529 if (mts.tree_bin[PENDING_TREE] == NOW_BIN) {
543 tiles_requiring_memory_but_oomed.push_back(tile); 530 tiles_requiring_memory_but_oomed.push_back(tile);
544 bytes_oom_in_now_bin_on_pending_tree += tile_bytes; 531 bytes_oom_in_now_bin_on_pending_tree += tile_bytes;
545 } 532 }
533 FreeResourcesForTile(tile);
534 higher_priority_tile_oomed = true;
546 continue; 535 continue;
547 } 536 }
537
548 tile_version.set_use_resource(); 538 tile_version.set_use_resource();
549 bytes_left -= tile_bytes; 539 bytes_left -= tile_bytes;
550 if (!tile_version.resource_ && 540
551 tile_version.memory_state_ == CAN_USE_MEMORY) { 541 // Tile shouldn't be rasterized if we've failed to assign
542 // gpu memory to a higher priority tile. This is important for
543 // two reasons:
544 // 1. Tile size should not impact raster priority.
545 // 2. Tile with unreleasable memory could otherwise incorrectly
546 // be added as it's not affected by |bytes_allocatable|.
547 if (higher_priority_tile_oomed)
548 continue;
549
550 if (!tile_version.resource_)
552 tiles_that_need_to_be_rasterized_.push_back(tile); 551 tiles_that_need_to_be_rasterized_.push_back(tile);
553 } 552
554 if (!tile_version.resource_ && tile->required_for_activation()) 553 if (!tile_version.resource_ && tile->required_for_activation())
555 AddRequiredTileForActivation(tile); 554 AddRequiredTileForActivation(tile);
555
556 if (tile_version.memory_state_ == USING_UNRELEASABLE_MEMORY &&
557 tile->required_for_activation()) {
558 // If after rasterizing, this tile has become required or the client has
559 // changed its mind about forcing tiles, do that now.
560 if (!tile->tile_version().forced_upload_ &&
561 client_->ShouldForceTileUploadsRequiredForActivationToComplete()) {
562 ForceTileUploadToComplete(tile);
563 }
564 }
556 } 565 }
557 566
558 // In OOM situation, we iterate tiles_, remove the memory for active tree 567 // 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 568 // 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()) { 569 if (!tiles_requiring_memory_but_oomed.empty()) {
561 size_t bytes_freed = 0; 570 size_t bytes_freed = 0;
562 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { 571 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
563 Tile* tile = *it; 572 Tile* tile = *it;
564 ManagedTileState& mts = tile->managed_state(); 573 ManagedTileState& mts = tile->managed_state();
565 ManagedTileState::TileVersion& tile_version = tile->tile_version(); 574 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, 613 "budget", global_state_.memory_limit_in_bytes,
605 "over", bytes_that_exceeded_memory_budget_in_now_bin); 614 "over", bytes_that_exceeded_memory_budget_in_now_bin);
606 } 615 }
607 memory_stats_from_last_assign_.total_budget_in_bytes = 616 memory_stats_from_last_assign_.total_budget_in_bytes =
608 global_state_.memory_limit_in_bytes; 617 global_state_.memory_limit_in_bytes;
609 memory_stats_from_last_assign_.bytes_allocated = 618 memory_stats_from_last_assign_.bytes_allocated =
610 bytes_allocatable - bytes_left; 619 bytes_allocatable - bytes_left;
611 memory_stats_from_last_assign_.bytes_unreleasable = unreleasable_bytes; 620 memory_stats_from_last_assign_.bytes_unreleasable = unreleasable_bytes;
612 memory_stats_from_last_assign_.bytes_over = 621 memory_stats_from_last_assign_.bytes_over =
613 bytes_that_exceeded_memory_budget_in_now_bin; 622 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 } 623 }
621 624
622 void TileManager::FreeResourcesForTile(Tile* tile) { 625 void TileManager::FreeResourcesForTile(Tile* tile) {
623 DCHECK(tile->tile_version().memory_state_ != USING_UNRELEASABLE_MEMORY); 626 DCHECK_NE(USING_UNRELEASABLE_MEMORY, tile->tile_version().memory_state_);
624 if (tile->tile_version().resource_) { 627 if (tile->tile_version().resource_) {
625 resource_pool_->ReleaseResource( 628 resource_pool_->ReleaseResource(
626 tile->tile_version().resource_.Pass()); 629 tile->tile_version().resource_.Pass());
627 } 630 }
628 tile->tile_version().memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; 631 tile->tile_version().memory_state_ = NOT_ALLOWED_TO_USE_MEMORY;
629 } 632 }
630 633
631 bool TileManager::CanDispatchRasterTask(Tile* tile) const { 634 void TileManager::ScheduleTasks() {
632 if (pending_tasks_ >= max_pending_tasks_) 635 TRACE_EVENT0("cc", "TileManager::ScheduleTasks");
633 return false; 636 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 637
640 void TileManager::DispatchMoreTasks() { 638 size_t bytes_pending_upload = bytes_pending_upload_;
641 TileVector tiles_with_image_decoding_tasks; 639 unsigned pending_tasks = 0;
642 640
643 // Process all tiles in the need_to_be_rasterized queue: 641 // Build a new task queue containing all task currently needed. Tasks
644 // 1. Dispatch image decode tasks. 642 // 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. 643 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. 644 it != tiles_that_need_to_be_rasterized_.end();
647 while (!tiles_that_need_to_be_rasterized_.empty()) { 645 ++it) {
648 Tile* tile = tiles_that_need_to_be_rasterized_.back(); 646 Tile* tile = *it;
647 ManagedTileState& mts = tile->managed_state();
649 648
650 DCHECK(tile->tile_version().requires_resource()); 649 // Skip tile if determined to not require resource.
650 if (!tile->tile_version().requires_resource())
651 continue;
651 652
652 if (DispatchImageDecodeTasksForTile(tile)) { 653 // Skip tile if already rasterized.
653 tiles_with_image_decoding_tasks.push_back(tile); 654 if (tile->tile_version().resource_)
654 } else if (!CanDispatchRasterTask(tile)) { 655 continue;
655 break; 656
656 } else { 657 // TODO(reveman): Remove throttling based on max pending tasks.
657 DispatchOneRasterTask(tile); 658 if (pending_tasks >= max_pending_tasks_)
658 } 659 break;
659 tiles_that_need_to_be_rasterized_.pop_back(); 660
661 // TODO(reveman): Remove throttling based on max pending uploads.
662 if (tiles_with_pending_upload_.size() >= kMaxPendingUploads)
663 break;
664
665 // TODO(reveman): Throttle based on shared memory usage rather
666 // than bytes pending upload.
667 size_t new_bytes_pending = bytes_pending_upload;
668 new_bytes_pending += tile->bytes_consumed_if_allocated();
669 if (new_bytes_pending > kMaxPendingUploadBytes)
670 break;
671 bytes_pending_upload = new_bytes_pending;
672
673 // Create raster task for this tile if necessary.
674 if (mts.raster_task.is_null())
675 mts.raster_task = CreateRasterTask(tile);
676
677 // Finally append raster task.
678 tasks.Append(mts.raster_task);
679 pending_tasks++;
660 } 680 }
661 681
662 // Put the saved tiles back into the queue. The order is reversed 682 if (!tasks.empty()) {
663 // to preserve original ordering. 683 RasterWorkerPool::Task root(&tasks);
664 tiles_that_need_to_be_rasterized_.insert( 684
665 tiles_that_need_to_be_rasterized_.end(), 685 // Schedule running of |tasks|. This replaces any previously
666 tiles_with_image_decoding_tasks.rbegin(), 686 // scheduled tasks and effectively cancels all tasks not present
667 tiles_with_image_decoding_tasks.rend()); 687 // in |tasks|.
688 raster_worker_pool_->ScheduleTasks(&root);
689 } else {
690 raster_worker_pool_->ScheduleTasks(NULL);
691 }
668 692
669 if (did_initialize_visible_tile_) { 693 if (did_initialize_visible_tile_) {
670 did_initialize_visible_tile_ = false; 694 did_initialize_visible_tile_ = false;
671 client_->DidInitializeVisibleTile(); 695 client_->DidInitializeVisibleTile();
672 } 696 }
673 } 697 }
674 698
675 bool TileManager::DispatchImageDecodeTasksForTile(Tile* tile) { 699 RasterWorkerPool::Task TileManager::CreateImageDecodeTask(
676 TRACE_EVENT0("cc", "TileManager::DispatchImageDecodeTasksForTile"); 700 Tile* tile, skia::LazyPixelRef* pixel_ref) {
677 ManagedTileState& mts = tile->managed_state(); 701 TRACE_EVENT0("cc", "TileManager::CreateImageDecodeTask");
678 bool pending_decode_tasks = false;
679 702
703 return RasterWorkerPool::Task(
704 base::Bind(&TileManager::RunImageDecodeTask,
705 pixel_ref,
706 tile->layer_id(),
707 rendering_stats_instrumentation_),
708 base::Bind(&TileManager::OnImageDecodeTaskCompleted,
709 base::Unretained(this),
710 make_scoped_refptr(tile),
711 pixel_ref->getGenerationID()));
712 }
713
714 void TileManager::OnImageDecodeTaskCompleted(scoped_refptr<Tile> tile,
715 uint32_t pixel_ref_id,
716 bool was_canceled) {
717 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted");
718 DCHECK(pending_decode_tasks_.find(pixel_ref_id) !=
719 pending_decode_tasks_.end());
720 pending_decode_tasks_.erase(pixel_ref_id);
721 }
722
723 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata(
724 const Tile& tile) const {
725 RasterTaskMetadata metadata;
726 const ManagedTileState& mts = tile.managed_state();
727 metadata.is_tile_in_pending_tree_now_bin =
728 mts.tree_bin[PENDING_TREE] == NOW_BIN;
729 metadata.tile_resolution = mts.resolution;
730 metadata.layer_id = tile.layer_id();
731 metadata.tile_id = &tile;
732 metadata.source_frame_number = tile.source_frame_number();
733 return metadata;
734 }
735
736 RasterWorkerPool::Task TileManager::CreateRasterTask(Tile* tile) {
737 TRACE_EVENT0("cc", "TileManager::CreateRasterTask");
738
739 scoped_ptr<ResourcePool::Resource> resource =
740 resource_pool_->AcquireResource(
741 tile->tile_size_.size(),
742 tile->tile_version().resource_format_);
743 resource_pool_->resource_provider()->AcquirePixelBuffer(resource->id());
744
745 DCHECK_EQ(CAN_USE_MEMORY, tile->tile_version().memory_state_);
746 tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY;
747
748 PicturePileImpl::Analysis* analysis = new PicturePileImpl::Analysis;
749
750 // MapPixelBuffer() returns NULL if context was lost at the time
751 // AcquirePixelBuffer() was called. For simplicity we still create
752 // a raster task that is essentially a noop in these situations.
753 uint8* buffer = resource_pool_->resource_provider()->MapPixelBuffer(
754 resource->id());
755
756 // Create and queue all image decode tasks that this tile depends on.
757 RasterWorkerPool::Task::Queue decode_tasks;
680 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(), 758 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(),
681 tile->contents_scale(), 759 tile->contents_scale(),
682 tile->picture_pile()); 760 tile->picture_pile());
683 iter; ++iter) { 761 iter; ++iter) {
684 skia::LazyPixelRef* pixel_ref = *iter; 762 skia::LazyPixelRef* pixel_ref = *iter;
685 uint32_t id = pixel_ref->getGenerationID(); 763 uint32_t id = pixel_ref->getGenerationID();
686 764
687 // Check if image has already been decoded. 765 // Append existing image decode task if available.
688 if (mts.decoded_pixel_refs.find(id) != mts.decoded_pixel_refs.end()) 766 PixelRefMap::iterator decode_task_it = pending_decode_tasks_.find(id);
689 continue; 767 if (decode_task_it != pending_decode_tasks_.end()) {
690 768 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; 769 continue;
695 } 770 }
696 771
697 // TODO(qinmin): passing correct image size to PrepareToDecode(). 772 // TODO(qinmin): passing correct image size to PrepareToDecode().
698 if (pixel_ref->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) { 773 if (pixel_ref->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) {
699 rendering_stats_instrumentation_->IncrementDeferredImageCacheHitCount(); 774 rendering_stats_instrumentation_->IncrementDeferredImageCacheHitCount();
700 mts.decoded_pixel_refs.insert(id);
701 continue; 775 continue;
702 } 776 }
703 777
704 if (pending_tasks_ >= max_pending_tasks_) 778 // Create and append new image decode task for this pixel ref.
705 break; 779 RasterWorkerPool::Task decode_task = CreateImageDecodeTask(
706 780 tile, pixel_ref);
707 DispatchOneImageDecodeTask(tile, pixel_ref); 781 decode_tasks.Append(decode_task);
708 pending_decode_tasks = true; 782 pending_decode_tasks_[id] = decode_task;
709 } 783 }
710 784
711 return pending_decode_tasks; 785 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(), 786 tile->picture_pile(),
772 base::Bind(&TileManager::RunAnalyzeAndRasterTask, 787 base::Bind(&TileManager::RunAnalyzeAndRasterTask,
773 base::Bind(&TileManager::RunAnalyzeTask, 788 base::Bind(&TileManager::RunAnalyzeTask,
774 analysis, 789 analysis,
775 tile->content_rect(), 790 tile->content_rect(),
776 tile->contents_scale(), 791 tile->contents_scale(),
777 use_color_estimator_, 792 use_color_estimator_,
778 GetRasterTaskMetadata(*tile), 793 GetRasterTaskMetadata(*tile),
779 rendering_stats_instrumentation_), 794 rendering_stats_instrumentation_),
780 base::Bind(&TileManager::RunRasterTask, 795 base::Bind(&TileManager::RunRasterTask,
781 buffer, 796 buffer,
782 analysis, 797 analysis,
783 tile->content_rect(), 798 tile->content_rect(),
784 tile->contents_scale(), 799 tile->contents_scale(),
785 GetRasterTaskMetadata(*tile), 800 GetRasterTaskMetadata(*tile),
786 rendering_stats_instrumentation_)), 801 rendering_stats_instrumentation_)),
787 base::Bind(&TileManager::OnRasterTaskCompleted, 802 base::Bind(&TileManager::OnRasterTaskCompleted,
788 base::Unretained(this), 803 base::Unretained(this),
789 tile, 804 make_scoped_refptr(tile),
790 base::Passed(&resource), 805 base::Passed(&resource),
791 base::Owned(analysis), 806 base::Owned(analysis)),
792 manage_tiles_call_count_)); 807 &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 } 808 }
808 809
809 void TileManager::OnRasterTaskCompleted( 810 void TileManager::OnRasterTaskCompleted(
810 scoped_refptr<Tile> tile, 811 scoped_refptr<Tile> tile,
811 scoped_ptr<ResourcePool::Resource> resource, 812 scoped_ptr<ResourcePool::Resource> resource,
812 PicturePileImpl::Analysis* analysis, 813 PicturePileImpl::Analysis* analysis,
813 int manage_tiles_call_count_when_dispatched) { 814 bool was_canceled) {
814 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); 815 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted");
815 816
816 pending_tasks_--; 817 ManagedTileState& mts = tile->managed_state();
818 DCHECK(!mts.raster_task.is_null());
819 mts.raster_task.Reset();
820
821 // Tile resources can't be freed until upload has completed.
822 DCHECK_EQ(USING_UNRELEASABLE_MEMORY, tile->tile_version().memory_state_);
817 823
818 // Release raster resources. 824 // Release raster resources.
819 resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id()); 825 resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id());
820 826
821 tile->tile_version().memory_state_ = USING_RELEASABLE_MEMORY; 827 if (was_canceled) {
828 tile->tile_version().memory_state_ = CAN_USE_MEMORY;
829 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id());
830 resource_pool_->ReleaseResource(resource.Pass());
831 return;
832 }
822 833
823 ManagedTileState& managed_tile_state = tile->managed_state(); 834 mts.picture_pile_analysis = *analysis;
824 managed_tile_state.picture_pile_analysis = *analysis; 835 mts.picture_pile_analyzed = true;
825 managed_tile_state.picture_pile_analyzed = true;
826 836
827 if (analysis->is_solid_color) { 837 if (analysis->is_solid_color) {
828 tile->tile_version().set_solid_color(analysis->solid_color); 838 tile->tile_version().set_solid_color(analysis->solid_color);
829 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); 839 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id());
830 resource_pool_->ReleaseResource(resource.Pass()); 840 resource_pool_->ReleaseResource(resource.Pass());
831 DidFinishTileInitialization(tile); 841 DidFinishTileInitialization(tile);
832 return; 842 return;
833 } 843 }
834 844
835 // Tile can be freed after the completion of the raster task. Call 845 resource_pool_->resource_provider()->BeginSetPixels(resource->id());
836 // AssignGpuMemoryToTiles() to re-assign gpu memory to highest priority 846 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 847
844 // Finish resource initialization we're still using memory. 848 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 849
849 resource_pool_->resource_provider()->BeginSetPixels(resource->id()); 850 bytes_pending_upload_ += tile->bytes_consumed_if_allocated();
850 has_performed_uploads_since_last_flush_ = true; 851 tiles_with_pending_upload_.push(tile);
851 852
852 tile->tile_version().resource_ = resource.Pass(); 853 if (tile->required_for_activation() &&
853 854 client_->ShouldForceTileUploadsRequiredForActivationToComplete())
854 bytes_pending_upload_ += tile->bytes_consumed_if_allocated(); 855 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 } 856 }
865 857
866 void TileManager::DidFinishTileInitialization(Tile* tile) { 858 void TileManager::DidFinishTileInitialization(Tile* tile) {
867 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0) 859 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0)
868 did_initialize_visible_tile_ = true; 860 did_initialize_visible_tile_ = true;
869 if (tile->required_for_activation()) { 861 if (tile->required_for_activation()) {
870 // It's possible that a tile required for activation is not in this list 862 // 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 863 // if it was marked as being required after being dispatched for
872 // rasterization but before AssignGPUMemory was called again. 864 // rasterization but before AssignGPUMemory was called again.
873 tiles_that_need_to_be_initialized_for_activation_.erase(tile); 865 tiles_that_need_to_be_initialized_for_activation_.erase(tile);
874 } 866 }
875 } 867 }
876 868
877 void TileManager::DidTileTreeBinChange(Tile* tile, 869 void TileManager::DidTileTreeBinChange(Tile* tile,
878 TileManagerBin new_tree_bin, 870 TileManagerBin new_tree_bin,
879 WhichTree tree) { 871 WhichTree tree) {
880 ManagedTileState& mts = tile->managed_state(); 872 ManagedTileState& mts = tile->managed_state();
881 mts.tree_bin[tree] = new_tree_bin; 873 mts.tree_bin[tree] = new_tree_bin;
882 } 874 }
883 875
884 // static 876 // static
877 void TileManager::RunImageDecodeTask(
878 skia::LazyPixelRef* pixel_ref,
879 int layer_id,
880 RenderingStatsInstrumentation* stats_instrumentation) {
881 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask");
882 devtools_instrumentation::ScopedLayerTask image_decode_task(
883 devtools_instrumentation::kImageDecodeTask, layer_id);
884 base::TimeTicks start_time = stats_instrumentation->StartRecording();
885 pixel_ref->Decode();
886 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
887 stats_instrumentation->AddDeferredImageDecode(duration);
888 }
889
890 // static
885 void TileManager::RunAnalyzeAndRasterTask( 891 void TileManager::RunAnalyzeAndRasterTask(
886 const RasterWorkerPool::RasterCallback& analyze_task, 892 const RasterWorkerPool::PictureTask::Callback& analyze_task,
887 const RasterWorkerPool::RasterCallback& raster_task, 893 const RasterWorkerPool::PictureTask::Callback& raster_task,
888 PicturePileImpl* picture_pile) { 894 PicturePileImpl* picture_pile) {
889 analyze_task.Run(picture_pile); 895 analyze_task.Run(picture_pile);
890 raster_task.Run(picture_pile); 896 raster_task.Run(picture_pile);
891 } 897 }
892 898
893 // static 899 // static
894 void TileManager::RunAnalyzeTask( 900 void TileManager::RunAnalyzeTask(
895 PicturePileImpl::Analysis* analysis, 901 PicturePileImpl::Analysis* analysis,
896 gfx::Rect rect, 902 gfx::Rect rect,
897 float contents_scale, 903 float contents_scale,
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 "Renderer4.PictureRasterTimeUS", 979 "Renderer4.PictureRasterTimeUS",
974 raster_stats.total_rasterize_time.InMicroseconds(), 980 raster_stats.total_rasterize_time.InMicroseconds(),
975 0, 981 0,
976 100000, 982 100000,
977 100); 983 100);
978 } else { 984 } else {
979 picture_pile->RasterToBitmap(&canvas, rect, contents_scale, NULL); 985 picture_pile->RasterToBitmap(&canvas, rect, contents_scale, NULL);
980 } 986 }
981 } 987 }
982 988
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 989 } // namespace cc
OLDNEW
« no previous file with comments | « cc/resources/tile_manager.h ('k') | cc/test/fake_tile_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698