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

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

Issue 62283012: cc: Added tile bundles (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month 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
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 "cc/debug/devtools_instrumentation.h" 15 #include "cc/debug/devtools_instrumentation.h"
16 #include "cc/debug/traced_value.h" 16 #include "cc/debug/traced_value.h"
17 #include "cc/resources/image_raster_worker_pool.h" 17 #include "cc/resources/image_raster_worker_pool.h"
18 #include "cc/resources/pixel_buffer_raster_worker_pool.h" 18 #include "cc/resources/pixel_buffer_raster_worker_pool.h"
19 #include "cc/resources/shared_tile_bundle.h"
19 #include "cc/resources/tile.h" 20 #include "cc/resources/tile.h"
20 #include "third_party/skia/include/core/SkCanvas.h" 21 #include "third_party/skia/include/core/SkCanvas.h"
21 #include "ui/gfx/rect_conversions.h" 22 #include "ui/gfx/rect_conversions.h"
22 23
23 namespace cc { 24 namespace cc {
24 25
25 namespace { 26 namespace {
26 27
27 // Memory limit policy works by mapping some bin states to the NEVER bin. 28 // Memory limit policy works by mapping some bin states to the NEVER bin.
28 const ManagedTileBin kBinPolicyMap[NUM_TILE_MEMORY_LIMIT_POLICIES][NUM_BINS] = { 29 const ManagedTileBin kBinPolicyMap[NUM_TILE_MEMORY_LIMIT_POLICIES][NUM_BINS] = {
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 did_check_for_completed_tasks_since_last_schedule_tasks_(true) { 213 did_check_for_completed_tasks_since_last_schedule_tasks_(true) {
213 raster_worker_pool_->SetClient(this); 214 raster_worker_pool_->SetClient(this);
214 } 215 }
215 216
216 TileManager::~TileManager() { 217 TileManager::~TileManager() {
217 // Reset global state and manage. This should cause 218 // Reset global state and manage. This should cause
218 // our memory usage to drop to zero. 219 // our memory usage to drop to zero.
219 global_state_ = GlobalStateThatImpactsTilePriority(); 220 global_state_ = GlobalStateThatImpactsTilePriority();
220 221
221 CleanUpReleasedTiles(); 222 CleanUpReleasedTiles();
223 DCHECK_EQ(0u, bundles_.size());
222 DCHECK_EQ(0u, tiles_.size()); 224 DCHECK_EQ(0u, tiles_.size());
223 225
224 RasterWorkerPool::RasterTask::Queue empty; 226 RasterWorkerPool::RasterTask::Queue empty;
225 raster_worker_pool_->ScheduleTasks(&empty); 227 raster_worker_pool_->ScheduleTasks(&empty);
226 228
227 // This should finish all pending tasks and release any uninitialized 229 // This should finish all pending tasks and release any uninitialized
228 // resources. 230 // resources.
229 raster_worker_pool_->Shutdown(); 231 raster_worker_pool_->Shutdown();
230 raster_worker_pool_->CheckForCompletedTasks(); 232 raster_worker_pool_->CheckForCompletedTasks();
231 233
232 DCHECK_EQ(0u, bytes_releasable_); 234 DCHECK_EQ(0u, bytes_releasable_);
233 DCHECK_EQ(0u, resources_releasable_); 235 DCHECK_EQ(0u, resources_releasable_);
234 } 236 }
235 237
236 void TileManager::Release(Tile* tile) { 238 void TileManager::Release(Tile* tile) {
237 prioritized_tiles_dirty_ = true; 239 prioritized_tiles_dirty_ = true;
238 released_tiles_.push_back(tile); 240 released_tiles_.push_back(tile);
239 } 241 }
240 242
243 void TileManager::Release(TileBundle* bundle) {
244 released_tile_bundles_.push_back(bundle);
245 }
246
241 void TileManager::DidChangeTilePriority(Tile* tile) { 247 void TileManager::DidChangeTilePriority(Tile* tile) {
242 prioritized_tiles_dirty_ = true; 248 prioritized_tiles_dirty_ = true;
243 } 249 }
244 250
245 bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const { 251 bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const {
246 return global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY; 252 return global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY;
247 } 253 }
248 254
249 void TileManager::CleanUpReleasedTiles() { 255 void TileManager::CleanUpReleasedTiles() {
256 // Clean up bundles first, since they might have tiles that will become
257 // released as well.
258 for (std::vector<TileBundle*>::iterator it = released_tile_bundles_.begin();
259 it != released_tile_bundles_.end();
260 ++it) {
261 TileBundle* bundle = *it;
262 DCHECK(bundles_.find(bundle->id()) != bundles_.end());
263 bundles_.erase(bundle->id());
264 delete bundle;
265 }
266 released_tile_bundles_.clear();
267
250 for (std::vector<Tile*>::iterator it = released_tiles_.begin(); 268 for (std::vector<Tile*>::iterator it = released_tiles_.begin();
251 it != released_tiles_.end(); 269 it != released_tiles_.end();
252 ++it) { 270 ++it) {
253 Tile* tile = *it; 271 Tile* tile = *it;
254 272
255 FreeResourcesForTile(tile); 273 FreeResourcesForTile(tile);
256 274
257 DCHECK(tiles_.find(tile->id()) != tiles_.end()); 275 DCHECK(tiles_.find(tile->id()) != tiles_.end());
258 tiles_.erase(tile->id()); 276 tiles_.erase(tile->id());
259 277
260 LayerCountMap::iterator layer_it = 278 LayerCountMap::iterator layer_it =
261 used_layer_counts_.find(tile->layer_id()); 279 used_layer_counts_.find(tile->layer_id());
262 DCHECK_GT(layer_it->second, 0); 280 DCHECK_GT(layer_it->second, 0);
263 if (--layer_it->second == 0) { 281 if (--layer_it->second == 0) {
264 used_layer_counts_.erase(layer_it); 282 used_layer_counts_.erase(layer_it);
265 image_decode_tasks_.erase(tile->layer_id()); 283 image_decode_tasks_.erase(tile->layer_id());
266 } 284 }
267 285
268 delete tile; 286 delete tile;
269 } 287 }
270
271 released_tiles_.clear(); 288 released_tiles_.clear();
272 } 289 }
273 290
274 void TileManager::UpdatePrioritizedTileSetIfNeeded() { 291 void TileManager::UpdatePrioritizedTileSetIfNeeded() {
275 if (!prioritized_tiles_dirty_) 292 if (!prioritized_tiles_dirty_)
276 return; 293 return;
277 294
278 CleanUpReleasedTiles(); 295 CleanUpReleasedTiles();
279 296
280 prioritized_tiles_.Clear(); 297 prioritized_tiles_.Clear();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins"); 363 TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins");
347 364
348 // Compute new stats to be return by GetMemoryStats(). 365 // Compute new stats to be return by GetMemoryStats().
349 memory_required_bytes_ = 0; 366 memory_required_bytes_ = 0;
350 memory_nice_to_have_bytes_ = 0; 367 memory_nice_to_have_bytes_ = 0;
351 368
352 const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy; 369 const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy;
353 const TreePriority tree_priority = global_state_.tree_priority; 370 const TreePriority tree_priority = global_state_.tree_priority;
354 371
355 // For each tree, bin into different categories of tiles. 372 // For each tree, bin into different categories of tiles.
356 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { 373 for (BundleSetIterator bundle_it(&bundles_); bundle_it; ++bundle_it) {
357 Tile* tile = it->second; 374 TilePriority active_priority = bundle_it->active_priority();
358 ManagedTileState& mts = tile->managed_state(); 375 TilePriority pending_priority = bundle_it->pending_priority();
376 TilePriority combined_priority(active_priority, pending_priority);
377 ManagedTileBin base_active_bin = BinFromTilePriority(active_priority);
378 ManagedTileBin base_pending_bin = BinFromTilePriority(pending_priority);
359 379
360 const ManagedTileState::TileVersion& tile_version = 380 for (SharedTileBundle::Iterator it(*bundle_it); it; ++it) {
361 tile->GetTileVersionForDrawing(); 381 Tile* tile = *it;
362 bool tile_is_ready_to_draw = tile_version.IsReadyToDraw(); 382 tile->set_is_visible(active_priority.distance_to_visible_in_pixels == 0);
363 bool tile_is_active = 383 ManagedTileState& mts = tile->managed_state();
364 tile_is_ready_to_draw ||
365 !mts.tile_versions[mts.raster_mode].raster_task_.is_null();
366 384
367 // Get the active priority and bin. 385 const ManagedTileState::TileVersion& tile_version =
368 TilePriority active_priority = tile->priority(ACTIVE_TREE); 386 tile->GetTileVersionForDrawing();
369 ManagedTileBin active_bin = BinFromTilePriority(active_priority); 387 bool tile_is_ready_to_draw = tile_version.IsReadyToDraw();
388 bool tile_is_active =
389 tile_is_ready_to_draw ||
390 !mts.tile_versions[mts.raster_mode].raster_task_.is_null();
370 391
371 // Get the pending priority and bin. 392 ManagedTileBin active_bin = base_active_bin;
372 TilePriority pending_priority = tile->priority(PENDING_TREE); 393 ManagedTileBin pending_bin = base_pending_bin;
373 ManagedTileBin pending_bin = BinFromTilePriority(pending_priority);
374 394
375 // Adjust pending bin state for low res tiles. This prevents 395 // Adjust pending bin state for low res tiles. This prevents
376 // pending tree low-res tiles from being initialized before 396 // pending tree low-res tiles from being initialized before
377 // high-res tiles. 397 // high-res tiles.
378 if (pending_priority.resolution == LOW_RESOLUTION) 398 if (pending_priority.resolution == LOW_RESOLUTION)
379 pending_bin = std::max(pending_bin, EVENTUALLY_BIN); 399 pending_bin = std::max(pending_bin, EVENTUALLY_BIN);
380 400
381 // Compute combined bin. 401 // Compute combined bin.
382 ManagedTileBin combined_bin = std::min(active_bin, pending_bin); 402 ManagedTileBin combined_bin = std::min(active_bin, pending_bin);
383 403
384 // Adjust bin state based on if ready to draw. 404 // Adjust bin state based on if ready to draw.
385 active_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][active_bin]; 405 active_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][active_bin];
enne (OOO) 2013/11/20 21:20:30 Ugh, all this logic is so complicated. Maybe afte
386 pending_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][pending_bin]; 406 pending_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][pending_bin];
387 combined_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][combined_bin]; 407 combined_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][combined_bin];
388 408
389 // Adjust bin state based on if active. 409 // Adjust bin state based on if active.
390 active_bin = kBinIsActiveMap[tile_is_active][active_bin]; 410 active_bin = kBinIsActiveMap[tile_is_active][active_bin];
391 pending_bin = kBinIsActiveMap[tile_is_active][pending_bin]; 411 pending_bin = kBinIsActiveMap[tile_is_active][pending_bin];
392 combined_bin = kBinIsActiveMap[tile_is_active][combined_bin]; 412 combined_bin = kBinIsActiveMap[tile_is_active][combined_bin];
393 413
394 ManagedTileBin tree_bin[NUM_TREES]; 414 ManagedTileBin tree_bin[NUM_TREES];
395 tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin]; 415 tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin];
396 tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin]; 416 tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin];
397 417
398 // The bin that the tile would have if the GPU memory manager had 418 // The bin that the tile would have if the GPU memory manager had
399 // a maximally permissive policy, send to the GPU memory manager 419 // a maximally permissive policy, send to the GPU memory manager
400 // to determine policy. 420 // to determine policy.
401 ManagedTileBin gpu_memmgr_stats_bin = NEVER_BIN; 421 ManagedTileBin gpu_memmgr_stats_bin = NEVER_BIN;
402 TilePriority tile_priority; 422 TilePriority tile_priority;
403 423
404 switch (tree_priority) { 424 switch (tree_priority) {
405 case SAME_PRIORITY_FOR_BOTH_TREES: 425 case SAME_PRIORITY_FOR_BOTH_TREES:
406 mts.bin = kBinPolicyMap[memory_policy][combined_bin]; 426 mts.bin = kBinPolicyMap[memory_policy][combined_bin];
407 gpu_memmgr_stats_bin = combined_bin; 427 gpu_memmgr_stats_bin = combined_bin;
408 tile_priority = tile->combined_priority(); 428 tile_priority = combined_priority;
409 break; 429 break;
410 case SMOOTHNESS_TAKES_PRIORITY: 430 case SMOOTHNESS_TAKES_PRIORITY:
411 mts.bin = tree_bin[ACTIVE_TREE]; 431 mts.bin = tree_bin[ACTIVE_TREE];
412 gpu_memmgr_stats_bin = active_bin; 432 gpu_memmgr_stats_bin = active_bin;
413 tile_priority = active_priority; 433 tile_priority = active_priority;
414 break; 434 break;
415 case NEW_CONTENT_TAKES_PRIORITY: 435 case NEW_CONTENT_TAKES_PRIORITY:
416 mts.bin = tree_bin[PENDING_TREE]; 436 mts.bin = tree_bin[PENDING_TREE];
417 gpu_memmgr_stats_bin = pending_bin; 437 gpu_memmgr_stats_bin = pending_bin;
418 tile_priority = pending_priority; 438 tile_priority = pending_priority;
419 break; 439 break;
440 }
441
442 if (!tile_is_ready_to_draw || tile_version.requires_resource()) {
443 if ((gpu_memmgr_stats_bin == NOW_BIN) ||
444 (gpu_memmgr_stats_bin == NOW_AND_READY_TO_DRAW_BIN))
445 memory_required_bytes_ += BytesConsumedIfAllocated(tile);
446 if (gpu_memmgr_stats_bin != NEVER_BIN)
447 memory_nice_to_have_bytes_ += BytesConsumedIfAllocated(tile);
448 }
449
450 // Bump up the priority if we determined it's NEVER_BIN on one tree,
451 // but is still required on the other tree.
452 bool is_in_never_bin_on_both_trees =
453 tree_bin[ACTIVE_TREE] == NEVER_BIN &&
454 tree_bin[PENDING_TREE] == NEVER_BIN;
455
456 if (mts.bin == NEVER_BIN && !is_in_never_bin_on_both_trees)
457 mts.bin = tile_is_active ? AT_LAST_AND_ACTIVE_BIN : AT_LAST_BIN;
458
459 mts.resolution = tile_priority.resolution;
460 mts.time_to_needed_in_seconds = tile_priority.time_to_visible_in_seconds;
461 mts.distance_to_visible_in_pixels =
462 tile_priority.distance_to_visible_in_pixels;
463 mts.required_for_activation = tile_priority.required_for_activation;
464
465 mts.visible_and_ready_to_draw =
466 tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN;
467
468 if (mts.bin == NEVER_BIN) {
469 FreeResourcesForTile(tile);
470 continue;
471 }
472
473 // Note that if the tile is visible_and_ready_to_draw, then we always want
474 // the priority to be NOW_AND_READY_TO_DRAW_BIN, even if HIGH_PRIORITY_BIN
475 // is something different. The reason for this is that if we're
476 // prioritizing the pending tree, we still want visible tiles to take the
477 // highest priority.
478 ManagedTileBin priority_bin = mts.visible_and_ready_to_draw
479 ? NOW_AND_READY_TO_DRAW_BIN
480 : mts.bin;
481
482 // Insert the tile into a priority set.
483 tiles->InsertTile(tile, priority_bin);
enne (OOO) 2013/11/20 00:14:34 Curious why tiles are in bins and not bundles, sin
vmpstr 2013/11/20 00:54:09 There's a few cases (namely required for activatio
420 } 484 }
421
422 if (!tile_is_ready_to_draw || tile_version.requires_resource()) {
423 if ((gpu_memmgr_stats_bin == NOW_BIN) ||
424 (gpu_memmgr_stats_bin == NOW_AND_READY_TO_DRAW_BIN))
425 memory_required_bytes_ += BytesConsumedIfAllocated(tile);
426 if (gpu_memmgr_stats_bin != NEVER_BIN)
427 memory_nice_to_have_bytes_ += BytesConsumedIfAllocated(tile);
428 }
429
430 // Bump up the priority if we determined it's NEVER_BIN on one tree,
431 // but is still required on the other tree.
432 bool is_in_never_bin_on_both_trees =
433 tree_bin[ACTIVE_TREE] == NEVER_BIN &&
434 tree_bin[PENDING_TREE] == NEVER_BIN;
435
436 if (mts.bin == NEVER_BIN && !is_in_never_bin_on_both_trees)
437 mts.bin = tile_is_active ? AT_LAST_AND_ACTIVE_BIN : AT_LAST_BIN;
438
439 mts.resolution = tile_priority.resolution;
440 mts.time_to_needed_in_seconds = tile_priority.time_to_visible_in_seconds;
441 mts.distance_to_visible_in_pixels =
442 tile_priority.distance_to_visible_in_pixels;
443 mts.required_for_activation = tile_priority.required_for_activation;
444
445 mts.visible_and_ready_to_draw =
446 tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN;
447
448 if (mts.bin == NEVER_BIN) {
449 FreeResourcesForTile(tile);
450 continue;
451 }
452
453 // Note that if the tile is visible_and_ready_to_draw, then we always want
454 // the priority to be NOW_AND_READY_TO_DRAW_BIN, even if HIGH_PRIORITY_BIN
455 // is something different. The reason for this is that if we're prioritizing
456 // the pending tree, we still want visible tiles to take the highest
457 // priority.
458 ManagedTileBin priority_bin = mts.visible_and_ready_to_draw
459 ? NOW_AND_READY_TO_DRAW_BIN
460 : mts.bin;
461
462 // Insert the tile into a priority set.
463 tiles->InsertTile(tile, priority_bin);
464 } 485 }
465 } 486 }
466 487
467 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { 488 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) {
468 TRACE_EVENT0("cc", "TileManager::ManageTiles"); 489 TRACE_EVENT0("cc", "TileManager::ManageTiles");
469 490
470 // Update internal state. 491 // Update internal state.
471 if (state != global_state_) { 492 if (state != global_state_) {
472 global_state_ = state; 493 global_state_ = state;
473 prioritized_tiles_dirty_ = true; 494 prioritized_tiles_dirty_ = true;
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 resource_pool_->ReleaseResource(resource.Pass()); 958 resource_pool_->ReleaseResource(resource.Pass());
938 } else { 959 } else {
939 tile_version.set_use_resource(); 960 tile_version.set_use_resource();
940 tile_version.resource_ = resource.Pass(); 961 tile_version.resource_ = resource.Pass();
941 962
942 bytes_releasable_ += BytesConsumedIfAllocated(tile); 963 bytes_releasable_ += BytesConsumedIfAllocated(tile);
943 ++resources_releasable_; 964 ++resources_releasable_;
944 } 965 }
945 966
946 FreeUnusedResourcesForTile(tile); 967 FreeUnusedResourcesForTile(tile);
947 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0) 968 if (tile->is_visible() == 0)
reveman 2013/11/20 01:34:37 is_visible() returning 0 means tile is visible?
948 did_initialize_visible_tile_ = true; 969 did_initialize_visible_tile_ = true;
949 } 970 }
950 971
951 scoped_refptr<Tile> TileManager::CreateTile(PicturePileImpl* picture_pile, 972 scoped_refptr<Tile> TileManager::CreateTile(PicturePileImpl* picture_pile,
952 gfx::Size tile_size, 973 gfx::Size tile_size,
953 gfx::Rect content_rect, 974 gfx::Rect content_rect,
954 gfx::Rect opaque_rect, 975 gfx::Rect opaque_rect,
955 float contents_scale, 976 float contents_scale,
956 int layer_id, 977 int layer_id,
957 int source_frame_number, 978 int source_frame_number,
958 bool can_use_lcd_text) { 979 bool can_use_lcd_text) {
959 scoped_refptr<Tile> tile = make_scoped_refptr(new Tile(this, 980 scoped_refptr<Tile> tile = make_scoped_refptr(new Tile(this,
960 picture_pile, 981 picture_pile,
961 tile_size, 982 tile_size,
962 content_rect, 983 content_rect,
963 opaque_rect, 984 opaque_rect,
964 contents_scale, 985 contents_scale,
965 layer_id, 986 layer_id,
966 source_frame_number, 987 source_frame_number,
967 can_use_lcd_text)); 988 can_use_lcd_text));
968 DCHECK(tiles_.find(tile->id()) == tiles_.end()); 989 DCHECK(tiles_.find(tile->id()) == tiles_.end());
969 990
970 tiles_[tile->id()] = tile; 991 tiles_[tile->id()] = tile;
971 used_layer_counts_[tile->layer_id()]++; 992 used_layer_counts_[tile->layer_id()]++;
972 prioritized_tiles_dirty_ = true; 993 prioritized_tiles_dirty_ = true;
973 return tile; 994 return tile;
974 } 995 }
975 996
997 scoped_refptr<TileBundle> TileManager::CreateTileBundle(int width,
998 int height,
999 int offset_x,
1000 int offset_y) {
1001 scoped_refptr<TileBundle> bundle = make_scoped_refptr(
1002 new TileBundle(this, width, height, offset_x, offset_y));
1003 bundles_[bundle->id()] = bundle;
1004 return bundle;
1005 }
1006
976 } // namespace cc 1007 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698