Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(251)

Side by Side Diff: cc/resources/tile_manager.cc

Issue 367833003: cc: Start using raster/eviction iterators. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 skia::RefPtr<SkPixelRef> pixel_ref_; 221 skia::RefPtr<SkPixelRef> pixel_ref_;
222 int layer_id_; 222 int layer_id_;
223 RenderingStatsInstrumentation* rendering_stats_; 223 RenderingStatsInstrumentation* rendering_stats_;
224 const base::Callback<void(bool was_canceled)> reply_; 224 const base::Callback<void(bool was_canceled)> reply_;
225 225
226 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); 226 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl);
227 }; 227 };
228 228
229 const size_t kScheduledRasterTasksLimit = 32u; 229 const size_t kScheduledRasterTasksLimit = 32u;
230 230
231 // Memory limit policy works by mapping some bin states to the NEVER bin.
232 const ManagedTileBin kBinPolicyMap[NUM_TILE_MEMORY_LIMIT_POLICIES][NUM_BINS] = {
233 // [ALLOW_NOTHING]
234 {NEVER_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
235 NEVER_BIN, // [NOW_BIN]
236 NEVER_BIN, // [SOON_BIN]
237 NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
238 NEVER_BIN, // [EVENTUALLY_BIN]
239 NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN]
240 NEVER_BIN, // [AT_LAST_BIN]
241 NEVER_BIN // [NEVER_BIN]
242 },
243 // [ALLOW_ABSOLUTE_MINIMUM]
244 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
245 NOW_BIN, // [NOW_BIN]
246 NEVER_BIN, // [SOON_BIN]
247 NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
248 NEVER_BIN, // [EVENTUALLY_BIN]
249 NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN]
250 NEVER_BIN, // [AT_LAST_BIN]
251 NEVER_BIN // [NEVER_BIN]
252 },
253 // [ALLOW_PREPAINT_ONLY]
254 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
255 NOW_BIN, // [NOW_BIN]
256 SOON_BIN, // [SOON_BIN]
257 NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
258 NEVER_BIN, // [EVENTUALLY_BIN]
259 NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN]
260 NEVER_BIN, // [AT_LAST_BIN]
261 NEVER_BIN // [NEVER_BIN]
262 },
263 // [ALLOW_ANYTHING]
264 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
265 NOW_BIN, // [NOW_BIN]
266 SOON_BIN, // [SOON_BIN]
267 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
268 EVENTUALLY_BIN, // [EVENTUALLY_BIN]
269 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
270 AT_LAST_BIN, // [AT_LAST_BIN]
271 NEVER_BIN // [NEVER_BIN]
272 }};
273
274 // Ready to draw works by mapping NOW_BIN to NOW_AND_READY_TO_DRAW_BIN.
275 const ManagedTileBin kBinReadyToDrawMap[2][NUM_BINS] = {
276 // Not ready
277 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
278 NOW_BIN, // [NOW_BIN]
279 SOON_BIN, // [SOON_BIN]
280 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
281 EVENTUALLY_BIN, // [EVENTUALLY_BIN]
282 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
283 AT_LAST_BIN, // [AT_LAST_BIN]
284 NEVER_BIN // [NEVER_BIN]
285 },
286 // Ready
287 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
288 NOW_AND_READY_TO_DRAW_BIN, // [NOW_BIN]
289 SOON_BIN, // [SOON_BIN]
290 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
291 EVENTUALLY_BIN, // [EVENTUALLY_BIN]
292 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
293 AT_LAST_BIN, // [AT_LAST_BIN]
294 NEVER_BIN // [NEVER_BIN]
295 }};
296
297 // Active works by mapping some bin stats to equivalent _ACTIVE_BIN state.
298 const ManagedTileBin kBinIsActiveMap[2][NUM_BINS] = {
299 // Inactive
300 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
301 NOW_BIN, // [NOW_BIN]
302 SOON_BIN, // [SOON_BIN]
303 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
304 EVENTUALLY_BIN, // [EVENTUALLY_BIN]
305 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
306 AT_LAST_BIN, // [AT_LAST_BIN]
307 NEVER_BIN // [NEVER_BIN]
308 },
309 // Active
310 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN]
311 NOW_BIN, // [NOW_BIN]
312 SOON_BIN, // [SOON_BIN]
313 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN]
314 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_BIN]
315 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN]
316 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_BIN]
317 NEVER_BIN // [NEVER_BIN]
318 }};
319
320 // Determine bin based on three categories of tiles: things we need now,
321 // things we need soon, and eventually.
322 inline ManagedTileBin BinFromTilePriority(const TilePriority& prio) {
323 if (prio.priority_bin == TilePriority::NOW)
324 return NOW_BIN;
325
326 if (prio.priority_bin == TilePriority::SOON)
327 return SOON_BIN;
328
329 if (prio.distance_to_visible == std::numeric_limits<float>::infinity())
330 return NEVER_BIN;
331
332 return EVENTUALLY_BIN;
333 }
334
335 } // namespace 231 } // namespace
336 232
337 RasterTaskCompletionStats::RasterTaskCompletionStats() 233 RasterTaskCompletionStats::RasterTaskCompletionStats()
338 : completed_count(0u), canceled_count(0u) {} 234 : completed_count(0u), canceled_count(0u) {}
339 235
340 scoped_refptr<base::debug::ConvertableToTraceFormat> 236 scoped_refptr<base::debug::ConvertableToTraceFormat>
341 RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) { 237 RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) {
342 scoped_refptr<base::debug::TracedValue> state = 238 scoped_refptr<base::debug::TracedValue> state =
343 new base::debug::TracedValue(); 239 new base::debug::TracedValue();
344 state->SetInteger("completed_count", stats.completed_count); 240 state->SetInteger("completed_count", stats.completed_count);
(...skipping 18 matching lines...) Expand all
363 TileManager::TileManager( 259 TileManager::TileManager(
364 TileManagerClient* client, 260 TileManagerClient* client,
365 base::SequencedTaskRunner* task_runner, 261 base::SequencedTaskRunner* task_runner,
366 ResourcePool* resource_pool, 262 ResourcePool* resource_pool,
367 Rasterizer* rasterizer, 263 Rasterizer* rasterizer,
368 RenderingStatsInstrumentation* rendering_stats_instrumentation) 264 RenderingStatsInstrumentation* rendering_stats_instrumentation)
369 : client_(client), 265 : client_(client),
370 task_runner_(task_runner), 266 task_runner_(task_runner),
371 resource_pool_(resource_pool), 267 resource_pool_(resource_pool),
372 rasterizer_(rasterizer), 268 rasterizer_(rasterizer),
373 prioritized_tiles_dirty_(false), 269 all_tiles_that_need_to_be_rasterized_are_scheduled_(true),
374 all_tiles_that_need_to_be_rasterized_have_memory_(true),
375 all_tiles_required_for_activation_have_memory_(true),
376 bytes_releasable_(0),
377 resources_releasable_(0),
378 ever_exceeded_memory_budget_(false),
379 rendering_stats_instrumentation_(rendering_stats_instrumentation), 270 rendering_stats_instrumentation_(rendering_stats_instrumentation),
380 did_initialize_visible_tile_(false), 271 did_initialize_visible_tile_(false),
381 did_check_for_completed_tasks_since_last_schedule_tasks_(true), 272 did_check_for_completed_tasks_since_last_schedule_tasks_(true),
382 ready_to_activate_check_notifier_( 273 ready_to_activate_check_notifier_(
383 task_runner_, 274 task_runner_,
384 base::Bind(&TileManager::CheckIfReadyToActivate, 275 base::Bind(&TileManager::CheckIfReadyToActivate,
385 base::Unretained(this))) { 276 base::Unretained(this))) {
386 rasterizer_->SetClient(this); 277 rasterizer_->SetClient(this);
387 } 278 }
388 279
389 TileManager::~TileManager() { 280 TileManager::~TileManager() {
390 // Reset global state and manage. This should cause 281 // Reset global state and manage. This should cause
391 // our memory usage to drop to zero. 282 // our memory usage to drop to zero.
392 global_state_ = GlobalStateThatImpactsTilePriority(); 283 global_state_ = GlobalStateThatImpactsTilePriority();
393 284
394 RasterTaskQueue empty; 285 RasterTaskQueue empty;
395 rasterizer_->ScheduleTasks(&empty); 286 rasterizer_->ScheduleTasks(&empty);
396 orphan_raster_tasks_.clear(); 287 orphan_raster_tasks_.clear();
397 288
398 // This should finish all pending tasks and release any uninitialized 289 // This should finish all pending tasks and release any uninitialized
399 // resources. 290 // resources.
400 rasterizer_->Shutdown(); 291 rasterizer_->Shutdown();
401 rasterizer_->CheckForCompletedTasks(); 292 rasterizer_->CheckForCompletedTasks();
402 293
403 prioritized_tiles_.Clear();
404
405 FreeResourcesForReleasedTiles(); 294 FreeResourcesForReleasedTiles();
406 CleanUpReleasedTiles(); 295 CleanUpReleasedTiles();
407
408 DCHECK_EQ(0u, bytes_releasable_);
409 DCHECK_EQ(0u, resources_releasable_);
410 } 296 }
411 297
412 void TileManager::Release(Tile* tile) { 298 void TileManager::Release(Tile* tile) {
413 DCHECK(TilePriority() == tile->combined_priority());
414
415 prioritized_tiles_dirty_ = true;
416 released_tiles_.push_back(tile); 299 released_tiles_.push_back(tile);
417 } 300 }
418 301
419 void TileManager::DidChangeTilePriority(Tile* tile) {
420 prioritized_tiles_dirty_ = true;
421 }
422
423 bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const { 302 bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const {
424 return global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY; 303 return global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY;
425 } 304 }
426 305
427 void TileManager::FreeResourcesForReleasedTiles() { 306 void TileManager::FreeResourcesForReleasedTiles() {
428 for (std::vector<Tile*>::iterator it = released_tiles_.begin(); 307 for (std::vector<Tile*>::iterator it = released_tiles_.begin();
429 it != released_tiles_.end(); 308 it != released_tiles_.end();
430 ++it) { 309 ++it) {
431 Tile* tile = *it; 310 Tile* tile = *it;
432 FreeResourcesForTile(tile); 311 FreeResourcesForTile(tile);
433 } 312 }
434 } 313 }
435 314
436 void TileManager::CleanUpReleasedTiles() { 315 void TileManager::CleanUpReleasedTiles() {
437 // Make sure |prioritized_tiles_| doesn't contain any of the tiles
438 // we're about to delete.
439 DCHECK(prioritized_tiles_.IsEmpty());
440
441 std::vector<Tile*>::iterator it = released_tiles_.begin(); 316 std::vector<Tile*>::iterator it = released_tiles_.begin();
442 while (it != released_tiles_.end()) { 317 while (it != released_tiles_.end()) {
443 Tile* tile = *it; 318 Tile* tile = *it;
444 319
445 if (tile->HasRasterTask()) { 320 if (tile->HasRasterTask()) {
446 ++it; 321 ++it;
447 continue; 322 continue;
448 } 323 }
449 324
450 DCHECK(!tile->HasResources()); 325 DCHECK(!tile->HasResources());
451 DCHECK(tiles_.find(tile->id()) != tiles_.end()); 326 DCHECK(tiles_.find(tile->id()) != tiles_.end());
452 tiles_.erase(tile->id()); 327 tiles_.erase(tile->id());
453 328
454 LayerCountMap::iterator layer_it = 329 LayerCountMap::iterator layer_it =
455 used_layer_counts_.find(tile->layer_id()); 330 used_layer_counts_.find(tile->layer_id());
456 DCHECK_GT(layer_it->second, 0); 331 DCHECK_GT(layer_it->second, 0);
457 if (--layer_it->second == 0) { 332 if (--layer_it->second == 0) {
458 used_layer_counts_.erase(layer_it); 333 used_layer_counts_.erase(layer_it);
459 image_decode_tasks_.erase(tile->layer_id()); 334 image_decode_tasks_.erase(tile->layer_id());
460 } 335 }
461 336
462 delete tile; 337 delete tile;
463 it = released_tiles_.erase(it); 338 it = released_tiles_.erase(it);
464 } 339 }
465 } 340 }
466 341
467 void TileManager::UpdatePrioritizedTileSetIfNeeded() {
468 if (!prioritized_tiles_dirty_)
469 return;
470
471 prioritized_tiles_.Clear();
472
473 FreeResourcesForReleasedTiles();
474 CleanUpReleasedTiles();
475
476 GetTilesWithAssignedBins(&prioritized_tiles_);
477 prioritized_tiles_dirty_ = false;
478 }
479
480 void TileManager::DidFinishRunningTasks() { 342 void TileManager::DidFinishRunningTasks() {
481 TRACE_EVENT0("cc", "TileManager::DidFinishRunningTasks"); 343 TRACE_EVENT0("cc", "TileManager::DidFinishRunningTasks");
482 344
483 bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() > 345 bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() >
484 global_state_.soft_memory_limit_in_bytes; 346 global_state_.soft_memory_limit_in_bytes;
485 347
486 // When OOM, keep re-assigning memory until we reach a steady state 348 // When OOM, keep re-assigning memory until we reach a steady state
487 // where top-priority tiles are initialized. 349 // where top-priority tiles are initialized.
488 if (all_tiles_that_need_to_be_rasterized_have_memory_ && 350 if (all_tiles_that_need_to_be_rasterized_are_scheduled_ &&
489 !memory_usage_above_limit) 351 !memory_usage_above_limit)
490 return; 352 return;
491 353
492 rasterizer_->CheckForCompletedTasks(); 354 rasterizer_->CheckForCompletedTasks();
493 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; 355 did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
494 356
495 TileVector tiles_that_need_to_be_rasterized; 357 TileVector tiles_that_need_to_be_rasterized;
496 AssignGpuMemoryToTiles(&prioritized_tiles_, 358 AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized);
497 &tiles_that_need_to_be_rasterized);
498 359
499 // |tiles_that_need_to_be_rasterized| will be empty when we reach a 360 // |tiles_that_need_to_be_rasterized| will be empty when we reach a
500 // steady memory state. Keep scheduling tasks until we reach this state. 361 // steady memory state. Keep scheduling tasks until we reach this state.
501 if (!tiles_that_need_to_be_rasterized.empty()) { 362 if (!tiles_that_need_to_be_rasterized.empty()) {
502 ScheduleTasks(tiles_that_need_to_be_rasterized); 363 ScheduleTasks(tiles_that_need_to_be_rasterized);
503 return; 364 return;
504 } 365 }
505 366
506 FreeResourcesForReleasedTiles(); 367 FreeResourcesForReleasedTiles();
507 368
(...skipping 22 matching lines...) Expand all
530 tile_version.set_rasterize_on_demand(); 391 tile_version.set_rasterize_on_demand();
531 client_->NotifyTileStateChanged(tile); 392 client_->NotifyTileStateChanged(tile);
532 } 393 }
533 } 394 }
534 395
535 DCHECK(IsReadyToActivate()); 396 DCHECK(IsReadyToActivate());
536 ready_to_activate_check_notifier_.Schedule(); 397 ready_to_activate_check_notifier_.Schedule();
537 } 398 }
538 399
539 void TileManager::DidFinishRunningTasksRequiredForActivation() { 400 void TileManager::DidFinishRunningTasksRequiredForActivation() {
540 // This is only a true indication that all tiles required for
541 // activation are initialized when no tiles are OOM. We need to
542 // wait for DidFinishRunningTasks() to be called, try to re-assign
543 // memory and in worst case use on-demand raster when tiles
544 // required for activation are OOM.
545 if (!all_tiles_required_for_activation_have_memory_)
546 return;
547
548 ready_to_activate_check_notifier_.Schedule(); 401 ready_to_activate_check_notifier_.Schedule();
549 } 402 }
550 403
551 void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) {
552 TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins");
553
554 const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy;
555 const TreePriority tree_priority = global_state_.tree_priority;
556
557 // For each tree, bin into different categories of tiles.
558 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
559 Tile* tile = it->second;
560 ManagedTileState& mts = tile->managed_state();
561
562 const ManagedTileState::TileVersion& tile_version =
563 tile->GetTileVersionForDrawing();
564 bool tile_is_ready_to_draw = tile_version.IsReadyToDraw();
565 bool tile_is_active = tile_is_ready_to_draw ||
566 mts.tile_versions[mts.raster_mode].raster_task_;
567
568 // Get the active priority and bin.
569 TilePriority active_priority = tile->priority(ACTIVE_TREE);
570 ManagedTileBin active_bin = BinFromTilePriority(active_priority);
571
572 // Get the pending priority and bin.
573 TilePriority pending_priority = tile->priority(PENDING_TREE);
574 ManagedTileBin pending_bin = BinFromTilePriority(pending_priority);
575
576 bool pending_is_low_res = pending_priority.resolution == LOW_RESOLUTION;
577 bool pending_is_non_ideal =
578 pending_priority.resolution == NON_IDEAL_RESOLUTION;
579 bool active_is_non_ideal =
580 active_priority.resolution == NON_IDEAL_RESOLUTION;
581
582 // Adjust bin state based on if ready to draw.
583 active_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][active_bin];
584 pending_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][pending_bin];
585
586 // Adjust bin state based on if active.
587 active_bin = kBinIsActiveMap[tile_is_active][active_bin];
588 pending_bin = kBinIsActiveMap[tile_is_active][pending_bin];
589
590 // We never want to paint new non-ideal tiles, as we always have
591 // a high-res tile covering that content (paint that instead).
592 if (!tile_is_ready_to_draw && active_is_non_ideal)
593 active_bin = NEVER_BIN;
594 if (!tile_is_ready_to_draw && pending_is_non_ideal)
595 pending_bin = NEVER_BIN;
596
597 ManagedTileBin tree_bin[NUM_TREES];
598 tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin];
599 tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin];
600
601 // Adjust pending bin state for low res tiles. This prevents pending tree
602 // low-res tiles from being initialized before high-res tiles.
603 if (pending_is_low_res)
604 tree_bin[PENDING_TREE] = std::max(tree_bin[PENDING_TREE], EVENTUALLY_BIN);
605
606 TilePriority tile_priority;
607 switch (tree_priority) {
608 case SAME_PRIORITY_FOR_BOTH_TREES:
609 mts.bin = std::min(tree_bin[ACTIVE_TREE], tree_bin[PENDING_TREE]);
610 tile_priority = tile->combined_priority();
611 break;
612 case SMOOTHNESS_TAKES_PRIORITY:
613 mts.bin = tree_bin[ACTIVE_TREE];
614 tile_priority = active_priority;
615 break;
616 case NEW_CONTENT_TAKES_PRIORITY:
617 mts.bin = tree_bin[PENDING_TREE];
618 tile_priority = pending_priority;
619 break;
620 default:
621 NOTREACHED();
622 }
623
624 // Bump up the priority if we determined it's NEVER_BIN on one tree,
625 // but is still required on the other tree.
626 bool is_in_never_bin_on_both_trees = tree_bin[ACTIVE_TREE] == NEVER_BIN &&
627 tree_bin[PENDING_TREE] == NEVER_BIN;
628
629 if (mts.bin == NEVER_BIN && !is_in_never_bin_on_both_trees)
630 mts.bin = tile_is_active ? AT_LAST_AND_ACTIVE_BIN : AT_LAST_BIN;
631
632 mts.resolution = tile_priority.resolution;
633 mts.priority_bin = tile_priority.priority_bin;
634 mts.distance_to_visible = tile_priority.distance_to_visible;
635 mts.required_for_activation = tile_priority.required_for_activation;
636
637 mts.visible_and_ready_to_draw =
638 tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN;
639
640 // Tiles that are required for activation shouldn't be in NEVER_BIN unless
641 // smoothness takes priority or memory policy allows nothing to be
642 // initialized.
643 DCHECK(!mts.required_for_activation || mts.bin != NEVER_BIN ||
644 tree_priority == SMOOTHNESS_TAKES_PRIORITY ||
645 memory_policy == ALLOW_NOTHING);
646
647 // If the tile is in NEVER_BIN and it does not have an active task, then we
648 // can release the resources early. If it does have the task however, we
649 // should keep it in the prioritized tile set to ensure that AssignGpuMemory
650 // can visit it.
651 if (mts.bin == NEVER_BIN &&
652 !mts.tile_versions[mts.raster_mode].raster_task_) {
653 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
654 continue;
655 }
656
657 // Insert the tile into a priority set.
658 tiles->InsertTile(tile, mts.bin);
659 }
660 }
661
662 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { 404 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) {
663 TRACE_EVENT0("cc", "TileManager::ManageTiles"); 405 TRACE_EVENT0("cc", "TileManager::ManageTiles");
664 406
665 // Update internal state. 407 global_state_ = state;
666 if (state != global_state_) {
667 global_state_ = state;
668 prioritized_tiles_dirty_ = true;
669 }
670 408
671 // We need to call CheckForCompletedTasks() once in-between each call 409 // We need to call CheckForCompletedTasks() once in-between each call
672 // to ScheduleTasks() to prevent canceled tasks from being scheduled. 410 // to ScheduleTasks() to prevent canceled tasks from being scheduled.
673 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { 411 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) {
674 rasterizer_->CheckForCompletedTasks(); 412 rasterizer_->CheckForCompletedTasks();
675 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; 413 did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
676 } 414 }
677 415
678 UpdatePrioritizedTileSetIfNeeded(); 416 FreeResourcesForReleasedTiles();
417 CleanUpReleasedTiles();
679 418
680 TileVector tiles_that_need_to_be_rasterized; 419 TileVector tiles_that_need_to_be_rasterized;
681 AssignGpuMemoryToTiles(&prioritized_tiles_, 420 AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized);
682 &tiles_that_need_to_be_rasterized);
683 421
684 // Finally, schedule rasterizer tasks. 422 // Finally, schedule rasterizer tasks.
685 ScheduleTasks(tiles_that_need_to_be_rasterized); 423 ScheduleTasks(tiles_that_need_to_be_rasterized);
686 424
687 TRACE_EVENT_INSTANT1("cc", 425 TRACE_EVENT_INSTANT1("cc",
688 "DidManage", 426 "DidManage",
689 TRACE_EVENT_SCOPE_THREAD, 427 TRACE_EVENT_SCOPE_THREAD,
690 "state", 428 "state",
691 BasicStateAsValue()); 429 BasicStateAsValue());
692 430
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 } 470 }
733 471
734 void TileManager::AllTilesAsValueInto(base::debug::TracedValue* state) const { 472 void TileManager::AllTilesAsValueInto(base::debug::TracedValue* state) const {
735 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { 473 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
736 state->BeginDictionary(); 474 state->BeginDictionary();
737 it->second->AsValueInto(state); 475 it->second->AsValueInto(state);
738 state->EndDictionary(); 476 state->EndDictionary();
739 } 477 }
740 } 478 }
741 479
480 void TileManager::RebuildEvictionQueueIfNeeded() {
481 if (eviction_priority_queue_is_up_to_date_)
482 return;
483
484 eviction_priority_queue_.Reset();
485 client_->BuildEvictionQueue(&eviction_priority_queue_,
486 global_state_.tree_priority);
487 eviction_priority_queue_is_up_to_date_ = true;
488 }
489
490 bool TileManager::FreeTileResourcesUntilUsageIsWithinLimit(
491 const MemoryUsage& limit,
492 MemoryUsage* usage) {
493 while (usage->Exceeds(limit)) {
494 RebuildEvictionQueueIfNeeded();
495 if (eviction_priority_queue_.IsEmpty())
496 return false;
497
498 Tile* tile = eviction_priority_queue_.Top();
499 *usage -= MemoryUsage::FromTile(tile);
500 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
501 eviction_priority_queue_.Pop();
502 }
503 return true;
504 }
505
506 bool TileManager::FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit(
507 const MemoryUsage& limit,
508 const TilePriority& other_priority,
509 MemoryUsage* usage) {
510 while (usage->Exceeds(limit)) {
511 RebuildEvictionQueueIfNeeded();
512 if (eviction_priority_queue_.IsEmpty())
513 return false;
514
515 Tile* tile = eviction_priority_queue_.Top();
516 if (!other_priority.IsHigherPriorityThan(
517 tile->priority_for_tree_priority(global_state_.tree_priority))) {
518 return false;
519 }
520
521 *usage -= MemoryUsage::FromTile(tile);
522 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
523 eviction_priority_queue_.Pop();
524 }
525 return true;
526 }
527
528 bool TileManager::TilePriorityViolatesMemoryPolicy(
529 const TilePriority& priority) {
530 switch (global_state_.memory_limit_policy) {
531 case ALLOW_NOTHING:
532 return true;
533 case ALLOW_ABSOLUTE_MINIMUM:
534 return priority.priority_bin > TilePriority::NOW;
535 case ALLOW_PREPAINT_ONLY:
536 return priority.priority_bin > TilePriority::SOON;
537 case ALLOW_ANYTHING:
538 return priority.distance_to_visible ==
539 std::numeric_limits<float>::infinity();
540 }
541 NOTREACHED();
542 return true;
543 }
544
742 void TileManager::AssignGpuMemoryToTiles( 545 void TileManager::AssignGpuMemoryToTiles(
743 PrioritizedTileSet* tiles,
744 TileVector* tiles_that_need_to_be_rasterized) { 546 TileVector* tiles_that_need_to_be_rasterized) {
745 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); 547 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles");
746 548
747 // Maintain the list of released resources that can potentially be re-used 549 // Maintain the list of released resources that can potentially be re-used
748 // or deleted. 550 // or deleted.
749 // If this operation becomes expensive too, only do this after some 551 // If this operation becomes expensive too, only do this after some
750 // resource(s) was returned. Note that in that case, one also need to 552 // resource(s) was returned. Note that in that case, one also need to
751 // invalidate when releasing some resource from the pool. 553 // invalidate when releasing some resource from the pool.
752 resource_pool_->CheckBusyResources(); 554 resource_pool_->CheckBusyResources();
753 555
754 // Now give memory out to the tiles until we're out, and build 556 // Now give memory out to the tiles until we're out, and build
755 // the needs-to-be-rasterized queue. 557 // the needs-to-be-rasterized queue.
756 all_tiles_that_need_to_be_rasterized_have_memory_ = true; 558 all_tiles_that_need_to_be_rasterized_are_scheduled_ = true;
757 all_tiles_required_for_activation_have_memory_ = true; 559 bool had_enough_memory_to_schedule_tiles_needed_now = true;
758 560
759 // Cast to prevent overflow. 561 MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes,
760 int64 soft_bytes_available = 562 global_state_.num_resources_limit);
761 static_cast<int64>(bytes_releasable_) + 563 MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes,
762 static_cast<int64>(global_state_.soft_memory_limit_in_bytes) - 564 global_state_.num_resources_limit);
763 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); 565 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(),
764 int64 hard_bytes_available = 566 resource_pool_->acquired_resource_count());
765 static_cast<int64>(bytes_releasable_) +
766 static_cast<int64>(global_state_.hard_memory_limit_in_bytes) -
767 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes());
768 int resources_available = resources_releasable_ +
769 global_state_.num_resources_limit -
770 resource_pool_->acquired_resource_count();
771 size_t soft_bytes_allocatable =
772 std::max(static_cast<int64>(0), soft_bytes_available);
773 size_t hard_bytes_allocatable =
774 std::max(static_cast<int64>(0), hard_bytes_available);
775 size_t resources_allocatable = std::max(0, resources_available);
776 567
777 size_t bytes_that_exceeded_memory_budget = 0; 568 eviction_priority_queue_is_up_to_date_ = false;
778 size_t soft_bytes_left = soft_bytes_allocatable; 569 raster_priority_queue_.Reset();
779 size_t hard_bytes_left = hard_bytes_allocatable; 570 client_->BuildRasterQueue(&raster_priority_queue_,
571 global_state_.tree_priority);
572 unsigned schedule_priority = 1u;
573 while (!raster_priority_queue_.IsEmpty()) {
574 Tile* tile = raster_priority_queue_.Top();
575 TilePriority priority =
576 tile->priority_for_tree_priority(global_state_.tree_priority);
780 577
781 size_t resources_left = resources_allocatable; 578 if (TilePriorityViolatesMemoryPolicy(priority))
782 bool oomed_soft = false; 579 break;
783 bool oomed_hard = false;
784 bool have_hit_soft_memory = false; // Soft memory comes after hard.
785 580
786 unsigned schedule_priority = 1u; 581 // We won't be able to schedule this tile, so break out early.
787 for (PrioritizedTileSet::Iterator it(tiles, true); it; ++it) { 582 if (tiles_that_need_to_be_rasterized->size() >=
788 Tile* tile = *it; 583 kScheduledRasterTasksLimit) {
584 all_tiles_that_need_to_be_rasterized_are_scheduled_ = false;
585 break;
586 }
587
789 ManagedTileState& mts = tile->managed_state(); 588 ManagedTileState& mts = tile->managed_state();
790
791 mts.scheduled_priority = schedule_priority++; 589 mts.scheduled_priority = schedule_priority++;
792
793 mts.raster_mode = tile->DetermineOverallRasterMode(); 590 mts.raster_mode = tile->DetermineOverallRasterMode();
794
795 ManagedTileState::TileVersion& tile_version = 591 ManagedTileState::TileVersion& tile_version =
796 mts.tile_versions[mts.raster_mode]; 592 mts.tile_versions[mts.raster_mode];
593 DCHECK(!tile_version.IsReadyToDraw());
797 594
798 // If this tile doesn't need a resource, then nothing to do. 595 // If the tile already has a raster_task, then the memory used by it is
799 if (!tile_version.requires_resource()) 596 // already accounted for in memory_usage. Otherwise, we'll have to acquire
800 continue; 597 // more memory to create a raster task.
801 598 MemoryUsage memory_required_by_tile_to_be_scheduled;
802 // If the tile is not needed, free it up. 599 if (!tile_version.raster_task_) {
803 if (mts.bin == NEVER_BIN) { 600 memory_required_by_tile_to_be_scheduled = MemoryUsage::FromConfig(
804 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); 601 tile->size(), resource_pool_->resource_format());
805 continue;
806 } 602 }
807 603
808 const bool tile_uses_hard_limit = mts.bin <= NOW_BIN; 604 bool tile_is_needed_now = priority.priority_bin == TilePriority::NOW;
809 const size_t bytes_if_allocated = BytesConsumedIfAllocated(tile);
810 const size_t tile_bytes_left =
811 (tile_uses_hard_limit) ? hard_bytes_left : soft_bytes_left;
812 605
813 // Hard-limit is reserved for tiles that would cause a calamity 606 // This is the memory limit that will be used by this tile. Depending on
814 // if they were to go away, so by definition they are the highest 607 // the tile priority, it will be one of hard_memory_limit or
815 // priority memory, and must be at the front of the list. 608 // soft_memory_limit.
816 DCHECK(!(have_hit_soft_memory && tile_uses_hard_limit)); 609 MemoryUsage& tile_memory_limit =
817 have_hit_soft_memory |= !tile_uses_hard_limit; 610 tile_is_needed_now ? hard_memory_limit : soft_memory_limit;
818 611
819 size_t tile_bytes = 0; 612 bool memory_usage_is_within_limit =
820 size_t tile_resources = 0; 613 FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit(
614 tile_memory_limit - memory_required_by_tile_to_be_scheduled,
615 priority,
616 &memory_usage);
821 617
822 // It costs to maintain a resource. 618 // If we couldn't fit the tile into our current memory limit, then we're
823 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { 619 // done.
824 if (mts.tile_versions[mode].resource_) { 620 if (!memory_usage_is_within_limit) {
825 tile_bytes += bytes_if_allocated; 621 if (tile_is_needed_now)
826 tile_resources++; 622 had_enough_memory_to_schedule_tiles_needed_now = false;
827 } 623 all_tiles_that_need_to_be_rasterized_are_scheduled_ = false;
624 break;
828 } 625 }
829 626
830 // Allow lower priority tiles with initialized resources to keep 627 memory_usage += memory_required_by_tile_to_be_scheduled;
831 // their memory by only assigning memory to new raster tasks if
832 // they can be scheduled.
833 bool reached_scheduled_raster_tasks_limit =
834 tiles_that_need_to_be_rasterized->size() >= kScheduledRasterTasksLimit;
835 if (!reached_scheduled_raster_tasks_limit) {
836 // If we don't have the required version, and it's not in flight
837 // then we'll have to pay to create a new task.
838 if (!tile_version.resource_ && !tile_version.raster_task_) {
839 tile_bytes += bytes_if_allocated;
840 tile_resources++;
841 }
842 }
843
844 // Tile is OOM.
845 if (tile_bytes > tile_bytes_left || tile_resources > resources_left) {
846 bool was_ready_to_draw = tile->IsReadyToDraw();
847
848 FreeResourcesForTile(tile);
849
850 // This tile was already on screen and now its resources have been
851 // released. In order to prevent checkerboarding, set this tile as
852 // rasterize on demand immediately.
853 if (mts.visible_and_ready_to_draw)
854 tile_version.set_rasterize_on_demand();
855
856 if (was_ready_to_draw)
857 client_->NotifyTileStateChanged(tile);
858
859 oomed_soft = true;
860 if (tile_uses_hard_limit) {
861 oomed_hard = true;
862 bytes_that_exceeded_memory_budget += tile_bytes;
863 }
864 } else {
865 resources_left -= tile_resources;
866 hard_bytes_left -= tile_bytes;
867 soft_bytes_left =
868 (soft_bytes_left > tile_bytes) ? soft_bytes_left - tile_bytes : 0;
869 if (tile_version.resource_)
870 continue;
871 }
872
873 DCHECK(!tile_version.resource_);
874
875 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized|
876 // has reached it's limit or we've failed to assign gpu memory to this
877 // or any higher priority tile. Preventing tiles that fit into memory
878 // budget to be rasterized when higher priority tile is oom is
879 // important for two reasons:
880 // 1. Tile size should not impact raster priority.
881 // 2. Tiles with existing raster task could otherwise incorrectly
882 // be added as they are not affected by |bytes_allocatable|.
883 bool can_schedule_tile =
884 !oomed_soft && !reached_scheduled_raster_tasks_limit;
885
886 if (!can_schedule_tile) {
887 all_tiles_that_need_to_be_rasterized_have_memory_ = false;
888 if (tile->required_for_activation())
889 all_tiles_required_for_activation_have_memory_ = false;
890 it.DisablePriorityOrdering();
891 continue;
892 }
893
894 tiles_that_need_to_be_rasterized->push_back(tile); 628 tiles_that_need_to_be_rasterized->push_back(tile);
629 raster_priority_queue_.Pop();
895 } 630 }
896 631
897 // OOM reporting uses hard-limit, soft-OOM is normal depending on limit. 632 // Note that we should try and further reduce memory in case the above loop
898 ever_exceeded_memory_budget_ |= oomed_hard; 633 // didn't reduce memory. This ensures that we always release as many resources
899 if (ever_exceeded_memory_budget_) { 634 // as possible to stay within the memory limit.
900 TRACE_COUNTER_ID2("cc", 635 FreeTileResourcesUntilUsageIsWithinLimit(hard_memory_limit, &memory_usage);
901 "over_memory_budget", 636
902 this, 637 UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget",
903 "budget", 638 !had_enough_memory_to_schedule_tiles_needed_now);
904 global_state_.hard_memory_limit_in_bytes,
905 "over",
906 bytes_that_exceeded_memory_budget);
907 }
908 UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget", oomed_hard);
909 memory_stats_from_last_assign_.total_budget_in_bytes = 639 memory_stats_from_last_assign_.total_budget_in_bytes =
910 global_state_.hard_memory_limit_in_bytes; 640 global_state_.hard_memory_limit_in_bytes;
911 memory_stats_from_last_assign_.bytes_allocated = 641 memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes();
912 hard_bytes_allocatable - hard_bytes_left; 642 memory_stats_from_last_assign_.had_enough_memory =
913 memory_stats_from_last_assign_.bytes_unreleasable = 643 had_enough_memory_to_schedule_tiles_needed_now;
914 resource_pool_->acquired_memory_usage_bytes() - bytes_releasable_;
915 memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget;
916 } 644 }
917 645
918 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) { 646 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) {
919 ManagedTileState& mts = tile->managed_state(); 647 ManagedTileState& mts = tile->managed_state();
920 if (mts.tile_versions[mode].resource_) { 648 if (mts.tile_versions[mode].resource_)
921 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass()); 649 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass());
922
923 DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile));
924 DCHECK_GE(resources_releasable_, 1u);
925
926 bytes_releasable_ -= BytesConsumedIfAllocated(tile);
927 --resources_releasable_;
928 }
929 } 650 }
930 651
931 void TileManager::FreeResourcesForTile(Tile* tile) { 652 void TileManager::FreeResourcesForTile(Tile* tile) {
932 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { 653 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
933 FreeResourceForTile(tile, static_cast<RasterMode>(mode)); 654 FreeResourceForTile(tile, static_cast<RasterMode>(mode));
934 } 655 }
935 } 656 }
936 657
937 void TileManager::FreeUnusedResourcesForTile(Tile* tile) { 658 void TileManager::FreeUnusedResourcesForTile(Tile* tile) {
938 DCHECK(tile->IsReadyToDraw()); 659 DCHECK(tile->IsReadyToDraw());
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 } 836 }
1116 837
1117 ++update_visible_tiles_stats_.completed_count; 838 ++update_visible_tiles_stats_.completed_count;
1118 839
1119 if (analysis.is_solid_color) { 840 if (analysis.is_solid_color) {
1120 tile_version.set_solid_color(analysis.solid_color); 841 tile_version.set_solid_color(analysis.solid_color);
1121 resource_pool_->ReleaseResource(resource.Pass()); 842 resource_pool_->ReleaseResource(resource.Pass());
1122 } else { 843 } else {
1123 tile_version.set_use_resource(); 844 tile_version.set_use_resource();
1124 tile_version.resource_ = resource.Pass(); 845 tile_version.resource_ = resource.Pass();
1125
1126 bytes_releasable_ += BytesConsumedIfAllocated(tile);
1127 ++resources_releasable_;
1128 } 846 }
1129 847
1130 FreeUnusedResourcesForTile(tile); 848 FreeUnusedResourcesForTile(tile);
1131 if (tile->priority(ACTIVE_TREE).distance_to_visible == 0.f) 849 if (tile->priority(ACTIVE_TREE).distance_to_visible == 0.f)
1132 did_initialize_visible_tile_ = true; 850 did_initialize_visible_tile_ = true;
1133 851
1134 client_->NotifyTileStateChanged(tile); 852 client_->NotifyTileStateChanged(tile);
1135 } 853 }
1136 854
1137 scoped_refptr<Tile> TileManager::CreateTile(PicturePileImpl* picture_pile, 855 scoped_refptr<Tile> TileManager::CreateTile(PicturePileImpl* picture_pile,
(...skipping 10 matching lines...) Expand all
1148 content_rect, 866 content_rect,
1149 opaque_rect, 867 opaque_rect,
1150 contents_scale, 868 contents_scale,
1151 layer_id, 869 layer_id,
1152 source_frame_number, 870 source_frame_number,
1153 flags)); 871 flags));
1154 DCHECK(tiles_.find(tile->id()) == tiles_.end()); 872 DCHECK(tiles_.find(tile->id()) == tiles_.end());
1155 873
1156 tiles_[tile->id()] = tile; 874 tiles_[tile->id()] = tile;
1157 used_layer_counts_[tile->layer_id()]++; 875 used_layer_counts_[tile->layer_id()]++;
1158 prioritized_tiles_dirty_ = true;
1159 return tile; 876 return tile;
1160 } 877 }
1161 878
1162 void TileManager::SetRasterizerForTesting(Rasterizer* rasterizer) { 879 void TileManager::SetRasterizerForTesting(Rasterizer* rasterizer) {
1163 rasterizer_ = rasterizer; 880 rasterizer_ = rasterizer;
1164 rasterizer_->SetClient(this); 881 rasterizer_->SetClient(this);
1165 } 882 }
1166 883
1167 bool TileManager::IsReadyToActivate() const { 884 bool TileManager::IsReadyToActivate() const {
1168 const std::vector<PictureLayerImpl*>& layers = client_->GetPictureLayers(); 885 const std::vector<PictureLayerImpl*>& layers = client_->GetPictureLayers();
(...skipping 11 matching lines...) Expand all
1180 void TileManager::CheckIfReadyToActivate() { 897 void TileManager::CheckIfReadyToActivate() {
1181 TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate"); 898 TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate");
1182 899
1183 rasterizer_->CheckForCompletedTasks(); 900 rasterizer_->CheckForCompletedTasks();
1184 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; 901 did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
1185 902
1186 if (IsReadyToActivate()) 903 if (IsReadyToActivate())
1187 client_->NotifyReadyToActivate(); 904 client_->NotifyReadyToActivate();
1188 } 905 }
1189 906
907 TileManager::MemoryUsage::MemoryUsage() : memory_bytes_(0), resource_count_(0) {
908 }
909
910 TileManager::MemoryUsage::MemoryUsage(int64 memory_bytes, int resource_count)
911 : memory_bytes_(memory_bytes), resource_count_(resource_count) {
912 }
913
914 // static
915 TileManager::MemoryUsage TileManager::MemoryUsage::FromConfig(
916 const gfx::Size& size,
917 ResourceFormat format) {
918 return MemoryUsage(Resource::MemorySizeBytes(size, format), 1);
919 }
920
921 // static
922 TileManager::MemoryUsage TileManager::MemoryUsage::FromTile(const Tile* tile) {
923 const ManagedTileState& mts = tile->managed_state();
924 MemoryUsage total_usage;
925 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
926 if (mts.tile_versions[mode].resource_) {
927 total_usage += MemoryUsage::FromConfig(
928 tile->size(), mts.tile_versions[mode].resource_->format());
929 }
930 }
931 return total_usage;
932 }
933
934 TileManager::MemoryUsage& TileManager::MemoryUsage::operator+=(
935 const MemoryUsage& other) {
936 memory_bytes_ += other.memory_bytes_;
937 resource_count_ += other.resource_count_;
938 return *this;
939 }
940
941 TileManager::MemoryUsage& TileManager::MemoryUsage::operator-=(
942 const MemoryUsage& other) {
943 memory_bytes_ -= other.memory_bytes_;
944 resource_count_ -= other.resource_count_;
945 return *this;
946 }
947
948 TileManager::MemoryUsage TileManager::MemoryUsage::operator-(
949 const MemoryUsage& other) {
950 MemoryUsage result = *this;
951 result -= other;
952 return result;
953 }
954
955 bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const {
956 return memory_bytes_ > limit.memory_bytes_ ||
957 resource_count_ >= limit.resource_count_;
958 }
959
1190 } // namespace cc 960 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698