| 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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 state->SetBoolean("is_cheap_to_raster", picture_pile_analysis.is_cheap_to_rast
er); | 185 state->SetBoolean("is_cheap_to_raster", picture_pile_analysis.is_cheap_to_rast
er); |
| 186 state->SetBoolean("is_transparent", picture_pile_analysis.is_transparent); | 186 state->SetBoolean("is_transparent", picture_pile_analysis.is_transparent); |
| 187 state->SetBoolean("is_solid_color", picture_pile_analysis.is_solid_color); | 187 state->SetBoolean("is_solid_color", picture_pile_analysis.is_solid_color); |
| 188 return state.PassAs<base::Value>(); | 188 return state.PassAs<base::Value>(); |
| 189 } | 189 } |
| 190 | 190 |
| 191 TileManager::TileManager( | 191 TileManager::TileManager( |
| 192 TileManagerClient* client, | 192 TileManagerClient* client, |
| 193 ResourceProvider* resource_provider, | 193 ResourceProvider* resource_provider, |
| 194 size_t num_raster_threads, | 194 size_t num_raster_threads, |
| 195 RenderingStatsRecorder* rendering_stats_recorder, |
| 195 bool use_cheapness_estimator, | 196 bool use_cheapness_estimator, |
| 196 bool use_color_estimator, | 197 bool use_color_estimator, |
| 197 bool prediction_benchmarking) | 198 bool prediction_benchmarking) |
| 198 : client_(client), | 199 : client_(client), |
| 199 resource_pool_(ResourcePool::Create(resource_provider)), | 200 resource_pool_(ResourcePool::Create(resource_provider)), |
| 200 raster_worker_pool_(RasterWorkerPool::Create(this, num_raster_threads)), | 201 raster_worker_pool_(RasterWorkerPool::Create(this, num_raster_threads)), |
| 201 manage_tiles_pending_(false), | 202 manage_tiles_pending_(false), |
| 202 manage_tiles_call_count_(0), | 203 manage_tiles_call_count_(0), |
| 203 bytes_pending_upload_(0), | 204 bytes_pending_upload_(0), |
| 204 has_performed_uploads_since_last_flush_(false), | 205 has_performed_uploads_since_last_flush_(false), |
| 205 ever_exceeded_memory_budget_(false), | 206 ever_exceeded_memory_budget_(false), |
| 206 record_rendering_stats_(false), | 207 rendering_stats_recorder_(rendering_stats_recorder), |
| 207 use_cheapness_estimator_(use_cheapness_estimator), | 208 use_cheapness_estimator_(use_cheapness_estimator), |
| 208 use_color_estimator_(use_color_estimator), | 209 use_color_estimator_(use_color_estimator), |
| 209 allow_cheap_tasks_(true), | 210 allow_cheap_tasks_(true), |
| 210 did_schedule_cheap_tasks_(false), | 211 did_schedule_cheap_tasks_(false), |
| 211 prediction_benchmarking_(prediction_benchmarking), | 212 prediction_benchmarking_(prediction_benchmarking), |
| 212 pending_tasks_(0), | 213 pending_tasks_(0), |
| 213 max_pending_tasks_(kMaxNumPendingTasksPerThread * num_raster_threads) { | 214 max_pending_tasks_(kMaxNumPendingTasksPerThread * num_raster_threads) { |
| 214 for (int i = 0; i < NUM_STATES; ++i) { | 215 for (int i = 0; i < NUM_STATES; ++i) { |
| 215 for (int j = 0; j < NUM_TREES; ++j) { | 216 for (int j = 0; j < NUM_TREES; ++j) { |
| 216 for (int k = 0; k < NUM_BINS; ++k) | 217 for (int k = 0; k < NUM_BINS; ++k) |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 size_t memoryUsedBytes; | 522 size_t memoryUsedBytes; |
| 522 GetMemoryStats(&memoryRequiredBytes, | 523 GetMemoryStats(&memoryRequiredBytes, |
| 523 &memoryNiceToHaveBytes, | 524 &memoryNiceToHaveBytes, |
| 524 &memoryUsedBytes); | 525 &memoryUsedBytes); |
| 525 requirements->SetInteger("memory_required_bytes", memoryRequiredBytes); | 526 requirements->SetInteger("memory_required_bytes", memoryRequiredBytes); |
| 526 requirements->SetInteger("memory_nice_to_have_bytes", memoryNiceToHaveBytes); | 527 requirements->SetInteger("memory_nice_to_have_bytes", memoryNiceToHaveBytes); |
| 527 requirements->SetInteger("memory_used_bytes", memoryUsedBytes); | 528 requirements->SetInteger("memory_used_bytes", memoryUsedBytes); |
| 528 return requirements.PassAs<base::Value>(); | 529 return requirements.PassAs<base::Value>(); |
| 529 } | 530 } |
| 530 | 531 |
| 531 void TileManager::SetRecordRenderingStats(bool record_rendering_stats) { | |
| 532 if (record_rendering_stats_ == record_rendering_stats) | |
| 533 return; | |
| 534 | |
| 535 record_rendering_stats_ = record_rendering_stats; | |
| 536 raster_worker_pool_->SetRecordRenderingStats(record_rendering_stats); | |
| 537 } | |
| 538 | |
| 539 void TileManager::GetRenderingStats(RenderingStats* stats) { | |
| 540 CHECK(record_rendering_stats_); | |
| 541 raster_worker_pool_->GetRenderingStats(stats); | |
| 542 stats->totalDeferredImageCacheHitCount = | |
| 543 rendering_stats_.totalDeferredImageCacheHitCount; | |
| 544 stats->totalImageGatheringCount = rendering_stats_.totalImageGatheringCount; | |
| 545 stats->totalImageGatheringTime = | |
| 546 rendering_stats_.totalImageGatheringTime; | |
| 547 } | |
| 548 | |
| 549 bool TileManager::HasPendingWorkScheduled(WhichTree tree) const { | 532 bool TileManager::HasPendingWorkScheduled(WhichTree tree) const { |
| 550 // Always true when ManageTiles() call is pending. | 533 // Always true when ManageTiles() call is pending. |
| 551 if (manage_tiles_pending_) | 534 if (manage_tiles_pending_) |
| 552 return true; | 535 return true; |
| 553 | 536 |
| 554 for (int i = 0; i < NUM_STATES; ++i) { | 537 for (int i = 0; i < NUM_STATES; ++i) { |
| 555 switch (i) { | 538 switch (i) { |
| 556 case WAITING_FOR_RASTER_STATE: | 539 case WAITING_FOR_RASTER_STATE: |
| 557 case RASTER_STATE: | 540 case RASTER_STATE: |
| 558 case UPLOAD_STATE: | 541 case UPLOAD_STATE: |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 managed_tile_state.picture_pile_analysis.is_transparent &= | 734 managed_tile_state.picture_pile_analysis.is_transparent &= |
| 752 use_color_estimator_; | 735 use_color_estimator_; |
| 753 managed_tile_state.picture_pile_analyzed = true; | 736 managed_tile_state.picture_pile_analyzed = true; |
| 754 } | 737 } |
| 755 } | 738 } |
| 756 | 739 |
| 757 void TileManager::GatherPixelRefsForTile(Tile* tile) { | 740 void TileManager::GatherPixelRefsForTile(Tile* tile) { |
| 758 TRACE_EVENT0("cc", "TileManager::GatherPixelRefsForTile"); | 741 TRACE_EVENT0("cc", "TileManager::GatherPixelRefsForTile"); |
| 759 ManagedTileState& managed_tile_state = tile->managed_state(); | 742 ManagedTileState& managed_tile_state = tile->managed_state(); |
| 760 if (managed_tile_state.need_to_gather_pixel_refs) { | 743 if (managed_tile_state.need_to_gather_pixel_refs) { |
| 761 base::TimeTicks gather_begin_time; | 744 base::TimeTicks start_time = rendering_stats_recorder_->StartRecording(); |
| 762 if (record_rendering_stats_) | |
| 763 gather_begin_time = base::TimeTicks::HighResNow(); | |
| 764 tile->picture_pile()->GatherPixelRefs( | 745 tile->picture_pile()->GatherPixelRefs( |
| 765 tile->content_rect_, | 746 tile->content_rect_, |
| 766 tile->contents_scale_, | 747 tile->contents_scale_, |
| 767 managed_tile_state.pending_pixel_refs); | 748 managed_tile_state.pending_pixel_refs); |
| 768 managed_tile_state.need_to_gather_pixel_refs = false; | 749 managed_tile_state.need_to_gather_pixel_refs = false; |
| 769 if (record_rendering_stats_) { | 750 base::TimeDelta duration = |
| 770 rendering_stats_.totalImageGatheringCount++; | 751 rendering_stats_recorder_->EndRecording(start_time); |
| 771 rendering_stats_.totalImageGatheringTime += | 752 rendering_stats_recorder_->AddImageGathering(duration); |
| 772 base::TimeTicks::HighResNow() - gather_begin_time; | |
| 773 } | |
| 774 } | 753 } |
| 775 } | 754 } |
| 776 | 755 |
| 777 void TileManager::DispatchImageDecodeTasksForTile(Tile* tile) { | 756 void TileManager::DispatchImageDecodeTasksForTile(Tile* tile) { |
| 778 GatherPixelRefsForTile(tile); | 757 GatherPixelRefsForTile(tile); |
| 779 std::list<skia::LazyPixelRef*>& pending_pixel_refs = | 758 std::list<skia::LazyPixelRef*>& pending_pixel_refs = |
| 780 tile->managed_state().pending_pixel_refs; | 759 tile->managed_state().pending_pixel_refs; |
| 781 std::list<skia::LazyPixelRef*>::iterator it = pending_pixel_refs.begin(); | 760 std::list<skia::LazyPixelRef*>::iterator it = pending_pixel_refs.begin(); |
| 782 while (it != pending_pixel_refs.end()) { | 761 while (it != pending_pixel_refs.end()) { |
| 783 if (pending_decode_tasks_.end() != pending_decode_tasks_.find( | 762 if (pending_decode_tasks_.end() != pending_decode_tasks_.find( |
| 784 (*it)->getGenerationID())) { | 763 (*it)->getGenerationID())) { |
| 785 ++it; | 764 ++it; |
| 786 continue; | 765 continue; |
| 787 } | 766 } |
| 788 // TODO(qinmin): passing correct image size to PrepareToDecode(). | 767 // TODO(qinmin): passing correct image size to PrepareToDecode(). |
| 789 if ((*it)->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) { | 768 if ((*it)->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) { |
| 790 rendering_stats_.totalDeferredImageCacheHitCount++; | 769 rendering_stats_recorder_->IncrementDeferredImageCacheHitCount(); |
| 791 pending_pixel_refs.erase(it++); | 770 pending_pixel_refs.erase(it++); |
| 792 } else { | 771 } else { |
| 793 if (pending_tasks_ >= max_pending_tasks_) | 772 if (pending_tasks_ >= max_pending_tasks_) |
| 794 return; | 773 return; |
| 795 DispatchOneImageDecodeTask(tile, *it); | 774 DispatchOneImageDecodeTask(tile, *it); |
| 796 ++it; | 775 ++it; |
| 797 } | 776 } |
| 798 } | 777 } |
| 799 } | 778 } |
| 800 | 779 |
| 801 void TileManager::DispatchOneImageDecodeTask( | 780 void TileManager::DispatchOneImageDecodeTask( |
| 802 scoped_refptr<Tile> tile, skia::LazyPixelRef* pixel_ref) { | 781 scoped_refptr<Tile> tile, skia::LazyPixelRef* pixel_ref) { |
| 803 TRACE_EVENT0("cc", "TileManager::DispatchOneImageDecodeTask"); | 782 TRACE_EVENT0("cc", "TileManager::DispatchOneImageDecodeTask"); |
| 804 uint32_t pixel_ref_id = pixel_ref->getGenerationID(); | 783 uint32_t pixel_ref_id = pixel_ref->getGenerationID(); |
| 805 DCHECK(pending_decode_tasks_.end() == | 784 DCHECK(pending_decode_tasks_.end() == |
| 806 pending_decode_tasks_.find(pixel_ref_id)); | 785 pending_decode_tasks_.find(pixel_ref_id)); |
| 807 pending_decode_tasks_[pixel_ref_id] = pixel_ref; | 786 pending_decode_tasks_[pixel_ref_id] = pixel_ref; |
| 808 | 787 |
| 809 raster_worker_pool_->PostTaskAndReply( | 788 raster_worker_pool_->PostTaskAndReply( |
| 810 base::Bind(&TileManager::RunImageDecodeTask, pixel_ref), | 789 base::Bind(&TileManager::RunImageDecodeTask, |
| 790 pixel_ref, |
| 791 rendering_stats_recorder_), |
| 811 base::Bind(&TileManager::OnImageDecodeTaskCompleted, | 792 base::Bind(&TileManager::OnImageDecodeTaskCompleted, |
| 812 base::Unretained(this), | 793 base::Unretained(this), |
| 813 tile, | 794 tile, |
| 814 pixel_ref_id)); | 795 pixel_ref_id)); |
| 815 pending_tasks_++; | 796 pending_tasks_++; |
| 816 } | 797 } |
| 817 | 798 |
| 818 void TileManager::OnImageDecodeTaskCompleted( | 799 void TileManager::OnImageDecodeTaskCompleted( |
| 819 scoped_refptr<Tile> tile, uint32_t pixel_ref_id) { | 800 scoped_refptr<Tile> tile, uint32_t pixel_ref_id) { |
| 820 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted"); | 801 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted"); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 allow_cheap_tasks_ && | 845 allow_cheap_tasks_ && |
| 865 global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY && | 846 global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY && |
| 866 managed_tile_state.picture_pile_analysis.is_cheap_to_raster; | 847 managed_tile_state.picture_pile_analysis.is_cheap_to_raster; |
| 867 raster_worker_pool_->PostRasterTaskAndReply( | 848 raster_worker_pool_->PostRasterTaskAndReply( |
| 868 tile->picture_pile(), | 849 tile->picture_pile(), |
| 869 is_cheap_task, | 850 is_cheap_task, |
| 870 base::Bind(&TileManager::RunRasterTask, | 851 base::Bind(&TileManager::RunRasterTask, |
| 871 buffer, | 852 buffer, |
| 872 tile->content_rect(), | 853 tile->content_rect(), |
| 873 tile->contents_scale(), | 854 tile->contents_scale(), |
| 874 GetRasterTaskMetadata(*tile)), | 855 GetRasterTaskMetadata(*tile), |
| 856 rendering_stats_recorder_), |
| 875 base::Bind(&TileManager::OnRasterTaskCompleted, | 857 base::Bind(&TileManager::OnRasterTaskCompleted, |
| 876 base::Unretained(this), | 858 base::Unretained(this), |
| 877 tile, | 859 tile, |
| 878 base::Passed(&resource), | 860 base::Passed(&resource), |
| 879 manage_tiles_call_count_)); | 861 manage_tiles_call_count_)); |
| 880 if (is_cheap_task && !did_schedule_cheap_tasks_) { | 862 if (is_cheap_task && !did_schedule_cheap_tasks_) { |
| 881 raster_worker_pool_->SetRunCheapTasksTimeLimit( | 863 raster_worker_pool_->SetRunCheapTasksTimeLimit( |
| 882 base::TimeTicks::Now() + | 864 base::TimeTicks::Now() + |
| 883 base::TimeDelta::FromMilliseconds(kRunCheapTasksTimeMs)); | 865 base::TimeDelta::FromMilliseconds(kRunCheapTasksTimeMs)); |
| 884 did_schedule_cheap_tasks_ = true; | 866 did_schedule_cheap_tasks_ = true; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 --raster_state_count_[mts.raster_state][tree][mts.tree_bin[tree]]; | 962 --raster_state_count_[mts.raster_state][tree][mts.tree_bin[tree]]; |
| 981 DCHECK_GE(raster_state_count_[mts.raster_state][tree][mts.tree_bin[tree]], 0); | 963 DCHECK_GE(raster_state_count_[mts.raster_state][tree][mts.tree_bin[tree]], 0); |
| 982 | 964 |
| 983 // Increment count for new bin. | 965 // Increment count for new bin. |
| 984 ++raster_state_count_[mts.raster_state][tree][new_tree_bin]; | 966 ++raster_state_count_[mts.raster_state][tree][new_tree_bin]; |
| 985 | 967 |
| 986 mts.tree_bin[tree] = new_tree_bin; | 968 mts.tree_bin[tree] = new_tree_bin; |
| 987 } | 969 } |
| 988 | 970 |
| 989 // static | 971 // static |
| 990 void TileManager::RunRasterTask(uint8* buffer, | 972 void TileManager::RunRasterTask( |
| 991 const gfx::Rect& rect, | 973 uint8* buffer, |
| 992 float contents_scale, | 974 const gfx::Rect& rect, |
| 993 const RasterTaskMetadata& metadata, | 975 float contents_scale, |
| 994 PicturePileImpl* picture_pile, | 976 const RasterTaskMetadata& metadata, |
| 995 RenderingStats* stats) { | 977 RenderingStatsRecorder* stats_recorder, |
| 978 PicturePileImpl* picture_pile) { |
| 996 TRACE_EVENT2( | 979 TRACE_EVENT2( |
| 997 "cc", "TileManager::RunRasterTask", | 980 "cc", "TileManager::RunRasterTask", |
| 998 "is_on_pending_tree", | 981 "is_on_pending_tree", |
| 999 metadata.is_tile_in_pending_tree_now_bin, | 982 metadata.is_tile_in_pending_tree_now_bin, |
| 1000 "is_low_res", | 983 "is_low_res", |
| 1001 metadata.tile_resolution == LOW_RESOLUTION); | 984 metadata.tile_resolution == LOW_RESOLUTION); |
| 1002 devtools_instrumentation::ScopedRasterTask raster_task(metadata.layer_id); | 985 devtools_instrumentation::ScopedRasterTask raster_task(metadata.layer_id); |
| 1003 | 986 |
| 1004 DCHECK(picture_pile); | 987 DCHECK(picture_pile); |
| 1005 DCHECK(buffer); | 988 DCHECK(buffer); |
| 1006 | 989 |
| 1007 SkBitmap bitmap; | 990 SkBitmap bitmap; |
| 1008 bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); | 991 bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); |
| 1009 bitmap.setPixels(buffer); | 992 bitmap.setPixels(buffer); |
| 1010 SkDevice device(bitmap); | 993 SkDevice device(bitmap); |
| 1011 SkCanvas canvas(&device); | 994 SkCanvas canvas(&device); |
| 1012 | 995 |
| 1013 base::TimeTicks begin_time; | 996 base::TimeTicks start_time = stats_recorder->StartRecording(); |
| 1014 if (stats) | |
| 1015 begin_time = base::TimeTicks::HighResNow(); | |
| 1016 | 997 |
| 1017 int64 total_pixels_rasterized = 0; | 998 int64 total_pixels_rasterized = 0; |
| 1018 picture_pile->Raster(&canvas, rect, contents_scale, | 999 picture_pile->Raster(&canvas, rect, contents_scale, |
| 1019 &total_pixels_rasterized); | 1000 &total_pixels_rasterized); |
| 1020 | 1001 |
| 1021 if (stats) { | 1002 base::TimeDelta duration = stats_recorder->EndRecording(start_time); |
| 1022 stats->totalPixelsRasterized += total_pixels_rasterized; | |
| 1023 | 1003 |
| 1024 base::TimeTicks end_time = base::TimeTicks::HighResNow(); | 1004 if (stats_recorder->record_rendering_stats()) { |
| 1025 base::TimeDelta duration = end_time - begin_time; | 1005 stats_recorder->AddRaster(duration, total_pixels_rasterized, metadata.is_til
e_in_pending_tree_now_bin); |
| 1026 stats->totalRasterizeTime += duration; | |
| 1027 if (metadata.is_tile_in_pending_tree_now_bin) | |
| 1028 stats->totalRasterizeTimeForNowBinsOnPendingTree += duration; | |
| 1029 | 1006 |
| 1030 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.PictureRasterTimeMS", | 1007 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.PictureRasterTimeMS", |
| 1031 duration.InMilliseconds(), | 1008 duration.InMilliseconds(), |
| 1032 0, | 1009 0, |
| 1033 10, | 1010 10, |
| 1034 10); | 1011 10); |
| 1035 | 1012 |
| 1036 if (metadata.prediction_benchmarking) { | 1013 if (metadata.prediction_benchmarking) { |
| 1037 PicturePileImpl::Analysis analysis; | 1014 PicturePileImpl::Analysis analysis; |
| 1038 picture_pile->AnalyzeInRect(rect, contents_scale, &analysis); | 1015 picture_pile->AnalyzeInRect(rect, contents_scale, &analysis); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 | 1088 |
| 1112 if (is_predicted_transparent) | 1089 if (is_predicted_transparent) |
| 1113 UMA_HISTOGRAM_BOOLEAN( | 1090 UMA_HISTOGRAM_BOOLEAN( |
| 1114 "Renderer4.ColorPredictor.PredictedTransparentIsActually", | 1091 "Renderer4.ColorPredictor.PredictedTransparentIsActually", |
| 1115 is_transparent); | 1092 is_transparent); |
| 1116 UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.IsActuallyTransparent", | 1093 UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.IsActuallyTransparent", |
| 1117 is_transparent); | 1094 is_transparent); |
| 1118 } | 1095 } |
| 1119 | 1096 |
| 1120 // static | 1097 // static |
| 1121 void TileManager::RunImageDecodeTask(skia::LazyPixelRef* pixel_ref, | 1098 void TileManager::RunImageDecodeTask( |
| 1122 RenderingStats* stats) { | 1099 skia::LazyPixelRef* pixel_ref, |
| 1100 RenderingStatsRecorder* stats_recorder) { |
| 1123 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask"); | 1101 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask"); |
| 1124 base::TimeTicks decode_begin_time; | 1102 base::TimeTicks start_time = stats_recorder->StartRecording(); |
| 1125 if (stats) | |
| 1126 decode_begin_time = base::TimeTicks::HighResNow(); | |
| 1127 pixel_ref->Decode(); | 1103 pixel_ref->Decode(); |
| 1128 if (stats) { | 1104 base::TimeDelta duration = stats_recorder->EndRecording(start_time); |
| 1129 stats->totalDeferredImageDecodeCount++; | 1105 stats_recorder->AddDeferredImageDecode(duration); |
| 1130 stats->totalDeferredImageDecodeTime += | |
| 1131 base::TimeTicks::HighResNow() - decode_begin_time; | |
| 1132 } | |
| 1133 } | 1106 } |
| 1134 | 1107 |
| 1135 } // namespace cc | 1108 } // namespace cc |
| OLD | NEW |