OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/tile_manager.h" | 5 #include "cc/tile_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 state->Set("resolution", TileResolutionAsValue(resolution).release()); | 170 state->Set("resolution", TileResolutionAsValue(resolution).release()); |
171 state->Set("time_to_needed_in_seconds", MathUtil::asValueSafely(time_to_needed
_in_seconds).release()); | 171 state->Set("time_to_needed_in_seconds", MathUtil::asValueSafely(time_to_needed
_in_seconds).release()); |
172 state->Set("distance_to_visible_in_pixels", MathUtil::asValueSafely(distance_t
o_visible_in_pixels).release()); | 172 state->Set("distance_to_visible_in_pixels", MathUtil::asValueSafely(distance_t
o_visible_in_pixels).release()); |
173 return state.PassAs<base::Value>(); | 173 return state.PassAs<base::Value>(); |
174 } | 174 } |
175 | 175 |
176 TileManager::TileManager( | 176 TileManager::TileManager( |
177 TileManagerClient* client, | 177 TileManagerClient* client, |
178 ResourceProvider* resource_provider, | 178 ResourceProvider* resource_provider, |
179 size_t num_raster_threads, | 179 size_t num_raster_threads, |
180 bool use_cheapness_estimator) | 180 bool use_cheapness_estimator, |
| 181 bool use_color_estimator, |
| 182 bool prediction_benchmarking) |
181 : client_(client), | 183 : client_(client), |
182 resource_pool_(ResourcePool::Create(resource_provider)), | 184 resource_pool_(ResourcePool::Create(resource_provider)), |
183 raster_worker_pool_(RasterWorkerPool::Create(this, num_raster_threads)), | 185 raster_worker_pool_(RasterWorkerPool::Create(this, num_raster_threads)), |
184 manage_tiles_pending_(false), | 186 manage_tiles_pending_(false), |
185 manage_tiles_call_count_(0), | 187 manage_tiles_call_count_(0), |
186 bytes_pending_upload_(0), | 188 bytes_pending_upload_(0), |
187 has_performed_uploads_since_last_flush_(false), | 189 has_performed_uploads_since_last_flush_(false), |
188 ever_exceeded_memory_budget_(false), | 190 ever_exceeded_memory_budget_(false), |
189 record_rendering_stats_(false), | 191 record_rendering_stats_(false), |
190 use_cheapness_estimator_(use_cheapness_estimator), | 192 use_cheapness_estimator_(use_cheapness_estimator), |
| 193 use_color_estimator_(use_color_estimator), |
191 allow_cheap_tasks_(true), | 194 allow_cheap_tasks_(true), |
192 did_schedule_cheap_tasks_(false) { | 195 did_schedule_cheap_tasks_(false), |
| 196 prediction_benchmarking_(prediction_benchmarking) { |
193 for (int i = 0; i < NUM_STATES; ++i) { | 197 for (int i = 0; i < NUM_STATES; ++i) { |
194 for (int j = 0; j < NUM_TREES; ++j) { | 198 for (int j = 0; j < NUM_TREES; ++j) { |
195 for (int k = 0; k < NUM_BINS; ++k) | 199 for (int k = 0; k < NUM_BINS; ++k) |
196 raster_state_count_[i][j][k] = 0; | 200 raster_state_count_[i][j][k] = 0; |
197 } | 201 } |
198 } | 202 } |
199 } | 203 } |
200 | 204 |
201 TileManager::~TileManager() { | 205 TileManager::~TileManager() { |
202 // Reset global state and manage. This should cause | 206 // Reset global state and manage. This should cause |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 DidTileTreeBinChange(tile, | 368 DidTileTreeBinChange(tile, |
365 bin_map[BinFromTilePriority(tile->priority(ACTIVE_TREE))], | 369 bin_map[BinFromTilePriority(tile->priority(ACTIVE_TREE))], |
366 ACTIVE_TREE); | 370 ACTIVE_TREE); |
367 DidTileTreeBinChange(tile, | 371 DidTileTreeBinChange(tile, |
368 bin_map[BinFromTilePriority(tile->priority(PENDING_TREE))], | 372 bin_map[BinFromTilePriority(tile->priority(PENDING_TREE))], |
369 PENDING_TREE); | 373 PENDING_TREE); |
370 | 374 |
371 for (int i = 0; i < NUM_BIN_PRIORITIES; ++i) | 375 for (int i = 0; i < NUM_BIN_PRIORITIES; ++i) |
372 mts.bin[i] = bin_map[mts.bin[i]]; | 376 mts.bin[i] = bin_map[mts.bin[i]]; |
373 | 377 |
374 if (tile->priority(ACTIVE_TREE).is_live || | 378 if (tile->managed_state().resource || |
375 tile->priority(PENDING_TREE).is_live || | |
376 tile->managed_state().resource || | |
377 tile->managed_state().resource_is_being_initialized) { | 379 tile->managed_state().resource_is_being_initialized) { |
378 live_or_allocated_tiles_.push_back(tile); | 380 live_or_allocated_tiles_.push_back(tile); |
| 381 } else if (tile->priority(ACTIVE_TREE).is_live || |
| 382 tile->priority(PENDING_TREE).is_live) { |
| 383 bool is_cheap = use_cheapness_estimator_ && |
| 384 tile->picture_pile()->IsCheapInRect(tile->content_rect(), |
| 385 tile->contents_scale()); |
| 386 tile->set_cheap(is_cheap); |
| 387 if (use_color_estimator_) { |
| 388 SkColor color; |
| 389 bool is_solid_color = tile->picture_pile()->GetColorIfSolidInRect( |
| 390 tile->content_rect(), |
| 391 tile->contents_scale(), |
| 392 &color); |
| 393 if (is_solid_color) |
| 394 tile->set_solid_color(color); |
| 395 |
| 396 bool is_transparent = tile->picture_pile()->IsTransparentInRect( |
| 397 tile->content_rect(), |
| 398 tile->contents_scale()); |
| 399 tile->set_transparent(is_transparent); |
| 400 } |
| 401 live_or_allocated_tiles_.push_back(tile); |
379 } | 402 } |
380 } | 403 } |
381 TRACE_COUNTER_ID1("cc", "LiveOrAllocatedTileCount", this, | 404 TRACE_COUNTER_ID1("cc", "LiveOrAllocatedTileCount", this, |
382 live_or_allocated_tiles_.size()); | 405 live_or_allocated_tiles_.size()); |
383 | 406 |
384 SortTiles(); | 407 SortTiles(); |
385 | 408 |
386 // Assign gpu memory and determine what tiles need to be rasterized. | 409 // Assign gpu memory and determine what tiles need to be rasterized. |
387 AssignGpuMemoryToTiles(); | 410 AssignGpuMemoryToTiles(); |
388 | 411 |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 // By clearing the tiles_that_need_to_be_rasterized_ vector and | 595 // By clearing the tiles_that_need_to_be_rasterized_ vector and |
573 // tiles_with_image_decoding_tasks_ list above we move all tiles | 596 // tiles_with_image_decoding_tasks_ list above we move all tiles |
574 // currently waiting for raster to idle state. | 597 // currently waiting for raster to idle state. |
575 // Call DidTileRasterStateChange() for each of these tiles to | 598 // Call DidTileRasterStateChange() for each of these tiles to |
576 // have this state change take effect. | 599 // have this state change take effect. |
577 // Some memory cannot be released. We figure out how much in this | 600 // Some memory cannot be released. We figure out how much in this |
578 // loop as well. | 601 // loop as well. |
579 for (TileVector::iterator it = live_or_allocated_tiles_.begin(); | 602 for (TileVector::iterator it = live_or_allocated_tiles_.begin(); |
580 it != live_or_allocated_tiles_.end(); ++it) { | 603 it != live_or_allocated_tiles_.end(); ++it) { |
581 Tile* tile = *it; | 604 Tile* tile = *it; |
| 605 if (tile->is_solid_color() || tile->is_transparent()) |
| 606 continue; |
582 if (!tile->managed_state().can_be_freed) | 607 if (!tile->managed_state().can_be_freed) |
583 unreleasable_bytes += tile->bytes_consumed_if_allocated(); | 608 unreleasable_bytes += tile->bytes_consumed_if_allocated(); |
584 if (tile->managed_state().raster_state == WAITING_FOR_RASTER_STATE) | 609 if (tile->managed_state().raster_state == WAITING_FOR_RASTER_STATE) |
585 DidTileRasterStateChange(tile, IDLE_STATE); | 610 DidTileRasterStateChange(tile, IDLE_STATE); |
586 } | 611 } |
587 | 612 |
588 size_t bytes_allocatable = global_state_.memory_limit_in_bytes - unreleasable_
bytes; | 613 size_t bytes_allocatable = global_state_.memory_limit_in_bytes - unreleasable_
bytes; |
589 size_t bytes_that_exceeded_memory_budget_in_now_bin = 0; | 614 size_t bytes_that_exceeded_memory_budget_in_now_bin = 0; |
590 size_t bytes_left = bytes_allocatable; | 615 size_t bytes_left = bytes_allocatable; |
591 for (TileVector::iterator it = live_or_allocated_tiles_.begin(); it != live_or
_allocated_tiles_.end(); ++it) { | 616 for (TileVector::iterator it = live_or_allocated_tiles_.begin(); it != live_or
_allocated_tiles_.end(); ++it) { |
592 Tile* tile = *it; | 617 Tile* tile = *it; |
| 618 if (tile->is_solid_color() || tile->is_transparent()) |
| 619 continue; |
| 620 |
593 size_t tile_bytes = tile->bytes_consumed_if_allocated(); | 621 size_t tile_bytes = tile->bytes_consumed_if_allocated(); |
594 ManagedTileState& managed_tile_state = tile->managed_state(); | 622 ManagedTileState& managed_tile_state = tile->managed_state(); |
595 if (!managed_tile_state.can_be_freed) | 623 if (!managed_tile_state.can_be_freed) |
596 continue; | 624 continue; |
597 if (managed_tile_state.bin[HIGH_PRIORITY_BIN] == NEVER_BIN && | 625 if (managed_tile_state.bin[HIGH_PRIORITY_BIN] == NEVER_BIN && |
598 managed_tile_state.bin[LOW_PRIORITY_BIN] == NEVER_BIN) { | 626 managed_tile_state.bin[LOW_PRIORITY_BIN] == NEVER_BIN) { |
599 managed_tile_state.can_use_gpu_memory = false; | 627 managed_tile_state.can_use_gpu_memory = false; |
600 FreeResourcesForTile(tile); | 628 FreeResourcesForTile(tile); |
601 continue; | 629 continue; |
602 } | 630 } |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 return resource.Pass(); | 815 return resource.Pass(); |
788 } | 816 } |
789 | 817 |
790 void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { | 818 void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { |
791 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); | 819 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); |
792 scoped_ptr<ResourcePool::Resource> resource = PrepareTileForRaster(tile); | 820 scoped_ptr<ResourcePool::Resource> resource = PrepareTileForRaster(tile); |
793 ResourceProvider::ResourceId resource_id = resource->id(); | 821 ResourceProvider::ResourceId resource_id = resource->id(); |
794 uint8* buffer = | 822 uint8* buffer = |
795 resource_pool_->resource_provider()->mapPixelBuffer(resource_id); | 823 resource_pool_->resource_provider()->mapPixelBuffer(resource_id); |
796 | 824 |
797 bool is_cheap = use_cheapness_estimator_ && allow_cheap_tasks_ && | |
798 tile->picture_pile()->IsCheapInRect(tile->content_rect_, | |
799 tile->contents_scale()); | |
800 raster_worker_pool_->PostRasterTaskAndReply( | 825 raster_worker_pool_->PostRasterTaskAndReply( |
801 tile->picture_pile(), | 826 tile->picture_pile(), |
802 is_cheap, | 827 allow_cheap_tasks_ && tile->is_cheap(), |
803 base::Bind(&TileManager::RunRasterTask, | 828 base::Bind(&TileManager::RunRasterTask, |
804 buffer, | 829 buffer, |
805 tile->content_rect(), | 830 tile->content_rect(), |
806 tile->contents_scale(), | 831 tile->contents_scale(), |
807 GetRasterTaskMetadata(*tile)), | 832 GetRasterTaskMetadata(*tile)), |
808 base::Bind(&TileManager::OnRasterTaskCompleted, | 833 base::Bind(&TileManager::OnRasterTaskCompleted, |
809 base::Unretained(this), | 834 base::Unretained(this), |
810 tile, | 835 tile, |
811 base::Passed(&resource), | 836 base::Passed(&resource), |
812 manage_tiles_call_count_)); | 837 manage_tiles_call_count_)); |
813 did_schedule_cheap_tasks_ |= is_cheap; | 838 did_schedule_cheap_tasks_ |= (allow_cheap_tasks_ && tile->is_cheap()); |
814 } | 839 } |
815 | 840 |
816 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata( | 841 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata( |
817 const Tile& tile) const { | 842 const Tile& tile) const { |
818 RasterTaskMetadata metadata; | 843 RasterTaskMetadata metadata; |
819 const ManagedTileState& mts = tile.managed_state(); | 844 const ManagedTileState& mts = tile.managed_state(); |
820 metadata.use_cheapness_estimator = use_cheapness_estimator_; | 845 metadata.prediction_benchmarking = prediction_benchmarking_; |
821 metadata.is_tile_in_pending_tree_now_bin = | 846 metadata.is_tile_in_pending_tree_now_bin = |
822 mts.tree_bin[PENDING_TREE] == NOW_BIN; | 847 mts.tree_bin[PENDING_TREE] == NOW_BIN; |
823 metadata.tile_resolution = mts.resolution; | 848 metadata.tile_resolution = mts.resolution; |
824 metadata.layer_id = tile.layer_id(); | 849 metadata.layer_id = tile.layer_id(); |
825 return metadata; | 850 return metadata; |
826 } | 851 } |
827 | 852 |
828 void TileManager::OnRasterTaskCompleted( | 853 void TileManager::OnRasterTaskCompleted( |
829 scoped_refptr<Tile> tile, | 854 scoped_refptr<Tile> tile, |
830 scoped_ptr<ResourcePool::Resource> resource, | 855 scoped_ptr<ResourcePool::Resource> resource, |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 SkDevice device(bitmap); | 960 SkDevice device(bitmap); |
936 SkCanvas canvas(&device); | 961 SkCanvas canvas(&device); |
937 | 962 |
938 base::TimeTicks begin_time; | 963 base::TimeTicks begin_time; |
939 if (stats) | 964 if (stats) |
940 begin_time = base::TimeTicks::HighResNow(); | 965 begin_time = base::TimeTicks::HighResNow(); |
941 | 966 |
942 int64 total_pixels_rasterized = 0; | 967 int64 total_pixels_rasterized = 0; |
943 picture_pile->Raster(&canvas, rect, contents_scale, | 968 picture_pile->Raster(&canvas, rect, contents_scale, |
944 &total_pixels_rasterized); | 969 &total_pixels_rasterized); |
945 | |
946 if (stats) { | 970 if (stats) { |
947 stats->totalPixelsRasterized += total_pixels_rasterized; | 971 stats->totalPixelsRasterized += total_pixels_rasterized; |
948 | 972 |
949 base::TimeTicks end_time = base::TimeTicks::HighResNow(); | 973 base::TimeTicks end_time = base::TimeTicks::HighResNow(); |
950 base::TimeDelta duration = end_time - begin_time; | 974 base::TimeDelta duration = end_time - begin_time; |
951 stats->totalRasterizeTime += duration; | 975 stats->totalRasterizeTime += duration; |
952 if (metadata.is_tile_in_pending_tree_now_bin) | 976 if (metadata.is_tile_in_pending_tree_now_bin) |
953 stats->totalRasterizeTimeForNowBinsOnPendingTree += duration; | 977 stats->totalRasterizeTimeForNowBinsOnPendingTree += duration; |
954 | 978 |
955 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.PictureRasterTimeMS", | 979 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.PictureRasterTimeMS", |
956 duration.InMilliseconds(), | 980 duration.InMilliseconds(), |
957 0, | 981 0, |
958 10, | 982 10, |
959 10); | 983 10); |
960 | 984 |
961 if (metadata.use_cheapness_estimator) { | 985 if (metadata.prediction_benchmarking) { |
962 bool is_predicted_cheap = | 986 bool is_predicted_cheap = |
963 picture_pile->IsCheapInRect(rect, contents_scale); | 987 picture_pile->IsCheapInRect(rect, contents_scale); |
964 bool is_actually_cheap = duration.InMillisecondsF() <= 1.0f; | 988 bool is_actually_cheap = duration.InMillisecondsF() <= 1.0f; |
965 RecordCheapnessPredictorResults(is_predicted_cheap, is_actually_cheap); | 989 RecordCheapnessPredictorResults(is_predicted_cheap, is_actually_cheap); |
| 990 |
| 991 SkColor solid_color; |
| 992 bool is_predicted_solid = |
| 993 picture_pile->GetColorIfSolidInRect(rect, contents_scale, &solid_color
); |
| 994 bool is_predicted_transparent = |
| 995 picture_pile->IsTransparentInRect(rect, contents_scale); |
| 996 |
| 997 RecordSolidColorPredictorResults( |
| 998 reinterpret_cast<SkColor*>(bitmap.getPixels()), |
| 999 bitmap.getSize() / bitmap.bytesPerPixel(), |
| 1000 is_predicted_solid, |
| 1001 solid_color, |
| 1002 is_predicted_transparent); |
966 } | 1003 } |
967 } | 1004 } |
968 } | 1005 } |
969 | 1006 |
970 // static | 1007 // static |
971 void TileManager::RecordCheapnessPredictorResults(bool is_predicted_cheap, | 1008 void TileManager::RecordCheapnessPredictorResults(bool is_predicted_cheap, |
972 bool is_actually_cheap) { | 1009 bool is_actually_cheap) { |
973 if (is_predicted_cheap && !is_actually_cheap) | 1010 if (is_predicted_cheap && !is_actually_cheap) |
974 UMA_HISTOGRAM_BOOLEAN("Renderer4.CheapPredictorBadlyWrong", true); | 1011 UMA_HISTOGRAM_BOOLEAN("Renderer4.CheapPredictorBadlyWrong", true); |
975 else if (!is_predicted_cheap && is_actually_cheap) | 1012 else if (!is_predicted_cheap && is_actually_cheap) |
976 UMA_HISTOGRAM_BOOLEAN("Renderer4.CheapPredictorSafelyWrong", true); | 1013 UMA_HISTOGRAM_BOOLEAN("Renderer4.CheapPredictorSafelyWrong", true); |
977 | 1014 |
978 UMA_HISTOGRAM_BOOLEAN("Renderer4.CheapPredictorAccuracy", | 1015 UMA_HISTOGRAM_BOOLEAN("Renderer4.CheapPredictorAccuracy", |
979 is_predicted_cheap == is_actually_cheap); | 1016 is_predicted_cheap == is_actually_cheap); |
980 } | 1017 } |
981 | 1018 |
982 // static | 1019 // static |
| 1020 void TileManager::RecordSolidColorPredictorResults( |
| 1021 const SkColor* actual_colors, |
| 1022 size_t color_count, |
| 1023 bool is_predicted_solid, |
| 1024 SkColor predicted_color, |
| 1025 bool is_predicted_transparent) { |
| 1026 DCHECK_GT(color_count, 0); |
| 1027 |
| 1028 bool is_actually_solid = true; |
| 1029 bool is_transparent = true; |
| 1030 |
| 1031 SkColor actual_color = *actual_colors; |
| 1032 for (int i = 0; i < color_count; ++i) { |
| 1033 SkColor current_color = actual_colors[i]; |
| 1034 if (current_color != actual_color || |
| 1035 SkColorGetA(current_color) != 255) |
| 1036 is_actually_solid = false; |
| 1037 |
| 1038 if (SkColorGetA(current_color) != 0) |
| 1039 is_transparent = false; |
| 1040 } |
| 1041 |
| 1042 if (is_predicted_solid && !is_actually_solid) |
| 1043 UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.WrongActualNotSolid", true); |
| 1044 else if (is_predicted_solid && |
| 1045 is_actually_solid && |
| 1046 predicted_color != actual_color) |
| 1047 UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.WrongColor", true); |
| 1048 else if (!is_predicted_solid && is_actually_solid) |
| 1049 UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.WrongActualSolid", true); |
| 1050 |
| 1051 bool correct_guess = (is_predicted_solid && is_actually_solid && |
| 1052 predicted_color == actual_color) || |
| 1053 (!is_predicted_solid && !is_actually_solid); |
| 1054 UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.Accuracy", correct_guess); |
| 1055 |
| 1056 if (correct_guess) |
| 1057 UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.IsCorrectSolid", |
| 1058 is_predicted_solid); |
| 1059 |
| 1060 if (is_predicted_transparent) |
| 1061 UMA_HISTOGRAM_BOOLEAN( |
| 1062 "Renderer4.ColorPredictor.PredictedTransparentIsActually", |
| 1063 is_transparent); |
| 1064 UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.IsActuallyTransparent", |
| 1065 is_transparent); |
| 1066 } |
| 1067 |
| 1068 // static |
983 void TileManager::RunImageDecodeTask(skia::LazyPixelRef* pixel_ref, | 1069 void TileManager::RunImageDecodeTask(skia::LazyPixelRef* pixel_ref, |
984 RenderingStats* stats) { | 1070 RenderingStats* stats) { |
985 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask"); | 1071 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask"); |
986 base::TimeTicks decode_begin_time; | 1072 base::TimeTicks decode_begin_time; |
987 if (stats) | 1073 if (stats) |
988 decode_begin_time = base::TimeTicks::HighResNow(); | 1074 decode_begin_time = base::TimeTicks::HighResNow(); |
989 pixel_ref->Decode(); | 1075 pixel_ref->Decode(); |
990 if (stats) { | 1076 if (stats) { |
991 stats->totalDeferredImageDecodeCount++; | 1077 stats->totalDeferredImageDecodeCount++; |
992 stats->totalDeferredImageDecodeTime += | 1078 stats->totalDeferredImageDecodeTime += |
993 base::TimeTicks::HighResNow() - decode_begin_time; | 1079 base::TimeTicks::HighResNow() - decode_begin_time; |
994 } | 1080 } |
995 } | 1081 } |
996 | 1082 |
997 } // namespace cc | 1083 } // namespace cc |
OLD | NEW |