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) { |
| 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 check_for_completed_set_pixels_pending_(false) { | 166 check_for_completed_set_pixels_pending_(false) { |
143 // Initialize all threads. | 167 // Initialize all threads. |
144 const std::string thread_name_prefix = kRasterThreadNamePrefix; | 168 const std::string thread_name_prefix = kRasterThreadNamePrefix; |
145 while (raster_threads_.size() < num_raster_threads) { | 169 while (raster_threads_.size() < num_raster_threads) { |
146 int thread_number = raster_threads_.size() + 1; | 170 int thread_number = raster_threads_.size() + 1; |
147 scoped_ptr<RasterThread> thread = make_scoped_ptr( | 171 scoped_ptr<RasterThread> thread = make_scoped_ptr( |
148 new RasterThread(thread_name_prefix + | 172 new RasterThread(thread_name_prefix + |
149 StringPrintf("Worker%d", thread_number).c_str())); | 173 StringPrintf("Worker%d", thread_number).c_str())); |
150 raster_threads_.append(thread.Pass()); | 174 raster_threads_.append(thread.Pass()); |
151 } | 175 } |
| 176 |
| 177 ResetBinCounts(); |
152 } | 178 } |
153 | 179 |
154 TileManager::~TileManager() { | 180 TileManager::~TileManager() { |
155 // Reset global state and manage. This should cause | 181 // Reset global state and manage. This should cause |
156 // our memory usage to drop to zero. | 182 // our memory usage to drop to zero. |
157 global_state_ = GlobalStateThatImpactsTilePriority(); | 183 global_state_ = GlobalStateThatImpactsTilePriority(); |
158 AssignGpuMemoryToTiles(); | 184 AssignGpuMemoryToTiles(); |
159 // This should finish all pending raster tasks and release any | 185 // This should finish all pending raster tasks and release any |
160 // uninitialized resources. | 186 // uninitialized resources. |
161 raster_threads_.clear(); | 187 raster_threads_.clear(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 return; | 243 return; |
218 client_->ScheduleCheckForCompletedSetPixels(); | 244 client_->ScheduleCheckForCompletedSetPixels(); |
219 check_for_completed_set_pixels_pending_ = true; | 245 check_for_completed_set_pixels_pending_ = true; |
220 } | 246 } |
221 | 247 |
222 class BinComparator { | 248 class BinComparator { |
223 public: | 249 public: |
224 bool operator() (const Tile* a, const Tile* b) const { | 250 bool operator() (const Tile* a, const Tile* b) const { |
225 const ManagedTileState& ams = a->managed_state(); | 251 const ManagedTileState& ams = a->managed_state(); |
226 const ManagedTileState& bms = b->managed_state(); | 252 const ManagedTileState& bms = b->managed_state(); |
227 if (ams.bin != bms.bin) | 253 if (ams.raster_bin != bms.raster_bin) |
228 return ams.bin < bms.bin; | 254 return ams.raster_bin < bms.raster_bin; |
229 | 255 |
230 if (ams.resolution != bms.resolution) | 256 if (ams.resolution != bms.resolution) |
231 return ams.resolution < ams.resolution; | 257 return ams.resolution < ams.resolution; |
232 | 258 |
233 return | 259 return |
234 ams.time_to_needed_in_seconds < | 260 ams.time_to_needed_in_seconds < |
235 bms.time_to_needed_in_seconds; | 261 bms.time_to_needed_in_seconds; |
236 } | 262 } |
237 }; | 263 }; |
238 | 264 |
239 void TileManager::ManageTiles() { | 265 void TileManager::ManageTiles() { |
240 TRACE_EVENT0("cc", "TileManager::ManageTiles"); | 266 TRACE_EVENT0("cc", "TileManager::ManageTiles"); |
241 manage_tiles_pending_ = false; | 267 manage_tiles_pending_ = false; |
242 ++manage_tiles_call_count_; | 268 ++manage_tiles_call_count_; |
243 | 269 |
244 // The amount of time for which we want to have prepainting coverage. | 270 const bool smoothness_takes_priority = |
245 const double prepainting_window_time_seconds = 1.0; | 271 global_state_.smoothness_takes_priority; |
246 const double backfling_guard_distance_pixels = 314.0; | |
247 | 272 |
248 const bool smoothness_takes_priority = global_state_.smoothness_takes_priority
; | 273 // For each tree, bin into different categories of tiles. |
249 | |
250 // Bin into three categories of tiles: things we need now, things we need soon
, and eventually | |
251 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 274 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
252 Tile* tile = *it; | 275 Tile* tile = *it; |
253 ManagedTileState& mts = tile->managed_state(); | 276 ManagedTileState& mts = tile->managed_state(); |
| 277 mts.bin[ACTIVE_TREE] = BinFromTilePriority(tile->priority(ACTIVE_TREE)); |
| 278 mts.bin[PENDING_TREE] = BinFromTilePriority(tile->priority(PENDING_TREE)); |
| 279 |
254 TilePriority prio; | 280 TilePriority prio; |
255 if (smoothness_takes_priority) | 281 if (smoothness_takes_priority) |
256 prio = tile->priority(ACTIVE_TREE); | 282 prio = tile->priority(ACTIVE_TREE); |
257 else | 283 else |
258 prio = tile->combined_priority(); | 284 prio = tile->combined_priority(); |
259 | 285 |
260 mts.resolution = prio.resolution; | 286 mts.resolution = prio.resolution; |
261 mts.time_to_needed_in_seconds = prio.time_to_needed_in_seconds(); | 287 mts.time_to_needed_in_seconds = prio.time_to_needed_in_seconds(); |
262 | 288 mts.raster_bin = BinFromTilePriority(prio); |
263 if (mts.time_to_needed_in_seconds == | |
264 std::numeric_limits<float>::max()) { | |
265 mts.bin = NEVER_BIN; | |
266 continue; | |
267 } | |
268 | |
269 if (mts.resolution == NON_IDEAL_RESOLUTION) { | |
270 mts.bin = EVENTUALLY_BIN; | |
271 continue; | |
272 } | |
273 | |
274 if (mts.time_to_needed_in_seconds == 0 || | |
275 prio.distance_to_visible_in_pixels < backfling_guard_distance_pixels) { | |
276 mts.bin = NOW_BIN; | |
277 continue; | |
278 } | |
279 | |
280 if (prio.time_to_needed_in_seconds() < prepainting_window_time_seconds) { | |
281 mts.bin = SOON_BIN; | |
282 continue; | |
283 } | |
284 | |
285 mts.bin = EVENTUALLY_BIN; | |
286 } | 289 } |
287 | 290 |
288 // Memory limit policy works by mapping some bin states to the NEVER bin. | 291 // Memory limit policy works by mapping some bin states to the NEVER bin. |
289 TileManagerBin bin_map[NUM_BINS]; | 292 TileManagerBin bin_map[NUM_BINS]; |
290 if (global_state_.memory_limit_policy == ALLOW_NOTHING) { | 293 if (global_state_.memory_limit_policy == ALLOW_NOTHING) { |
291 bin_map[NOW_BIN] = NEVER_BIN; | 294 bin_map[NOW_BIN] = NEVER_BIN; |
292 bin_map[SOON_BIN] = NEVER_BIN; | 295 bin_map[SOON_BIN] = NEVER_BIN; |
293 bin_map[EVENTUALLY_BIN] = NEVER_BIN; | 296 bin_map[EVENTUALLY_BIN] = NEVER_BIN; |
294 bin_map[NEVER_BIN] = NEVER_BIN; | 297 bin_map[NEVER_BIN] = NEVER_BIN; |
295 } else if (global_state_.memory_limit_policy == ALLOW_ABSOLUTE_MINIMUM) { | 298 } else if (global_state_.memory_limit_policy == ALLOW_ABSOLUTE_MINIMUM) { |
296 bin_map[NOW_BIN] = NOW_BIN; | 299 bin_map[NOW_BIN] = NOW_BIN; |
297 bin_map[SOON_BIN] = NEVER_BIN; | 300 bin_map[SOON_BIN] = NEVER_BIN; |
298 bin_map[EVENTUALLY_BIN] = NEVER_BIN; | 301 bin_map[EVENTUALLY_BIN] = NEVER_BIN; |
299 bin_map[NEVER_BIN] = NEVER_BIN; | 302 bin_map[NEVER_BIN] = NEVER_BIN; |
300 } else if (global_state_.memory_limit_policy == ALLOW_PREPAINT_ONLY) { | 303 } else if (global_state_.memory_limit_policy == ALLOW_PREPAINT_ONLY) { |
301 bin_map[NOW_BIN] = NOW_BIN; | 304 bin_map[NOW_BIN] = NOW_BIN; |
302 bin_map[SOON_BIN] = SOON_BIN; | 305 bin_map[SOON_BIN] = SOON_BIN; |
303 bin_map[EVENTUALLY_BIN] = NEVER_BIN; | 306 bin_map[EVENTUALLY_BIN] = NEVER_BIN; |
304 bin_map[NEVER_BIN] = NEVER_BIN; | 307 bin_map[NEVER_BIN] = NEVER_BIN; |
305 } else { | 308 } else { |
306 bin_map[NOW_BIN] = NOW_BIN; | 309 bin_map[NOW_BIN] = NOW_BIN; |
307 bin_map[SOON_BIN] = SOON_BIN; | 310 bin_map[SOON_BIN] = SOON_BIN; |
308 bin_map[EVENTUALLY_BIN] = EVENTUALLY_BIN; | 311 bin_map[EVENTUALLY_BIN] = EVENTUALLY_BIN; |
309 bin_map[NEVER_BIN] = NEVER_BIN; | 312 bin_map[NEVER_BIN] = NEVER_BIN; |
310 } | 313 } |
311 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 314 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
312 Tile* tile = *it; | 315 Tile* tile = *it; |
313 TileManagerBin bin = bin_map[tile->managed_state().bin]; | 316 ManagedTileState& mts = tile->managed_state(); |
314 tile->managed_state().bin = bin; | 317 mts.bin[ACTIVE_TREE] = bin_map[mts.bin[ACTIVE_TREE]]; |
| 318 mts.bin[PENDING_TREE] = bin_map[mts.bin[PENDING_TREE]]; |
| 319 mts.raster_bin = bin_map[mts.raster_bin]; |
| 320 } |
| 321 |
| 322 // Update bin counts. |
| 323 ResetBinCounts(); |
| 324 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| 325 Tile* tile = *it; |
| 326 ManagedTileState& mts = tile->managed_state(); |
| 327 for (int i = 0; i < NUM_TREES; ++i) |
| 328 tiles_in_bin_count_[mts.bin[i]][i]++; |
| 329 |
| 330 // Increment drawable count if GetResourceId() doesn't return 0. |
| 331 if (tile->GetResourceId()) { |
| 332 for (int i = 0; i < NUM_TREES; ++i) |
| 333 drawable_tiles_in_bin_count_[mts.bin[i]][i]++; |
| 334 } |
315 } | 335 } |
316 | 336 |
317 // Sort by bin. | 337 // Sort by bin. |
318 std::sort(tiles_.begin(), tiles_.end(), BinComparator()); | 338 std::sort(tiles_.begin(), tiles_.end(), BinComparator()); |
319 | 339 |
320 // Assign gpu memory and determine what tiles need to be rasterized. | 340 // Assign gpu memory and determine what tiles need to be rasterized. |
321 AssignGpuMemoryToTiles(); | 341 AssignGpuMemoryToTiles(); |
322 | 342 |
323 // Finally, kick the rasterizer. | 343 // Finally, kick the rasterizer. |
324 DispatchMoreTasks(); | 344 DispatchMoreTasks(); |
(...skipping 15 matching lines...) Expand all Loading... |
340 | 360 |
341 // It's now safe to release the pixel buffer. | 361 // It's now safe to release the pixel buffer. |
342 resource_pool_->resource_provider()->releasePixelBuffer( | 362 resource_pool_->resource_provider()->releasePixelBuffer( |
343 tile->managed_state().resource->id()); | 363 tile->managed_state().resource->id()); |
344 | 364 |
345 DidFinishTileInitialization(tile); | 365 DidFinishTileInitialization(tile); |
346 tiles_with_pending_set_pixels_.pop(); | 366 tiles_with_pending_set_pixels_.pop(); |
347 } | 367 } |
348 } | 368 } |
349 | 369 |
350 void TileManager::renderingStats(RenderingStats* stats) { | 370 void TileManager::GetRenderingStats(RenderingStats* stats) { |
351 stats->totalRasterizeTimeInSeconds = | 371 stats->totalRasterizeTimeInSeconds = |
352 rendering_stats_.totalRasterizeTimeInSeconds; | 372 rendering_stats_.totalRasterizeTimeInSeconds; |
353 stats->totalPixelsRasterized = rendering_stats_.totalPixelsRasterized; | 373 stats->totalPixelsRasterized = rendering_stats_.totalPixelsRasterized; |
354 stats->totalDeferredImageDecodeCount = | 374 stats->totalDeferredImageDecodeCount = |
355 rendering_stats_.totalDeferredImageDecodeCount; | 375 rendering_stats_.totalDeferredImageDecodeCount; |
356 stats->totalDeferredImageCacheHitCount = | 376 stats->totalDeferredImageCacheHitCount = |
357 rendering_stats_.totalDeferredImageCacheHitCount; | 377 rendering_stats_.totalDeferredImageCacheHitCount; |
358 stats->totalImageGatheringCount = rendering_stats_.totalImageGatheringCount; | 378 stats->totalImageGatheringCount = rendering_stats_.totalImageGatheringCount; |
359 stats->totalDeferredImageDecodeTimeInSeconds = | 379 stats->totalDeferredImageDecodeTimeInSeconds = |
360 rendering_stats_.totalDeferredImageDecodeTimeInSeconds; | 380 rendering_stats_.totalDeferredImageDecodeTimeInSeconds; |
361 stats->totalImageGatheringTimeInSeconds = | 381 stats->totalImageGatheringTimeInSeconds = |
362 rendering_stats_.totalImageGatheringTimeInSeconds; | 382 rendering_stats_.totalImageGatheringTimeInSeconds; |
363 } | 383 } |
364 | 384 |
| 385 int TileManager::GetTilesInBinCount(TileManagerBin bin, WhichTree tree) { |
| 386 DCHECK(bin >= 0); |
| 387 DCHECK(bin < NUM_BINS); |
| 388 DCHECK(tree >= 0); |
| 389 DCHECK(tree < NUM_TREES); |
| 390 return tiles_in_bin_count_[bin][tree]; |
| 391 } |
| 392 |
| 393 int TileManager::GetDrawableTilesInBinCount( |
| 394 TileManagerBin bin, WhichTree tree) { |
| 395 DCHECK(bin >= 0); |
| 396 DCHECK(bin < NUM_BINS); |
| 397 DCHECK(tree >= 0); |
| 398 DCHECK(tree < NUM_TREES); |
| 399 return drawable_tiles_in_bin_count_[bin][tree]; |
| 400 } |
| 401 |
| 402 void TileManager::ResetBinCounts() { |
| 403 for (int i = 0; i < NUM_BINS; ++i) |
| 404 for (int j = 0; j < NUM_TREES; ++j) |
| 405 tiles_in_bin_count_[i][j] = drawable_tiles_in_bin_count_[i][j] = 0; |
| 406 } |
| 407 |
365 void TileManager::AssignGpuMemoryToTiles() { | 408 void TileManager::AssignGpuMemoryToTiles() { |
366 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); | 409 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); |
367 // Some memory cannot be released. Figure out which. | 410 // Some memory cannot be released. Figure out which. |
368 size_t unreleasable_bytes = 0; | 411 size_t unreleasable_bytes = 0; |
369 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 412 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
370 Tile* tile = *it; | 413 Tile* tile = *it; |
371 if (!tile->managed_state().can_be_freed) | 414 if (!tile->managed_state().can_be_freed) |
372 unreleasable_bytes += tile->bytes_consumed_if_allocated(); | 415 unreleasable_bytes += tile->bytes_consumed_if_allocated(); |
373 } | 416 } |
374 | 417 |
375 // Now give memory out to the tiles until we're out, and build | 418 // Now give memory out to the tiles until we're out, and build |
376 // the needs-to-be-rasterized queue. | 419 // the needs-to-be-rasterized queue. |
377 tiles_that_need_to_be_rasterized_.erase( | 420 tiles_that_need_to_be_rasterized_.erase( |
378 tiles_that_need_to_be_rasterized_.begin(), | 421 tiles_that_need_to_be_rasterized_.begin(), |
379 tiles_that_need_to_be_rasterized_.end()); | 422 tiles_that_need_to_be_rasterized_.end()); |
380 | 423 |
381 // Reset the image decoding list so that we don't mess up with tile | 424 // Reset the image decoding list so that we don't mess up with tile |
382 // priorities. Tiles will be added to the image decoding list again | 425 // priorities. Tiles will be added to the image decoding list again |
383 // when DispatchMoreTasks() is called. | 426 // when DispatchMoreTasks() is called. |
384 tiles_with_image_decoding_tasks_.clear(); | 427 tiles_with_image_decoding_tasks_.clear(); |
385 | 428 |
386 size_t bytes_left = global_state_.memory_limit_in_bytes - unreleasable_bytes; | 429 size_t bytes_left = global_state_.memory_limit_in_bytes - unreleasable_bytes; |
387 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 430 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
388 Tile* tile = *it; | 431 Tile* tile = *it; |
389 size_t tile_bytes = tile->bytes_consumed_if_allocated(); | 432 size_t tile_bytes = tile->bytes_consumed_if_allocated(); |
390 ManagedTileState& managed_tile_state = tile->managed_state(); | 433 ManagedTileState& managed_tile_state = tile->managed_state(); |
391 if (!managed_tile_state.can_be_freed) | 434 if (!managed_tile_state.can_be_freed) |
392 continue; | 435 continue; |
393 if (managed_tile_state.bin == NEVER_BIN) { | 436 if (managed_tile_state.raster_bin == NEVER_BIN) { |
394 managed_tile_state.can_use_gpu_memory = false; | 437 managed_tile_state.can_use_gpu_memory = false; |
395 FreeResourcesForTile(tile); | 438 FreeResourcesForTile(tile); |
396 continue; | 439 continue; |
397 } | 440 } |
398 if (tile_bytes > bytes_left) { | 441 if (tile_bytes > bytes_left) { |
399 managed_tile_state.can_use_gpu_memory = false; | 442 managed_tile_state.can_use_gpu_memory = false; |
400 FreeResourcesForTile(tile); | 443 FreeResourcesForTile(tile); |
401 continue; | 444 continue; |
402 } | 445 } |
403 bytes_left -= tile_bytes; | 446 bytes_left -= tile_bytes; |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 managed_tile_state.resource_is_being_initialized = false; | 680 managed_tile_state.resource_is_being_initialized = false; |
638 } | 681 } |
639 DispatchMoreTasks(); | 682 DispatchMoreTasks(); |
640 } | 683 } |
641 | 684 |
642 void TileManager::DidFinishTileInitialization(Tile* tile) { | 685 void TileManager::DidFinishTileInitialization(Tile* tile) { |
643 ManagedTileState& managed_tile_state = tile->managed_state(); | 686 ManagedTileState& managed_tile_state = tile->managed_state(); |
644 DCHECK(managed_tile_state.resource); | 687 DCHECK(managed_tile_state.resource); |
645 managed_tile_state.resource_is_being_initialized = false; | 688 managed_tile_state.resource_is_being_initialized = false; |
646 managed_tile_state.can_be_freed = true; | 689 managed_tile_state.can_be_freed = true; |
| 690 for (int i = 0; i < NUM_TREES; ++i) |
| 691 drawable_tiles_in_bin_count_[managed_tile_state.bin[i]][i]++; |
647 } | 692 } |
648 | 693 |
649 } | 694 } |
OLD | NEW |