OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/tile_manager.h" | 5 #include "cc/tile_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 13 matching lines...) Expand all Loading... | |
24 | 24 |
25 const char* kRasterThreadNamePrefix = "CompositorRaster"; | 25 const char* kRasterThreadNamePrefix = "CompositorRaster"; |
26 | 26 |
27 const int kMaxRasterThreads = 64; | 27 const int kMaxRasterThreads = 64; |
28 const int kDefaultNumberOfRasterThreads = 1; | 28 const int kDefaultNumberOfRasterThreads = 1; |
29 | 29 |
30 // Allow two pending raster tasks per thread. This keeps resource usage | 30 // Allow two pending raster tasks per thread. This keeps resource usage |
31 // low while making sure raster threads aren't unnecessarily idle. | 31 // low while making sure raster threads aren't unnecessarily idle. |
32 const int kNumPendingRasterTasksPerThread = 2; | 32 const int kNumPendingRasterTasksPerThread = 2; |
33 | 33 |
34 // Determine bin based on three categories of tiles: things we need now, | |
35 // things we need soon, and eventually. | |
36 cc::TileManagerBin BinFromTilePriority(const cc::TilePriority& prio) { | |
enne (OOO)
2012/12/16 01:26:44
This is a nice refactoring.
| |
37 | |
38 // The amount of time for which we want to have prepainting coverage. | |
39 const double prepainting_window_time_seconds = 1.0; | |
40 const double backfling_guard_distance_pixels = 314.0; | |
41 | |
42 if (prio.time_to_needed_in_seconds() == std::numeric_limits<float>::max()) | |
43 return cc::NEVER_BIN; | |
44 | |
45 if (prio.resolution == cc::NON_IDEAL_RESOLUTION) | |
46 return cc::EVENTUALLY_BIN; | |
47 | |
48 if (prio.time_to_needed_in_seconds() == 0 || | |
49 prio.distance_to_visible_in_pixels < backfling_guard_distance_pixels) | |
50 return cc::NOW_BIN; | |
51 | |
52 if (prio.time_to_needed_in_seconds() < prepainting_window_time_seconds) | |
53 return cc::SOON_BIN; | |
54 | |
55 return cc::EVENTUALLY_BIN; | |
56 } | |
57 | |
34 } // namespace | 58 } // namespace |
35 | 59 |
36 namespace cc { | 60 namespace cc { |
37 | 61 |
38 class RasterThread : public base::Thread { | 62 class RasterThread : public base::Thread { |
39 public: | 63 public: |
40 RasterThread(const std::string name) | 64 RasterThread(const std::string name) |
41 : base::Thread(name.c_str()), | 65 : base::Thread(name.c_str()), |
42 num_pending_tasks_(0) { | 66 num_pending_tasks_(0) { |
43 Start(); | 67 Start(); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 check_for_completed_set_pixels_pending_(false) { | 161 check_for_completed_set_pixels_pending_(false) { |
138 // Initialize all threads. | 162 // Initialize all threads. |
139 const std::string thread_name_prefix = kRasterThreadNamePrefix; | 163 const std::string thread_name_prefix = kRasterThreadNamePrefix; |
140 while (raster_threads_.size() < num_raster_threads) { | 164 while (raster_threads_.size() < num_raster_threads) { |
141 int thread_number = raster_threads_.size() + 1; | 165 int thread_number = raster_threads_.size() + 1; |
142 scoped_ptr<RasterThread> thread = make_scoped_ptr( | 166 scoped_ptr<RasterThread> thread = make_scoped_ptr( |
143 new RasterThread(thread_name_prefix + | 167 new RasterThread(thread_name_prefix + |
144 StringPrintf("Worker%d", thread_number).c_str())); | 168 StringPrintf("Worker%d", thread_number).c_str())); |
145 raster_threads_.append(thread.Pass()); | 169 raster_threads_.append(thread.Pass()); |
146 } | 170 } |
171 | |
172 ResetBinCounts(); | |
147 } | 173 } |
148 | 174 |
149 TileManager::~TileManager() { | 175 TileManager::~TileManager() { |
150 // Reset global state and manage. This should cause | 176 // Reset global state and manage. This should cause |
151 // our memory usage to drop to zero. | 177 // our memory usage to drop to zero. |
152 global_state_ = GlobalStateThatImpactsTilePriority(); | 178 global_state_ = GlobalStateThatImpactsTilePriority(); |
153 AssignGpuMemoryToTiles(); | 179 AssignGpuMemoryToTiles(); |
154 // This should finish all pending raster tasks and release any | 180 // This should finish all pending raster tasks and release any |
155 // uninitialized resources. | 181 // uninitialized resources. |
156 raster_threads_.clear(); | 182 raster_threads_.clear(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 return; | 238 return; |
213 client_->ScheduleCheckForCompletedSetPixels(); | 239 client_->ScheduleCheckForCompletedSetPixels(); |
214 check_for_completed_set_pixels_pending_ = true; | 240 check_for_completed_set_pixels_pending_ = true; |
215 } | 241 } |
216 | 242 |
217 class BinComparator { | 243 class BinComparator { |
218 public: | 244 public: |
219 bool operator() (const Tile* a, const Tile* b) const { | 245 bool operator() (const Tile* a, const Tile* b) const { |
220 const ManagedTileState& ams = a->managed_state(); | 246 const ManagedTileState& ams = a->managed_state(); |
221 const ManagedTileState& bms = b->managed_state(); | 247 const ManagedTileState& bms = b->managed_state(); |
222 if (ams.bin != bms.bin) | 248 if (ams.raster_bin != bms.raster_bin) |
223 return ams.bin < bms.bin; | 249 return ams.raster_bin < bms.raster_bin; |
224 | 250 |
225 if (ams.resolution != bms.resolution) | 251 if (ams.resolution != bms.resolution) |
226 return ams.resolution < ams.resolution; | 252 return ams.resolution < ams.resolution; |
227 | 253 |
228 return | 254 return |
229 ams.time_to_needed_in_seconds < | 255 ams.time_to_needed_in_seconds < |
230 bms.time_to_needed_in_seconds; | 256 bms.time_to_needed_in_seconds; |
231 } | 257 } |
232 }; | 258 }; |
233 | 259 |
234 void TileManager::ManageTiles() { | 260 void TileManager::ManageTiles() { |
235 TRACE_EVENT0("cc", "TileManager::ManageTiles"); | 261 TRACE_EVENT0("cc", "TileManager::ManageTiles"); |
236 manage_tiles_pending_ = false; | 262 manage_tiles_pending_ = false; |
237 | 263 |
238 // The amount of time for which we want to have prepainting coverage. | 264 const bool smoothness_takes_priority = |
239 const double prepainting_window_time_seconds = 1.0; | 265 global_state_.smoothness_takes_priority; |
240 const double backfling_guard_distance_pixels = 314.0; | |
241 | 266 |
242 const bool smoothness_takes_priority = global_state_.smoothness_takes_priority ; | 267 // For each tree, bin into different categories of tiles. |
243 | |
244 // Bin into three categories of tiles: things we need now, things we need soon , and eventually | |
245 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 268 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
246 Tile* tile = *it; | 269 Tile* tile = *it; |
247 ManagedTileState& mts = tile->managed_state(); | 270 ManagedTileState& mts = tile->managed_state(); |
271 mts.bin[ACTIVE_TREE] = BinFromTilePriority(tile->priority(ACTIVE_TREE)); | |
272 mts.bin[PENDING_TREE] = BinFromTilePriority(tile->priority(PENDING_TREE)); | |
273 | |
248 TilePriority prio; | 274 TilePriority prio; |
249 if (smoothness_takes_priority) | 275 if (smoothness_takes_priority) |
250 prio = tile->priority(ACTIVE_TREE); | 276 prio = tile->priority(ACTIVE_TREE); |
251 else | 277 else |
252 prio = tile->combined_priority(); | 278 prio = tile->combined_priority(); |
253 | 279 |
254 mts.resolution = prio.resolution; | 280 mts.resolution = prio.resolution; |
255 mts.time_to_needed_in_seconds = prio.time_to_needed_in_seconds(); | 281 mts.time_to_needed_in_seconds = prio.time_to_needed_in_seconds(); |
256 | 282 mts.raster_bin = BinFromTilePriority(prio); |
257 if (mts.time_to_needed_in_seconds == | |
258 std::numeric_limits<float>::max()) { | |
259 mts.bin = NEVER_BIN; | |
260 continue; | |
261 } | |
262 | |
263 if (mts.resolution == NON_IDEAL_RESOLUTION) { | |
264 mts.bin = EVENTUALLY_BIN; | |
265 continue; | |
266 } | |
267 | |
268 if (mts.time_to_needed_in_seconds == 0 || | |
269 prio.distance_to_visible_in_pixels < backfling_guard_distance_pixels) { | |
270 mts.bin = NOW_BIN; | |
271 continue; | |
272 } | |
273 | |
274 if (prio.time_to_needed_in_seconds() < prepainting_window_time_seconds) { | |
275 mts.bin = SOON_BIN; | |
276 continue; | |
277 } | |
278 | |
279 mts.bin = EVENTUALLY_BIN; | |
280 } | 283 } |
281 | 284 |
282 // Memory limit policy works by mapping some bin states to the NEVER bin. | 285 // Memory limit policy works by mapping some bin states to the NEVER bin. |
283 TileManagerBin bin_map[NUM_BINS]; | 286 TileManagerBin bin_map[NUM_BINS]; |
284 if (global_state_.memory_limit_policy == ALLOW_NOTHING) { | 287 if (global_state_.memory_limit_policy == ALLOW_NOTHING) { |
285 bin_map[NOW_BIN] = NEVER_BIN; | 288 bin_map[NOW_BIN] = NEVER_BIN; |
286 bin_map[SOON_BIN] = NEVER_BIN; | 289 bin_map[SOON_BIN] = NEVER_BIN; |
287 bin_map[EVENTUALLY_BIN] = NEVER_BIN; | 290 bin_map[EVENTUALLY_BIN] = NEVER_BIN; |
288 bin_map[NEVER_BIN] = NEVER_BIN; | 291 bin_map[NEVER_BIN] = NEVER_BIN; |
289 } else if (global_state_.memory_limit_policy == ALLOW_ABSOLUTE_MINIMUM) { | 292 } else if (global_state_.memory_limit_policy == ALLOW_ABSOLUTE_MINIMUM) { |
290 bin_map[NOW_BIN] = NOW_BIN; | 293 bin_map[NOW_BIN] = NOW_BIN; |
291 bin_map[SOON_BIN] = NEVER_BIN; | 294 bin_map[SOON_BIN] = NEVER_BIN; |
292 bin_map[EVENTUALLY_BIN] = NEVER_BIN; | 295 bin_map[EVENTUALLY_BIN] = NEVER_BIN; |
293 bin_map[NEVER_BIN] = NEVER_BIN; | 296 bin_map[NEVER_BIN] = NEVER_BIN; |
294 } else if (global_state_.memory_limit_policy == ALLOW_PREPAINT_ONLY) { | 297 } else if (global_state_.memory_limit_policy == ALLOW_PREPAINT_ONLY) { |
295 bin_map[NOW_BIN] = NOW_BIN; | 298 bin_map[NOW_BIN] = NOW_BIN; |
296 bin_map[SOON_BIN] = SOON_BIN; | 299 bin_map[SOON_BIN] = SOON_BIN; |
297 bin_map[EVENTUALLY_BIN] = NEVER_BIN; | 300 bin_map[EVENTUALLY_BIN] = NEVER_BIN; |
298 bin_map[NEVER_BIN] = NEVER_BIN; | 301 bin_map[NEVER_BIN] = NEVER_BIN; |
299 } else { | 302 } else { |
300 bin_map[NOW_BIN] = NOW_BIN; | 303 bin_map[NOW_BIN] = NOW_BIN; |
301 bin_map[SOON_BIN] = SOON_BIN; | 304 bin_map[SOON_BIN] = SOON_BIN; |
302 bin_map[EVENTUALLY_BIN] = EVENTUALLY_BIN; | 305 bin_map[EVENTUALLY_BIN] = EVENTUALLY_BIN; |
303 bin_map[NEVER_BIN] = NEVER_BIN; | 306 bin_map[NEVER_BIN] = NEVER_BIN; |
304 } | 307 } |
305 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 308 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
306 Tile* tile = *it; | 309 Tile* tile = *it; |
307 TileManagerBin bin = bin_map[tile->managed_state().bin]; | 310 ManagedTileState& mts = tile->managed_state(); |
308 tile->managed_state().bin = bin; | 311 mts.bin[ACTIVE_TREE] = bin_map[mts.bin[ACTIVE_TREE]]; |
312 mts.bin[PENDING_TREE] = bin_map[mts.bin[PENDING_TREE]]; | |
313 mts.raster_bin = bin_map[mts.raster_bin]; | |
314 } | |
315 | |
316 // Update bin counts. | |
317 ResetBinCounts(); | |
318 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | |
319 Tile* tile = *it; | |
320 ManagedTileState& mts = tile->managed_state(); | |
321 for (int i = 0; i < NUM_TREES; ++i) | |
322 tiles_in_bin_count_[mts.bin[i]][i]++; | |
323 | |
324 // Increment drawable count if GetResourceId() doesn't return 0. | |
325 if (tile->GetResourceId()) { | |
326 for (int i = 0; i < NUM_TREES; ++i) | |
327 drawable_tiles_in_bin_count_[mts.bin[i]][i]++; | |
328 } | |
309 } | 329 } |
310 | 330 |
311 // Sort by bin. | 331 // Sort by bin. |
312 std::sort(tiles_.begin(), tiles_.end(), BinComparator()); | 332 std::sort(tiles_.begin(), tiles_.end(), BinComparator()); |
313 | 333 |
314 // Assign gpu memory and determine what tiles need to be rasterized. | 334 // Assign gpu memory and determine what tiles need to be rasterized. |
315 AssignGpuMemoryToTiles(); | 335 AssignGpuMemoryToTiles(); |
316 | 336 |
317 // Finally, kick the rasterizer. | 337 // Finally, kick the rasterizer. |
318 DispatchMoreTasks(); | 338 DispatchMoreTasks(); |
(...skipping 15 matching lines...) Expand all Loading... | |
334 | 354 |
335 // It's now safe to release the pixel buffer. | 355 // It's now safe to release the pixel buffer. |
336 resource_pool_->resource_provider()->releasePixelBuffer( | 356 resource_pool_->resource_provider()->releasePixelBuffer( |
337 tile->managed_state().resource->id()); | 357 tile->managed_state().resource->id()); |
338 | 358 |
339 DidFinishTileInitialization(tile); | 359 DidFinishTileInitialization(tile); |
340 tiles_with_pending_set_pixels_.pop(); | 360 tiles_with_pending_set_pixels_.pop(); |
341 } | 361 } |
342 } | 362 } |
343 | 363 |
344 void TileManager::renderingStats(RenderingStats* stats) { | 364 void TileManager::GetRenderingStats(RenderingStats* stats) { |
345 stats->totalRasterizeTimeInSeconds = | 365 stats->totalRasterizeTimeInSeconds = |
346 rendering_stats_.totalRasterizeTimeInSeconds; | 366 rendering_stats_.totalRasterizeTimeInSeconds; |
347 stats->totalPixelsRasterized = rendering_stats_.totalPixelsRasterized; | 367 stats->totalPixelsRasterized = rendering_stats_.totalPixelsRasterized; |
348 } | 368 } |
349 | 369 |
370 int TileManager::GetTilesInBinCount(TileManagerBin bin, WhichTree tree) { | |
371 DCHECK(bin >= 0); | |
372 DCHECK(bin < NUM_BINS); | |
373 DCHECK(tree >= 0); | |
374 DCHECK(tree < NUM_TREES); | |
375 return tiles_in_bin_count_[bin][tree]; | |
376 } | |
377 | |
378 int TileManager::GetDrawableTilesInBinCount( | |
379 TileManagerBin bin, WhichTree tree) { | |
380 DCHECK(bin >= 0); | |
381 DCHECK(bin < NUM_BINS); | |
382 DCHECK(tree >= 0); | |
383 DCHECK(tree < NUM_TREES); | |
384 return drawable_tiles_in_bin_count_[bin][tree]; | |
385 } | |
386 | |
387 void TileManager::ResetBinCounts() { | |
388 for (int i = 0; i < NUM_BINS; ++i) | |
389 for (int j = 0; j < NUM_TREES; ++j) | |
390 tiles_in_bin_count_[i][j] = drawable_tiles_in_bin_count_[i][j] = 0; | |
391 } | |
392 | |
350 void TileManager::AssignGpuMemoryToTiles() { | 393 void TileManager::AssignGpuMemoryToTiles() { |
351 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); | 394 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); |
352 // Some memory cannot be released. Figure out which. | 395 // Some memory cannot be released. Figure out which. |
353 size_t unreleasable_bytes = 0; | 396 size_t unreleasable_bytes = 0; |
354 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 397 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
355 Tile* tile = *it; | 398 Tile* tile = *it; |
356 if (!tile->managed_state().can_be_freed) | 399 if (!tile->managed_state().can_be_freed) |
357 unreleasable_bytes += tile->bytes_consumed_if_allocated(); | 400 unreleasable_bytes += tile->bytes_consumed_if_allocated(); |
358 } | 401 } |
359 | 402 |
(...skipping 12 matching lines...) Expand all Loading... | |
372 } | 415 } |
373 tiles_with_image_decoding_tasks_.clear(); | 416 tiles_with_image_decoding_tasks_.clear(); |
374 | 417 |
375 size_t bytes_left = global_state_.memory_limit_in_bytes - unreleasable_bytes; | 418 size_t bytes_left = global_state_.memory_limit_in_bytes - unreleasable_bytes; |
376 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 419 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
377 Tile* tile = *it; | 420 Tile* tile = *it; |
378 size_t tile_bytes = tile->bytes_consumed_if_allocated(); | 421 size_t tile_bytes = tile->bytes_consumed_if_allocated(); |
379 ManagedTileState& managed_tile_state = tile->managed_state(); | 422 ManagedTileState& managed_tile_state = tile->managed_state(); |
380 if (!managed_tile_state.can_be_freed) | 423 if (!managed_tile_state.can_be_freed) |
381 continue; | 424 continue; |
382 if (managed_tile_state.bin == NEVER_BIN) { | 425 if (managed_tile_state.raster_bin == NEVER_BIN) { |
383 managed_tile_state.can_use_gpu_memory = false; | 426 managed_tile_state.can_use_gpu_memory = false; |
384 FreeResourcesForTile(tile); | 427 FreeResourcesForTile(tile); |
385 continue; | 428 continue; |
386 } | 429 } |
387 if (tile_bytes > bytes_left) { | 430 if (tile_bytes > bytes_left) { |
388 managed_tile_state.can_use_gpu_memory = false; | 431 managed_tile_state.can_use_gpu_memory = false; |
389 FreeResourcesForTile(tile); | 432 FreeResourcesForTile(tile); |
390 continue; | 433 continue; |
391 } | 434 } |
392 bytes_left -= tile_bytes; | 435 bytes_left -= tile_bytes; |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
612 managed_tile_state.resource_is_being_initialized = false; | 655 managed_tile_state.resource_is_being_initialized = false; |
613 } | 656 } |
614 DispatchMoreTasks(); | 657 DispatchMoreTasks(); |
615 } | 658 } |
616 | 659 |
617 void TileManager::DidFinishTileInitialization(Tile* tile) { | 660 void TileManager::DidFinishTileInitialization(Tile* tile) { |
618 ManagedTileState& managed_tile_state = tile->managed_state(); | 661 ManagedTileState& managed_tile_state = tile->managed_state(); |
619 DCHECK(managed_tile_state.resource); | 662 DCHECK(managed_tile_state.resource); |
620 managed_tile_state.resource_is_being_initialized = false; | 663 managed_tile_state.resource_is_being_initialized = false; |
621 managed_tile_state.can_be_freed = true; | 664 managed_tile_state.can_be_freed = true; |
665 for (int i = 0; i < NUM_TREES; ++i) | |
666 drawable_tiles_in_bin_count_[managed_tile_state.bin[i]][i]++; | |
622 } | 667 } |
623 | 668 |
624 } | 669 } |
OLD | NEW |