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