| 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 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/json/json_writer.h" | 12 #include "base/json/json_writer.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/trace_event/trace_event_argument.h" | 15 #include "base/trace_event/trace_event_argument.h" |
| 16 #include "cc/debug/devtools_instrumentation.h" | 16 #include "cc/debug/devtools_instrumentation.h" |
| 17 #include "cc/debug/frame_viewer_instrumentation.h" | 17 #include "cc/debug/frame_viewer_instrumentation.h" |
| 18 #include "cc/debug/traced_value.h" | 18 #include "cc/debug/traced_value.h" |
| 19 #include "cc/layers/picture_layer_impl.h" | 19 #include "cc/layers/picture_layer_impl.h" |
| 20 #include "cc/resources/raster_buffer.h" | 20 #include "cc/resources/raster_buffer.h" |
| 21 #include "cc/resources/rasterizer.h" | |
| 22 #include "cc/resources/tile.h" | 21 #include "cc/resources/tile.h" |
| 23 #include "cc/resources/tile_task_runner.h" | 22 #include "cc/resources/tile_task_runner.h" |
| 24 #include "ui/gfx/geometry/rect_conversions.h" | 23 #include "ui/gfx/geometry/rect_conversions.h" |
| 25 | 24 |
| 26 namespace cc { | 25 namespace cc { |
| 27 namespace { | 26 namespace { |
| 28 | 27 |
| 29 // Flag to indicate whether we should try and detect that | 28 // Flag to indicate whether we should try and detect that |
| 30 // a tile is of solid color. | 29 // a tile is of solid color. |
| 31 const bool kUseColorEstimator = true; | 30 const bool kUseColorEstimator = true; |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 state->SetInteger("canceled_count", stats.canceled_count); | 195 state->SetInteger("canceled_count", stats.canceled_count); |
| 197 return state; | 196 return state; |
| 198 } | 197 } |
| 199 | 198 |
| 200 // static | 199 // static |
| 201 scoped_ptr<TileManager> TileManager::Create( | 200 scoped_ptr<TileManager> TileManager::Create( |
| 202 TileManagerClient* client, | 201 TileManagerClient* client, |
| 203 base::SequencedTaskRunner* task_runner, | 202 base::SequencedTaskRunner* task_runner, |
| 204 ResourcePool* resource_pool, | 203 ResourcePool* resource_pool, |
| 205 TileTaskRunner* tile_task_runner, | 204 TileTaskRunner* tile_task_runner, |
| 206 Rasterizer* rasterizer, | |
| 207 size_t scheduled_raster_task_limit) { | 205 size_t scheduled_raster_task_limit) { |
| 208 return make_scoped_ptr(new TileManager(client, task_runner, resource_pool, | 206 return make_scoped_ptr(new TileManager(client, task_runner, resource_pool, |
| 209 tile_task_runner, rasterizer, | 207 tile_task_runner, |
| 210 scheduled_raster_task_limit)); | 208 scheduled_raster_task_limit)); |
| 211 } | 209 } |
| 212 | 210 |
| 213 TileManager::TileManager( | 211 TileManager::TileManager( |
| 214 TileManagerClient* client, | 212 TileManagerClient* client, |
| 215 const scoped_refptr<base::SequencedTaskRunner>& task_runner, | 213 const scoped_refptr<base::SequencedTaskRunner>& task_runner, |
| 216 ResourcePool* resource_pool, | 214 ResourcePool* resource_pool, |
| 217 TileTaskRunner* tile_task_runner, | 215 TileTaskRunner* tile_task_runner, |
| 218 Rasterizer* rasterizer, | |
| 219 size_t scheduled_raster_task_limit) | 216 size_t scheduled_raster_task_limit) |
| 220 : client_(client), | 217 : client_(client), |
| 221 task_runner_(task_runner), | 218 task_runner_(task_runner), |
| 222 resource_pool_(resource_pool), | 219 resource_pool_(resource_pool), |
| 223 tile_task_runner_(tile_task_runner), | 220 tile_task_runner_(tile_task_runner), |
| 224 rasterizer_(rasterizer), | |
| 225 scheduled_raster_task_limit_(scheduled_raster_task_limit), | 221 scheduled_raster_task_limit_(scheduled_raster_task_limit), |
| 226 all_tiles_that_need_to_be_rasterized_are_scheduled_(true), | 222 all_tiles_that_need_to_be_rasterized_are_scheduled_(true), |
| 227 did_check_for_completed_tasks_since_last_schedule_tasks_(true), | 223 did_check_for_completed_tasks_since_last_schedule_tasks_(true), |
| 228 did_oom_on_last_assign_(false), | 224 did_oom_on_last_assign_(false), |
| 229 ready_to_activate_notifier_( | |
| 230 task_runner_.get(), | |
| 231 base::Bind(&TileManager::NotifyReadyToActivate, | |
| 232 base::Unretained(this))), | |
| 233 ready_to_draw_notifier_( | |
| 234 task_runner_.get(), | |
| 235 base::Bind(&TileManager::NotifyReadyToDraw, base::Unretained(this))), | |
| 236 ready_to_activate_check_notifier_( | 225 ready_to_activate_check_notifier_( |
| 237 task_runner_.get(), | 226 task_runner_.get(), |
| 238 base::Bind(&TileManager::CheckIfReadyToActivate, | 227 base::Bind(&TileManager::CheckIfReadyToActivate, |
| 239 base::Unretained(this))), | 228 base::Unretained(this))), |
| 240 ready_to_draw_check_notifier_( | 229 ready_to_draw_check_notifier_( |
| 241 task_runner_.get(), | 230 task_runner_.get(), |
| 242 base::Bind(&TileManager::CheckIfReadyToDraw, base::Unretained(this))), | 231 base::Bind(&TileManager::CheckIfReadyToDraw, base::Unretained(this))), |
| 243 more_tiles_need_prepare_check_notifier_( | 232 more_tiles_need_prepare_check_notifier_( |
| 244 task_runner_.get(), | 233 task_runner_.get(), |
| 245 base::Bind(&TileManager::CheckIfMoreTilesNeedToBePrepared, | 234 base::Bind(&TileManager::CheckIfMoreTilesNeedToBePrepared, |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 | 330 |
| 342 NOTREACHED(); | 331 NOTREACHED(); |
| 343 } | 332 } |
| 344 | 333 |
| 345 void TileManager::PrepareTiles( | 334 void TileManager::PrepareTiles( |
| 346 const GlobalStateThatImpactsTilePriority& state) { | 335 const GlobalStateThatImpactsTilePriority& state) { |
| 347 TRACE_EVENT0("cc", "TileManager::PrepareTiles"); | 336 TRACE_EVENT0("cc", "TileManager::PrepareTiles"); |
| 348 | 337 |
| 349 global_state_ = state; | 338 global_state_ = state; |
| 350 | 339 |
| 351 PrepareTilesMode prepare_tiles_mode = rasterizer_->GetPrepareTilesMode(); | 340 // We need to call CheckForCompletedTasks() once in-between each call |
| 341 // to ScheduleTasks() to prevent canceled tasks from being scheduled. |
| 342 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { |
| 343 tile_task_runner_->CheckForCompletedTasks(); |
| 344 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| 345 } |
| 352 | 346 |
| 353 // TODO(hendrikw): Consider moving some of this code to the rasterizer. | 347 FreeResourcesForReleasedTiles(); |
| 354 if (prepare_tiles_mode != PrepareTilesMode::PREPARE_NONE) { | 348 CleanUpReleasedTiles(); |
| 355 // We need to call CheckForCompletedTasks() once in-between each call | |
| 356 // to ScheduleTasks() to prevent canceled tasks from being scheduled. | |
| 357 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { | |
| 358 tile_task_runner_->CheckForCompletedTasks(); | |
| 359 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | |
| 360 } | |
| 361 | 349 |
| 362 FreeResourcesForReleasedTiles(); | 350 TileVector tiles_that_need_to_be_rasterized; |
| 363 CleanUpReleasedTiles(); | 351 scoped_ptr<RasterTilePriorityQueue> raster_priority_queue( |
| 352 client_->BuildRasterQueue(global_state_.tree_priority, |
| 353 RasterTilePriorityQueue::Type::ALL)); |
| 354 AssignGpuMemoryToTiles(raster_priority_queue.get(), |
| 355 scheduled_raster_task_limit_, |
| 356 &tiles_that_need_to_be_rasterized); |
| 364 | 357 |
| 365 TileVector tiles_that_need_to_be_rasterized; | 358 // Inform the client that will likely require a draw if the highest priority |
| 366 scoped_ptr<RasterTilePriorityQueue> raster_priority_queue( | 359 // tile that will be rasterized is required for draw. |
| 367 client_->BuildRasterQueue(global_state_.tree_priority, | 360 client_->SetIsLikelyToRequireADraw( |
| 368 RasterTilePriorityQueue::Type::ALL)); | 361 !tiles_that_need_to_be_rasterized.empty() && |
| 369 AssignGpuMemoryToTiles(raster_priority_queue.get(), | 362 (*tiles_that_need_to_be_rasterized.begin())->required_for_draw()); |
| 370 scheduled_raster_task_limit_, | |
| 371 &tiles_that_need_to_be_rasterized); | |
| 372 | 363 |
| 373 // Inform the client that will likely require a draw if the highest priority | 364 // Schedule tile tasks. |
| 374 // tile that will be rasterized is required for draw. | 365 ScheduleTasks(tiles_that_need_to_be_rasterized); |
| 375 client_->SetIsLikelyToRequireADraw( | |
| 376 !tiles_that_need_to_be_rasterized.empty() && | |
| 377 (*tiles_that_need_to_be_rasterized.begin())->required_for_draw()); | |
| 378 | 366 |
| 379 // Schedule tile tasks. | 367 did_notify_ready_to_activate_ = false; |
| 380 ScheduleTasks(tiles_that_need_to_be_rasterized); | 368 did_notify_ready_to_draw_ = false; |
| 381 | |
| 382 did_notify_ready_to_activate_ = false; | |
| 383 did_notify_ready_to_draw_ = false; | |
| 384 } else { | |
| 385 if (global_state_.hard_memory_limit_in_bytes == 0) { | |
| 386 resource_pool_->CheckBusyResources(false); | |
| 387 MemoryUsage memory_limit(0, 0); | |
| 388 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), | |
| 389 resource_pool_->acquired_resource_count()); | |
| 390 FreeTileResourcesUntilUsageIsWithinLimit(nullptr, memory_limit, | |
| 391 &memory_usage); | |
| 392 } | |
| 393 | |
| 394 did_notify_ready_to_activate_ = false; | |
| 395 did_notify_ready_to_draw_ = false; | |
| 396 ready_to_activate_notifier_.Schedule(); | |
| 397 ready_to_draw_notifier_.Schedule(); | |
| 398 } | |
| 399 | 369 |
| 400 TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD, | 370 TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD, |
| 401 "state", BasicStateAsValue()); | 371 "state", BasicStateAsValue()); |
| 402 | 372 |
| 403 TRACE_COUNTER_ID1("cc", "unused_memory_bytes", this, | 373 TRACE_COUNTER_ID1("cc", "unused_memory_bytes", this, |
| 404 resource_pool_->total_memory_usage_bytes() - | 374 resource_pool_->total_memory_usage_bytes() - |
| 405 resource_pool_->acquired_memory_usage_bytes()); | |
| 406 } | |
| 407 | |
| 408 void TileManager::SynchronouslyRasterizeTiles( | |
| 409 const GlobalStateThatImpactsTilePriority& state) { | |
| 410 TRACE_EVENT0("cc", "TileManager::SynchronouslyRasterizeTiles"); | |
| 411 | |
| 412 DCHECK(rasterizer_->GetPrepareTilesMode() != | |
| 413 PrepareTilesMode::RASTERIZE_PRIORITIZED_TILES); | |
| 414 | |
| 415 global_state_ = state; | |
| 416 | |
| 417 FreeResourcesForReleasedTiles(); | |
| 418 CleanUpReleasedTiles(); | |
| 419 | |
| 420 scoped_ptr<RasterTilePriorityQueue> required_for_draw_queue( | |
| 421 client_->BuildRasterQueue( | |
| 422 global_state_.tree_priority, | |
| 423 RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW)); | |
| 424 TileVector tiles_that_need_to_be_rasterized; | |
| 425 AssignGpuMemoryToTiles(required_for_draw_queue.get(), | |
| 426 std::numeric_limits<size_t>::max(), | |
| 427 &tiles_that_need_to_be_rasterized); | |
| 428 | |
| 429 // Since we are synchronously rasterizing all tiles, we don't require further | |
| 430 // draws for that. Set the flag to false so that we can clear it if it was set | |
| 431 // earlier by PrepareTiles. | |
| 432 client_->SetIsLikelyToRequireADraw(false); | |
| 433 | |
| 434 // We must reduce the amount of unused resources before calling | |
| 435 // RunTasks to prevent usage from rising above limits. | |
| 436 resource_pool_->ReduceResourceUsage(); | |
| 437 | |
| 438 // Run and complete all raster task synchronously. | |
| 439 rasterizer_->RasterizeTiles( | |
| 440 tiles_that_need_to_be_rasterized, resource_pool_, | |
| 441 tile_task_runner_->GetResourceFormat(), | |
| 442 base::Bind(&TileManager::UpdateTileDrawInfo, base::Unretained(this))); | |
| 443 | |
| 444 // Use on-demand raster for any required-for-draw tiles that have not been | |
| 445 // assigned memory after reaching a steady memory state. | |
| 446 // TODO(hendrikw): Figure out why this would improve jank on some tests - See | |
| 447 // crbug.com/449288 | |
| 448 required_for_draw_queue = client_->BuildRasterQueue( | |
| 449 global_state_.tree_priority, | |
| 450 RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); | |
| 451 | |
| 452 // Change to OOM mode for any tiles that have not been been assigned memory. | |
| 453 // This ensures that we draw even when OOM. | |
| 454 for (; !required_for_draw_queue->IsEmpty(); required_for_draw_queue->Pop()) { | |
| 455 Tile* tile = required_for_draw_queue->Top(); | |
| 456 tile->draw_info().set_oom(); | |
| 457 client_->NotifyTileStateChanged(tile); | |
| 458 } | |
| 459 | |
| 460 TRACE_EVENT_INSTANT1("cc", "DidRasterize", TRACE_EVENT_SCOPE_THREAD, "state", | |
| 461 BasicStateAsValue()); | |
| 462 | |
| 463 TRACE_COUNTER_ID1("cc", "unused_memory_bytes", this, | |
| 464 resource_pool_->total_memory_usage_bytes() - | |
| 465 resource_pool_->acquired_memory_usage_bytes()); | 375 resource_pool_->acquired_memory_usage_bytes()); |
| 466 } | 376 } |
| 467 | 377 |
| 468 void TileManager::UpdateVisibleTiles( | 378 void TileManager::UpdateVisibleTiles( |
| 469 const GlobalStateThatImpactsTilePriority& state) { | 379 const GlobalStateThatImpactsTilePriority& state) { |
| 470 TRACE_EVENT0("cc", "TileManager::UpdateVisibleTiles"); | 380 TRACE_EVENT0("cc", "TileManager::UpdateVisibleTiles"); |
| 471 | 381 |
| 472 tile_task_runner_->CheckForCompletedTasks(); | 382 tile_task_runner_->CheckForCompletedTasks(); |
| 473 | 383 |
| 474 DCHECK(rasterizer_); | |
| 475 PrepareTilesMode prepare_tiles_mode = rasterizer_->GetPrepareTilesMode(); | |
| 476 if (prepare_tiles_mode != PrepareTilesMode::RASTERIZE_PRIORITIZED_TILES) | |
| 477 SynchronouslyRasterizeTiles(state); | |
| 478 | |
| 479 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 384 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| 480 | 385 |
| 481 TRACE_EVENT_INSTANT1( | 386 TRACE_EVENT_INSTANT1( |
| 482 "cc", | 387 "cc", |
| 483 "DidUpdateVisibleTiles", | 388 "DidUpdateVisibleTiles", |
| 484 TRACE_EVENT_SCOPE_THREAD, | 389 TRACE_EVENT_SCOPE_THREAD, |
| 485 "stats", | 390 "stats", |
| 486 RasterTaskCompletionStatsAsValue(update_visible_tiles_stats_)); | 391 RasterTaskCompletionStatsAsValue(update_visible_tiles_stats_)); |
| 487 update_visible_tiles_stats_ = RasterTaskCompletionStats(); | 392 update_visible_tiles_stats_ = RasterTaskCompletionStats(); |
| 488 } | 393 } |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 result -= other; | 969 result -= other; |
| 1065 return result; | 970 return result; |
| 1066 } | 971 } |
| 1067 | 972 |
| 1068 bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const { | 973 bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const { |
| 1069 return memory_bytes_ > limit.memory_bytes_ || | 974 return memory_bytes_ > limit.memory_bytes_ || |
| 1070 resource_count_ > limit.resource_count_; | 975 resource_count_ > limit.resource_count_; |
| 1071 } | 976 } |
| 1072 | 977 |
| 1073 } // namespace cc | 978 } // namespace cc |
| OLD | NEW |