Home | History | Annotate | Download | only in resources
      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
      3 // found in the LICENSE file.
      4 
      5 #include "cc/resources/tile_manager.h"
      6 
      7 #include <algorithm>
      8 #include <limits>
      9 #include <string>
     10 
     11 #include "base/bind.h"
     12 #include "base/json/json_writer.h"
     13 #include "base/logging.h"
     14 #include "base/metrics/histogram.h"
     15 #include "cc/debug/devtools_instrumentation.h"
     16 #include "cc/debug/traced_value.h"
     17 #include "cc/resources/image_raster_worker_pool.h"
     18 #include "cc/resources/pixel_buffer_raster_worker_pool.h"
     19 #include "cc/resources/tile.h"
     20 #include "third_party/skia/include/core/SkCanvas.h"
     21 #include "ui/gfx/rect_conversions.h"
     22 
     23 namespace cc {
     24 
     25 namespace {
     26 
     27 // Memory limit policy works by mapping some bin states to the NEVER bin.
     28 const ManagedTileBin kBinPolicyMap[NUM_TILE_MEMORY_LIMIT_POLICIES][NUM_BINS] = {
     29   {  // [ALLOW_NOTHING]
     30     NEVER_BIN,                  // [NOW_AND_READY_TO_DRAW_BIN]
     31     NEVER_BIN,                  // [NOW_BIN]
     32     NEVER_BIN,                  // [SOON_BIN]
     33     NEVER_BIN,                  // [EVENTUALLY_AND_ACTIVE_BIN]
     34     NEVER_BIN,                  // [EVENTUALLY_BIN]
     35     NEVER_BIN,                  // [NEVER_AND_ACTIVE_BIN]
     36     NEVER_BIN                   // [NEVER_BIN]
     37   }, {  // [ALLOW_ABSOLUTE_MINIMUM]
     38     NOW_AND_READY_TO_DRAW_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
     39     NOW_BIN,                    // [NOW_BIN]
     40     NEVER_BIN,                  // [SOON_BIN]
     41     NEVER_BIN,                  // [EVENTUALLY_AND_ACTIVE_BIN]
     42     NEVER_BIN,                  // [EVENTUALLY_BIN]
     43     NEVER_BIN,                  // [NEVER_AND_ACTIVE_BIN]
     44     NEVER_BIN                   // [NEVER_BIN]
     45   }, {  // [ALLOW_PREPAINT_ONLY]
     46     NOW_AND_READY_TO_DRAW_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
     47     NOW_BIN,                    // [NOW_BIN]
     48     SOON_BIN,                   // [SOON_BIN]
     49     NEVER_BIN,                  // [EVENTUALLY_AND_ACTIVE_BIN]
     50     NEVER_BIN,                  // [EVENTUALLY_BIN]
     51     NEVER_BIN,                  // [NEVER_AND_ACTIVE_BIN]
     52     NEVER_BIN                   // [NEVER_BIN]
     53   }, {  // [ALLOW_ANYTHING]
     54     NOW_AND_READY_TO_DRAW_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
     55     NOW_BIN,                    // [NOW_BIN]
     56     SOON_BIN,                   // [SOON_BIN]
     57     EVENTUALLY_AND_ACTIVE_BIN,  // [EVENTUALLY_AND_ACTIVE_BIN]
     58     EVENTUALLY_BIN,             // [EVENTUALLY_BIN]
     59     NEVER_AND_ACTIVE_BIN,       // [NEVER_AND_ACTIVE_BIN]
     60     NEVER_BIN                   // [NEVER_BIN]
     61   }
     62 };
     63 
     64 // Determine bin based on three categories of tiles: things we need now,
     65 // things we need soon, and eventually.
     66 inline ManagedTileBin BinFromTilePriority(const TilePriority& prio,
     67                                           TreePriority tree_priority,
     68                                           bool is_ready_to_draw,
     69                                           bool is_active) {
     70   // The amount of time/pixels for which we want to have prepainting coverage.
     71   // Note: All very arbitrary constants: metric-based tuning is welcome!
     72   const float kPrepaintingWindowTimeSeconds = 1.0f;
     73   const float kBackflingGuardDistancePixels = 314.0f;
     74   // Note: The max distances here assume that SOON_BIN will never help overcome
     75   // raster being too slow (only caching in advance will do that), so we just
     76   // need enough padding to handle some latency and per-tile variability.
     77   const float kMaxPrepaintingDistancePixelsHighRes = 2000.0f;
     78   const float kMaxPrepaintingDistancePixelsLowRes = 4000.0f;
     79 
     80   // Don't let low res tiles be in the now bin unless we're in a mode where
     81   // we're prioritizing checkerboard prevention.
     82   bool can_be_in_now_bin = tree_priority == SMOOTHNESS_TAKES_PRIORITY ||
     83                            prio.resolution != LOW_RESOLUTION;
     84 
     85   if (prio.distance_to_visible_in_pixels ==
     86       std::numeric_limits<float>::infinity())
     87     return is_active ? NEVER_AND_ACTIVE_BIN : NEVER_BIN;
     88 
     89   if (can_be_in_now_bin && prio.time_to_visible_in_seconds == 0)
     90     return is_ready_to_draw ? NOW_AND_READY_TO_DRAW_BIN : NOW_BIN;
     91 
     92   if (prio.resolution == NON_IDEAL_RESOLUTION)
     93     return is_active ? EVENTUALLY_AND_ACTIVE_BIN : EVENTUALLY_BIN;
     94 
     95   float max_prepainting_distance_pixels =
     96       (prio.resolution == HIGH_RESOLUTION)
     97           ? kMaxPrepaintingDistancePixelsHighRes
     98           : kMaxPrepaintingDistancePixelsLowRes;
     99 
    100   // Soon bin if we are within backfling-guard, or under both the time window
    101   // and the max distance window.
    102   if (prio.distance_to_visible_in_pixels < kBackflingGuardDistancePixels ||
    103       (prio.time_to_visible_in_seconds < kPrepaintingWindowTimeSeconds &&
    104        prio.distance_to_visible_in_pixels <= max_prepainting_distance_pixels))
    105     return SOON_BIN;
    106 
    107   return is_active ? EVENTUALLY_AND_ACTIVE_BIN : EVENTUALLY_BIN;
    108 }
    109 
    110 // Limit to the number of raster tasks that can be scheduled.
    111 // This is high enough to not cause unnecessary scheduling but
    112 // gives us an insurance that we're not spending a huge amount
    113 // of time scheduling one enormous set of tasks.
    114 const size_t kMaxRasterTasks = 256u;
    115 
    116 }  // namespace
    117 
    118 RasterTaskCompletionStats::RasterTaskCompletionStats()
    119     : completed_count(0u),
    120       canceled_count(0u) {
    121 }
    122 
    123 scoped_ptr<base::Value> RasterTaskCompletionStatsAsValue(
    124     const RasterTaskCompletionStats& stats) {
    125   scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
    126   state->SetInteger("completed_count", stats.completed_count);
    127   state->SetInteger("canceled_count", stats.canceled_count);
    128   return state.PassAs<base::Value>();
    129 }
    130 
    131 // static
    132 scoped_ptr<TileManager> TileManager::Create(
    133     TileManagerClient* client,
    134     ResourceProvider* resource_provider,
    135     size_t num_raster_threads,
    136     RenderingStatsInstrumentation* rendering_stats_instrumentation,
    137     bool use_map_image) {
    138   return make_scoped_ptr(
    139       new TileManager(client,
    140                       resource_provider,
    141                       use_map_image ?
    142                       ImageRasterWorkerPool::Create(
    143                           resource_provider, num_raster_threads) :
    144                       PixelBufferRasterWorkerPool::Create(
    145                           resource_provider, num_raster_threads),
    146                       num_raster_threads,
    147                       rendering_stats_instrumentation,
    148                       resource_provider->best_texture_format()));
    149 }
    150 
    151 TileManager::TileManager(
    152     TileManagerClient* client,
    153     ResourceProvider* resource_provider,
    154     scoped_ptr<RasterWorkerPool> raster_worker_pool,
    155     size_t num_raster_threads,
    156     RenderingStatsInstrumentation* rendering_stats_instrumentation,
    157     GLenum texture_format)
    158     : client_(client),
    159       resource_pool_(ResourcePool::Create(resource_provider)),
    160       raster_worker_pool_(raster_worker_pool.Pass()),
    161       all_tiles_that_need_to_be_rasterized_have_memory_(true),
    162       all_tiles_required_for_activation_have_memory_(true),
    163       all_tiles_required_for_activation_have_been_initialized_(true),
    164       ever_exceeded_memory_budget_(false),
    165       rendering_stats_instrumentation_(rendering_stats_instrumentation),
    166       did_initialize_visible_tile_(false),
    167       texture_format_(texture_format) {
    168   raster_worker_pool_->SetClient(this);
    169 }
    170 
    171 TileManager::~TileManager() {
    172   // Reset global state and manage. This should cause
    173   // our memory usage to drop to zero.
    174   global_state_ = GlobalStateThatImpactsTilePriority();
    175 
    176   // Clear |prioritized_tiles_| so that tiles kept alive by it can be freed.
    177   prioritized_tiles_.Clear();
    178   DCHECK_EQ(0u, tiles_.size());
    179 
    180   TileVector empty;
    181   ScheduleTasks(empty);
    182 
    183   // This should finish all pending tasks and release any uninitialized
    184   // resources.
    185   raster_worker_pool_->Shutdown();
    186   raster_worker_pool_->CheckForCompletedTasks();
    187 }
    188 
    189 void TileManager::SetGlobalState(
    190     const GlobalStateThatImpactsTilePriority& global_state) {
    191   global_state_ = global_state;
    192   resource_pool_->SetResourceUsageLimits(
    193       global_state_.memory_limit_in_bytes,
    194       global_state_.unused_memory_limit_in_bytes,
    195       global_state_.num_resources_limit);
    196 }
    197 
    198 void TileManager::RegisterTile(Tile* tile) {
    199   DCHECK(!tile->required_for_activation());
    200   DCHECK(tiles_.find(tile->id()) == tiles_.end());
    201 
    202   tiles_[tile->id()] = tile;
    203 }
    204 
    205 void TileManager::UnregisterTile(Tile* tile) {
    206   FreeResourcesForTile(tile);
    207 
    208   DCHECK(tiles_.find(tile->id()) != tiles_.end());
    209   tiles_.erase(tile->id());
    210 }
    211 
    212 bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const {
    213   return GlobalState().tree_priority != SMOOTHNESS_TAKES_PRIORITY;
    214 }
    215 
    216 void TileManager::DidFinishRunningTasks() {
    217   TRACE_EVENT0("cc", "TileManager::DidFinishRunningTasks");
    218 
    219   // When OOM, keep re-assigning memory until we reach a steady state
    220   // where top-priority tiles are initialized.
    221   if (all_tiles_that_need_to_be_rasterized_have_memory_)
    222     return;
    223 
    224   raster_worker_pool_->CheckForCompletedTasks();
    225 
    226   TileVector tiles_that_need_to_be_rasterized;
    227   AssignGpuMemoryToTiles(&prioritized_tiles_,
    228                          &tiles_that_need_to_be_rasterized);
    229 
    230   // |tiles_that_need_to_be_rasterized| will be empty when we reach a
    231   // steady memory state. Keep scheduling tasks until we reach this state.
    232   if (!tiles_that_need_to_be_rasterized.empty()) {
    233     ScheduleTasks(tiles_that_need_to_be_rasterized);
    234     return;
    235   }
    236 
    237   // Use on-demand raster for any required-for-activation tiles that have not
    238   // been been assigned memory after reaching a steady memory state. This
    239   // ensures that we activate even when OOM.
    240   for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
    241     Tile* tile = it->second;
    242     ManagedTileState& mts = tile->managed_state();
    243     ManagedTileState::TileVersion& tile_version =
    244         mts.tile_versions[mts.raster_mode];
    245 
    246     if (tile->required_for_activation() && !tile_version.IsReadyToDraw())
    247       tile_version.set_rasterize_on_demand();
    248   }
    249 
    250   client_->NotifyReadyToActivate();
    251 }
    252 
    253 void TileManager::DidFinishRunningTasksRequiredForActivation() {
    254   // This is only a true indication that all tiles required for
    255   // activation are initialized when no tiles are OOM. We need to
    256   // wait for DidFinishRunningTasks() to be called, try to re-assign
    257   // memory and in worst case use on-demand raster when tiles
    258   // required for activation are OOM.
    259   if (!all_tiles_required_for_activation_have_memory_)
    260     return;
    261 
    262   client_->NotifyReadyToActivate();
    263 }
    264 
    265 void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) {
    266   TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins");
    267 
    268   const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy;
    269   const TreePriority tree_priority = global_state_.tree_priority;
    270 
    271   // For each tree, bin into different categories of tiles.
    272   for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
    273     Tile* tile = it->second;
    274     ManagedTileState& mts = tile->managed_state();
    275 
    276     TilePriority prio[NUM_BIN_PRIORITIES];
    277     switch (tree_priority) {
    278       case SAME_PRIORITY_FOR_BOTH_TREES:
    279         prio[HIGH_PRIORITY_BIN] = prio[LOW_PRIORITY_BIN] =
    280             tile->combined_priority();
    281         break;
    282       case SMOOTHNESS_TAKES_PRIORITY:
    283         prio[HIGH_PRIORITY_BIN] = tile->priority(ACTIVE_TREE);
    284         prio[LOW_PRIORITY_BIN] = tile->priority(PENDING_TREE);
    285         break;
    286       case NEW_CONTENT_TAKES_PRIORITY:
    287         prio[HIGH_PRIORITY_BIN] = tile->priority(PENDING_TREE);
    288         prio[LOW_PRIORITY_BIN] = tile->priority(ACTIVE_TREE);
    289         break;
    290     }
    291 
    292     bool tile_is_ready_to_draw = tile->IsReadyToDraw();
    293     bool tile_is_active =
    294         tile_is_ready_to_draw ||
    295         !mts.tile_versions[mts.raster_mode].raster_task_.is_null();
    296 
    297     mts.resolution = prio[HIGH_PRIORITY_BIN].resolution;
    298     mts.time_to_needed_in_seconds =
    299         prio[HIGH_PRIORITY_BIN].time_to_visible_in_seconds;
    300     mts.distance_to_visible_in_pixels =
    301         prio[HIGH_PRIORITY_BIN].distance_to_visible_in_pixels;
    302     mts.required_for_activation =
    303         prio[HIGH_PRIORITY_BIN].required_for_activation;
    304 
    305     mts.bin[HIGH_PRIORITY_BIN] =
    306         BinFromTilePriority(prio[HIGH_PRIORITY_BIN],
    307                             tree_priority,
    308                             tile_is_ready_to_draw,
    309                             tile_is_active);
    310     mts.bin[LOW_PRIORITY_BIN] =
    311         BinFromTilePriority(prio[LOW_PRIORITY_BIN],
    312                             tree_priority,
    313                             tile_is_ready_to_draw,
    314                             tile_is_active);
    315     mts.gpu_memmgr_stats_bin =
    316         BinFromTilePriority(tile->combined_priority(),
    317                             tree_priority,
    318                             tile_is_ready_to_draw,
    319                             tile_is_active);
    320 
    321     ManagedTileBin active_bin =
    322         BinFromTilePriority(tile->priority(ACTIVE_TREE),
    323                             tree_priority,
    324                             tile_is_ready_to_draw,
    325                             tile_is_active);
    326     mts.tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin];
    327 
    328     ManagedTileBin pending_bin =
    329         BinFromTilePriority(tile->priority(PENDING_TREE),
    330                             tree_priority,
    331                             tile_is_ready_to_draw,
    332                             tile_is_active);
    333     mts.tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin];
    334 
    335     for (int i = 0; i < NUM_BIN_PRIORITIES; ++i)
    336       mts.bin[i] = kBinPolicyMap[memory_policy][mts.bin[i]];
    337 
    338     mts.visible_and_ready_to_draw =
    339         mts.tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN;
    340 
    341     if (mts.is_in_never_bin_on_both_trees()) {
    342       FreeResourcesForTile(tile);
    343       continue;
    344     }
    345 
    346     // Note that if the tile is visible_and_ready_to_draw, then we always want
    347     // the priority to be NOW_AND_READY_TO_DRAW_BIN, even if HIGH_PRIORITY_BIN
    348     // is something different. The reason for this is that if we're prioritizing
    349     // the pending tree, we still want visible tiles to take the highest
    350     // priority.
    351     ManagedTileBin priority_bin = mts.visible_and_ready_to_draw
    352                                   ? NOW_AND_READY_TO_DRAW_BIN
    353                                   : mts.bin[HIGH_PRIORITY_BIN];
    354 
    355     // Insert the tile into a priority set.
    356     tiles->InsertTile(tile, priority_bin);
    357   }
    358 }
    359 
    360 void TileManager::GetPrioritizedTileSet(PrioritizedTileSet* tiles) {
    361   TRACE_EVENT0("cc", "TileManager::GetPrioritizedTileSet");
    362 
    363   GetTilesWithAssignedBins(tiles);
    364   tiles->Sort();
    365 }
    366 
    367 void TileManager::ManageTiles() {
    368   TRACE_EVENT0("cc", "TileManager::ManageTiles");
    369 
    370   // Clear |prioritized_tiles_| so that tiles kept alive by it can be freed.
    371   prioritized_tiles_.Clear();
    372 
    373   GetPrioritizedTileSet(&prioritized_tiles_);
    374 
    375   TileVector tiles_that_need_to_be_rasterized;
    376   AssignGpuMemoryToTiles(&prioritized_tiles_,
    377                          &tiles_that_need_to_be_rasterized);
    378   CleanUpUnusedImageDecodeTasks();
    379 
    380   TRACE_EVENT_INSTANT1(
    381       "cc", "DidManage", TRACE_EVENT_SCOPE_THREAD,
    382       "state", TracedValue::FromValue(BasicStateAsValue().release()));
    383 
    384   // Finally, schedule rasterizer tasks.
    385   ScheduleTasks(tiles_that_need_to_be_rasterized);
    386 }
    387 
    388 bool TileManager::UpdateVisibleTiles() {
    389   TRACE_EVENT0("cc", "TileManager::UpdateVisibleTiles");
    390 
    391   raster_worker_pool_->CheckForCompletedTasks();
    392 
    393   TRACE_EVENT_INSTANT1(
    394       "cc", "DidUpdateVisibleTiles", TRACE_EVENT_SCOPE_THREAD,
    395       "stats", TracedValue::FromValue(
    396           RasterTaskCompletionStatsAsValue(
    397               update_visible_tiles_stats_).release()));
    398   update_visible_tiles_stats_ = RasterTaskCompletionStats();
    399 
    400   bool did_initialize_visible_tile = did_initialize_visible_tile_;
    401   did_initialize_visible_tile_ = false;
    402   return did_initialize_visible_tile;
    403 }
    404 
    405 void TileManager::GetMemoryStats(
    406     size_t* memory_required_bytes,
    407     size_t* memory_nice_to_have_bytes,
    408     size_t* memory_used_bytes) const {
    409   *memory_required_bytes = 0;
    410   *memory_nice_to_have_bytes = 0;
    411   *memory_used_bytes = resource_pool_->acquired_memory_usage_bytes();
    412   for (TileMap::const_iterator it = tiles_.begin();
    413        it != tiles_.end();
    414        ++it) {
    415     const Tile* tile = it->second;
    416     const ManagedTileState& mts = tile->managed_state();
    417 
    418     const ManagedTileState::TileVersion& tile_version =
    419         tile->GetTileVersionForDrawing();
    420     if (tile_version.IsReadyToDraw() &&
    421         !tile_version.requires_resource())
    422       continue;
    423 
    424     size_t tile_bytes = tile->bytes_consumed_if_allocated();
    425     if ((mts.gpu_memmgr_stats_bin == NOW_BIN) ||
    426         (mts.gpu_memmgr_stats_bin == NOW_AND_READY_TO_DRAW_BIN))
    427       *memory_required_bytes += tile_bytes;
    428     if (mts.gpu_memmgr_stats_bin != NEVER_BIN)
    429       *memory_nice_to_have_bytes += tile_bytes;
    430   }
    431 }
    432 
    433 scoped_ptr<base::Value> TileManager::BasicStateAsValue() const {
    434   scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
    435   state->SetInteger("tile_count", tiles_.size());
    436   state->Set("global_state", global_state_.AsValue().release());
    437   state->Set("memory_requirements", GetMemoryRequirementsAsValue().release());
    438   return state.PassAs<base::Value>();
    439 }
    440 
    441 scoped_ptr<base::Value> TileManager::AllTilesAsValue() const {
    442   scoped_ptr<base::ListValue> state(new base::ListValue());
    443   for (TileMap::const_iterator it = tiles_.begin();
    444        it != tiles_.end();
    445        it++) {
    446     state->Append(it->second->AsValue().release());
    447   }
    448   return state.PassAs<base::Value>();
    449 }
    450 
    451 scoped_ptr<base::Value> TileManager::GetMemoryRequirementsAsValue() const {
    452   scoped_ptr<base::DictionaryValue> requirements(
    453       new base::DictionaryValue());
    454 
    455   size_t memory_required_bytes;
    456   size_t memory_nice_to_have_bytes;
    457   size_t memory_used_bytes;
    458   GetMemoryStats(&memory_required_bytes,
    459                  &memory_nice_to_have_bytes,
    460                  &memory_used_bytes);
    461   requirements->SetInteger("memory_required_bytes", memory_required_bytes);
    462   requirements->SetInteger("memory_nice_to_have_bytes",
    463                            memory_nice_to_have_bytes);
    464   requirements->SetInteger("memory_used_bytes", memory_used_bytes);
    465   return requirements.PassAs<base::Value>();
    466 }
    467 
    468 RasterMode TileManager::DetermineRasterMode(const Tile* tile) const {
    469   DCHECK(tile);
    470   DCHECK(tile->picture_pile());
    471 
    472   const ManagedTileState& mts = tile->managed_state();
    473   RasterMode current_mode = mts.raster_mode;
    474 
    475   RasterMode raster_mode = HIGH_QUALITY_RASTER_MODE;
    476   if (tile->managed_state().resolution == LOW_RESOLUTION)
    477     raster_mode = LOW_QUALITY_RASTER_MODE;
    478   else if (tile->can_use_lcd_text())
    479     raster_mode = HIGH_QUALITY_RASTER_MODE;
    480   else if (mts.tile_versions[current_mode].has_text_ ||
    481            !mts.tile_versions[current_mode].IsReadyToDraw())
    482     raster_mode = HIGH_QUALITY_NO_LCD_RASTER_MODE;
    483 
    484   return std::min(raster_mode, current_mode);
    485 }
    486 
    487 void TileManager::AssignGpuMemoryToTiles(
    488     PrioritizedTileSet* tiles,
    489     TileVector* tiles_that_need_to_be_rasterized) {
    490   TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles");
    491 
    492   // Now give memory out to the tiles until we're out, and build
    493   // the needs-to-be-rasterized queue.
    494   size_t bytes_releasable = 0;
    495   size_t resources_releasable = 0;
    496   for (PrioritizedTileSet::PriorityIterator it(tiles);
    497        it;
    498        ++it) {
    499     const Tile* tile = *it;
    500     const ManagedTileState& mts = tile->managed_state();
    501     for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
    502       if (mts.tile_versions[mode].resource_) {
    503         bytes_releasable += tile->bytes_consumed_if_allocated();
    504         resources_releasable++;
    505       }
    506     }
    507   }
    508 
    509   all_tiles_that_need_to_be_rasterized_have_memory_ = true;
    510   all_tiles_required_for_activation_have_memory_ = true;
    511   all_tiles_required_for_activation_have_been_initialized_ = true;
    512 
    513   // Cast to prevent overflow.
    514   int64 bytes_available =
    515       static_cast<int64>(bytes_releasable) +
    516       static_cast<int64>(global_state_.memory_limit_in_bytes) -
    517       static_cast<int64>(resource_pool_->acquired_memory_usage_bytes());
    518   int resources_available =
    519       resources_releasable +
    520       global_state_.num_resources_limit -
    521       resource_pool_->acquired_resource_count();
    522 
    523   size_t bytes_allocatable =
    524       std::max(static_cast<int64>(0), bytes_available);
    525   size_t resources_allocatable = std::max(0, resources_available);
    526 
    527   size_t bytes_that_exceeded_memory_budget = 0;
    528   size_t bytes_left = bytes_allocatable;
    529   size_t resources_left = resources_allocatable;
    530   bool oomed = false;
    531 
    532   unsigned schedule_priority = 1u;
    533   for (PrioritizedTileSet::PriorityIterator it(tiles);
    534        it;
    535        ++it) {
    536     Tile* tile = *it;
    537     ManagedTileState& mts = tile->managed_state();
    538 
    539     mts.scheduled_priority = schedule_priority++;
    540 
    541     mts.raster_mode = DetermineRasterMode(tile);
    542 
    543     ManagedTileState::TileVersion& tile_version =
    544         mts.tile_versions[mts.raster_mode];
    545 
    546     // If this tile doesn't need a resource, then nothing to do.
    547     if (!tile_version.requires_resource())
    548       continue;
    549 
    550     // If the tile is not needed, free it up.
    551     if (mts.is_in_never_bin_on_both_trees()) {
    552       FreeResourcesForTile(tile);
    553       continue;
    554     }
    555 
    556     size_t tile_bytes = 0;
    557     size_t tile_resources = 0;
    558 
    559     // It costs to maintain a resource.
    560     for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
    561       if (mts.tile_versions[mode].resource_) {
    562         tile_bytes += tile->bytes_consumed_if_allocated();
    563         tile_resources++;
    564       }
    565     }
    566 
    567     // Allow lower priority tiles with initialized resources to keep
    568     // their memory by only assigning memory to new raster tasks if
    569     // they can be scheduled.
    570     if (tiles_that_need_to_be_rasterized->size() < kMaxRasterTasks) {
    571       // If we don't have the required version, and it's not in flight
    572       // then we'll have to pay to create a new task.
    573       if (!tile_version.resource_ && tile_version.raster_task_.is_null()) {
    574         tile_bytes += tile->bytes_consumed_if_allocated();
    575         tile_resources++;
    576       }
    577     }
    578 
    579     // Tile is OOM.
    580     if (tile_bytes > bytes_left || tile_resources > resources_left) {
    581       FreeResourcesForTile(tile);
    582 
    583       // This tile was already on screen and now its resources have been
    584       // released. In order to prevent checkerboarding, set this tile as
    585       // rasterize on demand immediately.
    586       if (mts.visible_and_ready_to_draw)
    587         tile_version.set_rasterize_on_demand();
    588 
    589       oomed = true;
    590       bytes_that_exceeded_memory_budget += tile_bytes;
    591     } else {
    592       bytes_left -= tile_bytes;
    593       resources_left -= tile_resources;
    594 
    595       if (tile_version.resource_)
    596         continue;
    597     }
    598 
    599     DCHECK(!tile_version.resource_);
    600 
    601     if (tile->required_for_activation())
    602       all_tiles_required_for_activation_have_been_initialized_ = false;
    603 
    604     // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized|
    605     // has reached it's limit or we've failed to assign gpu memory to this
    606     // or any higher priority tile. Preventing tiles that fit into memory
    607     // budget to be rasterized when higher priority tile is oom is
    608     // important for two reasons:
    609     // 1. Tile size should not impact raster priority.
    610     // 2. Tiles with existing raster task could otherwise incorrectly
    611     //    be added as they are not affected by |bytes_allocatable|.
    612     if (oomed || tiles_that_need_to_be_rasterized->size() >= kMaxRasterTasks) {
    613       all_tiles_that_need_to_be_rasterized_have_memory_ = false;
    614       if (tile->required_for_activation())
    615         all_tiles_required_for_activation_have_memory_ = false;
    616       continue;
    617     }
    618 
    619     tiles_that_need_to_be_rasterized->push_back(tile);
    620   }
    621 
    622   ever_exceeded_memory_budget_ |= bytes_that_exceeded_memory_budget > 0;
    623   if (ever_exceeded_memory_budget_) {
    624       TRACE_COUNTER_ID2("cc", "over_memory_budget", this,
    625                         "budget", global_state_.memory_limit_in_bytes,
    626                         "over", bytes_that_exceeded_memory_budget);
    627   }
    628   memory_stats_from_last_assign_.total_budget_in_bytes =
    629       global_state_.memory_limit_in_bytes;
    630   memory_stats_from_last_assign_.bytes_allocated =
    631       bytes_allocatable - bytes_left;
    632   memory_stats_from_last_assign_.bytes_unreleasable =
    633       bytes_allocatable - bytes_releasable;
    634   memory_stats_from_last_assign_.bytes_over =
    635       bytes_that_exceeded_memory_budget;
    636 }
    637 
    638 void TileManager::CleanUpUnusedImageDecodeTasks() {
    639   // Calculate a set of layers that are used by at least one tile.
    640   base::hash_set<int> used_layers;
    641   for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it)
    642     used_layers.insert(it->second->layer_id());
    643 
    644   // Now calculate the set of layers in |image_decode_tasks_| that are not used
    645   // by any tile.
    646   std::vector<int> unused_layers;
    647   for (LayerPixelRefTaskMap::iterator it = image_decode_tasks_.begin();
    648        it != image_decode_tasks_.end();
    649        ++it) {
    650     if (used_layers.find(it->first) == used_layers.end())
    651       unused_layers.push_back(it->first);
    652   }
    653 
    654   // Erase unused layers from |image_decode_tasks_|.
    655   for (std::vector<int>::iterator it = unused_layers.begin();
    656        it != unused_layers.end();
    657        ++it) {
    658     image_decode_tasks_.erase(*it);
    659   }
    660 }
    661 
    662 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) {
    663   ManagedTileState& mts = tile->managed_state();
    664   if (mts.tile_versions[mode].resource_) {
    665     resource_pool_->ReleaseResource(
    666         mts.tile_versions[mode].resource_.Pass());
    667   }
    668 }
    669 
    670 void TileManager::FreeResourcesForTile(Tile* tile) {
    671   for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
    672     FreeResourceForTile(tile, static_cast<RasterMode>(mode));
    673   }
    674 }
    675 
    676 void TileManager::FreeUnusedResourcesForTile(Tile* tile) {
    677   DCHECK(tile->IsReadyToDraw());
    678   ManagedTileState& mts = tile->managed_state();
    679   RasterMode used_mode = HIGH_QUALITY_NO_LCD_RASTER_MODE;
    680   for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
    681     if (mts.tile_versions[mode].IsReadyToDraw()) {
    682       used_mode = static_cast<RasterMode>(mode);
    683       break;
    684     }
    685   }
    686 
    687   for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
    688     if (mode != used_mode)
    689       FreeResourceForTile(tile, static_cast<RasterMode>(mode));
    690   }
    691 }
    692 
    693 void TileManager::ScheduleTasks(
    694     const TileVector& tiles_that_need_to_be_rasterized) {
    695   TRACE_EVENT1("cc", "TileManager::ScheduleTasks",
    696                "count", tiles_that_need_to_be_rasterized.size());
    697   RasterWorkerPool::RasterTask::Queue tasks;
    698 
    699   // Build a new task queue containing all task currently needed. Tasks
    700   // are added in order of priority, highest priority task first.
    701   for (TileVector::const_iterator it = tiles_that_need_to_be_rasterized.begin();
    702        it != tiles_that_need_to_be_rasterized.end();
    703        ++it) {
    704     Tile* tile = *it;
    705     ManagedTileState& mts = tile->managed_state();
    706     ManagedTileState::TileVersion& tile_version =
    707         mts.tile_versions[mts.raster_mode];
    708 
    709     DCHECK(tile_version.requires_resource());
    710     DCHECK(!tile_version.resource_);
    711 
    712     if (tile_version.raster_task_.is_null())
    713       tile_version.raster_task_ = CreateRasterTask(tile);
    714 
    715     tasks.Append(tile_version.raster_task_, tile->required_for_activation());
    716   }
    717 
    718   // We must reduce the amount of unused resoruces before calling
    719   // ScheduleTasks to prevent usage from rising above limits.
    720   resource_pool_->ReduceResourceUsage();
    721 
    722   // Schedule running of |tasks|. This replaces any previously
    723   // scheduled tasks and effectively cancels all tasks not present
    724   // in |tasks|.
    725   raster_worker_pool_->ScheduleTasks(&tasks);
    726 }
    727 
    728 RasterWorkerPool::Task TileManager::CreateImageDecodeTask(
    729     Tile* tile, skia::LazyPixelRef* pixel_ref) {
    730   return RasterWorkerPool::CreateImageDecodeTask(
    731       pixel_ref,
    732       tile->layer_id(),
    733       rendering_stats_instrumentation_,
    734       base::Bind(&TileManager::OnImageDecodeTaskCompleted,
    735                  base::Unretained(this),
    736                  tile->layer_id(),
    737                  base::Unretained(pixel_ref)));
    738 }
    739 
    740 RasterWorkerPool::RasterTask TileManager::CreateRasterTask(Tile* tile) {
    741   ManagedTileState& mts = tile->managed_state();
    742 
    743   scoped_ptr<ResourcePool::Resource> resource =
    744       resource_pool_->AcquireResource(tile->tile_size_.size(),
    745                                       texture_format_);
    746   const Resource* const_resource = resource.get();
    747 
    748   // Create and queue all image decode tasks that this tile depends on.
    749   RasterWorkerPool::Task::Set decode_tasks;
    750   PixelRefTaskMap& existing_pixel_refs = image_decode_tasks_[tile->layer_id()];
    751   for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(),
    752                                               tile->contents_scale(),
    753                                               tile->picture_pile());
    754        iter; ++iter) {
    755     skia::LazyPixelRef* pixel_ref = *iter;
    756     uint32_t id = pixel_ref->getGenerationID();
    757 
    758     // Append existing image decode task if available.
    759     PixelRefTaskMap::iterator decode_task_it = existing_pixel_refs.find(id);
    760     if (decode_task_it != existing_pixel_refs.end()) {
    761       decode_tasks.Insert(decode_task_it->second);
    762       continue;
    763     }
    764 
    765     // Create and append new image decode task for this pixel ref.
    766     RasterWorkerPool::Task decode_task = CreateImageDecodeTask(
    767         tile, pixel_ref);
    768     decode_tasks.Insert(decode_task);
    769     existing_pixel_refs[id] = decode_task;
    770   }
    771 
    772   return RasterWorkerPool::CreateRasterTask(
    773       const_resource,
    774       tile->picture_pile(),
    775       tile->content_rect(),
    776       tile->contents_scale(),
    777       mts.raster_mode,
    778       mts.tree_bin[PENDING_TREE] == NOW_BIN,
    779       mts.resolution,
    780       tile->layer_id(),
    781       static_cast<const void *>(tile),
    782       tile->source_frame_number(),
    783       rendering_stats_instrumentation_,
    784       base::Bind(&TileManager::OnRasterTaskCompleted,
    785                  base::Unretained(this),
    786                  tile->id(),
    787                  base::Passed(&resource),
    788                  mts.raster_mode),
    789       &decode_tasks);
    790 }
    791 
    792 void TileManager::OnImageDecodeTaskCompleted(
    793     int layer_id,
    794     skia::LazyPixelRef* pixel_ref,
    795     bool was_canceled) {
    796   // If the task was canceled, we need to clean it up
    797   // from |image_decode_tasks_|.
    798   if (!was_canceled)
    799     return;
    800 
    801   LayerPixelRefTaskMap::iterator layer_it =
    802       image_decode_tasks_.find(layer_id);
    803 
    804   if (layer_it == image_decode_tasks_.end())
    805     return;
    806 
    807   PixelRefTaskMap& pixel_ref_tasks = layer_it->second;
    808   PixelRefTaskMap::iterator task_it =
    809       pixel_ref_tasks.find(pixel_ref->getGenerationID());
    810 
    811   if (task_it != pixel_ref_tasks.end())
    812     pixel_ref_tasks.erase(task_it);
    813 }
    814 
    815 void TileManager::OnRasterTaskCompleted(
    816     Tile::Id tile_id,
    817     scoped_ptr<ResourcePool::Resource> resource,
    818     RasterMode raster_mode,
    819     const PicturePileImpl::Analysis& analysis,
    820     bool was_canceled) {
    821   TileMap::iterator it = tiles_.find(tile_id);
    822   if (it == tiles_.end()) {
    823     ++update_visible_tiles_stats_.canceled_count;
    824     resource_pool_->ReleaseResource(resource.Pass());
    825     return;
    826   }
    827 
    828   Tile* tile = it->second;
    829   ManagedTileState& mts = tile->managed_state();
    830   ManagedTileState::TileVersion& tile_version =
    831       mts.tile_versions[raster_mode];
    832   DCHECK(!tile_version.raster_task_.is_null());
    833   tile_version.raster_task_.Reset();
    834 
    835   if (was_canceled) {
    836     ++update_visible_tiles_stats_.canceled_count;
    837     resource_pool_->ReleaseResource(resource.Pass());
    838     return;
    839   }
    840 
    841   ++update_visible_tiles_stats_.completed_count;
    842 
    843   tile_version.set_has_text(analysis.has_text);
    844   if (analysis.is_solid_color) {
    845     tile_version.set_solid_color(analysis.solid_color);
    846     resource_pool_->ReleaseResource(resource.Pass());
    847   } else {
    848     tile_version.set_use_resource();
    849     tile_version.resource_ = resource.Pass();
    850   }
    851 
    852   FreeUnusedResourcesForTile(tile);
    853   if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0)
    854     did_initialize_visible_tile_ = true;
    855 }
    856 
    857 }  // namespace cc
    858