• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/debug/trace_event_argument.h"
13 #include "base/json/json_writer.h"
14 #include "base/logging.h"
15 #include "base/metrics/histogram.h"
16 #include "cc/debug/devtools_instrumentation.h"
17 #include "cc/debug/frame_viewer_instrumentation.h"
18 #include "cc/debug/traced_value.h"
19 #include "cc/layers/picture_layer_impl.h"
20 #include "cc/resources/raster_buffer.h"
21 #include "cc/resources/rasterizer.h"
22 #include "cc/resources/tile.h"
23 #include "skia/ext/paint_simplifier.h"
24 #include "third_party/skia/include/core/SkBitmap.h"
25 #include "third_party/skia/include/core/SkPixelRef.h"
26 #include "ui/gfx/rect_conversions.h"
27 
28 namespace cc {
29 namespace {
30 
31 // Flag to indicate whether we should try and detect that
32 // a tile is of solid color.
33 const bool kUseColorEstimator = true;
34 
35 class RasterTaskImpl : public RasterTask {
36  public:
RasterTaskImpl(const Resource * resource,PicturePileImpl * picture_pile,const gfx::Rect & content_rect,float contents_scale,RasterMode raster_mode,TileResolution tile_resolution,int layer_id,const void * tile_id,int source_frame_number,bool analyze_picture,RenderingStatsInstrumentation * rendering_stats,const base::Callback<void (const PicturePileImpl::Analysis &,bool)> & reply,ImageDecodeTask::Vector * dependencies)37   RasterTaskImpl(
38       const Resource* resource,
39       PicturePileImpl* picture_pile,
40       const gfx::Rect& content_rect,
41       float contents_scale,
42       RasterMode raster_mode,
43       TileResolution tile_resolution,
44       int layer_id,
45       const void* tile_id,
46       int source_frame_number,
47       bool analyze_picture,
48       RenderingStatsInstrumentation* rendering_stats,
49       const base::Callback<void(const PicturePileImpl::Analysis&, bool)>& reply,
50       ImageDecodeTask::Vector* dependencies)
51       : RasterTask(resource, dependencies),
52         picture_pile_(picture_pile),
53         content_rect_(content_rect),
54         contents_scale_(contents_scale),
55         raster_mode_(raster_mode),
56         tile_resolution_(tile_resolution),
57         layer_id_(layer_id),
58         tile_id_(tile_id),
59         source_frame_number_(source_frame_number),
60         analyze_picture_(analyze_picture),
61         rendering_stats_(rendering_stats),
62         reply_(reply) {}
63 
64   // Overridden from Task:
RunOnWorkerThread()65   virtual void RunOnWorkerThread() OVERRIDE {
66     TRACE_EVENT0("cc", "RasterizerTaskImpl::RunOnWorkerThread");
67 
68     DCHECK(picture_pile_.get());
69     DCHECK(raster_buffer_);
70 
71     if (analyze_picture_) {
72       Analyze(picture_pile_.get());
73       if (analysis_.is_solid_color)
74         return;
75     }
76 
77     Raster(picture_pile_.get());
78   }
79 
80   // Overridden from RasterizerTask:
ScheduleOnOriginThread(RasterizerTaskClient * client)81   virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
82     DCHECK(!raster_buffer_);
83     raster_buffer_ = client->AcquireBufferForRaster(resource());
84   }
CompleteOnOriginThread(RasterizerTaskClient * client)85   virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {
86     client->ReleaseBufferForRaster(raster_buffer_.Pass());
87   }
RunReplyOnOriginThread()88   virtual void RunReplyOnOriginThread() OVERRIDE {
89     DCHECK(!raster_buffer_);
90     reply_.Run(analysis_, !HasFinishedRunning());
91   }
92 
93  protected:
~RasterTaskImpl()94   virtual ~RasterTaskImpl() { DCHECK(!raster_buffer_); }
95 
96  private:
Analyze(const PicturePileImpl * picture_pile)97   void Analyze(const PicturePileImpl* picture_pile) {
98     frame_viewer_instrumentation::ScopedAnalyzeTask analyze_task(
99         tile_id_, tile_resolution_, source_frame_number_, layer_id_);
100 
101     DCHECK(picture_pile);
102 
103     picture_pile->AnalyzeInRect(
104         content_rect_, contents_scale_, &analysis_, rendering_stats_);
105 
106     // Record the solid color prediction.
107     UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed",
108                           analysis_.is_solid_color);
109 
110     // Clear the flag if we're not using the estimator.
111     analysis_.is_solid_color &= kUseColorEstimator;
112   }
113 
Raster(const PicturePileImpl * picture_pile)114   void Raster(const PicturePileImpl* picture_pile) {
115     frame_viewer_instrumentation::ScopedRasterTask raster_task(
116         tile_id_,
117         tile_resolution_,
118         source_frame_number_,
119         layer_id_,
120         raster_mode_);
121     devtools_instrumentation::ScopedLayerTask layer_task(
122         devtools_instrumentation::kRasterTask, layer_id_);
123 
124     skia::RefPtr<SkCanvas> canvas = raster_buffer_->AcquireSkCanvas();
125     DCHECK(canvas);
126 
127     skia::RefPtr<SkDrawFilter> draw_filter;
128     switch (raster_mode_) {
129       case LOW_QUALITY_RASTER_MODE:
130         draw_filter = skia::AdoptRef(new skia::PaintSimplifier);
131         break;
132       case HIGH_QUALITY_RASTER_MODE:
133         break;
134       case NUM_RASTER_MODES:
135       default:
136         NOTREACHED();
137     }
138     canvas->setDrawFilter(draw_filter.get());
139 
140     base::TimeDelta prev_rasterize_time =
141         rendering_stats_->impl_thread_rendering_stats().rasterize_time;
142 
143     // Only record rasterization time for highres tiles, because
144     // lowres tiles are not required for activation and therefore
145     // introduce noise in the measurement (sometimes they get rasterized
146     // before we draw and sometimes they aren't)
147     RenderingStatsInstrumentation* stats =
148         tile_resolution_ == HIGH_RESOLUTION ? rendering_stats_ : NULL;
149     DCHECK(picture_pile);
150     picture_pile->RasterToBitmap(
151         canvas.get(), content_rect_, contents_scale_, stats);
152 
153     if (rendering_stats_->record_rendering_stats()) {
154       base::TimeDelta current_rasterize_time =
155           rendering_stats_->impl_thread_rendering_stats().rasterize_time;
156       LOCAL_HISTOGRAM_CUSTOM_COUNTS(
157           "Renderer4.PictureRasterTimeUS",
158           (current_rasterize_time - prev_rasterize_time).InMicroseconds(),
159           0,
160           100000,
161           100);
162     }
163 
164     raster_buffer_->ReleaseSkCanvas(canvas);
165   }
166 
167   PicturePileImpl::Analysis analysis_;
168   scoped_refptr<PicturePileImpl> picture_pile_;
169   gfx::Rect content_rect_;
170   float contents_scale_;
171   RasterMode raster_mode_;
172   TileResolution tile_resolution_;
173   int layer_id_;
174   const void* tile_id_;
175   int source_frame_number_;
176   bool analyze_picture_;
177   RenderingStatsInstrumentation* rendering_stats_;
178   const base::Callback<void(const PicturePileImpl::Analysis&, bool)> reply_;
179   scoped_ptr<RasterBuffer> raster_buffer_;
180 
181   DISALLOW_COPY_AND_ASSIGN(RasterTaskImpl);
182 };
183 
184 class ImageDecodeTaskImpl : public ImageDecodeTask {
185  public:
ImageDecodeTaskImpl(SkPixelRef * pixel_ref,int layer_id,RenderingStatsInstrumentation * rendering_stats,const base::Callback<void (bool was_canceled)> & reply)186   ImageDecodeTaskImpl(SkPixelRef* pixel_ref,
187                       int layer_id,
188                       RenderingStatsInstrumentation* rendering_stats,
189                       const base::Callback<void(bool was_canceled)>& reply)
190       : pixel_ref_(skia::SharePtr(pixel_ref)),
191         layer_id_(layer_id),
192         rendering_stats_(rendering_stats),
193         reply_(reply) {}
194 
195   // Overridden from Task:
RunOnWorkerThread()196   virtual void RunOnWorkerThread() OVERRIDE {
197     TRACE_EVENT0("cc", "ImageDecodeTaskImpl::RunOnWorkerThread");
198 
199     devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
200         pixel_ref_.get());
201     // This will cause the image referred to by pixel ref to be decoded.
202     pixel_ref_->lockPixels();
203     pixel_ref_->unlockPixels();
204   }
205 
206   // Overridden from RasterizerTask:
ScheduleOnOriginThread(RasterizerTaskClient * client)207   virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
CompleteOnOriginThread(RasterizerTaskClient * client)208   virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {}
RunReplyOnOriginThread()209   virtual void RunReplyOnOriginThread() OVERRIDE {
210     reply_.Run(!HasFinishedRunning());
211   }
212 
213  protected:
~ImageDecodeTaskImpl()214   virtual ~ImageDecodeTaskImpl() {}
215 
216  private:
217   skia::RefPtr<SkPixelRef> pixel_ref_;
218   int layer_id_;
219   RenderingStatsInstrumentation* rendering_stats_;
220   const base::Callback<void(bool was_canceled)> reply_;
221 
222   DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl);
223 };
224 
225 const size_t kScheduledRasterTasksLimit = 32u;
226 
227 // Memory limit policy works by mapping some bin states to the NEVER bin.
228 const ManagedTileBin kBinPolicyMap[NUM_TILE_MEMORY_LIMIT_POLICIES][NUM_BINS] = {
229     // [ALLOW_NOTHING]
230     {NEVER_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
231      NEVER_BIN,  // [NOW_BIN]
232      NEVER_BIN,  // [SOON_BIN]
233      NEVER_BIN,  // [EVENTUALLY_AND_ACTIVE_BIN]
234      NEVER_BIN,  // [EVENTUALLY_BIN]
235      NEVER_BIN,  // [AT_LAST_AND_ACTIVE_BIN]
236      NEVER_BIN,  // [AT_LAST_BIN]
237      NEVER_BIN   // [NEVER_BIN]
238     },
239     // [ALLOW_ABSOLUTE_MINIMUM]
240     {NOW_AND_READY_TO_DRAW_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
241      NOW_BIN,                    // [NOW_BIN]
242      NEVER_BIN,                  // [SOON_BIN]
243      NEVER_BIN,                  // [EVENTUALLY_AND_ACTIVE_BIN]
244      NEVER_BIN,                  // [EVENTUALLY_BIN]
245      NEVER_BIN,                  // [AT_LAST_AND_ACTIVE_BIN]
246      NEVER_BIN,                  // [AT_LAST_BIN]
247      NEVER_BIN                   // [NEVER_BIN]
248     },
249     // [ALLOW_PREPAINT_ONLY]
250     {NOW_AND_READY_TO_DRAW_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
251      NOW_BIN,                    // [NOW_BIN]
252      SOON_BIN,                   // [SOON_BIN]
253      NEVER_BIN,                  // [EVENTUALLY_AND_ACTIVE_BIN]
254      NEVER_BIN,                  // [EVENTUALLY_BIN]
255      NEVER_BIN,                  // [AT_LAST_AND_ACTIVE_BIN]
256      NEVER_BIN,                  // [AT_LAST_BIN]
257      NEVER_BIN                   // [NEVER_BIN]
258     },
259     // [ALLOW_ANYTHING]
260     {NOW_AND_READY_TO_DRAW_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
261      NOW_BIN,                    // [NOW_BIN]
262      SOON_BIN,                   // [SOON_BIN]
263      EVENTUALLY_AND_ACTIVE_BIN,  // [EVENTUALLY_AND_ACTIVE_BIN]
264      EVENTUALLY_BIN,             // [EVENTUALLY_BIN]
265      AT_LAST_AND_ACTIVE_BIN,     // [AT_LAST_AND_ACTIVE_BIN]
266      AT_LAST_BIN,                // [AT_LAST_BIN]
267      NEVER_BIN                   // [NEVER_BIN]
268     }};
269 
270 // Ready to draw works by mapping NOW_BIN to NOW_AND_READY_TO_DRAW_BIN.
271 const ManagedTileBin kBinReadyToDrawMap[2][NUM_BINS] = {
272     // Not ready
273     {NOW_AND_READY_TO_DRAW_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
274      NOW_BIN,                    // [NOW_BIN]
275      SOON_BIN,                   // [SOON_BIN]
276      EVENTUALLY_AND_ACTIVE_BIN,  // [EVENTUALLY_AND_ACTIVE_BIN]
277      EVENTUALLY_BIN,             // [EVENTUALLY_BIN]
278      AT_LAST_AND_ACTIVE_BIN,     // [AT_LAST_AND_ACTIVE_BIN]
279      AT_LAST_BIN,                // [AT_LAST_BIN]
280      NEVER_BIN                   // [NEVER_BIN]
281     },
282     // Ready
283     {NOW_AND_READY_TO_DRAW_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
284      NOW_AND_READY_TO_DRAW_BIN,  // [NOW_BIN]
285      SOON_BIN,                   // [SOON_BIN]
286      EVENTUALLY_AND_ACTIVE_BIN,  // [EVENTUALLY_AND_ACTIVE_BIN]
287      EVENTUALLY_BIN,             // [EVENTUALLY_BIN]
288      AT_LAST_AND_ACTIVE_BIN,     // [AT_LAST_AND_ACTIVE_BIN]
289      AT_LAST_BIN,                // [AT_LAST_BIN]
290      NEVER_BIN                   // [NEVER_BIN]
291     }};
292 
293 // Active works by mapping some bin stats to equivalent _ACTIVE_BIN state.
294 const ManagedTileBin kBinIsActiveMap[2][NUM_BINS] = {
295     // Inactive
296     {NOW_AND_READY_TO_DRAW_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
297      NOW_BIN,                    // [NOW_BIN]
298      SOON_BIN,                   // [SOON_BIN]
299      EVENTUALLY_AND_ACTIVE_BIN,  // [EVENTUALLY_AND_ACTIVE_BIN]
300      EVENTUALLY_BIN,             // [EVENTUALLY_BIN]
301      AT_LAST_AND_ACTIVE_BIN,     // [AT_LAST_AND_ACTIVE_BIN]
302      AT_LAST_BIN,                // [AT_LAST_BIN]
303      NEVER_BIN                   // [NEVER_BIN]
304     },
305     // Active
306     {NOW_AND_READY_TO_DRAW_BIN,  // [NOW_AND_READY_TO_DRAW_BIN]
307      NOW_BIN,                    // [NOW_BIN]
308      SOON_BIN,                   // [SOON_BIN]
309      EVENTUALLY_AND_ACTIVE_BIN,  // [EVENTUALLY_AND_ACTIVE_BIN]
310      EVENTUALLY_AND_ACTIVE_BIN,  // [EVENTUALLY_BIN]
311      AT_LAST_AND_ACTIVE_BIN,     // [AT_LAST_AND_ACTIVE_BIN]
312      AT_LAST_AND_ACTIVE_BIN,     // [AT_LAST_BIN]
313      NEVER_BIN                   // [NEVER_BIN]
314     }};
315 
316 // Determine bin based on three categories of tiles: things we need now,
317 // things we need soon, and eventually.
BinFromTilePriority(const TilePriority & prio)318 inline ManagedTileBin BinFromTilePriority(const TilePriority& prio) {
319   if (prio.priority_bin == TilePriority::NOW)
320     return NOW_BIN;
321 
322   if (prio.priority_bin == TilePriority::SOON)
323     return SOON_BIN;
324 
325   if (prio.distance_to_visible == std::numeric_limits<float>::infinity())
326     return NEVER_BIN;
327 
328   return EVENTUALLY_BIN;
329 }
330 
331 }  // namespace
332 
RasterTaskCompletionStats()333 RasterTaskCompletionStats::RasterTaskCompletionStats()
334     : completed_count(0u), canceled_count(0u) {}
335 
336 scoped_refptr<base::debug::ConvertableToTraceFormat>
RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats & stats)337 RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) {
338   scoped_refptr<base::debug::TracedValue> state =
339       new base::debug::TracedValue();
340   state->SetInteger("completed_count", stats.completed_count);
341   state->SetInteger("canceled_count", stats.canceled_count);
342   return state;
343 }
344 
345 // static
Create(TileManagerClient * client,base::SequencedTaskRunner * task_runner,ResourcePool * resource_pool,Rasterizer * rasterizer,RenderingStatsInstrumentation * rendering_stats_instrumentation)346 scoped_ptr<TileManager> TileManager::Create(
347     TileManagerClient* client,
348     base::SequencedTaskRunner* task_runner,
349     ResourcePool* resource_pool,
350     Rasterizer* rasterizer,
351     RenderingStatsInstrumentation* rendering_stats_instrumentation) {
352   return make_scoped_ptr(new TileManager(client,
353                                          task_runner,
354                                          resource_pool,
355                                          rasterizer,
356                                          rendering_stats_instrumentation));
357 }
358 
TileManager(TileManagerClient * client,const scoped_refptr<base::SequencedTaskRunner> & task_runner,ResourcePool * resource_pool,Rasterizer * rasterizer,RenderingStatsInstrumentation * rendering_stats_instrumentation)359 TileManager::TileManager(
360     TileManagerClient* client,
361     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
362     ResourcePool* resource_pool,
363     Rasterizer* rasterizer,
364     RenderingStatsInstrumentation* rendering_stats_instrumentation)
365     : client_(client),
366       task_runner_(task_runner),
367       resource_pool_(resource_pool),
368       rasterizer_(rasterizer),
369       prioritized_tiles_dirty_(false),
370       all_tiles_that_need_to_be_rasterized_have_memory_(true),
371       all_tiles_required_for_activation_have_memory_(true),
372       bytes_releasable_(0),
373       resources_releasable_(0),
374       ever_exceeded_memory_budget_(false),
375       rendering_stats_instrumentation_(rendering_stats_instrumentation),
376       did_initialize_visible_tile_(false),
377       did_check_for_completed_tasks_since_last_schedule_tasks_(true),
378       did_oom_on_last_assign_(false),
379       ready_to_activate_check_notifier_(
380           task_runner_.get(),
381           base::Bind(&TileManager::CheckIfReadyToActivate,
382                      base::Unretained(this))) {
383   rasterizer_->SetClient(this);
384 }
385 
~TileManager()386 TileManager::~TileManager() {
387   // Reset global state and manage. This should cause
388   // our memory usage to drop to zero.
389   global_state_ = GlobalStateThatImpactsTilePriority();
390 
391   RasterTaskQueue empty;
392   rasterizer_->ScheduleTasks(&empty);
393   orphan_raster_tasks_.clear();
394 
395   // This should finish all pending tasks and release any uninitialized
396   // resources.
397   rasterizer_->Shutdown();
398   rasterizer_->CheckForCompletedTasks();
399 
400   prioritized_tiles_.Clear();
401 
402   FreeResourcesForReleasedTiles();
403   CleanUpReleasedTiles();
404 
405   DCHECK_EQ(0u, bytes_releasable_);
406   DCHECK_EQ(0u, resources_releasable_);
407 }
408 
Release(Tile * tile)409 void TileManager::Release(Tile* tile) {
410   DCHECK(TilePriority() == tile->combined_priority());
411 
412   prioritized_tiles_dirty_ = true;
413   released_tiles_.push_back(tile);
414 }
415 
DidChangeTilePriority(Tile * tile)416 void TileManager::DidChangeTilePriority(Tile* tile) {
417   prioritized_tiles_dirty_ = true;
418 }
419 
TasksThatShouldBeForcedToComplete() const420 TaskSetCollection TileManager::TasksThatShouldBeForcedToComplete() const {
421   TaskSetCollection tasks_that_should_be_forced_to_complete;
422   if (global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY)
423     tasks_that_should_be_forced_to_complete[REQUIRED_FOR_ACTIVATION] = true;
424   return tasks_that_should_be_forced_to_complete;
425 }
426 
FreeResourcesForReleasedTiles()427 void TileManager::FreeResourcesForReleasedTiles() {
428   for (std::vector<Tile*>::iterator it = released_tiles_.begin();
429        it != released_tiles_.end();
430        ++it) {
431     Tile* tile = *it;
432     FreeResourcesForTile(tile);
433   }
434 }
435 
CleanUpReleasedTiles()436 void TileManager::CleanUpReleasedTiles() {
437   // Make sure |prioritized_tiles_| doesn't contain any of the tiles
438   // we're about to delete.
439   DCHECK(prioritized_tiles_.IsEmpty());
440 
441   std::vector<Tile*>::iterator it = released_tiles_.begin();
442   while (it != released_tiles_.end()) {
443     Tile* tile = *it;
444 
445     if (tile->HasRasterTask()) {
446       ++it;
447       continue;
448     }
449 
450     DCHECK(!tile->HasResources());
451     DCHECK(tiles_.find(tile->id()) != tiles_.end());
452     tiles_.erase(tile->id());
453 
454     LayerCountMap::iterator layer_it =
455         used_layer_counts_.find(tile->layer_id());
456     DCHECK_GT(layer_it->second, 0);
457     if (--layer_it->second == 0) {
458       used_layer_counts_.erase(layer_it);
459       image_decode_tasks_.erase(tile->layer_id());
460     }
461 
462     delete tile;
463     it = released_tiles_.erase(it);
464   }
465 }
466 
UpdatePrioritizedTileSetIfNeeded()467 void TileManager::UpdatePrioritizedTileSetIfNeeded() {
468   if (!prioritized_tiles_dirty_)
469     return;
470 
471   prioritized_tiles_.Clear();
472 
473   FreeResourcesForReleasedTiles();
474   CleanUpReleasedTiles();
475 
476   GetTilesWithAssignedBins(&prioritized_tiles_);
477   prioritized_tiles_dirty_ = false;
478 }
479 
DidFinishRunningTasks(TaskSet task_set)480 void TileManager::DidFinishRunningTasks(TaskSet task_set) {
481   if (task_set == ALL) {
482     TRACE_EVENT1("cc", "TileManager::DidFinishRunningTasks", "task_set", "ALL");
483 
484     bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() >
485                                     global_state_.soft_memory_limit_in_bytes;
486 
487     // When OOM, keep re-assigning memory until we reach a steady state
488     // where top-priority tiles are initialized.
489     if (all_tiles_that_need_to_be_rasterized_have_memory_ &&
490         !memory_usage_above_limit)
491       return;
492 
493     rasterizer_->CheckForCompletedTasks();
494     did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
495 
496     TileVector tiles_that_need_to_be_rasterized;
497     AssignGpuMemoryToTiles(&prioritized_tiles_,
498                            &tiles_that_need_to_be_rasterized);
499 
500     // |tiles_that_need_to_be_rasterized| will be empty when we reach a
501     // steady memory state. Keep scheduling tasks until we reach this state.
502     if (!tiles_that_need_to_be_rasterized.empty()) {
503       ScheduleTasks(tiles_that_need_to_be_rasterized);
504       return;
505     }
506 
507     FreeResourcesForReleasedTiles();
508 
509     resource_pool_->ReduceResourceUsage();
510 
511     // We don't reserve memory for required-for-activation tiles during
512     // accelerated gestures, so we just postpone activation when we don't
513     // have these tiles, and activate after the accelerated gesture.
514     // Likewise if we don't allow any tiles (as is the case when we're
515     // invisible), if we have tiles that aren't ready, then we shouldn't
516     // activate as activation can cause checkerboards.
517     bool allow_rasterize_on_demand =
518         global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY &&
519         global_state_.memory_limit_policy != ALLOW_NOTHING;
520 
521     // Use on-demand raster for any required-for-activation tiles that have not
522     // been been assigned memory after reaching a steady memory state. This
523     // ensures that we activate even when OOM.
524     for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
525       Tile* tile = it->second;
526       ManagedTileState& mts = tile->managed_state();
527       ManagedTileState::TileVersion& tile_version =
528           mts.tile_versions[mts.raster_mode];
529 
530       if (tile->required_for_activation() && !tile_version.IsReadyToDraw()) {
531         // If we can't raster on demand, give up early (and don't activate).
532         if (!allow_rasterize_on_demand)
533           return;
534 
535         tile_version.set_rasterize_on_demand();
536         client_->NotifyTileStateChanged(tile);
537       }
538     }
539 
540     DCHECK(IsReadyToActivate());
541     ready_to_activate_check_notifier_.Schedule();
542     return;
543   }
544 
545   if (task_set == REQUIRED_FOR_ACTIVATION) {
546     TRACE_EVENT2("cc",
547                  "TileManager::DidFinishRunningTasks",
548                  "task_set",
549                  "REQUIRED_FOR_ACTIVATION",
550                  "all_tiles_required_for_activation_have_memory",
551                  all_tiles_required_for_activation_have_memory_);
552     // This is only a true indication that all tiles required for
553     // activation are initialized when no tiles are OOM. We need to
554     // wait for DidFinishRunningTasks() to be called, try to re-assign
555     // memory and in worst case use on-demand raster when tiles
556     // required for activation are OOM.
557     if (!all_tiles_required_for_activation_have_memory_)
558       return;
559 
560     ready_to_activate_check_notifier_.Schedule();
561   }
562 }
563 
GetTilesWithAssignedBins(PrioritizedTileSet * tiles)564 void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) {
565   TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins");
566 
567   const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy;
568   const TreePriority tree_priority = global_state_.tree_priority;
569 
570   // For each tree, bin into different categories of tiles.
571   for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
572     Tile* tile = it->second;
573     ManagedTileState& mts = tile->managed_state();
574 
575     const ManagedTileState::TileVersion& tile_version =
576         tile->GetTileVersionForDrawing();
577     bool tile_is_ready_to_draw = tile_version.IsReadyToDraw();
578     bool tile_is_active = tile_is_ready_to_draw ||
579                           mts.tile_versions[mts.raster_mode].raster_task_.get();
580 
581     // Get the active priority and bin.
582     TilePriority active_priority = tile->priority(ACTIVE_TREE);
583     ManagedTileBin active_bin = BinFromTilePriority(active_priority);
584 
585     // Get the pending priority and bin.
586     TilePriority pending_priority = tile->priority(PENDING_TREE);
587     ManagedTileBin pending_bin = BinFromTilePriority(pending_priority);
588 
589     bool pending_is_low_res = pending_priority.resolution == LOW_RESOLUTION;
590     bool pending_is_non_ideal =
591         pending_priority.resolution == NON_IDEAL_RESOLUTION;
592     bool active_is_non_ideal =
593         active_priority.resolution == NON_IDEAL_RESOLUTION;
594 
595     // Adjust bin state based on if ready to draw.
596     active_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][active_bin];
597     pending_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][pending_bin];
598 
599     // Adjust bin state based on if active.
600     active_bin = kBinIsActiveMap[tile_is_active][active_bin];
601     pending_bin = kBinIsActiveMap[tile_is_active][pending_bin];
602 
603     // We never want to paint new non-ideal tiles, as we always have
604     // a high-res tile covering that content (paint that instead).
605     if (!tile_is_ready_to_draw && active_is_non_ideal)
606       active_bin = NEVER_BIN;
607     if (!tile_is_ready_to_draw && pending_is_non_ideal)
608       pending_bin = NEVER_BIN;
609 
610     ManagedTileBin tree_bin[NUM_TREES];
611     tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin];
612     tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin];
613 
614     // Adjust pending bin state for low res tiles. This prevents pending tree
615     // low-res tiles from being initialized before high-res tiles.
616     if (pending_is_low_res)
617       tree_bin[PENDING_TREE] = std::max(tree_bin[PENDING_TREE], EVENTUALLY_BIN);
618 
619     TilePriority tile_priority;
620     switch (tree_priority) {
621       case SAME_PRIORITY_FOR_BOTH_TREES:
622         mts.bin = std::min(tree_bin[ACTIVE_TREE], tree_bin[PENDING_TREE]);
623         tile_priority = tile->combined_priority();
624         break;
625       case SMOOTHNESS_TAKES_PRIORITY:
626         mts.bin = tree_bin[ACTIVE_TREE];
627         tile_priority = active_priority;
628         break;
629       case NEW_CONTENT_TAKES_PRIORITY:
630         mts.bin = tree_bin[PENDING_TREE];
631         tile_priority = pending_priority;
632         break;
633       default:
634         NOTREACHED();
635     }
636 
637     // Bump up the priority if we determined it's NEVER_BIN on one tree,
638     // but is still required on the other tree.
639     bool is_in_never_bin_on_both_trees = tree_bin[ACTIVE_TREE] == NEVER_BIN &&
640                                          tree_bin[PENDING_TREE] == NEVER_BIN;
641 
642     if (mts.bin == NEVER_BIN && !is_in_never_bin_on_both_trees)
643       mts.bin = tile_is_active ? AT_LAST_AND_ACTIVE_BIN : AT_LAST_BIN;
644 
645     mts.resolution = tile_priority.resolution;
646     mts.priority_bin = tile_priority.priority_bin;
647     mts.distance_to_visible = tile_priority.distance_to_visible;
648     mts.required_for_activation = tile_priority.required_for_activation;
649 
650     mts.visible_and_ready_to_draw =
651         tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN;
652 
653     // Tiles that are required for activation shouldn't be in NEVER_BIN unless
654     // smoothness takes priority or memory policy allows nothing to be
655     // initialized.
656     DCHECK(!mts.required_for_activation || mts.bin != NEVER_BIN ||
657            tree_priority == SMOOTHNESS_TAKES_PRIORITY ||
658            memory_policy == ALLOW_NOTHING);
659 
660     // If the tile is in NEVER_BIN and it does not have an active task, then we
661     // can release the resources early. If it does have the task however, we
662     // should keep it in the prioritized tile set to ensure that AssignGpuMemory
663     // can visit it.
664     if (mts.bin == NEVER_BIN &&
665         !mts.tile_versions[mts.raster_mode].raster_task_.get()) {
666       FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
667       continue;
668     }
669 
670     // Insert the tile into a priority set.
671     tiles->InsertTile(tile, mts.bin);
672   }
673 }
674 
ManageTiles(const GlobalStateThatImpactsTilePriority & state)675 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) {
676   TRACE_EVENT0("cc", "TileManager::ManageTiles");
677 
678   // Update internal state.
679   if (state != global_state_) {
680     global_state_ = state;
681     prioritized_tiles_dirty_ = true;
682   }
683 
684   // We need to call CheckForCompletedTasks() once in-between each call
685   // to ScheduleTasks() to prevent canceled tasks from being scheduled.
686   if (!did_check_for_completed_tasks_since_last_schedule_tasks_) {
687     rasterizer_->CheckForCompletedTasks();
688     did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
689   }
690 
691   UpdatePrioritizedTileSetIfNeeded();
692 
693   TileVector tiles_that_need_to_be_rasterized;
694   AssignGpuMemoryToTiles(&prioritized_tiles_,
695                          &tiles_that_need_to_be_rasterized);
696 
697   // Finally, schedule rasterizer tasks.
698   ScheduleTasks(tiles_that_need_to_be_rasterized);
699 
700   TRACE_EVENT_INSTANT1("cc",
701                        "DidManage",
702                        TRACE_EVENT_SCOPE_THREAD,
703                        "state",
704                        BasicStateAsValue());
705 
706   TRACE_COUNTER_ID1("cc",
707                     "unused_memory_bytes",
708                     this,
709                     resource_pool_->total_memory_usage_bytes() -
710                         resource_pool_->acquired_memory_usage_bytes());
711 }
712 
UpdateVisibleTiles()713 bool TileManager::UpdateVisibleTiles() {
714   TRACE_EVENT0("cc", "TileManager::UpdateVisibleTiles");
715 
716   rasterizer_->CheckForCompletedTasks();
717   did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
718 
719   TRACE_EVENT_INSTANT1(
720       "cc",
721       "DidUpdateVisibleTiles",
722       TRACE_EVENT_SCOPE_THREAD,
723       "stats",
724       RasterTaskCompletionStatsAsValue(update_visible_tiles_stats_));
725   update_visible_tiles_stats_ = RasterTaskCompletionStats();
726 
727   bool did_initialize_visible_tile = did_initialize_visible_tile_;
728   did_initialize_visible_tile_ = false;
729   return did_initialize_visible_tile;
730 }
731 
732 scoped_refptr<base::debug::ConvertableToTraceFormat>
BasicStateAsValue() const733 TileManager::BasicStateAsValue() const {
734   scoped_refptr<base::debug::TracedValue> value =
735       new base::debug::TracedValue();
736   BasicStateAsValueInto(value.get());
737   return value;
738 }
739 
BasicStateAsValueInto(base::debug::TracedValue * state) const740 void TileManager::BasicStateAsValueInto(base::debug::TracedValue* state) const {
741   state->SetInteger("tile_count", tiles_.size());
742   state->SetBoolean("did_oom_on_last_assign", did_oom_on_last_assign_);
743   state->BeginDictionary("global_state");
744   global_state_.AsValueInto(state);
745   state->EndDictionary();
746 }
747 
AssignGpuMemoryToTiles(PrioritizedTileSet * tiles,TileVector * tiles_that_need_to_be_rasterized)748 void TileManager::AssignGpuMemoryToTiles(
749     PrioritizedTileSet* tiles,
750     TileVector* tiles_that_need_to_be_rasterized) {
751   TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles");
752 
753   // Maintain the list of released resources that can potentially be re-used
754   // or deleted.
755   // If this operation becomes expensive too, only do this after some
756   // resource(s) was returned. Note that in that case, one also need to
757   // invalidate when releasing some resource from the pool.
758   resource_pool_->CheckBusyResources();
759 
760   // Now give memory out to the tiles until we're out, and build
761   // the needs-to-be-rasterized queue.
762   all_tiles_that_need_to_be_rasterized_have_memory_ = true;
763   all_tiles_required_for_activation_have_memory_ = true;
764 
765   // Cast to prevent overflow.
766   int64 soft_bytes_available =
767       static_cast<int64>(bytes_releasable_) +
768       static_cast<int64>(global_state_.soft_memory_limit_in_bytes) -
769       static_cast<int64>(resource_pool_->acquired_memory_usage_bytes());
770   int64 hard_bytes_available =
771       static_cast<int64>(bytes_releasable_) +
772       static_cast<int64>(global_state_.hard_memory_limit_in_bytes) -
773       static_cast<int64>(resource_pool_->acquired_memory_usage_bytes());
774   int resources_available = resources_releasable_ +
775                             global_state_.num_resources_limit -
776                             resource_pool_->acquired_resource_count();
777   size_t soft_bytes_allocatable =
778       std::max(static_cast<int64>(0), soft_bytes_available);
779   size_t hard_bytes_allocatable =
780       std::max(static_cast<int64>(0), hard_bytes_available);
781   size_t resources_allocatable = std::max(0, resources_available);
782 
783   size_t bytes_that_exceeded_memory_budget = 0;
784   size_t soft_bytes_left = soft_bytes_allocatable;
785   size_t hard_bytes_left = hard_bytes_allocatable;
786 
787   size_t resources_left = resources_allocatable;
788   bool oomed_soft = false;
789   bool oomed_hard = false;
790   bool have_hit_soft_memory = false;  // Soft memory comes after hard.
791 
792   unsigned schedule_priority = 1u;
793   for (PrioritizedTileSet::Iterator it(tiles, true); it; ++it) {
794     Tile* tile = *it;
795     ManagedTileState& mts = tile->managed_state();
796 
797     mts.scheduled_priority = schedule_priority++;
798 
799     mts.raster_mode = tile->DetermineOverallRasterMode();
800 
801     ManagedTileState::TileVersion& tile_version =
802         mts.tile_versions[mts.raster_mode];
803 
804     // If this tile doesn't need a resource, then nothing to do.
805     if (!tile_version.requires_resource())
806       continue;
807 
808     // If the tile is not needed, free it up.
809     if (mts.bin == NEVER_BIN) {
810       FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
811       continue;
812     }
813 
814     const bool tile_uses_hard_limit = mts.bin <= NOW_BIN;
815     const size_t bytes_if_allocated = BytesConsumedIfAllocated(tile);
816     const size_t tile_bytes_left =
817         (tile_uses_hard_limit) ? hard_bytes_left : soft_bytes_left;
818 
819     // Hard-limit is reserved for tiles that would cause a calamity
820     // if they were to go away, so by definition they are the highest
821     // priority memory, and must be at the front of the list.
822     DCHECK(!(have_hit_soft_memory && tile_uses_hard_limit));
823     have_hit_soft_memory |= !tile_uses_hard_limit;
824 
825     size_t tile_bytes = 0;
826     size_t tile_resources = 0;
827 
828     // It costs to maintain a resource.
829     for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
830       if (mts.tile_versions[mode].resource_) {
831         tile_bytes += bytes_if_allocated;
832         tile_resources++;
833       }
834     }
835 
836     // Allow lower priority tiles with initialized resources to keep
837     // their memory by only assigning memory to new raster tasks if
838     // they can be scheduled.
839     bool reached_scheduled_raster_tasks_limit =
840         tiles_that_need_to_be_rasterized->size() >= kScheduledRasterTasksLimit;
841     if (!reached_scheduled_raster_tasks_limit) {
842       // If we don't have the required version, and it's not in flight
843       // then we'll have to pay to create a new task.
844       if (!tile_version.resource_ && !tile_version.raster_task_.get()) {
845         tile_bytes += bytes_if_allocated;
846         tile_resources++;
847       }
848     }
849 
850     // Tile is OOM.
851     if (tile_bytes > tile_bytes_left || tile_resources > resources_left) {
852       FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
853 
854       // This tile was already on screen and now its resources have been
855       // released. In order to prevent checkerboarding, set this tile as
856       // rasterize on demand immediately.
857       if (mts.visible_and_ready_to_draw)
858         tile_version.set_rasterize_on_demand();
859 
860       oomed_soft = true;
861       if (tile_uses_hard_limit) {
862         oomed_hard = true;
863         bytes_that_exceeded_memory_budget += tile_bytes;
864       }
865     } else {
866       resources_left -= tile_resources;
867       hard_bytes_left -= tile_bytes;
868       soft_bytes_left =
869           (soft_bytes_left > tile_bytes) ? soft_bytes_left - tile_bytes : 0;
870       if (tile_version.resource_)
871         continue;
872     }
873 
874     DCHECK(!tile_version.resource_);
875 
876     // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized|
877     // has reached it's limit or we've failed to assign gpu memory to this
878     // or any higher priority tile. Preventing tiles that fit into memory
879     // budget to be rasterized when higher priority tile is oom is
880     // important for two reasons:
881     // 1. Tile size should not impact raster priority.
882     // 2. Tiles with existing raster task could otherwise incorrectly
883     //    be added as they are not affected by |bytes_allocatable|.
884     bool can_schedule_tile =
885         !oomed_soft && !reached_scheduled_raster_tasks_limit;
886 
887     if (!can_schedule_tile) {
888       all_tiles_that_need_to_be_rasterized_have_memory_ = false;
889       if (tile->required_for_activation())
890         all_tiles_required_for_activation_have_memory_ = false;
891       it.DisablePriorityOrdering();
892       continue;
893     }
894 
895     tiles_that_need_to_be_rasterized->push_back(tile);
896   }
897 
898   // OOM reporting uses hard-limit, soft-OOM is normal depending on limit.
899   ever_exceeded_memory_budget_ |= oomed_hard;
900   if (ever_exceeded_memory_budget_) {
901     TRACE_COUNTER_ID2("cc",
902                       "over_memory_budget",
903                       this,
904                       "budget",
905                       global_state_.hard_memory_limit_in_bytes,
906                       "over",
907                       bytes_that_exceeded_memory_budget);
908   }
909   did_oom_on_last_assign_ = oomed_hard;
910   UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget", oomed_hard);
911   memory_stats_from_last_assign_.total_budget_in_bytes =
912       global_state_.hard_memory_limit_in_bytes;
913   memory_stats_from_last_assign_.bytes_allocated =
914       hard_bytes_allocatable - hard_bytes_left;
915   memory_stats_from_last_assign_.bytes_unreleasable =
916       resource_pool_->acquired_memory_usage_bytes() - bytes_releasable_;
917   memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget;
918 }
919 
FreeResourceForTile(Tile * tile,RasterMode mode)920 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) {
921   ManagedTileState& mts = tile->managed_state();
922   if (mts.tile_versions[mode].resource_) {
923     resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass());
924 
925     DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile));
926     DCHECK_GE(resources_releasable_, 1u);
927 
928     bytes_releasable_ -= BytesConsumedIfAllocated(tile);
929     --resources_releasable_;
930   }
931 }
932 
FreeResourcesForTile(Tile * tile)933 void TileManager::FreeResourcesForTile(Tile* tile) {
934   for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
935     FreeResourceForTile(tile, static_cast<RasterMode>(mode));
936   }
937 }
938 
FreeUnusedResourcesForTile(Tile * tile)939 void TileManager::FreeUnusedResourcesForTile(Tile* tile) {
940   DCHECK(tile->IsReadyToDraw());
941   ManagedTileState& mts = tile->managed_state();
942   RasterMode used_mode = LOW_QUALITY_RASTER_MODE;
943   for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
944     if (mts.tile_versions[mode].IsReadyToDraw()) {
945       used_mode = static_cast<RasterMode>(mode);
946       break;
947     }
948   }
949 
950   for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
951     if (mode != used_mode)
952       FreeResourceForTile(tile, static_cast<RasterMode>(mode));
953   }
954 }
955 
FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(Tile * tile)956 void TileManager::FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(
957     Tile* tile) {
958   bool was_ready_to_draw = tile->IsReadyToDraw();
959   FreeResourcesForTile(tile);
960   if (was_ready_to_draw)
961     client_->NotifyTileStateChanged(tile);
962 }
963 
ScheduleTasks(const TileVector & tiles_that_need_to_be_rasterized)964 void TileManager::ScheduleTasks(
965     const TileVector& tiles_that_need_to_be_rasterized) {
966   TRACE_EVENT1("cc",
967                "TileManager::ScheduleTasks",
968                "count",
969                tiles_that_need_to_be_rasterized.size());
970 
971   DCHECK(did_check_for_completed_tasks_since_last_schedule_tasks_);
972 
973   raster_queue_.Reset();
974 
975   // Build a new task queue containing all task currently needed. Tasks
976   // are added in order of priority, highest priority task first.
977   for (TileVector::const_iterator it = tiles_that_need_to_be_rasterized.begin();
978        it != tiles_that_need_to_be_rasterized.end();
979        ++it) {
980     Tile* tile = *it;
981     ManagedTileState& mts = tile->managed_state();
982     ManagedTileState::TileVersion& tile_version =
983         mts.tile_versions[mts.raster_mode];
984 
985     DCHECK(tile_version.requires_resource());
986     DCHECK(!tile_version.resource_);
987 
988     if (!tile_version.raster_task_.get())
989       tile_version.raster_task_ = CreateRasterTask(tile);
990 
991     TaskSetCollection task_sets;
992     if (tile->required_for_activation())
993       task_sets.set(REQUIRED_FOR_ACTIVATION);
994     task_sets.set(ALL);
995     raster_queue_.items.push_back(
996         RasterTaskQueue::Item(tile_version.raster_task_.get(), task_sets));
997   }
998 
999   // We must reduce the amount of unused resoruces before calling
1000   // ScheduleTasks to prevent usage from rising above limits.
1001   resource_pool_->ReduceResourceUsage();
1002 
1003   // Schedule running of |raster_tasks_|. This replaces any previously
1004   // scheduled tasks and effectively cancels all tasks not present
1005   // in |raster_tasks_|.
1006   rasterizer_->ScheduleTasks(&raster_queue_);
1007 
1008   // It's now safe to clean up orphan tasks as raster worker pool is not
1009   // allowed to keep around unreferenced raster tasks after ScheduleTasks() has
1010   // been called.
1011   orphan_raster_tasks_.clear();
1012 
1013   did_check_for_completed_tasks_since_last_schedule_tasks_ = false;
1014 }
1015 
CreateImageDecodeTask(Tile * tile,SkPixelRef * pixel_ref)1016 scoped_refptr<ImageDecodeTask> TileManager::CreateImageDecodeTask(
1017     Tile* tile,
1018     SkPixelRef* pixel_ref) {
1019   return make_scoped_refptr(new ImageDecodeTaskImpl(
1020       pixel_ref,
1021       tile->layer_id(),
1022       rendering_stats_instrumentation_,
1023       base::Bind(&TileManager::OnImageDecodeTaskCompleted,
1024                  base::Unretained(this),
1025                  tile->layer_id(),
1026                  base::Unretained(pixel_ref))));
1027 }
1028 
CreateRasterTask(Tile * tile)1029 scoped_refptr<RasterTask> TileManager::CreateRasterTask(Tile* tile) {
1030   ManagedTileState& mts = tile->managed_state();
1031 
1032   scoped_ptr<ScopedResource> resource =
1033       resource_pool_->AcquireResource(tile->size());
1034   const ScopedResource* const_resource = resource.get();
1035 
1036   // Create and queue all image decode tasks that this tile depends on.
1037   ImageDecodeTask::Vector decode_tasks;
1038   PixelRefTaskMap& existing_pixel_refs = image_decode_tasks_[tile->layer_id()];
1039   for (PicturePileImpl::PixelRefIterator iter(
1040            tile->content_rect(), tile->contents_scale(), tile->picture_pile());
1041        iter;
1042        ++iter) {
1043     SkPixelRef* pixel_ref = *iter;
1044     uint32_t id = pixel_ref->getGenerationID();
1045 
1046     // Append existing image decode task if available.
1047     PixelRefTaskMap::iterator decode_task_it = existing_pixel_refs.find(id);
1048     if (decode_task_it != existing_pixel_refs.end()) {
1049       decode_tasks.push_back(decode_task_it->second);
1050       continue;
1051     }
1052 
1053     // Create and append new image decode task for this pixel ref.
1054     scoped_refptr<ImageDecodeTask> decode_task =
1055         CreateImageDecodeTask(tile, pixel_ref);
1056     decode_tasks.push_back(decode_task);
1057     existing_pixel_refs[id] = decode_task;
1058   }
1059 
1060   return make_scoped_refptr(
1061       new RasterTaskImpl(const_resource,
1062                          tile->picture_pile(),
1063                          tile->content_rect(),
1064                          tile->contents_scale(),
1065                          mts.raster_mode,
1066                          mts.resolution,
1067                          tile->layer_id(),
1068                          static_cast<const void*>(tile),
1069                          tile->source_frame_number(),
1070                          tile->use_picture_analysis(),
1071                          rendering_stats_instrumentation_,
1072                          base::Bind(&TileManager::OnRasterTaskCompleted,
1073                                     base::Unretained(this),
1074                                     tile->id(),
1075                                     base::Passed(&resource),
1076                                     mts.raster_mode),
1077                          &decode_tasks));
1078 }
1079 
OnImageDecodeTaskCompleted(int layer_id,SkPixelRef * pixel_ref,bool was_canceled)1080 void TileManager::OnImageDecodeTaskCompleted(int layer_id,
1081                                              SkPixelRef* pixel_ref,
1082                                              bool was_canceled) {
1083   // If the task was canceled, we need to clean it up
1084   // from |image_decode_tasks_|.
1085   if (!was_canceled)
1086     return;
1087 
1088   LayerPixelRefTaskMap::iterator layer_it = image_decode_tasks_.find(layer_id);
1089   if (layer_it == image_decode_tasks_.end())
1090     return;
1091 
1092   PixelRefTaskMap& pixel_ref_tasks = layer_it->second;
1093   PixelRefTaskMap::iterator task_it =
1094       pixel_ref_tasks.find(pixel_ref->getGenerationID());
1095 
1096   if (task_it != pixel_ref_tasks.end())
1097     pixel_ref_tasks.erase(task_it);
1098 }
1099 
OnRasterTaskCompleted(Tile::Id tile_id,scoped_ptr<ScopedResource> resource,RasterMode raster_mode,const PicturePileImpl::Analysis & analysis,bool was_canceled)1100 void TileManager::OnRasterTaskCompleted(
1101     Tile::Id tile_id,
1102     scoped_ptr<ScopedResource> resource,
1103     RasterMode raster_mode,
1104     const PicturePileImpl::Analysis& analysis,
1105     bool was_canceled) {
1106   DCHECK(tiles_.find(tile_id) != tiles_.end());
1107 
1108   Tile* tile = tiles_[tile_id];
1109   ManagedTileState& mts = tile->managed_state();
1110   ManagedTileState::TileVersion& tile_version = mts.tile_versions[raster_mode];
1111   DCHECK(tile_version.raster_task_.get());
1112   orphan_raster_tasks_.push_back(tile_version.raster_task_);
1113   tile_version.raster_task_ = NULL;
1114 
1115   if (was_canceled) {
1116     ++update_visible_tiles_stats_.canceled_count;
1117     resource_pool_->ReleaseResource(resource.Pass());
1118     return;
1119   }
1120 
1121   ++update_visible_tiles_stats_.completed_count;
1122 
1123   if (analysis.is_solid_color) {
1124     tile_version.set_solid_color(analysis.solid_color);
1125     resource_pool_->ReleaseResource(resource.Pass());
1126   } else {
1127     tile_version.set_use_resource();
1128     tile_version.resource_ = resource.Pass();
1129 
1130     bytes_releasable_ += BytesConsumedIfAllocated(tile);
1131     ++resources_releasable_;
1132   }
1133 
1134   FreeUnusedResourcesForTile(tile);
1135   if (tile->priority(ACTIVE_TREE).distance_to_visible == 0.f)
1136     did_initialize_visible_tile_ = true;
1137 
1138   client_->NotifyTileStateChanged(tile);
1139 }
1140 
CreateTile(PicturePileImpl * picture_pile,const gfx::Size & tile_size,const gfx::Rect & content_rect,float contents_scale,int layer_id,int source_frame_number,int flags)1141 scoped_refptr<Tile> TileManager::CreateTile(PicturePileImpl* picture_pile,
1142                                             const gfx::Size& tile_size,
1143                                             const gfx::Rect& content_rect,
1144                                             float contents_scale,
1145                                             int layer_id,
1146                                             int source_frame_number,
1147                                             int flags) {
1148   scoped_refptr<Tile> tile = make_scoped_refptr(new Tile(this,
1149                                                          picture_pile,
1150                                                          tile_size,
1151                                                          content_rect,
1152                                                          contents_scale,
1153                                                          layer_id,
1154                                                          source_frame_number,
1155                                                          flags));
1156   DCHECK(tiles_.find(tile->id()) == tiles_.end());
1157 
1158   tiles_[tile->id()] = tile.get();
1159   used_layer_counts_[tile->layer_id()]++;
1160   prioritized_tiles_dirty_ = true;
1161   return tile;
1162 }
1163 
SetRasterizerForTesting(Rasterizer * rasterizer)1164 void TileManager::SetRasterizerForTesting(Rasterizer* rasterizer) {
1165   rasterizer_ = rasterizer;
1166   rasterizer_->SetClient(this);
1167 }
1168 
IsReadyToActivate() const1169 bool TileManager::IsReadyToActivate() const {
1170   const std::vector<PictureLayerImpl*>& layers = client_->GetPictureLayers();
1171 
1172   for (std::vector<PictureLayerImpl*>::const_iterator it = layers.begin();
1173        it != layers.end();
1174        ++it) {
1175     if (!(*it)->AllTilesRequiredForActivationAreReadyToDraw())
1176       return false;
1177   }
1178 
1179   return true;
1180 }
1181 
CheckIfReadyToActivate()1182 void TileManager::CheckIfReadyToActivate() {
1183   TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate");
1184 
1185   rasterizer_->CheckForCompletedTasks();
1186   did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
1187 
1188   if (IsReadyToActivate())
1189     client_->NotifyReadyToActivate();
1190 }
1191 
1192 }  // namespace cc
1193