OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/resources/tile_manager.h" | 5 #include "cc/resources/tile_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |