OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/debug/rasterize_and_record_benchmark_impl.h" | |
6 | |
7 #include <algorithm> | |
8 #include <limits> | |
9 | |
10 #include "base/basictypes.h" | |
11 #include "base/values.h" | |
12 #include "cc/debug/lap_timer.h" | |
13 #include "cc/layers/layer_impl.h" | |
14 #include "cc/layers/picture_layer_impl.h" | |
15 #include "cc/resources/tile_task_worker_pool.h" | |
16 #include "cc/trees/layer_tree_host_common.h" | |
17 #include "cc/trees/layer_tree_host_impl.h" | |
18 #include "cc/trees/layer_tree_impl.h" | |
19 #include "ui/gfx/geometry/rect.h" | |
20 | |
21 namespace cc { | |
22 | |
23 namespace { | |
24 | |
25 const int kDefaultRasterizeRepeatCount = 100; | |
26 | |
27 void RunBenchmark(RasterSource* raster_source, | |
28 const gfx::Rect& content_rect, | |
29 float contents_scale, | |
30 size_t repeat_count, | |
31 base::TimeDelta* min_time, | |
32 bool* is_solid_color) { | |
33 // Parameters for LapTimer. | |
34 const int kTimeLimitMillis = 1; | |
35 const int kWarmupRuns = 0; | |
36 const int kTimeCheckInterval = 1; | |
37 | |
38 *min_time = base::TimeDelta::Max(); | |
39 for (size_t i = 0; i < repeat_count; ++i) { | |
40 // Run for a minimum amount of time to avoid problems with timer | |
41 // quantization when the layer is very small. | |
42 LapTimer timer(kWarmupRuns, | |
43 base::TimeDelta::FromMilliseconds(kTimeLimitMillis), | |
44 kTimeCheckInterval); | |
45 do { | |
46 SkBitmap bitmap; | |
47 bitmap.allocPixels(SkImageInfo::MakeN32Premul(content_rect.width(), | |
48 content_rect.height())); | |
49 SkCanvas canvas(bitmap); | |
50 RasterSource::SolidColorAnalysis analysis; | |
51 | |
52 raster_source->PerformSolidColorAnalysis(content_rect, contents_scale, | |
53 &analysis); | |
54 raster_source->PlaybackToCanvas(&canvas, content_rect, contents_scale); | |
55 | |
56 *is_solid_color = analysis.is_solid_color; | |
57 | |
58 timer.NextLap(); | |
59 } while (!timer.HasTimeLimitExpired()); | |
60 base::TimeDelta duration = | |
61 base::TimeDelta::FromMillisecondsD(timer.MsPerLap()); | |
62 if (duration < *min_time) | |
63 *min_time = duration; | |
64 } | |
65 } | |
66 | |
67 class FixedInvalidationPictureLayerTilingClient | |
68 : public PictureLayerTilingClient { | |
69 public: | |
70 FixedInvalidationPictureLayerTilingClient( | |
71 PictureLayerTilingClient* base_client, | |
72 const Region invalidation) | |
73 : base_client_(base_client), invalidation_(invalidation) {} | |
74 | |
75 scoped_refptr<Tile> CreateTile(float contents_scale, | |
76 const gfx::Rect& content_rect) override { | |
77 return base_client_->CreateTile(contents_scale, content_rect); | |
78 } | |
79 | |
80 gfx::Size CalculateTileSize(const gfx::Size& content_bounds) const override { | |
81 return base_client_->CalculateTileSize(content_bounds); | |
82 } | |
83 | |
84 // This is the only function that returns something different from the base | |
85 // client. Avoids sharing tiles in this area. | |
86 const Region* GetPendingInvalidation() override { return &invalidation_; } | |
87 | |
88 const PictureLayerTiling* GetPendingOrActiveTwinTiling( | |
89 const PictureLayerTiling* tiling) const override { | |
90 return base_client_->GetPendingOrActiveTwinTiling(tiling); | |
91 } | |
92 | |
93 PictureLayerTiling* GetRecycledTwinTiling( | |
94 const PictureLayerTiling* tiling) override { | |
95 return base_client_->GetRecycledTwinTiling(tiling); | |
96 } | |
97 | |
98 TilePriority::PriorityBin GetMaxTilePriorityBin() const override { | |
99 return base_client_->GetMaxTilePriorityBin(); | |
100 } | |
101 | |
102 WhichTree GetTree() const override { return base_client_->GetTree(); } | |
103 | |
104 bool RequiresHighResToDraw() const override { | |
105 return base_client_->RequiresHighResToDraw(); | |
106 } | |
107 | |
108 private: | |
109 PictureLayerTilingClient* base_client_; | |
110 Region invalidation_; | |
111 }; | |
112 | |
113 } // namespace | |
114 | |
115 RasterizeAndRecordBenchmarkImpl::RasterizeAndRecordBenchmarkImpl( | |
116 scoped_refptr<base::MessageLoopProxy> origin_loop, | |
117 base::Value* value, | |
118 const MicroBenchmarkImpl::DoneCallback& callback) | |
119 : MicroBenchmarkImpl(callback, origin_loop), | |
120 rasterize_repeat_count_(kDefaultRasterizeRepeatCount) { | |
121 base::DictionaryValue* settings = nullptr; | |
122 value->GetAsDictionary(&settings); | |
123 if (!settings) | |
124 return; | |
125 | |
126 if (settings->HasKey("rasterize_repeat_count")) | |
127 settings->GetInteger("rasterize_repeat_count", &rasterize_repeat_count_); | |
128 } | |
129 | |
130 RasterizeAndRecordBenchmarkImpl::~RasterizeAndRecordBenchmarkImpl() {} | |
131 | |
132 void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit( | |
133 LayerTreeHostImpl* host) { | |
134 LayerTreeHostCommon::CallFunctionForSubtree( | |
135 host->RootLayer(), [this](LayerImpl* layer) { | |
136 rasterize_results_.total_layers++; | |
137 layer->RunMicroBenchmark(this); | |
138 }); | |
139 | |
140 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); | |
141 result->SetDouble("rasterize_time_ms", | |
142 rasterize_results_.total_best_time.InMillisecondsF()); | |
143 result->SetDouble("total_pictures_in_pile_size", | |
144 rasterize_results_.total_memory_usage); | |
145 result->SetInteger("pixels_rasterized", rasterize_results_.pixels_rasterized); | |
146 result->SetInteger("pixels_rasterized_with_non_solid_color", | |
147 rasterize_results_.pixels_rasterized_with_non_solid_color); | |
148 result->SetInteger("pixels_rasterized_as_opaque", | |
149 rasterize_results_.pixels_rasterized_as_opaque); | |
150 result->SetInteger("total_layers", rasterize_results_.total_layers); | |
151 result->SetInteger("total_picture_layers", | |
152 rasterize_results_.total_picture_layers); | |
153 result->SetInteger("total_picture_layers_with_no_content", | |
154 rasterize_results_.total_picture_layers_with_no_content); | |
155 result->SetInteger("total_picture_layers_off_screen", | |
156 rasterize_results_.total_picture_layers_off_screen); | |
157 | |
158 NotifyDone(result.Pass()); | |
159 } | |
160 | |
161 void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) { | |
162 rasterize_results_.total_picture_layers++; | |
163 if (!layer->CanHaveTilings()) { | |
164 rasterize_results_.total_picture_layers_with_no_content++; | |
165 return; | |
166 } | |
167 if (layer->visible_content_rect().IsEmpty()) { | |
168 rasterize_results_.total_picture_layers_off_screen++; | |
169 return; | |
170 } | |
171 | |
172 FixedInvalidationPictureLayerTilingClient client( | |
173 layer, gfx::Rect(layer->content_bounds())); | |
174 | |
175 // In this benchmark, we will create a local tiling set and measure how long | |
176 // it takes to rasterize content. As such, the actual settings used here don't | |
177 // really matter. | |
178 const LayerTreeSettings& settings = layer->layer_tree_impl()->settings(); | |
179 scoped_ptr<PictureLayerTilingSet> tiling_set = PictureLayerTilingSet::Create( | |
180 &client, settings.max_tiles_for_interest_area, | |
181 settings.skewport_target_time_in_seconds, | |
182 settings.skewport_extrapolation_limit_in_content_pixels); | |
183 | |
184 PictureLayerTiling* tiling = tiling_set->AddTiling(layer->contents_scale_x(), | |
185 layer->GetRasterSource()); | |
186 tiling->CreateAllTilesForTesting(); | |
187 for (PictureLayerTiling::CoverageIterator it( | |
188 tiling, layer->contents_scale_x(), layer->visible_content_rect()); | |
189 it; | |
190 ++it) { | |
191 DCHECK(*it); | |
192 | |
193 RasterSource* raster_source = (*it)->raster_source(); | |
194 gfx::Rect content_rect = (*it)->content_rect(); | |
195 float contents_scale = (*it)->contents_scale(); | |
196 | |
197 base::TimeDelta min_time; | |
198 bool is_solid_color = false; | |
199 RunBenchmark(raster_source, content_rect, contents_scale, | |
200 rasterize_repeat_count_, &min_time, &is_solid_color); | |
201 | |
202 int tile_size = content_rect.width() * content_rect.height(); | |
203 if (layer->contents_opaque()) | |
204 rasterize_results_.pixels_rasterized_as_opaque += tile_size; | |
205 | |
206 if (!is_solid_color) | |
207 rasterize_results_.pixels_rasterized_with_non_solid_color += tile_size; | |
208 | |
209 rasterize_results_.pixels_rasterized += tile_size; | |
210 rasterize_results_.total_best_time += min_time; | |
211 } | |
212 | |
213 const RasterSource* layer_raster_source = layer->GetRasterSource(); | |
214 rasterize_results_.total_memory_usage += | |
215 layer_raster_source->GetPictureMemoryUsage(); | |
216 } | |
217 | |
218 RasterizeAndRecordBenchmarkImpl::RasterizeResults::RasterizeResults() | |
219 : pixels_rasterized(0), | |
220 pixels_rasterized_with_non_solid_color(0), | |
221 pixels_rasterized_as_opaque(0), | |
222 total_memory_usage(0), | |
223 total_layers(0), | |
224 total_picture_layers(0), | |
225 total_picture_layers_with_no_content(0), | |
226 total_picture_layers_off_screen(0) { | |
227 } | |
228 | |
229 RasterizeAndRecordBenchmarkImpl::RasterizeResults::~RasterizeResults() {} | |
230 | |
231 } // namespace cc | |
OLD | NEW |