Support HTTP/2 drafts 14 and 15 simultaneously.
[chromium-blink-merge.git] / cc / debug / rasterize_and_record_benchmark_impl.cc
blob07058d0871fae4b0a443a64d82d06d5023547ea8
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.
5 #include "cc/debug/rasterize_and_record_benchmark_impl.h"
7 #include <algorithm>
8 #include <limits>
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/raster_worker_pool.h"
16 #include "cc/trees/layer_tree_host_common.h"
17 #include "cc/trees/layer_tree_host_impl.h"
18 #include "ui/gfx/geometry/rect.h"
20 namespace cc {
22 namespace {
24 const int kDefaultRasterizeRepeatCount = 100;
26 class BenchmarkRasterTask : public Task {
27 public:
28 BenchmarkRasterTask(RasterSource* raster_source,
29 const gfx::Rect& content_rect,
30 float contents_scale,
31 size_t repeat_count)
32 : raster_source_(raster_source),
33 content_rect_(content_rect),
34 contents_scale_(contents_scale),
35 repeat_count_(repeat_count),
36 is_solid_color_(false),
37 best_time_(base::TimeDelta::Max()) {}
39 // Overridden from Task:
40 void RunOnWorkerThread() override {
41 // Parameters for LapTimer.
42 const int kTimeLimitMillis = 1;
43 const int kWarmupRuns = 0;
44 const int kTimeCheckInterval = 1;
46 for (size_t i = 0; i < repeat_count_; ++i) {
47 // Run for a minimum amount of time to avoid problems with timer
48 // quantization when the layer is very small.
49 LapTimer timer(kWarmupRuns,
50 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
51 kTimeCheckInterval);
52 do {
53 SkBitmap bitmap;
54 bitmap.allocPixels(SkImageInfo::MakeN32Premul(content_rect_.width(),
55 content_rect_.height()));
56 SkCanvas canvas(bitmap);
57 RasterSource::SolidColorAnalysis analysis;
59 raster_source_->PerformSolidColorAnalysis(content_rect_,
60 contents_scale_, &analysis);
61 raster_source_->PlaybackToCanvas(&canvas, content_rect_,
62 contents_scale_);
64 is_solid_color_ = analysis.is_solid_color;
66 timer.NextLap();
67 } while (!timer.HasTimeLimitExpired());
68 base::TimeDelta duration =
69 base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
70 if (duration < best_time_)
71 best_time_ = duration;
75 bool IsSolidColor() const { return is_solid_color_; }
76 base::TimeDelta GetBestTime() const { return best_time_; }
78 private:
79 ~BenchmarkRasterTask() override {}
81 RasterSource* raster_source_;
82 gfx::Rect content_rect_;
83 float contents_scale_;
84 size_t repeat_count_;
85 bool is_solid_color_;
86 base::TimeDelta best_time_;
89 class FixedInvalidationPictureLayerTilingClient
90 : public PictureLayerTilingClient {
91 public:
92 FixedInvalidationPictureLayerTilingClient(
93 PictureLayerTilingClient* base_client,
94 const Region invalidation)
95 : base_client_(base_client), invalidation_(invalidation) {}
97 scoped_refptr<Tile> CreateTile(PictureLayerTiling* tiling,
98 const gfx::Rect& content_rect) override {
99 return base_client_->CreateTile(tiling, content_rect);
102 RasterSource* GetRasterSource() override {
103 return base_client_->GetRasterSource();
106 gfx::Size CalculateTileSize(const gfx::Size& content_bounds) const override {
107 return base_client_->CalculateTileSize(content_bounds);
110 // This is the only function that returns something different from the base
111 // client. Avoids sharing tiles in this area.
112 const Region* GetPendingInvalidation() override { return &invalidation_; }
114 const PictureLayerTiling* GetPendingOrActiveTwinTiling(
115 const PictureLayerTiling* tiling) const override {
116 return base_client_->GetPendingOrActiveTwinTiling(tiling);
119 PictureLayerTiling* GetRecycledTwinTiling(
120 const PictureLayerTiling* tiling) override {
121 return base_client_->GetRecycledTwinTiling(tiling);
124 TilePriority::PriorityBin GetMaxTilePriorityBin() const override {
125 return base_client_->GetMaxTilePriorityBin();
128 size_t GetMaxTilesForInterestArea() const override {
129 return base_client_->GetMaxTilesForInterestArea();
132 float GetSkewportTargetTimeInSeconds() const override {
133 return base_client_->GetSkewportTargetTimeInSeconds();
136 int GetSkewportExtrapolationLimitInContentPixels() const override {
137 return base_client_->GetSkewportExtrapolationLimitInContentPixels();
140 WhichTree GetTree() const override { return base_client_->GetTree(); }
142 bool RequiresHighResToDraw() const override {
143 return base_client_->RequiresHighResToDraw();
146 private:
147 PictureLayerTilingClient* base_client_;
148 Region invalidation_;
151 } // namespace
153 RasterizeAndRecordBenchmarkImpl::RasterizeAndRecordBenchmarkImpl(
154 scoped_refptr<base::MessageLoopProxy> origin_loop,
155 base::Value* value,
156 const MicroBenchmarkImpl::DoneCallback& callback)
157 : MicroBenchmarkImpl(callback, origin_loop),
158 rasterize_repeat_count_(kDefaultRasterizeRepeatCount) {
159 base::DictionaryValue* settings = nullptr;
160 value->GetAsDictionary(&settings);
161 if (!settings)
162 return;
164 if (settings->HasKey("rasterize_repeat_count"))
165 settings->GetInteger("rasterize_repeat_count", &rasterize_repeat_count_);
168 RasterizeAndRecordBenchmarkImpl::~RasterizeAndRecordBenchmarkImpl() {}
170 void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit(
171 LayerTreeHostImpl* host) {
172 LayerTreeHostCommon::CallFunctionForSubtree(
173 host->RootLayer(),
174 base::Bind(&RasterizeAndRecordBenchmarkImpl::Run,
175 base::Unretained(this)));
177 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
178 result->SetDouble("rasterize_time_ms",
179 rasterize_results_.total_best_time.InMillisecondsF());
180 result->SetInteger("pixels_rasterized", rasterize_results_.pixels_rasterized);
181 result->SetInteger("pixels_rasterized_with_non_solid_color",
182 rasterize_results_.pixels_rasterized_with_non_solid_color);
183 result->SetInteger("pixels_rasterized_as_opaque",
184 rasterize_results_.pixels_rasterized_as_opaque);
185 result->SetInteger("total_layers", rasterize_results_.total_layers);
186 result->SetInteger("total_picture_layers",
187 rasterize_results_.total_picture_layers);
188 result->SetInteger("total_picture_layers_with_no_content",
189 rasterize_results_.total_picture_layers_with_no_content);
190 result->SetInteger("total_picture_layers_off_screen",
191 rasterize_results_.total_picture_layers_off_screen);
193 NotifyDone(result.Pass());
196 void RasterizeAndRecordBenchmarkImpl::Run(LayerImpl* layer) {
197 rasterize_results_.total_layers++;
198 layer->RunMicroBenchmark(this);
201 void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {
202 rasterize_results_.total_picture_layers++;
203 if (!layer->DrawsContent()) {
204 rasterize_results_.total_picture_layers_with_no_content++;
205 return;
207 if (layer->visible_content_rect().IsEmpty()) {
208 rasterize_results_.total_picture_layers_off_screen++;
209 return;
212 TaskGraphRunner* task_graph_runner = RasterWorkerPool::GetTaskGraphRunner();
213 DCHECK(task_graph_runner);
215 if (!task_namespace_.IsValid())
216 task_namespace_ = task_graph_runner->GetNamespaceToken();
218 FixedInvalidationPictureLayerTilingClient client(
219 layer, gfx::Rect(layer->content_bounds()));
220 PictureLayerTilingSet tiling_set(&client);
222 PictureLayerTiling* tiling =
223 tiling_set.AddTiling(layer->contents_scale_x(), layer->bounds());
224 tiling->CreateAllTilesForTesting();
225 for (PictureLayerTiling::CoverageIterator it(
226 tiling, layer->contents_scale_x(), layer->visible_content_rect());
228 ++it) {
229 DCHECK(*it);
231 RasterSource* raster_source = (*it)->raster_source();
232 gfx::Rect content_rect = (*it)->content_rect();
233 float contents_scale = (*it)->contents_scale();
235 scoped_refptr<BenchmarkRasterTask> benchmark_raster_task(
236 new BenchmarkRasterTask(raster_source,
237 content_rect,
238 contents_scale,
239 rasterize_repeat_count_));
241 TaskGraph graph;
243 graph.nodes.push_back(
244 TaskGraph::Node(benchmark_raster_task.get(),
245 RasterWorkerPool::kBenchmarkRasterTaskPriority,
246 0u));
248 task_graph_runner->ScheduleTasks(task_namespace_, &graph);
249 task_graph_runner->WaitForTasksToFinishRunning(task_namespace_);
251 Task::Vector completed_tasks;
252 task_graph_runner->CollectCompletedTasks(task_namespace_, &completed_tasks);
253 DCHECK_EQ(1u, completed_tasks.size());
254 DCHECK_EQ(completed_tasks[0], benchmark_raster_task);
256 int tile_size = content_rect.width() * content_rect.height();
257 base::TimeDelta min_time = benchmark_raster_task->GetBestTime();
258 bool is_solid_color = benchmark_raster_task->IsSolidColor();
260 if (layer->contents_opaque())
261 rasterize_results_.pixels_rasterized_as_opaque += tile_size;
263 if (!is_solid_color) {
264 rasterize_results_.pixels_rasterized_with_non_solid_color += tile_size;
267 rasterize_results_.pixels_rasterized += tile_size;
268 rasterize_results_.total_best_time += min_time;
272 RasterizeAndRecordBenchmarkImpl::RasterizeResults::RasterizeResults()
273 : pixels_rasterized(0),
274 pixels_rasterized_with_non_solid_color(0),
275 pixels_rasterized_as_opaque(0),
276 total_layers(0),
277 total_picture_layers(0),
278 total_picture_layers_with_no_content(0),
279 total_picture_layers_off_screen(0) {}
281 RasterizeAndRecordBenchmarkImpl::RasterizeResults::~RasterizeResults() {}
283 } // namespace cc