blob: aa6c1ade943a605f4ad0c1623c0fc93d74f823e7 [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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>
Ben Murdocheb525c52013-07-10 11:40:50 +01008#include <limits>
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009#include <string>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010
11#include "base/bind.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000012#include "base/json/json_writer.h"
13#include "base/logging.h"
14#include "base/metrics/histogram.h"
15#include "cc/debug/devtools_instrumentation.h"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010016#include "cc/debug/traced_value.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010017#include "cc/resources/image_raster_worker_pool.h"
18#include "cc/resources/pixel_buffer_raster_worker_pool.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000019#include "cc/resources/tile.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010020#include "third_party/skia/include/core/SkCanvas.h"
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010021#include "ui/gfx/rect_conversions.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000022
23namespace cc {
24
25namespace {
26
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010027// Memory limit policy works by mapping some bin states to the NEVER bin.
28const ManagedTileBin kBinPolicyMap[NUM_TILE_MEMORY_LIMIT_POLICIES][NUM_BINS] = {
29 { // [ALLOW_NOTHING]
Ben Murdochbb1529c2013-08-08 10:24:53 +010030 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]
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010037 }, { // [ALLOW_ABSOLUTE_MINIMUM]
Ben Murdochbb1529c2013-08-08 10:24:53 +010038 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]
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010045 }, { // [ALLOW_PREPAINT_ONLY]
Ben Murdochbb1529c2013-08-08 10:24:53 +010046 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]
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010053 }, { // [ALLOW_ANYTHING]
Ben Murdochbb1529c2013-08-08 10:24:53 +010054 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]
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010061 }
62};
63
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000064// Determine bin based on three categories of tiles: things we need now,
65// things we need soon, and eventually.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010066inline ManagedTileBin BinFromTilePriority(const TilePriority& prio,
Ben Murdochbb1529c2013-08-08 10:24:53 +010067 TreePriority tree_priority,
68 bool is_ready_to_draw,
69 bool is_active) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000070 // The amount of time for which we want to have prepainting coverage.
71 const float kPrepaintingWindowTimeSeconds = 1.0f;
72 const float kBackflingGuardDistancePixels = 314.0f;
73
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010074 // Don't let low res tiles be in the now bin unless we're in a mode where
75 // we're prioritizing checkerboard prevention.
76 bool can_be_in_now_bin = tree_priority == SMOOTHNESS_TAKES_PRIORITY ||
77 prio.resolution != LOW_RESOLUTION;
78
Ben Murdocheb525c52013-07-10 11:40:50 +010079 if (prio.distance_to_visible_in_pixels ==
80 std::numeric_limits<float>::infinity())
Ben Murdochbb1529c2013-08-08 10:24:53 +010081 return is_active ? NEVER_AND_ACTIVE_BIN : NEVER_BIN;
Ben Murdocheb525c52013-07-10 11:40:50 +010082
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010083 if (can_be_in_now_bin && prio.time_to_visible_in_seconds == 0)
Ben Murdochbb1529c2013-08-08 10:24:53 +010084 return is_ready_to_draw ? NOW_AND_READY_TO_DRAW_BIN : NOW_BIN;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000085
86 if (prio.resolution == NON_IDEAL_RESOLUTION)
Ben Murdochbb1529c2013-08-08 10:24:53 +010087 return is_active ? EVENTUALLY_AND_ACTIVE_BIN : EVENTUALLY_BIN;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000088
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010089 if (prio.distance_to_visible_in_pixels < kBackflingGuardDistancePixels ||
90 prio.time_to_visible_in_seconds < kPrepaintingWindowTimeSeconds)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000091 return SOON_BIN;
92
Ben Murdochbb1529c2013-08-08 10:24:53 +010093 return is_active ? EVENTUALLY_AND_ACTIVE_BIN : EVENTUALLY_BIN;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000094}
95
Ben Murdochca12bfa2013-07-23 11:17:05 +010096// Limit to the number of raster tasks that can be scheduled.
97// This is high enough to not cause unnecessary scheduling but
98// gives us an insurance that we're not spending a huge amount
99// of time scheduling one enormous set of tasks.
100const size_t kMaxRasterTasks = 256u;
101
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000102} // namespace
103
Ben Murdochca12bfa2013-07-23 11:17:05 +0100104RasterTaskCompletionStats::RasterTaskCompletionStats()
105 : completed_count(0u),
106 canceled_count(0u) {
107}
108
109scoped_ptr<base::Value> RasterTaskCompletionStatsAsValue(
110 const RasterTaskCompletionStats& stats) {
111 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
112 state->SetInteger("completed_count", stats.completed_count);
113 state->SetInteger("canceled_count", stats.canceled_count);
114 return state.PassAs<base::Value>();
115}
116
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100117// static
118scoped_ptr<TileManager> TileManager::Create(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000119 TileManagerClient* client,
120 ResourceProvider* resource_provider,
121 size_t num_raster_threads,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100122 RenderingStatsInstrumentation* rendering_stats_instrumentation,
123 bool use_map_image) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100124 return make_scoped_ptr(
125 new TileManager(client,
126 resource_provider,
127 use_map_image ?
128 ImageRasterWorkerPool::Create(
129 resource_provider, num_raster_threads) :
130 PixelBufferRasterWorkerPool::Create(
131 resource_provider, num_raster_threads),
132 num_raster_threads,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100133 rendering_stats_instrumentation,
134 resource_provider->best_texture_format()));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100135}
136
137TileManager::TileManager(
138 TileManagerClient* client,
139 ResourceProvider* resource_provider,
140 scoped_ptr<RasterWorkerPool> raster_worker_pool,
141 size_t num_raster_threads,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100142 RenderingStatsInstrumentation* rendering_stats_instrumentation,
143 GLenum texture_format)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000144 : client_(client),
145 resource_pool_(ResourcePool::Create(resource_provider)),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100146 raster_worker_pool_(raster_worker_pool.Pass()),
Ben Murdochca12bfa2013-07-23 11:17:05 +0100147 all_tiles_that_need_to_be_rasterized_have_memory_(true),
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100148 all_tiles_required_for_activation_have_memory_(true),
Ben Murdochca12bfa2013-07-23 11:17:05 +0100149 all_tiles_required_for_activation_have_been_initialized_(true),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000150 ever_exceeded_memory_budget_(false),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100151 rendering_stats_instrumentation_(rendering_stats_instrumentation),
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100152 did_initialize_visible_tile_(false),
153 texture_format_(texture_format) {
154 raster_worker_pool_->SetClient(this);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000155}
156
157TileManager::~TileManager() {
158 // Reset global state and manage. This should cause
159 // our memory usage to drop to zero.
160 global_state_ = GlobalStateThatImpactsTilePriority();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100161
Ben Murdochbb1529c2013-08-08 10:24:53 +0100162 // Clear |prioritized_tiles_| so that tiles kept alive by it can be freed.
163 prioritized_tiles_.Clear();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100164 DCHECK_EQ(0u, tiles_.size());
165
166 TileVector empty;
167 ScheduleTasks(empty);
168
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000169 // This should finish all pending tasks and release any uninitialized
170 // resources.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100171 raster_worker_pool_->Shutdown();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100172 raster_worker_pool_->CheckForCompletedTasks();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000173}
174
175void TileManager::SetGlobalState(
176 const GlobalStateThatImpactsTilePriority& global_state) {
177 global_state_ = global_state;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100178 resource_pool_->SetMemoryUsageLimits(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100179 global_state_.memory_limit_in_bytes,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100180 global_state_.unused_memory_limit_in_bytes,
181 global_state_.num_resources_limit);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000182}
183
184void TileManager::RegisterTile(Tile* tile) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100185 DCHECK(!tile->required_for_activation());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100186 DCHECK(tiles_.find(tile->id()) == tiles_.end());
187
188 tiles_[tile->id()] = tile;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000189}
190
191void TileManager::UnregisterTile(Tile* tile) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000192 FreeResourcesForTile(tile);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100193
194 DCHECK(tiles_.find(tile->id()) != tiles_.end());
195 tiles_.erase(tile->id());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000196}
197
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100198bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const {
Ben Murdocheb525c52013-07-10 11:40:50 +0100199 return GlobalState().tree_priority != SMOOTHNESS_TAKES_PRIORITY;
200}
201
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100202void TileManager::DidFinishRunningTasks() {
203 TRACE_EVENT0("cc", "TileManager::DidFinishRunningTasks");
204
Ben Murdocheb525c52013-07-10 11:40:50 +0100205 // When OOM, keep re-assigning memory until we reach a steady state
206 // where top-priority tiles are initialized.
Ben Murdochca12bfa2013-07-23 11:17:05 +0100207 if (all_tiles_that_need_to_be_rasterized_have_memory_)
Ben Murdocheb525c52013-07-10 11:40:50 +0100208 return;
209
210 raster_worker_pool_->CheckForCompletedTasks();
211
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100212 TileVector tiles_that_need_to_be_rasterized;
Ben Murdochbb1529c2013-08-08 10:24:53 +0100213 AssignGpuMemoryToTiles(&prioritized_tiles_,
214 &tiles_that_need_to_be_rasterized);
Ben Murdocheb525c52013-07-10 11:40:50 +0100215
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100216 // |tiles_that_need_to_be_rasterized| will be empty when we reach a
Ben Murdocheb525c52013-07-10 11:40:50 +0100217 // steady memory state. Keep scheduling tasks until we reach this state.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100218 if (!tiles_that_need_to_be_rasterized.empty()) {
219 ScheduleTasks(tiles_that_need_to_be_rasterized);
Ben Murdocheb525c52013-07-10 11:40:50 +0100220 return;
221 }
222
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100223 // Use on-demand raster for any required-for-activation tiles that have not
224 // been been assigned memory after reaching a steady memory state. This
225 // ensures that we activate even when OOM.
226 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
227 Tile* tile = it->second;
Ben Murdocheb525c52013-07-10 11:40:50 +0100228 ManagedTileState& mts = tile->managed_state();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100229 ManagedTileState::TileVersion& tile_version =
230 mts.tile_versions[mts.raster_mode];
Ben Murdocheb525c52013-07-10 11:40:50 +0100231
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100232 if (tile->required_for_activation() && !tile_version.IsReadyToDraw())
233 tile_version.set_rasterize_on_demand();
234 }
235
Ben Murdocheb525c52013-07-10 11:40:50 +0100236 client_->NotifyReadyToActivate();
237}
238
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100239void TileManager::DidFinishRunningTasksRequiredForActivation() {
Ben Murdocheb525c52013-07-10 11:40:50 +0100240 // This is only a true indication that all tiles required for
241 // activation are initialized when no tiles are OOM. We need to
242 // wait for DidFinishRunningTasks() to be called, try to re-assign
243 // memory and in worst case use on-demand raster when tiles
244 // required for activation are OOM.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100245 if (!all_tiles_required_for_activation_have_memory_)
Ben Murdocheb525c52013-07-10 11:40:50 +0100246 return;
247
248 client_->NotifyReadyToActivate();
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100249}
250
Ben Murdochbb1529c2013-08-08 10:24:53 +0100251void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100252 TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins");
253
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100254 const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000255 const TreePriority tree_priority = global_state_.tree_priority;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000256
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000257 // For each tree, bin into different categories of tiles.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100258 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
259 Tile* tile = it->second;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000260 ManagedTileState& mts = tile->managed_state();
261
262 TilePriority prio[NUM_BIN_PRIORITIES];
263 switch (tree_priority) {
264 case SAME_PRIORITY_FOR_BOTH_TREES:
265 prio[HIGH_PRIORITY_BIN] = prio[LOW_PRIORITY_BIN] =
266 tile->combined_priority();
267 break;
268 case SMOOTHNESS_TAKES_PRIORITY:
269 prio[HIGH_PRIORITY_BIN] = tile->priority(ACTIVE_TREE);
270 prio[LOW_PRIORITY_BIN] = tile->priority(PENDING_TREE);
271 break;
272 case NEW_CONTENT_TAKES_PRIORITY:
273 prio[HIGH_PRIORITY_BIN] = tile->priority(PENDING_TREE);
274 prio[LOW_PRIORITY_BIN] = tile->priority(ACTIVE_TREE);
275 break;
276 }
277
Ben Murdochbb1529c2013-08-08 10:24:53 +0100278 bool tile_is_ready_to_draw = tile->IsReadyToDraw();
279 bool tile_is_active =
280 tile_is_ready_to_draw ||
281 !mts.tile_versions[mts.raster_mode].raster_task_.is_null();
282
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000283 mts.resolution = prio[HIGH_PRIORITY_BIN].resolution;
284 mts.time_to_needed_in_seconds =
285 prio[HIGH_PRIORITY_BIN].time_to_visible_in_seconds;
286 mts.distance_to_visible_in_pixels =
287 prio[HIGH_PRIORITY_BIN].distance_to_visible_in_pixels;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100288 mts.required_for_activation =
289 prio[HIGH_PRIORITY_BIN].required_for_activation;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000290
Ben Murdochbb1529c2013-08-08 10:24:53 +0100291 mts.bin[HIGH_PRIORITY_BIN] =
292 BinFromTilePriority(prio[HIGH_PRIORITY_BIN],
293 tree_priority,
294 tile_is_ready_to_draw,
295 tile_is_active);
296 mts.bin[LOW_PRIORITY_BIN] =
297 BinFromTilePriority(prio[LOW_PRIORITY_BIN],
298 tree_priority,
299 tile_is_ready_to_draw,
300 tile_is_active);
301 mts.gpu_memmgr_stats_bin =
302 BinFromTilePriority(tile->combined_priority(),
303 tree_priority,
304 tile_is_ready_to_draw,
305 tile_is_active);
306
307 ManagedTileBin active_bin =
308 BinFromTilePriority(tile->priority(ACTIVE_TREE),
309 tree_priority,
310 tile_is_ready_to_draw,
311 tile_is_active);
312 mts.tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin];
313
314 ManagedTileBin pending_bin =
315 BinFromTilePriority(tile->priority(PENDING_TREE),
316 tree_priority,
317 tile_is_ready_to_draw,
318 tile_is_active);
319 mts.tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin];
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000320
321 for (int i = 0; i < NUM_BIN_PRIORITIES; ++i)
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100322 mts.bin[i] = kBinPolicyMap[memory_policy][mts.bin[i]];
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100323
324 mts.visible_and_ready_to_draw =
Ben Murdochbb1529c2013-08-08 10:24:53 +0100325 mts.tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100326
Ben Murdochbb1529c2013-08-08 10:24:53 +0100327 if (mts.is_in_never_bin_on_both_trees()) {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100328 FreeResourcesForTile(tile);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100329 continue;
330 }
331
332 // Note that if the tile is visible_and_ready_to_draw, then we always want
333 // the priority to be NOW_AND_READY_TO_DRAW_BIN, even if HIGH_PRIORITY_BIN
334 // is something different. The reason for this is that if we're prioritizing
335 // the pending tree, we still want visible tiles to take the highest
336 // priority.
337 ManagedTileBin priority_bin = mts.visible_and_ready_to_draw
338 ? NOW_AND_READY_TO_DRAW_BIN
339 : mts.bin[HIGH_PRIORITY_BIN];
340
341 // Insert the tile into a priority set.
342 tiles->InsertTile(tile, priority_bin);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000343 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100344}
345
Ben Murdochbb1529c2013-08-08 10:24:53 +0100346void TileManager::GetPrioritizedTileSet(PrioritizedTileSet* tiles) {
347 TRACE_EVENT0("cc", "TileManager::GetPrioritizedTileSet");
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100348
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100349 GetTilesWithAssignedBins(tiles);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100350 tiles->Sort();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100351}
352
353void TileManager::ManageTiles() {
354 TRACE_EVENT0("cc", "TileManager::ManageTiles");
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100355
Ben Murdochbb1529c2013-08-08 10:24:53 +0100356 // Clear |prioritized_tiles_| so that tiles kept alive by it can be freed.
357 prioritized_tiles_.Clear();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100358
Ben Murdochbb1529c2013-08-08 10:24:53 +0100359 GetPrioritizedTileSet(&prioritized_tiles_);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100360
361 TileVector tiles_that_need_to_be_rasterized;
Ben Murdochbb1529c2013-08-08 10:24:53 +0100362 AssignGpuMemoryToTiles(&prioritized_tiles_,
363 &tiles_that_need_to_be_rasterized);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100364 CleanUpUnusedImageDecodeTasks();
365
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100366 TRACE_EVENT_INSTANT1(
367 "cc", "DidManage", TRACE_EVENT_SCOPE_THREAD,
368 "state", TracedValue::FromValue(BasicStateAsValue().release()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000369
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100370 // Finally, schedule rasterizer tasks.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100371 ScheduleTasks(tiles_that_need_to_be_rasterized);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000372}
373
Ben Murdochca12bfa2013-07-23 11:17:05 +0100374bool TileManager::UpdateVisibleTiles() {
375 TRACE_EVENT0("cc", "TileManager::UpdateVisibleTiles");
376
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100377 raster_worker_pool_->CheckForCompletedTasks();
Ben Murdocheb525c52013-07-10 11:40:50 +0100378
Ben Murdochca12bfa2013-07-23 11:17:05 +0100379 TRACE_EVENT_INSTANT1(
380 "cc", "DidUpdateVisibleTiles", TRACE_EVENT_SCOPE_THREAD,
381 "stats", TracedValue::FromValue(
382 RasterTaskCompletionStatsAsValue(
383 update_visible_tiles_stats_).release()));
384 update_visible_tiles_stats_ = RasterTaskCompletionStats();
385
386 bool did_initialize_visible_tile = did_initialize_visible_tile_;
387 did_initialize_visible_tile_ = false;
388 return did_initialize_visible_tile;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000389}
390
391void TileManager::GetMemoryStats(
392 size_t* memory_required_bytes,
393 size_t* memory_nice_to_have_bytes,
394 size_t* memory_used_bytes) const {
395 *memory_required_bytes = 0;
396 *memory_nice_to_have_bytes = 0;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100397 *memory_used_bytes = resource_pool_->acquired_memory_usage_bytes();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100398 for (TileMap::const_iterator it = tiles_.begin();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100399 it != tiles_.end();
400 ++it) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100401 const Tile* tile = it->second;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100402 const ManagedTileState& mts = tile->managed_state();
403
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100404 const ManagedTileState::TileVersion& tile_version =
405 tile->GetTileVersionForDrawing();
406 if (tile_version.IsReadyToDraw() &&
407 !tile_version.requires_resource())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000408 continue;
409
410 size_t tile_bytes = tile->bytes_consumed_if_allocated();
Ben Murdochbb1529c2013-08-08 10:24:53 +0100411 if ((mts.gpu_memmgr_stats_bin == NOW_BIN) ||
412 (mts.gpu_memmgr_stats_bin == NOW_AND_READY_TO_DRAW_BIN))
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000413 *memory_required_bytes += tile_bytes;
414 if (mts.gpu_memmgr_stats_bin != NEVER_BIN)
415 *memory_nice_to_have_bytes += tile_bytes;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000416 }
417}
418
419scoped_ptr<base::Value> TileManager::BasicStateAsValue() const {
420 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100421 state->SetInteger("tile_count", tiles_.size());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000422 state->Set("global_state", global_state_.AsValue().release());
423 state->Set("memory_requirements", GetMemoryRequirementsAsValue().release());
424 return state.PassAs<base::Value>();
425}
426
427scoped_ptr<base::Value> TileManager::AllTilesAsValue() const {
428 scoped_ptr<base::ListValue> state(new base::ListValue());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100429 for (TileMap::const_iterator it = tiles_.begin();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100430 it != tiles_.end();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000431 it++) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100432 state->Append(it->second->AsValue().release());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000433 }
434 return state.PassAs<base::Value>();
435}
436
437scoped_ptr<base::Value> TileManager::GetMemoryRequirementsAsValue() const {
438 scoped_ptr<base::DictionaryValue> requirements(
439 new base::DictionaryValue());
440
441 size_t memory_required_bytes;
442 size_t memory_nice_to_have_bytes;
443 size_t memory_used_bytes;
444 GetMemoryStats(&memory_required_bytes,
445 &memory_nice_to_have_bytes,
446 &memory_used_bytes);
447 requirements->SetInteger("memory_required_bytes", memory_required_bytes);
448 requirements->SetInteger("memory_nice_to_have_bytes",
449 memory_nice_to_have_bytes);
450 requirements->SetInteger("memory_used_bytes", memory_used_bytes);
451 return requirements.PassAs<base::Value>();
452}
453
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100454RasterMode TileManager::DetermineRasterMode(const Tile* tile) const {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100455 DCHECK(tile);
456 DCHECK(tile->picture_pile());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000457
Ben Murdocheb525c52013-07-10 11:40:50 +0100458 const ManagedTileState& mts = tile->managed_state();
459 RasterMode current_mode = mts.raster_mode;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100460
Ben Murdocheb525c52013-07-10 11:40:50 +0100461 RasterMode raster_mode = HIGH_QUALITY_RASTER_MODE;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100462 if (tile->managed_state().resolution == LOW_RESOLUTION)
463 raster_mode = LOW_QUALITY_RASTER_MODE;
Ben Murdocheb525c52013-07-10 11:40:50 +0100464 else if (tile->can_use_lcd_text())
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100465 raster_mode = HIGH_QUALITY_RASTER_MODE;
Ben Murdocheb525c52013-07-10 11:40:50 +0100466 else if (mts.tile_versions[current_mode].has_text_ ||
467 !mts.tile_versions[current_mode].IsReadyToDraw())
468 raster_mode = HIGH_QUALITY_NO_LCD_RASTER_MODE;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100469
Ben Murdocheb525c52013-07-10 11:40:50 +0100470 return std::min(raster_mode, current_mode);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000471}
472
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100473void TileManager::AssignGpuMemoryToTiles(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100474 PrioritizedTileSet* tiles,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100475 TileVector* tiles_that_need_to_be_rasterized) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000476 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000477
478 // Now give memory out to the tiles until we're out, and build
479 // the needs-to-be-rasterized queue.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100480 size_t bytes_releasable = 0;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100481 size_t resources_releasable = 0;
Ben Murdochbb1529c2013-08-08 10:24:53 +0100482 for (PrioritizedTileSet::PriorityIterator it(tiles);
483 it;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100484 ++it) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100485 const Tile* tile = *it;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100486 const ManagedTileState& mts = tile->managed_state();
487 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100488 if (mts.tile_versions[mode].resource_) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100489 bytes_releasable += tile->bytes_consumed_if_allocated();
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100490 resources_releasable++;
491 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100492 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000493 }
494
Ben Murdochca12bfa2013-07-23 11:17:05 +0100495 all_tiles_that_need_to_be_rasterized_have_memory_ = true;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100496 all_tiles_required_for_activation_have_memory_ = true;
Ben Murdochca12bfa2013-07-23 11:17:05 +0100497 all_tiles_required_for_activation_have_been_initialized_ = true;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100498
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100499 // Cast to prevent overflow.
500 int64 bytes_available =
501 static_cast<int64>(bytes_releasable) +
502 static_cast<int64>(global_state_.memory_limit_in_bytes) -
503 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes());
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100504 int resources_available = resources_releasable +
505 global_state_.num_resources_limit -
506 resource_pool_->NumResources();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100507
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000508 size_t bytes_allocatable =
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100509 std::max(static_cast<int64>(0), bytes_available);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100510 size_t resources_allocatable = std::max(0, resources_available);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100511
Ben Murdocheb525c52013-07-10 11:40:50 +0100512 size_t bytes_that_exceeded_memory_budget = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000513 size_t bytes_left = bytes_allocatable;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100514 size_t resources_left = resources_allocatable;
Ben Murdochca12bfa2013-07-23 11:17:05 +0100515 bool oomed = false;
Ben Murdoch2385ea32013-08-06 11:01:04 +0100516
517 unsigned schedule_priority = 1u;
Ben Murdochbb1529c2013-08-08 10:24:53 +0100518 for (PrioritizedTileSet::PriorityIterator it(tiles);
519 it;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000520 ++it) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100521 Tile* tile = *it;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000522 ManagedTileState& mts = tile->managed_state();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100523
Ben Murdoch2385ea32013-08-06 11:01:04 +0100524 mts.scheduled_priority = schedule_priority++;
525
Ben Murdocheb525c52013-07-10 11:40:50 +0100526 mts.raster_mode = DetermineRasterMode(tile);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100527
528 ManagedTileState::TileVersion& tile_version =
529 mts.tile_versions[mts.raster_mode];
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100530
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100531 // If this tile doesn't need a resource, then nothing to do.
532 if (!tile_version.requires_resource())
533 continue;
534
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100535 // If the tile is not needed, free it up.
536 if (mts.is_in_never_bin_on_both_trees()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000537 FreeResourcesForTile(tile);
538 continue;
539 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100540
541 size_t tile_bytes = 0;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100542 size_t tile_resources = 0;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100543
544 // It costs to maintain a resource.
545 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100546 if (mts.tile_versions[mode].resource_) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100547 tile_bytes += tile->bytes_consumed_if_allocated();
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100548 tile_resources++;
549 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100550 }
551
Ben Murdochca12bfa2013-07-23 11:17:05 +0100552 // Allow lower priority tiles with initialized resources to keep
553 // their memory by only assigning memory to new raster tasks if
554 // they can be scheduled.
555 if (tiles_that_need_to_be_rasterized->size() < kMaxRasterTasks) {
556 // If we don't have the required version, and it's not in flight
557 // then we'll have to pay to create a new task.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100558 if (!tile_version.resource_ && tile_version.raster_task_.is_null()) {
Ben Murdochca12bfa2013-07-23 11:17:05 +0100559 tile_bytes += tile->bytes_consumed_if_allocated();
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100560 tile_resources++;
561 }
Ben Murdochca12bfa2013-07-23 11:17:05 +0100562 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100563
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100564 // Tile is OOM.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100565 if (tile_bytes > bytes_left || tile_resources > resources_left) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100566 FreeResourcesForTile(tile);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100567
Ben Murdochca12bfa2013-07-23 11:17:05 +0100568 // This tile was already on screen and now its resources have been
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100569 // released. In order to prevent checkerboarding, set this tile as
570 // rasterize on demand immediately.
571 if (mts.visible_and_ready_to_draw)
572 tile_version.set_rasterize_on_demand();
573
Ben Murdochca12bfa2013-07-23 11:17:05 +0100574 oomed = true;
Ben Murdocheb525c52013-07-10 11:40:50 +0100575 bytes_that_exceeded_memory_budget += tile_bytes;
Ben Murdochca12bfa2013-07-23 11:17:05 +0100576 } else {
577 bytes_left -= tile_bytes;
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100578 resources_left -= tile_resources;
Ben Murdochca12bfa2013-07-23 11:17:05 +0100579
580 if (tile_version.resource_)
581 continue;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000582 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100583
Ben Murdochca12bfa2013-07-23 11:17:05 +0100584 DCHECK(!tile_version.resource_);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100585
Ben Murdochca12bfa2013-07-23 11:17:05 +0100586 if (tile->required_for_activation())
587 all_tiles_required_for_activation_have_been_initialized_ = false;
588
589 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized|
590 // has reached it's limit or we've failed to assign gpu memory to this
591 // or any higher priority tile. Preventing tiles that fit into memory
592 // budget to be rasterized when higher priority tile is oom is
593 // important for two reasons:
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100594 // 1. Tile size should not impact raster priority.
Ben Murdochca12bfa2013-07-23 11:17:05 +0100595 // 2. Tiles with existing raster task could otherwise incorrectly
596 // be added as they are not affected by |bytes_allocatable|.
597 if (oomed || tiles_that_need_to_be_rasterized->size() >= kMaxRasterTasks) {
598 all_tiles_that_need_to_be_rasterized_have_memory_ = false;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100599 if (tile->required_for_activation())
600 all_tiles_required_for_activation_have_memory_ = false;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100601 continue;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100602 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100603
Ben Murdochca12bfa2013-07-23 11:17:05 +0100604 tiles_that_need_to_be_rasterized->push_back(tile);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100605 }
606
Ben Murdocheb525c52013-07-10 11:40:50 +0100607 ever_exceeded_memory_budget_ |= bytes_that_exceeded_memory_budget > 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000608 if (ever_exceeded_memory_budget_) {
609 TRACE_COUNTER_ID2("cc", "over_memory_budget", this,
610 "budget", global_state_.memory_limit_in_bytes,
Ben Murdocheb525c52013-07-10 11:40:50 +0100611 "over", bytes_that_exceeded_memory_budget);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000612 }
613 memory_stats_from_last_assign_.total_budget_in_bytes =
614 global_state_.memory_limit_in_bytes;
615 memory_stats_from_last_assign_.bytes_allocated =
616 bytes_allocatable - bytes_left;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100617 memory_stats_from_last_assign_.bytes_unreleasable =
618 bytes_allocatable - bytes_releasable;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000619 memory_stats_from_last_assign_.bytes_over =
Ben Murdocheb525c52013-07-10 11:40:50 +0100620 bytes_that_exceeded_memory_budget;
621}
622
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100623void TileManager::CleanUpUnusedImageDecodeTasks() {
624 // Calculate a set of layers that are used by at least one tile.
625 base::hash_set<int> used_layers;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100626 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it)
627 used_layers.insert(it->second->layer_id());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100628
629 // Now calculate the set of layers in |image_decode_tasks_| that are not used
630 // by any tile.
631 std::vector<int> unused_layers;
632 for (LayerPixelRefTaskMap::iterator it = image_decode_tasks_.begin();
633 it != image_decode_tasks_.end();
634 ++it) {
635 if (used_layers.find(it->first) == used_layers.end())
636 unused_layers.push_back(it->first);
637 }
638
639 // Erase unused layers from |image_decode_tasks_|.
640 for (std::vector<int>::iterator it = unused_layers.begin();
641 it != unused_layers.end();
642 ++it) {
643 image_decode_tasks_.erase(*it);
644 }
645}
646
647void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100648 ManagedTileState& mts = tile->managed_state();
649 if (mts.tile_versions[mode].resource_) {
650 resource_pool_->ReleaseResource(
651 mts.tile_versions[mode].resource_.Pass());
652 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000653}
654
655void TileManager::FreeResourcesForTile(Tile* tile) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100656 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100657 FreeResourceForTile(tile, static_cast<RasterMode>(mode));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000658 }
659}
660
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100661void TileManager::FreeUnusedResourcesForTile(Tile* tile) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100662 DCHECK(tile->IsReadyToDraw());
663 ManagedTileState& mts = tile->managed_state();
664 RasterMode used_mode = HIGH_QUALITY_NO_LCD_RASTER_MODE;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100665 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100666 if (mts.tile_versions[mode].IsReadyToDraw()) {
667 used_mode = static_cast<RasterMode>(mode);
668 break;
669 }
670 }
671
672 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
673 if (mode != used_mode)
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100674 FreeResourceForTile(tile, static_cast<RasterMode>(mode));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000675 }
676}
677
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100678void TileManager::ScheduleTasks(
679 const TileVector& tiles_that_need_to_be_rasterized) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100680 TRACE_EVENT1("cc", "TileManager::ScheduleTasks",
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100681 "count", tiles_that_need_to_be_rasterized.size());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100682 RasterWorkerPool::RasterTask::Queue tasks;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000683
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100684 // Build a new task queue containing all task currently needed. Tasks
685 // are added in order of priority, highest priority task first.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100686 for (TileVector::const_iterator it = tiles_that_need_to_be_rasterized.begin();
687 it != tiles_that_need_to_be_rasterized.end();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100688 ++it) {
689 Tile* tile = *it;
690 ManagedTileState& mts = tile->managed_state();
691 ManagedTileState::TileVersion& tile_version =
692 mts.tile_versions[mts.raster_mode];
693
694 DCHECK(tile_version.requires_resource());
695 DCHECK(!tile_version.resource_);
696
697 if (tile_version.raster_task_.is_null())
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100698 tile_version.raster_task_ = CreateRasterTask(tile);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100699
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100700 tasks.Append(tile_version.raster_task_, tile->required_for_activation());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100701 }
702
703 // Schedule running of |tasks|. This replaces any previously
704 // scheduled tasks and effectively cancels all tasks not present
705 // in |tasks|.
706 raster_worker_pool_->ScheduleTasks(&tasks);
707}
708
709RasterWorkerPool::Task TileManager::CreateImageDecodeTask(
710 Tile* tile, skia::LazyPixelRef* pixel_ref) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100711 return RasterWorkerPool::CreateImageDecodeTask(
712 pixel_ref,
713 tile->layer_id(),
714 rendering_stats_instrumentation_,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000715 base::Bind(&TileManager::OnImageDecodeTaskCompleted,
716 base::Unretained(this),
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100717 tile->layer_id(),
718 base::Unretained(pixel_ref)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000719}
720
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100721RasterWorkerPool::RasterTask TileManager::CreateRasterTask(Tile* tile) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100722 ManagedTileState& mts = tile->managed_state();
723
724 scoped_ptr<ResourcePool::Resource> resource =
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100725 resource_pool_->AcquireResource(tile->tile_size_.size(),
726 texture_format_);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100727 const Resource* const_resource = resource.get();
728
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100729 // Create and queue all image decode tasks that this tile depends on.
730 RasterWorkerPool::Task::Set decode_tasks;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100731 PixelRefTaskMap& existing_pixel_refs = image_decode_tasks_[tile->layer_id()];
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100732 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(),
733 tile->contents_scale(),
734 tile->picture_pile());
735 iter; ++iter) {
736 skia::LazyPixelRef* pixel_ref = *iter;
737 uint32_t id = pixel_ref->getGenerationID();
738
739 // Append existing image decode task if available.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100740 PixelRefTaskMap::iterator decode_task_it = existing_pixel_refs.find(id);
741 if (decode_task_it != existing_pixel_refs.end()) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100742 decode_tasks.Insert(decode_task_it->second);
743 continue;
744 }
745
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100746 // Create and append new image decode task for this pixel ref.
747 RasterWorkerPool::Task decode_task = CreateImageDecodeTask(
748 tile, pixel_ref);
749 decode_tasks.Insert(decode_task);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100750 existing_pixel_refs[id] = decode_task;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100751 }
752
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100753 return RasterWorkerPool::CreateRasterTask(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100754 const_resource,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100755 tile->picture_pile(),
756 tile->content_rect(),
757 tile->contents_scale(),
758 mts.raster_mode,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100759 mts.tree_bin[PENDING_TREE] == NOW_BIN,
760 mts.resolution,
761 tile->layer_id(),
762 static_cast<const void *>(tile),
763 tile->source_frame_number(),
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100764 rendering_stats_instrumentation_,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100765 base::Bind(&TileManager::OnRasterTaskCompleted,
766 base::Unretained(this),
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100767 tile->id(),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100768 base::Passed(&resource),
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100769 mts.raster_mode),
Ben Murdocheb525c52013-07-10 11:40:50 +0100770 &decode_tasks);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100771}
772
773void TileManager::OnImageDecodeTaskCompleted(
774 int layer_id,
775 skia::LazyPixelRef* pixel_ref,
776 bool was_canceled) {
777 // If the task was canceled, we need to clean it up
778 // from |image_decode_tasks_|.
779 if (!was_canceled)
780 return;
781
782 LayerPixelRefTaskMap::iterator layer_it =
783 image_decode_tasks_.find(layer_id);
784
785 if (layer_it == image_decode_tasks_.end())
786 return;
787
788 PixelRefTaskMap& pixel_ref_tasks = layer_it->second;
789 PixelRefTaskMap::iterator task_it =
790 pixel_ref_tasks.find(pixel_ref->getGenerationID());
791
792 if (task_it != pixel_ref_tasks.end())
793 pixel_ref_tasks.erase(task_it);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100794}
795
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000796void TileManager::OnRasterTaskCompleted(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100797 Tile::Id tile_id,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000798 scoped_ptr<ResourcePool::Resource> resource,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100799 RasterMode raster_mode,
800 const PicturePileImpl::Analysis& analysis,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100801 bool was_canceled) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100802 TileMap::iterator it = tiles_.find(tile_id);
803 if (it == tiles_.end()) {
Ben Murdochca12bfa2013-07-23 11:17:05 +0100804 ++update_visible_tiles_stats_.canceled_count;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100805 resource_pool_->ReleaseResource(resource.Pass());
806 return;
807 }
808
809 Tile* tile = it->second;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100810 ManagedTileState& mts = tile->managed_state();
811 ManagedTileState::TileVersion& tile_version =
812 mts.tile_versions[raster_mode];
813 DCHECK(!tile_version.raster_task_.is_null());
814 tile_version.raster_task_.Reset();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000815
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100816 if (was_canceled) {
Ben Murdochca12bfa2013-07-23 11:17:05 +0100817 ++update_visible_tiles_stats_.canceled_count;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100818 resource_pool_->ReleaseResource(resource.Pass());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100819 return;
820 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000821
Ben Murdochca12bfa2013-07-23 11:17:05 +0100822 ++update_visible_tiles_stats_.completed_count;
823
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100824 tile_version.set_has_text(analysis.has_text);
825 if (analysis.is_solid_color) {
826 tile_version.set_solid_color(analysis.solid_color);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000827 resource_pool_->ReleaseResource(resource.Pass());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100828 } else {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100829 tile_version.set_use_resource();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100830 tile_version.resource_ = resource.Pass();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000831 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100832
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100833 FreeUnusedResourcesForTile(tile);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000834 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100835 did_initialize_visible_tile_ = true;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000836}
837
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000838} // namespace cc