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/resources/tile_manager.h" | 5 #include "cc/resources/tile_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 skia::RefPtr<SkPixelRef> pixel_ref_; | 239 skia::RefPtr<SkPixelRef> pixel_ref_; |
240 int layer_id_; | 240 int layer_id_; |
241 RenderingStatsInstrumentation* rendering_stats_; | 241 RenderingStatsInstrumentation* rendering_stats_; |
242 const base::Callback<void(bool was_canceled)> reply_; | 242 const base::Callback<void(bool was_canceled)> reply_; |
243 | 243 |
244 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); | 244 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); |
245 }; | 245 }; |
246 | 246 |
247 const size_t kScheduledRasterTasksLimit = 32u; | 247 const size_t kScheduledRasterTasksLimit = 32u; |
248 | 248 |
249 // Memory limit policy works by mapping some bin states to the NEVER bin. | |
250 const ManagedTileBin kBinPolicyMap[NUM_TILE_MEMORY_LIMIT_POLICIES][NUM_BINS] = { | |
251 // [ALLOW_NOTHING] | |
252 {NEVER_BIN, // [NOW_AND_READY_TO_DRAW_BIN] | |
253 NEVER_BIN, // [NOW_BIN] | |
254 NEVER_BIN, // [SOON_BIN] | |
255 NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] | |
256 NEVER_BIN, // [EVENTUALLY_BIN] | |
257 NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN] | |
258 NEVER_BIN, // [AT_LAST_BIN] | |
259 NEVER_BIN // [NEVER_BIN] | |
260 }, | |
261 // [ALLOW_ABSOLUTE_MINIMUM] | |
262 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] | |
263 NOW_BIN, // [NOW_BIN] | |
264 NEVER_BIN, // [SOON_BIN] | |
265 NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] | |
266 NEVER_BIN, // [EVENTUALLY_BIN] | |
267 NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN] | |
268 NEVER_BIN, // [AT_LAST_BIN] | |
269 NEVER_BIN // [NEVER_BIN] | |
270 }, | |
271 // [ALLOW_PREPAINT_ONLY] | |
272 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] | |
273 NOW_BIN, // [NOW_BIN] | |
274 SOON_BIN, // [SOON_BIN] | |
275 NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] | |
276 NEVER_BIN, // [EVENTUALLY_BIN] | |
277 NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN] | |
278 NEVER_BIN, // [AT_LAST_BIN] | |
279 NEVER_BIN // [NEVER_BIN] | |
280 }, | |
281 // [ALLOW_ANYTHING] | |
282 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] | |
283 NOW_BIN, // [NOW_BIN] | |
284 SOON_BIN, // [SOON_BIN] | |
285 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] | |
286 EVENTUALLY_BIN, // [EVENTUALLY_BIN] | |
287 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN] | |
288 AT_LAST_BIN, // [AT_LAST_BIN] | |
289 NEVER_BIN // [NEVER_BIN] | |
290 }}; | |
291 | |
292 // Ready to draw works by mapping NOW_BIN to NOW_AND_READY_TO_DRAW_BIN. | |
293 const ManagedTileBin kBinReadyToDrawMap[2][NUM_BINS] = { | |
294 // Not ready | |
295 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] | |
296 NOW_BIN, // [NOW_BIN] | |
297 SOON_BIN, // [SOON_BIN] | |
298 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] | |
299 EVENTUALLY_BIN, // [EVENTUALLY_BIN] | |
300 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN] | |
301 AT_LAST_BIN, // [AT_LAST_BIN] | |
302 NEVER_BIN // [NEVER_BIN] | |
303 }, | |
304 // Ready | |
305 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] | |
306 NOW_AND_READY_TO_DRAW_BIN, // [NOW_BIN] | |
307 SOON_BIN, // [SOON_BIN] | |
308 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] | |
309 EVENTUALLY_BIN, // [EVENTUALLY_BIN] | |
310 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN] | |
311 AT_LAST_BIN, // [AT_LAST_BIN] | |
312 NEVER_BIN // [NEVER_BIN] | |
313 }}; | |
314 | |
315 // Active works by mapping some bin stats to equivalent _ACTIVE_BIN state. | |
316 const ManagedTileBin kBinIsActiveMap[2][NUM_BINS] = { | |
317 // Inactive | |
318 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] | |
319 NOW_BIN, // [NOW_BIN] | |
320 SOON_BIN, // [SOON_BIN] | |
321 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] | |
322 EVENTUALLY_BIN, // [EVENTUALLY_BIN] | |
323 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN] | |
324 AT_LAST_BIN, // [AT_LAST_BIN] | |
325 NEVER_BIN // [NEVER_BIN] | |
326 }, | |
327 // Active | |
328 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] | |
329 NOW_BIN, // [NOW_BIN] | |
330 SOON_BIN, // [SOON_BIN] | |
331 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] | |
332 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_BIN] | |
333 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN] | |
334 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_BIN] | |
335 NEVER_BIN // [NEVER_BIN] | |
336 }}; | |
337 | |
338 // Determine bin based on three categories of tiles: things we need now, | |
339 // things we need soon, and eventually. | |
340 inline ManagedTileBin BinFromTilePriority(const TilePriority& prio) { | |
341 const float kBackflingGuardDistancePixels = 314.0f; | |
342 | |
343 if (prio.priority_bin == TilePriority::NOW) | |
344 return NOW_BIN; | |
345 | |
346 if (prio.priority_bin == TilePriority::SOON || | |
347 prio.distance_to_visible < kBackflingGuardDistancePixels) | |
348 return SOON_BIN; | |
349 | |
350 if (prio.distance_to_visible == std::numeric_limits<float>::infinity()) | |
351 return NEVER_BIN; | |
352 | |
353 return EVENTUALLY_BIN; | |
354 } | |
355 | |
356 } // namespace | 249 } // namespace |
357 | 250 |
358 RasterTaskCompletionStats::RasterTaskCompletionStats() | 251 RasterTaskCompletionStats::RasterTaskCompletionStats() |
359 : completed_count(0u), canceled_count(0u) {} | 252 : completed_count(0u), canceled_count(0u) {} |
360 | 253 |
361 scoped_ptr<base::Value> RasterTaskCompletionStatsAsValue( | 254 scoped_ptr<base::Value> RasterTaskCompletionStatsAsValue( |
362 const RasterTaskCompletionStats& stats) { | 255 const RasterTaskCompletionStats& stats) { |
363 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | 256 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
364 state->SetInteger("completed_count", stats.completed_count); | 257 state->SetInteger("completed_count", stats.completed_count); |
365 state->SetInteger("canceled_count", stats.canceled_count); | 258 state->SetInteger("canceled_count", stats.canceled_count); |
(...skipping 21 matching lines...) Expand all Loading... | |
387 TileManager::TileManager( | 280 TileManager::TileManager( |
388 TileManagerClient* client, | 281 TileManagerClient* client, |
389 ResourcePool* resource_pool, | 282 ResourcePool* resource_pool, |
390 Rasterizer* rasterizer, | 283 Rasterizer* rasterizer, |
391 Rasterizer* gpu_rasterizer, | 284 Rasterizer* gpu_rasterizer, |
392 size_t max_raster_usage_bytes, | 285 size_t max_raster_usage_bytes, |
393 bool use_rasterize_on_demand, | 286 bool use_rasterize_on_demand, |
394 RenderingStatsInstrumentation* rendering_stats_instrumentation) | 287 RenderingStatsInstrumentation* rendering_stats_instrumentation) |
395 : client_(client), | 288 : client_(client), |
396 resource_pool_(resource_pool), | 289 resource_pool_(resource_pool), |
397 prioritized_tiles_dirty_(false), | |
398 all_tiles_that_need_to_be_rasterized_have_memory_(true), | 290 all_tiles_that_need_to_be_rasterized_have_memory_(true), |
399 all_tiles_required_for_activation_have_memory_(true), | 291 all_tiles_required_for_activation_have_memory_(true), |
400 memory_required_bytes_(0), | |
401 memory_nice_to_have_bytes_(0), | |
402 bytes_releasable_(0), | 292 bytes_releasable_(0), |
403 resources_releasable_(0), | 293 resources_releasable_(0), |
404 max_raster_usage_bytes_(max_raster_usage_bytes), | 294 max_raster_usage_bytes_(max_raster_usage_bytes), |
405 ever_exceeded_memory_budget_(false), | 295 ever_exceeded_memory_budget_(false), |
406 rendering_stats_instrumentation_(rendering_stats_instrumentation), | 296 rendering_stats_instrumentation_(rendering_stats_instrumentation), |
407 did_initialize_visible_tile_(false), | 297 did_initialize_visible_tile_(false), |
408 did_check_for_completed_tasks_since_last_schedule_tasks_(true), | 298 did_check_for_completed_tasks_since_last_schedule_tasks_(true), |
409 use_rasterize_on_demand_(use_rasterize_on_demand) { | 299 use_rasterize_on_demand_(use_rasterize_on_demand) { |
410 Rasterizer* rasterizers[NUM_RASTERIZER_TYPES] = { | 300 Rasterizer* rasterizers[NUM_RASTERIZER_TYPES] = { |
411 rasterizer, // RASTERIZER_TYPE_DEFAULT | 301 rasterizer, // RASTERIZER_TYPE_DEFAULT |
(...skipping 25 matching lines...) Expand all Loading... | |
437 | 327 |
438 for (std::vector<PictureLayerImpl*>::iterator it = layers_.begin(); | 328 for (std::vector<PictureLayerImpl*>::iterator it = layers_.begin(); |
439 it != layers_.end(); | 329 it != layers_.end(); |
440 ++it) { | 330 ++it) { |
441 (*it)->DidUnregisterLayer(); | 331 (*it)->DidUnregisterLayer(); |
442 } | 332 } |
443 layers_.clear(); | 333 layers_.clear(); |
444 } | 334 } |
445 | 335 |
446 void TileManager::Release(Tile* tile) { | 336 void TileManager::Release(Tile* tile) { |
447 prioritized_tiles_dirty_ = true; | |
448 released_tiles_.push_back(tile); | 337 released_tiles_.push_back(tile); |
449 } | 338 } |
450 | 339 |
451 void TileManager::DidChangeTilePriority(Tile* tile) { | |
452 prioritized_tiles_dirty_ = true; | |
453 } | |
454 | |
455 bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const { | 340 bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const { |
456 return global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY; | 341 return global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY; |
457 } | 342 } |
458 | 343 |
459 void TileManager::CleanUpReleasedTiles() { | 344 void TileManager::CleanUpReleasedTiles() { |
460 for (std::vector<Tile*>::iterator it = released_tiles_.begin(); | 345 for (std::vector<Tile*>::iterator it = released_tiles_.begin(); |
461 it != released_tiles_.end(); | 346 it != released_tiles_.end(); |
462 ++it) { | 347 ++it) { |
463 Tile* tile = *it; | 348 Tile* tile = *it; |
464 ManagedTileState& mts = tile->managed_state(); | 349 ManagedTileState& mts = tile->managed_state(); |
(...skipping 13 matching lines...) Expand all Loading... | |
478 used_layer_counts_.erase(layer_it); | 363 used_layer_counts_.erase(layer_it); |
479 image_decode_tasks_.erase(tile->layer_id()); | 364 image_decode_tasks_.erase(tile->layer_id()); |
480 } | 365 } |
481 | 366 |
482 delete tile; | 367 delete tile; |
483 } | 368 } |
484 | 369 |
485 released_tiles_.clear(); | 370 released_tiles_.clear(); |
486 } | 371 } |
487 | 372 |
488 void TileManager::UpdatePrioritizedTileSetIfNeeded() { | |
489 if (!prioritized_tiles_dirty_) | |
490 return; | |
491 | |
492 CleanUpReleasedTiles(); | |
493 | |
494 prioritized_tiles_.Clear(); | |
495 GetTilesWithAssignedBins(&prioritized_tiles_); | |
496 prioritized_tiles_dirty_ = false; | |
497 } | |
498 | |
499 void TileManager::DidFinishRunningTasks() { | 373 void TileManager::DidFinishRunningTasks() { |
500 TRACE_EVENT0("cc", "TileManager::DidFinishRunningTasks"); | 374 TRACE_EVENT0("cc", "TileManager::DidFinishRunningTasks"); |
501 | 375 |
502 bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() > | 376 bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() > |
503 global_state_.soft_memory_limit_in_bytes; | 377 global_state_.soft_memory_limit_in_bytes; |
504 | 378 |
505 // When OOM, keep re-assigning memory until we reach a steady state | 379 // When OOM, keep re-assigning memory until we reach a steady state |
506 // where top-priority tiles are initialized. | 380 // where top-priority tiles are initialized. |
507 if (all_tiles_that_need_to_be_rasterized_have_memory_ && | 381 if (all_tiles_that_need_to_be_rasterized_have_memory_ && |
508 !memory_usage_above_limit) | 382 !memory_usage_above_limit) |
509 return; | 383 return; |
510 | 384 |
511 rasterizer_delegate_->CheckForCompletedTasks(); | 385 rasterizer_delegate_->CheckForCompletedTasks(); |
512 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 386 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
513 | 387 |
514 TileVector tiles_that_need_to_be_rasterized; | 388 TileVector tiles_that_need_to_be_rasterized; |
515 AssignGpuMemoryToTiles(&prioritized_tiles_, | 389 AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized); |
516 &tiles_that_need_to_be_rasterized); | |
517 | 390 |
518 // |tiles_that_need_to_be_rasterized| will be empty when we reach a | 391 // |tiles_that_need_to_be_rasterized| will be empty when we reach a |
519 // steady memory state. Keep scheduling tasks until we reach this state. | 392 // steady memory state. Keep scheduling tasks until we reach this state. |
520 if (!tiles_that_need_to_be_rasterized.empty()) { | 393 if (!tiles_that_need_to_be_rasterized.empty()) { |
521 ScheduleTasks(tiles_that_need_to_be_rasterized); | 394 ScheduleTasks(tiles_that_need_to_be_rasterized); |
522 return; | 395 return; |
523 } | 396 } |
524 | 397 |
525 resource_pool_->ReduceResourceUsage(); | 398 resource_pool_->ReduceResourceUsage(); |
526 | 399 |
(...skipping 29 matching lines...) Expand all Loading... | |
556 // activation are initialized when no tiles are OOM. We need to | 429 // activation are initialized when no tiles are OOM. We need to |
557 // wait for DidFinishRunningTasks() to be called, try to re-assign | 430 // wait for DidFinishRunningTasks() to be called, try to re-assign |
558 // memory and in worst case use on-demand raster when tiles | 431 // memory and in worst case use on-demand raster when tiles |
559 // required for activation are OOM. | 432 // required for activation are OOM. |
560 if (!all_tiles_required_for_activation_have_memory_) | 433 if (!all_tiles_required_for_activation_have_memory_) |
561 return; | 434 return; |
562 | 435 |
563 client_->NotifyReadyToActivate(); | 436 client_->NotifyReadyToActivate(); |
564 } | 437 } |
565 | 438 |
566 void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) { | |
567 TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins"); | |
568 | |
569 // Compute new stats to be return by GetMemoryStats(). | |
570 memory_required_bytes_ = 0; | |
571 memory_nice_to_have_bytes_ = 0; | |
572 | |
573 const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy; | |
574 const TreePriority tree_priority = global_state_.tree_priority; | |
575 | |
576 // For each tree, bin into different categories of tiles. | |
577 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | |
578 Tile* tile = it->second; | |
579 ManagedTileState& mts = tile->managed_state(); | |
580 | |
581 const ManagedTileState::TileVersion& tile_version = | |
582 tile->GetTileVersionForDrawing(); | |
583 bool tile_is_ready_to_draw = tile_version.IsReadyToDraw(); | |
584 bool tile_is_active = tile_is_ready_to_draw || | |
585 mts.tile_versions[mts.raster_mode].raster_task_; | |
586 | |
587 // Get the active priority and bin. | |
588 TilePriority active_priority = tile->priority(ACTIVE_TREE); | |
589 ManagedTileBin active_bin = BinFromTilePriority(active_priority); | |
590 | |
591 // Get the pending priority and bin. | |
592 TilePriority pending_priority = tile->priority(PENDING_TREE); | |
593 ManagedTileBin pending_bin = BinFromTilePriority(pending_priority); | |
594 | |
595 bool pending_is_low_res = pending_priority.resolution == LOW_RESOLUTION; | |
596 bool pending_is_non_ideal = | |
597 pending_priority.resolution == NON_IDEAL_RESOLUTION; | |
598 bool active_is_non_ideal = | |
599 active_priority.resolution == NON_IDEAL_RESOLUTION; | |
600 | |
601 // Adjust pending bin state for low res tiles. This prevents | |
602 // pending tree low-res tiles from being initialized before | |
603 // high-res tiles. | |
604 if (pending_is_low_res) | |
605 pending_bin = std::max(pending_bin, EVENTUALLY_BIN); | |
606 | |
607 // Adjust bin state based on if ready to draw. | |
608 active_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][active_bin]; | |
609 pending_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][pending_bin]; | |
610 | |
611 // Adjust bin state based on if active. | |
612 active_bin = kBinIsActiveMap[tile_is_active][active_bin]; | |
613 pending_bin = kBinIsActiveMap[tile_is_active][pending_bin]; | |
614 | |
615 // We never want to paint new non-ideal tiles, as we always have | |
616 // a high-res tile covering that content (paint that instead). | |
617 if (!tile_is_ready_to_draw && active_is_non_ideal) | |
618 active_bin = NEVER_BIN; | |
619 if (!tile_is_ready_to_draw && pending_is_non_ideal) | |
620 pending_bin = NEVER_BIN; | |
621 | |
622 // Compute combined bin. | |
623 ManagedTileBin combined_bin = std::min(active_bin, pending_bin); | |
624 | |
625 if (!tile_is_ready_to_draw || tile_version.requires_resource()) { | |
626 // The bin that the tile would have if the GPU memory manager had | |
627 // a maximally permissive policy, send to the GPU memory manager | |
628 // to determine policy. | |
629 ManagedTileBin gpu_memmgr_stats_bin = combined_bin; | |
630 if ((gpu_memmgr_stats_bin == NOW_BIN) || | |
631 (gpu_memmgr_stats_bin == NOW_AND_READY_TO_DRAW_BIN)) | |
632 memory_required_bytes_ += BytesConsumedIfAllocated(tile); | |
633 if (gpu_memmgr_stats_bin != NEVER_BIN) | |
634 memory_nice_to_have_bytes_ += BytesConsumedIfAllocated(tile); | |
635 } | |
636 | |
637 ManagedTileBin tree_bin[NUM_TREES]; | |
638 tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin]; | |
639 tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin]; | |
640 | |
641 TilePriority tile_priority; | |
642 switch (tree_priority) { | |
643 case SAME_PRIORITY_FOR_BOTH_TREES: | |
644 mts.bin = kBinPolicyMap[memory_policy][combined_bin]; | |
645 tile_priority = tile->combined_priority(); | |
646 break; | |
647 case SMOOTHNESS_TAKES_PRIORITY: | |
648 mts.bin = tree_bin[ACTIVE_TREE]; | |
649 tile_priority = active_priority; | |
650 break; | |
651 case NEW_CONTENT_TAKES_PRIORITY: | |
652 mts.bin = tree_bin[PENDING_TREE]; | |
653 tile_priority = pending_priority; | |
654 break; | |
655 } | |
656 | |
657 // Bump up the priority if we determined it's NEVER_BIN on one tree, | |
658 // but is still required on the other tree. | |
659 bool is_in_never_bin_on_both_trees = tree_bin[ACTIVE_TREE] == NEVER_BIN && | |
660 tree_bin[PENDING_TREE] == NEVER_BIN; | |
661 | |
662 if (mts.bin == NEVER_BIN && !is_in_never_bin_on_both_trees) | |
663 mts.bin = tile_is_active ? AT_LAST_AND_ACTIVE_BIN : AT_LAST_BIN; | |
664 | |
665 mts.resolution = tile_priority.resolution; | |
666 mts.priority_bin = tile_priority.priority_bin; | |
667 mts.distance_to_visible = tile_priority.distance_to_visible; | |
668 mts.required_for_activation = tile_priority.required_for_activation; | |
669 | |
670 mts.visible_and_ready_to_draw = | |
671 tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN; | |
672 | |
673 // If the tile is in NEVER_BIN and it does not have an active task, then we | |
674 // can release the resources early. If it does have the task however, we | |
675 // should keep it in the prioritized tile set to ensure that AssignGpuMemory | |
676 // can visit it. | |
677 if (mts.bin == NEVER_BIN && | |
678 !mts.tile_versions[mts.raster_mode].raster_task_) { | |
679 FreeResourcesForTile(tile); | |
680 continue; | |
681 } | |
682 | |
683 // Insert the tile into a priority set. | |
684 tiles->InsertTile(tile, mts.bin); | |
685 } | |
686 } | |
687 | |
688 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { | 439 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { |
689 TRACE_EVENT0("cc", "TileManager::ManageTiles"); | 440 TRACE_EVENT0("cc", "TileManager::ManageTiles"); |
690 | 441 |
691 // Update internal state. | 442 // Update internal state. |
692 if (state != global_state_) { | 443 global_state_ = state; |
693 global_state_ = state; | 444 |
694 prioritized_tiles_dirty_ = true; | 445 // TODO(vmpstr): See if we still need to keep tiles alive when layers release |
695 } | 446 // them. |
447 CleanUpReleasedTiles(); | |
696 | 448 |
697 // We need to call CheckForCompletedTasks() once in-between each call | 449 // We need to call CheckForCompletedTasks() once in-between each call |
698 // to ScheduleTasks() to prevent canceled tasks from being scheduled. | 450 // to ScheduleTasks() to prevent canceled tasks from being scheduled. |
699 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { | 451 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { |
700 rasterizer_delegate_->CheckForCompletedTasks(); | 452 rasterizer_delegate_->CheckForCompletedTasks(); |
701 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 453 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
702 } | 454 } |
703 | 455 |
704 UpdatePrioritizedTileSetIfNeeded(); | |
705 | |
706 TileVector tiles_that_need_to_be_rasterized; | 456 TileVector tiles_that_need_to_be_rasterized; |
707 AssignGpuMemoryToTiles(&prioritized_tiles_, | 457 AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized); |
708 &tiles_that_need_to_be_rasterized); | |
709 | 458 |
710 // Finally, schedule rasterizer tasks. | 459 // Finally, schedule rasterizer tasks. |
711 ScheduleTasks(tiles_that_need_to_be_rasterized); | 460 ScheduleTasks(tiles_that_need_to_be_rasterized); |
712 | 461 |
713 TRACE_EVENT_INSTANT1("cc", | 462 TRACE_EVENT_INSTANT1("cc", |
714 "DidManage", | 463 "DidManage", |
715 TRACE_EVENT_SCOPE_THREAD, | 464 TRACE_EVENT_SCOPE_THREAD, |
716 "state", | 465 "state", |
717 TracedValue::FromValue(BasicStateAsValue().release())); | 466 TracedValue::FromValue(BasicStateAsValue().release())); |
718 | 467 |
(...skipping 21 matching lines...) Expand all Loading... | |
740 | 489 |
741 bool did_initialize_visible_tile = did_initialize_visible_tile_; | 490 bool did_initialize_visible_tile = did_initialize_visible_tile_; |
742 did_initialize_visible_tile_ = false; | 491 did_initialize_visible_tile_ = false; |
743 return did_initialize_visible_tile; | 492 return did_initialize_visible_tile; |
744 } | 493 } |
745 | 494 |
746 void TileManager::GetMemoryStats(size_t* memory_required_bytes, | 495 void TileManager::GetMemoryStats(size_t* memory_required_bytes, |
747 size_t* memory_nice_to_have_bytes, | 496 size_t* memory_nice_to_have_bytes, |
748 size_t* memory_allocated_bytes, | 497 size_t* memory_allocated_bytes, |
749 size_t* memory_used_bytes) const { | 498 size_t* memory_used_bytes) const { |
750 *memory_required_bytes = memory_required_bytes_; | 499 *memory_required_bytes = resource_pool_->total_memory_usage_bytes(); |
751 *memory_nice_to_have_bytes = memory_nice_to_have_bytes_; | 500 *memory_nice_to_have_bytes = resource_pool_->total_memory_usage_bytes(); |
reveman
2014/04/28 19:39:18
what's our plan for computing these properly?
vmpstr
2014/04/28 20:56:42
That's a good question. There's no good way for us
reveman
2014/04/28 21:43:15
The end result is that these values are used by th
vmpstr
2014/04/28 22:44:38
Yeah that's the thing that always made me a bit he
reveman
2014/05/20 23:01:00
Doesn't have to be precise. I don't think memory_r
| |
752 *memory_allocated_bytes = resource_pool_->total_memory_usage_bytes(); | 501 *memory_allocated_bytes = resource_pool_->total_memory_usage_bytes(); |
753 *memory_used_bytes = resource_pool_->acquired_memory_usage_bytes(); | 502 *memory_used_bytes = resource_pool_->acquired_memory_usage_bytes(); |
754 } | 503 } |
755 | 504 |
756 scoped_ptr<base::Value> TileManager::BasicStateAsValue() const { | 505 scoped_ptr<base::Value> TileManager::BasicStateAsValue() const { |
757 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | 506 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
758 state->SetInteger("tile_count", tiles_.size()); | 507 state->SetInteger("tile_count", tiles_.size()); |
759 state->Set("global_state", global_state_.AsValue().release()); | 508 state->Set("global_state", global_state_.AsValue().release()); |
760 state->Set("memory_requirements", GetMemoryRequirementsAsValue().release()); | 509 state->Set("memory_requirements", GetMemoryRequirementsAsValue().release()); |
761 return state.PassAs<base::Value>(); | 510 return state.PassAs<base::Value>(); |
(...skipping 20 matching lines...) Expand all Loading... | |
782 &memory_used_bytes); | 531 &memory_used_bytes); |
783 requirements->SetInteger("memory_required_bytes", memory_required_bytes); | 532 requirements->SetInteger("memory_required_bytes", memory_required_bytes); |
784 requirements->SetInteger("memory_nice_to_have_bytes", | 533 requirements->SetInteger("memory_nice_to_have_bytes", |
785 memory_nice_to_have_bytes); | 534 memory_nice_to_have_bytes); |
786 requirements->SetInteger("memory_allocated_bytes", memory_allocated_bytes); | 535 requirements->SetInteger("memory_allocated_bytes", memory_allocated_bytes); |
787 requirements->SetInteger("memory_used_bytes", memory_used_bytes); | 536 requirements->SetInteger("memory_used_bytes", memory_used_bytes); |
788 return requirements.PassAs<base::Value>(); | 537 return requirements.PassAs<base::Value>(); |
789 } | 538 } |
790 | 539 |
791 void TileManager::AssignGpuMemoryToTiles( | 540 void TileManager::AssignGpuMemoryToTiles( |
792 PrioritizedTileSet* tiles, | |
793 TileVector* tiles_that_need_to_be_rasterized) { | 541 TileVector* tiles_that_need_to_be_rasterized) { |
794 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); | 542 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); |
795 | 543 |
796 // Maintain the list of released resources that can potentially be re-used | 544 // Maintain the list of released resources that can potentially be re-used |
797 // or deleted. | 545 // or deleted. |
798 // If this operation becomes expensive too, only do this after some | 546 // If this operation becomes expensive too, only do this after some |
799 // resource(s) was returned. Note that in that case, one also need to | 547 // resource(s) was returned. Note that in that case, one also need to |
800 // invalidate when releasing some resource from the pool. | 548 // invalidate when releasing some resource from the pool. |
801 resource_pool_->CheckBusyResources(); | 549 resource_pool_->CheckBusyResources(); |
802 | 550 |
803 // Now give memory out to the tiles until we're out, and build | 551 // Now give memory out to the tiles until we're out, and build |
804 // the needs-to-be-rasterized queue. | 552 // the needs-to-be-rasterized queue. |
805 all_tiles_that_need_to_be_rasterized_have_memory_ = true; | 553 all_tiles_that_need_to_be_rasterized_have_memory_ = true; |
806 all_tiles_required_for_activation_have_memory_ = true; | 554 all_tiles_required_for_activation_have_memory_ = true; |
807 | 555 |
808 // Cast to prevent overflow. | 556 // Cast to prevent overflow. |
809 int64 soft_bytes_available = | 557 int64 soft_bytes_available = |
810 static_cast<int64>(bytes_releasable_) + | |
811 static_cast<int64>(global_state_.soft_memory_limit_in_bytes) - | 558 static_cast<int64>(global_state_.soft_memory_limit_in_bytes) - |
812 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); | 559 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); |
813 int64 hard_bytes_available = | 560 int64 hard_bytes_available = |
814 static_cast<int64>(bytes_releasable_) + | |
815 static_cast<int64>(global_state_.hard_memory_limit_in_bytes) - | 561 static_cast<int64>(global_state_.hard_memory_limit_in_bytes) - |
816 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); | 562 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); |
817 int resources_available = resources_releasable_ + | 563 int resources_available = global_state_.num_resources_limit - |
818 global_state_.num_resources_limit - | |
819 resource_pool_->acquired_resource_count(); | 564 resource_pool_->acquired_resource_count(); |
820 size_t soft_bytes_allocatable = | 565 |
821 std::max(static_cast<int64>(0), soft_bytes_available); | 566 EvictionTileIterator eviction_it(this, global_state_.tree_priority); |
822 size_t hard_bytes_allocatable = | 567 bool evicted_tiles_required_for_activation = false; |
823 std::max(static_cast<int64>(0), hard_bytes_available); | 568 |
824 size_t resources_allocatable = std::max(0, resources_available); | 569 // Evict resources if we're OOM before processing any tiles. |
570 while (hard_bytes_available < 0 || resources_available < 0) { | |
reveman
2014/04/28 19:39:18
can you fold this into the loop below instead of d
vmpstr
2014/04/28 20:56:42
It has to be outside of the loop since the raster
reveman
2014/04/28 21:43:15
It's not clear to me why these eviction cases need
vmpstr
2014/04/28 22:44:38
I kind of reworked this a bit (I put the memory li
| |
571 if (!eviction_it) | |
572 break; | |
573 | |
574 Tile* eviction_tile = *eviction_it; | |
575 const TilePriority& eviction_priority = | |
576 eviction_tile->priority_for_tree_priority(global_state_.tree_priority); | |
577 size_t eviction_bytes_if_allocated = | |
578 BytesConsumedIfAllocated(eviction_tile); | |
579 ManagedTileState& eviction_mts = eviction_tile->managed_state(); | |
580 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { | |
581 if (eviction_mts.tile_versions[mode].resource_) { | |
582 hard_bytes_available += eviction_bytes_if_allocated; | |
583 if (eviction_priority.priority_bin != TilePriority::NOW) | |
584 soft_bytes_available += eviction_bytes_if_allocated; | |
585 resources_available++; | |
586 } | |
587 } | |
588 FreeResourcesForTile(eviction_tile); | |
589 ++eviction_it; | |
590 | |
591 evicted_tiles_required_for_activation |= | |
592 eviction_tile->required_for_activation(); | |
593 } | |
594 | |
595 int64 soft_bytes_allocatable = soft_bytes_available; | |
596 int64 hard_bytes_allocatable = hard_bytes_available; | |
597 int resources_allocatable = resources_available; | |
825 | 598 |
826 size_t bytes_that_exceeded_memory_budget = 0; | 599 size_t bytes_that_exceeded_memory_budget = 0; |
827 size_t soft_bytes_left = soft_bytes_allocatable; | 600 int64 soft_bytes_left = soft_bytes_allocatable; |
828 size_t hard_bytes_left = hard_bytes_allocatable; | 601 int64 hard_bytes_left = hard_bytes_allocatable; |
829 | 602 |
830 size_t resources_left = resources_allocatable; | 603 int* resources_left = &resources_allocatable; |
831 bool oomed_soft = false; | 604 bool oomed_soft = false; |
832 bool oomed_hard = false; | 605 bool oomed_hard = false; |
833 bool have_hit_soft_memory = false; // Soft memory comes after hard. | 606 bool have_hit_soft_memory = false; // Soft memory comes after hard. |
834 | 607 |
835 // Memory we assign to raster tasks now will be deducted from our memory | 608 // Memory we assign to raster tasks now will be deducted from our memory |
836 // in future iterations if priorities change. By assigning at most half | 609 // in future iterations if priorities change. By assigning at most half |
837 // the raster limit, we will always have another 50% left even if priorities | 610 // the raster limit, we will always have another 50% left even if priorities |
838 // change completely (assuming we check for completed/cancelled rasters | 611 // change completely (assuming we check for completed/cancelled rasters |
839 // between each call to this function). | 612 // between each call to this function). |
840 size_t max_raster_bytes = max_raster_usage_bytes_ / 2; | 613 size_t max_raster_bytes = max_raster_usage_bytes_ / 2; |
841 size_t raster_bytes = 0; | 614 size_t raster_bytes = 0; |
842 | 615 |
843 unsigned schedule_priority = 1u; | 616 unsigned schedule_priority = 1u; |
844 for (PrioritizedTileSet::Iterator it(tiles, true); it; ++it) { | 617 for (RasterTileIterator it(this, global_state_.tree_priority); it; ++it) { |
845 Tile* tile = *it; | 618 Tile* tile = *it; |
619 TilePriority priority = | |
620 tile->priority_for_tree_priority(global_state_.tree_priority); | |
621 | |
622 bool tile_violates_memory_policy = false; | |
623 switch (global_state_.memory_limit_policy) { | |
624 case ALLOW_NOTHING: | |
625 tile_violates_memory_policy = true; | |
626 break; | |
627 case ALLOW_ABSOLUTE_MINIMUM: | |
628 tile_violates_memory_policy = priority.priority_bin > TilePriority::NOW; | |
629 break; | |
630 case ALLOW_PREPAINT_ONLY: | |
631 tile_violates_memory_policy = | |
632 priority.priority_bin > TilePriority::SOON; | |
633 break; | |
634 case ALLOW_ANYTHING: | |
635 case NUM_TILE_MEMORY_LIMIT_POLICIES: | |
636 break; | |
637 } | |
638 | |
639 if (tile_violates_memory_policy) | |
640 break; | |
641 | |
846 ManagedTileState& mts = tile->managed_state(); | 642 ManagedTileState& mts = tile->managed_state(); |
847 | 643 |
848 mts.scheduled_priority = schedule_priority++; | 644 mts.scheduled_priority = schedule_priority++; |
849 | 645 |
850 mts.raster_mode = tile->DetermineOverallRasterMode(); | 646 mts.raster_mode = tile->DetermineOverallRasterMode(); |
851 | 647 |
852 ManagedTileState::TileVersion& tile_version = | 648 ManagedTileState::TileVersion& tile_version = |
853 mts.tile_versions[mts.raster_mode]; | 649 mts.tile_versions[mts.raster_mode]; |
854 | 650 |
855 // If this tile doesn't need a resource, then nothing to do. | 651 // If this version is ready to draw, then nothing to do. |
856 if (!tile_version.requires_resource()) | 652 if (tile_version.IsReadyToDraw()) |
857 continue; | 653 continue; |
858 | 654 |
859 // If the tile is not needed, free it up. | 655 const bool tile_uses_hard_limit = |
860 if (mts.bin == NEVER_BIN) { | 656 priority.priority_bin == TilePriority::NOW; |
861 FreeResourcesForTile(tile); | |
862 continue; | |
863 } | |
864 | 657 |
865 const bool tile_uses_hard_limit = mts.bin <= NOW_BIN; | |
866 const size_t bytes_if_allocated = BytesConsumedIfAllocated(tile); | 658 const size_t bytes_if_allocated = BytesConsumedIfAllocated(tile); |
867 const size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated; | 659 const size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated; |
868 const size_t tile_bytes_left = | 660 int64* tile_bytes_left = |
869 (tile_uses_hard_limit) ? hard_bytes_left : soft_bytes_left; | 661 (tile_uses_hard_limit) ? &hard_bytes_left : &soft_bytes_left; |
870 | 662 |
871 // Hard-limit is reserved for tiles that would cause a calamity | 663 // Hard-limit is reserved for tiles that would cause a calamity |
872 // if they were to go away, so by definition they are the highest | 664 // if they were to go away, so by definition they are the highest |
873 // priority memory, and must be at the front of the list. | 665 // priority memory, and must be at the front of the list. |
874 DCHECK(!(have_hit_soft_memory && tile_uses_hard_limit)); | 666 DCHECK(!(have_hit_soft_memory && tile_uses_hard_limit)); |
875 have_hit_soft_memory |= !tile_uses_hard_limit; | 667 have_hit_soft_memory |= !tile_uses_hard_limit; |
876 | 668 |
877 size_t tile_bytes = 0; | 669 int64 tile_bytes = 0; |
878 size_t tile_resources = 0; | 670 int tile_resources = 0; |
879 | 671 |
880 // It costs to maintain a resource. | 672 // It costs to maintain a resource. |
881 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { | 673 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { |
882 if (mts.tile_versions[mode].resource_) { | 674 if (mts.tile_versions[mode].resource_) { |
883 tile_bytes += bytes_if_allocated; | 675 tile_bytes += bytes_if_allocated; |
884 tile_resources++; | 676 tile_resources++; |
885 } | 677 } |
886 } | 678 } |
887 | 679 |
888 // Allow lower priority tiles with initialized resources to keep | 680 // If we don't have the required version, and it's not in flight |
889 // their memory by only assigning memory to new raster tasks if | 681 // then we'll have to pay to create a new task. |
890 // they can be scheduled. | 682 if (!tile_version.resource_ && !tile_version.raster_task_) { |
891 if (raster_bytes_if_rastered <= max_raster_bytes) { | 683 tile_bytes += bytes_if_allocated; |
892 // If we don't have the required version, and it's not in flight | 684 tile_resources++; |
893 // then we'll have to pay to create a new task. | |
894 if (!tile_version.resource_ && !tile_version.raster_task_) { | |
895 tile_bytes += bytes_if_allocated; | |
896 tile_resources++; | |
897 } | |
898 } | 685 } |
899 | 686 |
900 // Tile is OOM. | 687 // Handle OOM tiles. |
901 if (tile_bytes > tile_bytes_left || tile_resources > resources_left) { | 688 while (tile_bytes > *tile_bytes_left || tile_resources > *resources_left) { |
902 FreeResourcesForTile(tile); | 689 if (!eviction_it) |
690 break; | |
903 | 691 |
692 Tile* eviction_tile = *eviction_it; | |
693 DCHECK(eviction_tile); | |
694 | |
695 TilePriority eviction_priority = | |
696 eviction_tile->priority_for_tree_priority( | |
697 global_state_.tree_priority); | |
698 | |
699 if (!priority.IsHigherPriorityThan(eviction_priority)) | |
700 break; | |
701 | |
702 size_t eviction_tile_bytes = 0; | |
703 size_t eviction_tile_resources = 0; | |
704 size_t eviction_bytes_if_allocated = BytesConsumedIfAllocated(tile); | |
705 ManagedTileState& eviction_mts = eviction_tile->managed_state(); | |
706 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { | |
707 if (eviction_mts.tile_versions[mode].resource_) { | |
708 eviction_tile_bytes += eviction_bytes_if_allocated; | |
709 eviction_tile_resources++; | |
710 } | |
711 } | |
712 | |
713 FreeResourcesForTile(eviction_tile); | |
714 ++eviction_it; | |
715 | |
716 evicted_tiles_required_for_activation |= | |
717 eviction_tile->required_for_activation(); | |
718 | |
719 *tile_bytes_left += eviction_tile_bytes; | |
720 *resources_left += eviction_tile_resources; | |
721 } | |
722 | |
723 // Tile is still OOM. | |
724 if (tile_bytes > *tile_bytes_left || tile_resources > *resources_left) { | |
904 // This tile was already on screen and now its resources have been | 725 // This tile was already on screen and now its resources have been |
905 // released. In order to prevent checkerboarding, set this tile as | 726 // released. In order to prevent checkerboarding, set this tile as |
906 // rasterize on demand immediately. | 727 // rasterize on demand immediately. |
907 if (mts.visible_and_ready_to_draw && use_rasterize_on_demand_) | 728 if (mts.visible_and_ready_to_draw && use_rasterize_on_demand_) |
908 tile_version.set_rasterize_on_demand(); | 729 tile_version.set_rasterize_on_demand(); |
909 | 730 |
910 oomed_soft = true; | 731 oomed_soft = true; |
911 if (tile_uses_hard_limit) { | 732 if (tile_uses_hard_limit) { |
912 oomed_hard = true; | 733 oomed_hard = true; |
913 bytes_that_exceeded_memory_budget += tile_bytes; | 734 bytes_that_exceeded_memory_budget += tile_bytes; |
914 } | 735 } |
915 } else { | 736 } else { |
916 resources_left -= tile_resources; | 737 *resources_left -= tile_resources; |
917 hard_bytes_left -= tile_bytes; | 738 hard_bytes_left -= tile_bytes; |
918 soft_bytes_left = | 739 soft_bytes_left = |
919 (soft_bytes_left > tile_bytes) ? soft_bytes_left - tile_bytes : 0; | 740 (soft_bytes_left > tile_bytes) ? soft_bytes_left - tile_bytes : 0; |
920 if (tile_version.resource_) | 741 if (tile_version.resource_) |
921 continue; | 742 continue; |
922 } | 743 } |
923 | 744 |
924 DCHECK(!tile_version.resource_); | 745 DCHECK(!tile_version.resource_); |
925 | 746 |
926 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized| | 747 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized| |
927 // has reached it's limit or we've failed to assign gpu memory to this | 748 // has reached it's limit or we've failed to assign gpu memory to this |
928 // or any higher priority tile. Preventing tiles that fit into memory | 749 // or any higher priority tile. Preventing tiles that fit into memory |
929 // budget to be rasterized when higher priority tile is oom is | 750 // budget to be rasterized when higher priority tile is oom is |
930 // important for two reasons: | 751 // important for two reasons: |
931 // 1. Tile size should not impact raster priority. | 752 // 1. Tile size should not impact raster priority. |
932 // 2. Tiles with existing raster task could otherwise incorrectly | 753 // 2. Tiles with existing raster task could otherwise incorrectly |
933 // be added as they are not affected by |bytes_allocatable|. | 754 // be added as they are not affected by |bytes_allocatable|. |
934 bool can_schedule_tile = | 755 bool can_schedule_tile = |
935 !oomed_soft && raster_bytes_if_rastered <= max_raster_bytes && | 756 !oomed_soft && raster_bytes_if_rastered <= max_raster_bytes && |
936 tiles_that_need_to_be_rasterized->size() < kScheduledRasterTasksLimit; | 757 tiles_that_need_to_be_rasterized->size() < kScheduledRasterTasksLimit; |
937 | 758 |
938 if (!can_schedule_tile) { | 759 if (!can_schedule_tile) { |
939 all_tiles_that_need_to_be_rasterized_have_memory_ = false; | 760 all_tiles_that_need_to_be_rasterized_have_memory_ = false; |
940 if (tile->required_for_activation()) | 761 all_tiles_required_for_activation_have_memory_ = |
941 all_tiles_required_for_activation_have_memory_ = false; | 762 !it.HasTilesRequiredForActivation() && |
942 it.DisablePriorityOrdering(); | 763 !evicted_tiles_required_for_activation; |
943 continue; | 764 break; |
944 } | 765 } |
945 | 766 |
946 raster_bytes = raster_bytes_if_rastered; | 767 raster_bytes = raster_bytes_if_rastered; |
947 tiles_that_need_to_be_rasterized->push_back(tile); | 768 tiles_that_need_to_be_rasterized->push_back(tile); |
948 } | 769 } |
949 | 770 |
950 // OOM reporting uses hard-limit, soft-OOM is normal depending on limit. | 771 // OOM reporting uses hard-limit, soft-OOM is normal depending on limit. |
951 ever_exceeded_memory_budget_ |= oomed_hard; | 772 ever_exceeded_memory_budget_ |= oomed_hard; |
952 if (ever_exceeded_memory_budget_) { | 773 if (ever_exceeded_memory_budget_) { |
953 TRACE_COUNTER_ID2("cc", | 774 TRACE_COUNTER_ID2("cc", |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1218 content_rect, | 1039 content_rect, |
1219 opaque_rect, | 1040 opaque_rect, |
1220 contents_scale, | 1041 contents_scale, |
1221 layer_id, | 1042 layer_id, |
1222 source_frame_number, | 1043 source_frame_number, |
1223 flags)); | 1044 flags)); |
1224 DCHECK(tiles_.find(tile->id()) == tiles_.end()); | 1045 DCHECK(tiles_.find(tile->id()) == tiles_.end()); |
1225 | 1046 |
1226 tiles_[tile->id()] = tile; | 1047 tiles_[tile->id()] = tile; |
1227 used_layer_counts_[tile->layer_id()]++; | 1048 used_layer_counts_[tile->layer_id()]++; |
1228 prioritized_tiles_dirty_ = true; | |
1229 return tile; | 1049 return tile; |
1230 } | 1050 } |
1231 | 1051 |
1232 void TileManager::RegisterPictureLayerImpl(PictureLayerImpl* layer) { | 1052 void TileManager::RegisterPictureLayerImpl(PictureLayerImpl* layer) { |
1233 DCHECK(std::find(layers_.begin(), layers_.end(), layer) == layers_.end()); | 1053 DCHECK(std::find(layers_.begin(), layers_.end(), layer) == layers_.end()); |
1234 layers_.push_back(layer); | 1054 layers_.push_back(layer); |
1235 } | 1055 } |
1236 | 1056 |
1237 void TileManager::UnregisterPictureLayerImpl(PictureLayerImpl* layer) { | 1057 void TileManager::UnregisterPictureLayerImpl(PictureLayerImpl* layer) { |
1238 std::vector<PictureLayerImpl*>::iterator it = | 1058 std::vector<PictureLayerImpl*>::iterator it = |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1315 | 1135 |
1316 if (paired_iterator.PeekTile(tree_priority_) != NULL) { | 1136 if (paired_iterator.PeekTile(tree_priority_) != NULL) { |
1317 paired_iterators_.push_back(paired_iterator); | 1137 paired_iterators_.push_back(paired_iterator); |
1318 iterator_heap_.push_back(&paired_iterators_.back()); | 1138 iterator_heap_.push_back(&paired_iterators_.back()); |
1319 } | 1139 } |
1320 } | 1140 } |
1321 | 1141 |
1322 std::make_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); | 1142 std::make_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); |
1323 } | 1143 } |
1324 | 1144 |
1145 TileManager::RasterTileIterator::RasterTileIterator( | |
1146 const RasterTileIterator& other) | |
1147 : comparator_(other.comparator_) { | |
1148 *this = other; | |
1149 } | |
1150 | |
1151 TileManager::RasterTileIterator& TileManager::RasterTileIterator::operator=( | |
1152 const RasterTileIterator& other) { | |
1153 paired_iterators_ = other.paired_iterators_; | |
1154 tree_priority_ = other.tree_priority_; | |
1155 comparator_ = other.comparator_; | |
1156 | |
1157 iterator_heap_.reserve(paired_iterators_.size()); | |
1158 for (size_t i = 0; i < paired_iterators_.size(); ++i) { | |
1159 if (paired_iterators_[i].PeekTile(tree_priority_) != NULL) | |
1160 iterator_heap_.push_back(&paired_iterators_[i]); | |
1161 } | |
1162 std::make_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); | |
1163 return *this; | |
1164 } | |
1165 | |
1325 TileManager::RasterTileIterator::~RasterTileIterator() {} | 1166 TileManager::RasterTileIterator::~RasterTileIterator() {} |
1326 | 1167 |
1168 bool TileManager::RasterTileIterator::HasTilesRequiredForActivation() const { | |
1169 for (std::vector<PairedPictureLayerIterator*>::const_iterator it = | |
1170 iterator_heap_.begin(); | |
1171 it != iterator_heap_.end(); | |
1172 ++it) { | |
1173 const PairedPictureLayerIterator* pair = *it; | |
1174 | |
1175 // Tiles required for activation can only come from pending layers. | |
1176 if (pair->pending_iterator.HasTilesRequiredForActivation()) | |
1177 return true; | |
1178 } | |
1179 return false; | |
1180 } | |
1181 | |
1327 TileManager::RasterTileIterator& TileManager::RasterTileIterator::operator++() { | 1182 TileManager::RasterTileIterator& TileManager::RasterTileIterator::operator++() { |
1328 DCHECK(*this); | 1183 DCHECK(*this); |
1329 | 1184 |
1330 std::pop_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); | 1185 std::pop_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); |
1331 PairedPictureLayerIterator* paired_iterator = iterator_heap_.back(); | 1186 PairedPictureLayerIterator* paired_iterator = iterator_heap_.back(); |
1332 iterator_heap_.pop_back(); | 1187 iterator_heap_.pop_back(); |
1333 | 1188 |
1334 paired_iterator->PopTile(tree_priority_); | 1189 paired_iterator->PopTile(tree_priority_); |
1335 if (paired_iterator->PeekTile(tree_priority_) != NULL) { | 1190 if (paired_iterator->PeekTile(tree_priority_) != NULL) { |
1336 iterator_heap_.push_back(paired_iterator); | 1191 iterator_heap_.push_back(paired_iterator); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1449 | 1304 |
1450 Tile* a_tile = **a_pair.first; | 1305 Tile* a_tile = **a_pair.first; |
1451 Tile* b_tile = **b_pair.first; | 1306 Tile* b_tile = **b_pair.first; |
1452 | 1307 |
1453 const TilePriority& a_priority = | 1308 const TilePriority& a_priority = |
1454 a_tile->priority_for_tree_priority(tree_priority_); | 1309 a_tile->priority_for_tree_priority(tree_priority_); |
1455 const TilePriority& b_priority = | 1310 const TilePriority& b_priority = |
1456 b_tile->priority_for_tree_priority(tree_priority_); | 1311 b_tile->priority_for_tree_priority(tree_priority_); |
1457 bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY; | 1312 bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY; |
1458 | 1313 |
1459 if (b_priority.resolution != a_priority.resolution) { | 1314 if (b_priority.priority_bin == a_priority.priority_bin && |
1315 b_priority.resolution != a_priority.resolution) { | |
1460 return (prioritize_low_res && b_priority.resolution == LOW_RESOLUTION) || | 1316 return (prioritize_low_res && b_priority.resolution == LOW_RESOLUTION) || |
1461 (!prioritize_low_res && b_priority.resolution == HIGH_RESOLUTION) || | 1317 (!prioritize_low_res && b_priority.resolution == HIGH_RESOLUTION) || |
1462 (a_priority.resolution == NON_IDEAL_RESOLUTION); | 1318 (a_priority.resolution == NON_IDEAL_RESOLUTION); |
1463 } | 1319 } |
1464 | 1320 |
1465 return b_priority.IsHigherPriorityThan(a_priority); | 1321 return b_priority.IsHigherPriorityThan(a_priority); |
1466 } | 1322 } |
1467 | 1323 |
1468 TileManager::EvictionTileIterator::EvictionTileIterator() | 1324 TileManager::EvictionTileIterator::EvictionTileIterator() |
1469 : comparator_(SAME_PRIORITY_FOR_BOTH_TREES) {} | 1325 : initialized_(true), |
1326 tile_manager_(NULL), | |
1327 comparator_(SAME_PRIORITY_FOR_BOTH_TREES) { | |
1328 } | |
1329 | |
1330 TileManager::EvictionTileIterator::EvictionTileIterator( | |
1331 const EvictionTileIterator& other) | |
1332 : comparator_(other.comparator_) { | |
1333 *this = other; | |
1334 } | |
1335 | |
1336 TileManager::EvictionTileIterator& TileManager::EvictionTileIterator::operator=( | |
1337 const EvictionTileIterator& other) { | |
1338 paired_iterators_ = other.paired_iterators_; | |
1339 tree_priority_ = other.tree_priority_; | |
1340 comparator_ = other.comparator_; | |
1341 initialized_ = other.initialized_; | |
1342 tile_manager_ = other.tile_manager_; | |
1343 | |
1344 iterator_heap_.reserve(paired_iterators_.size()); | |
1345 for (size_t i = 0; i < paired_iterators_.size(); ++i) { | |
1346 if (paired_iterators_[i].PeekTile(tree_priority_) != NULL) | |
1347 iterator_heap_.push_back(&paired_iterators_[i]); | |
1348 } | |
1349 std::make_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); | |
1350 return *this; | |
1351 } | |
1470 | 1352 |
1471 TileManager::EvictionTileIterator::EvictionTileIterator( | 1353 TileManager::EvictionTileIterator::EvictionTileIterator( |
1472 TileManager* tile_manager, | 1354 TileManager* tile_manager, |
1473 TreePriority tree_priority) | 1355 TreePriority tree_priority) |
1474 : tree_priority_(tree_priority), comparator_(tree_priority) { | 1356 : initialized_(false), |
1357 tile_manager_(tile_manager), | |
1358 tree_priority_(tree_priority), | |
1359 comparator_(tree_priority) { | |
1360 } | |
1361 | |
1362 void TileManager::EvictionTileIterator::Initialize() { | |
1475 std::vector<TileManager::PairedPictureLayer> paired_layers; | 1363 std::vector<TileManager::PairedPictureLayer> paired_layers; |
1476 | 1364 |
1477 tile_manager->GetPairedPictureLayers(&paired_layers); | 1365 tile_manager_->GetPairedPictureLayers(&paired_layers); |
1478 | 1366 |
1479 paired_iterators_.reserve(paired_layers.size()); | 1367 paired_iterators_.reserve(paired_layers.size()); |
1480 iterator_heap_.reserve(paired_layers.size()); | 1368 iterator_heap_.reserve(paired_layers.size()); |
1481 for (std::vector<TileManager::PairedPictureLayer>::iterator it = | 1369 for (std::vector<TileManager::PairedPictureLayer>::iterator it = |
1482 paired_layers.begin(); | 1370 paired_layers.begin(); |
1483 it != paired_layers.end(); | 1371 it != paired_layers.end(); |
1484 ++it) { | 1372 ++it) { |
1485 PairedPictureLayerIterator paired_iterator; | 1373 PairedPictureLayerIterator paired_iterator; |
1486 if (it->active_layer) { | 1374 if (it->active_layer) { |
1487 paired_iterator.active_iterator = | 1375 paired_iterator.active_iterator = |
1488 PictureLayerImpl::LayerEvictionTileIterator(it->active_layer, | 1376 PictureLayerImpl::LayerEvictionTileIterator(it->active_layer, |
1489 tree_priority_); | 1377 tree_priority_); |
1490 } | 1378 } |
1491 | 1379 |
1492 if (it->pending_layer) { | 1380 if (it->pending_layer) { |
1493 paired_iterator.pending_iterator = | 1381 paired_iterator.pending_iterator = |
1494 PictureLayerImpl::LayerEvictionTileIterator(it->pending_layer, | 1382 PictureLayerImpl::LayerEvictionTileIterator(it->pending_layer, |
1495 tree_priority_); | 1383 tree_priority_); |
1496 } | 1384 } |
1497 | 1385 |
1498 if (paired_iterator.PeekTile(tree_priority_) != NULL) { | 1386 if (paired_iterator.PeekTile(tree_priority_) != NULL) { |
1499 paired_iterators_.push_back(paired_iterator); | 1387 paired_iterators_.push_back(paired_iterator); |
1500 iterator_heap_.push_back(&paired_iterators_.back()); | 1388 iterator_heap_.push_back(&paired_iterators_.back()); |
1501 } | 1389 } |
1502 } | 1390 } |
1503 | 1391 |
1504 std::make_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); | 1392 std::make_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); |
1393 initialized_ = true; | |
1505 } | 1394 } |
1506 | 1395 |
1507 TileManager::EvictionTileIterator::~EvictionTileIterator() {} | 1396 TileManager::EvictionTileIterator::~EvictionTileIterator() {} |
1508 | 1397 |
1509 TileManager::EvictionTileIterator& TileManager::EvictionTileIterator:: | 1398 TileManager::EvictionTileIterator& TileManager::EvictionTileIterator:: |
1510 operator++() { | 1399 operator++() { |
1400 DCHECK(initialized_); | |
1401 | |
1511 std::pop_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); | 1402 std::pop_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); |
1512 PairedPictureLayerIterator* paired_iterator = iterator_heap_.back(); | 1403 PairedPictureLayerIterator* paired_iterator = iterator_heap_.back(); |
1513 iterator_heap_.pop_back(); | 1404 iterator_heap_.pop_back(); |
1514 | 1405 |
1515 paired_iterator->PopTile(tree_priority_); | 1406 paired_iterator->PopTile(tree_priority_); |
1516 if (paired_iterator->PeekTile(tree_priority_) != NULL) { | 1407 if (paired_iterator->PeekTile(tree_priority_) != NULL) { |
1517 iterator_heap_.push_back(paired_iterator); | 1408 iterator_heap_.push_back(paired_iterator); |
1518 std::push_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); | 1409 std::push_heap(iterator_heap_.begin(), iterator_heap_.end(), comparator_); |
1519 } | 1410 } |
1520 return *this; | 1411 return *this; |
1521 } | 1412 } |
1522 | 1413 |
1523 TileManager::EvictionTileIterator::operator bool() const { | 1414 TileManager::EvictionTileIterator::operator bool() { |
1415 if (!initialized_) | |
1416 Initialize(); | |
1417 | |
1524 return !iterator_heap_.empty(); | 1418 return !iterator_heap_.empty(); |
1525 } | 1419 } |
1526 | 1420 |
1527 Tile* TileManager::EvictionTileIterator::operator*() { | 1421 Tile* TileManager::EvictionTileIterator::operator*() { |
1422 DCHECK(initialized_); | |
1528 DCHECK(*this); | 1423 DCHECK(*this); |
1529 return iterator_heap_.front()->PeekTile(tree_priority_); | 1424 return iterator_heap_.front()->PeekTile(tree_priority_); |
1530 } | 1425 } |
1531 | 1426 |
1532 TileManager::EvictionTileIterator::PairedPictureLayerIterator:: | 1427 TileManager::EvictionTileIterator::PairedPictureLayerIterator:: |
1533 PairedPictureLayerIterator() {} | 1428 PairedPictureLayerIterator() {} |
1534 | 1429 |
1535 TileManager::EvictionTileIterator::PairedPictureLayerIterator:: | 1430 TileManager::EvictionTileIterator::PairedPictureLayerIterator:: |
1536 ~PairedPictureLayerIterator() {} | 1431 ~PairedPictureLayerIterator() {} |
1537 | 1432 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1624 | 1519 |
1625 if (b_priority.resolution != a_priority.resolution) { | 1520 if (b_priority.resolution != a_priority.resolution) { |
1626 return (prioritize_low_res && b_priority.resolution == LOW_RESOLUTION) || | 1521 return (prioritize_low_res && b_priority.resolution == LOW_RESOLUTION) || |
1627 (!prioritize_low_res && b_priority.resolution == HIGH_RESOLUTION) || | 1522 (!prioritize_low_res && b_priority.resolution == HIGH_RESOLUTION) || |
1628 (a_priority.resolution == NON_IDEAL_RESOLUTION); | 1523 (a_priority.resolution == NON_IDEAL_RESOLUTION); |
1629 } | 1524 } |
1630 return a_priority.IsHigherPriorityThan(b_priority); | 1525 return a_priority.IsHigherPriorityThan(b_priority); |
1631 } | 1526 } |
1632 | 1527 |
1633 } // namespace cc | 1528 } // namespace cc |
OLD | NEW |