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.h"
6
7 #include <algorithm>
8 #include <limits>
9
10 #include "base/basictypes.h"
11 #include "base/values.h"
12 #include "cc/debug/rasterize_and_record_benchmark_impl.h"
13 #include "cc/layers/layer.h"
14 #include "cc/layers/picture_layer.h"
15 #include "cc/trees/layer_tree_host.h"
16 #include "cc/trees/layer_tree_host_common.h"
17 #include "ui/gfx/rect.h"
18
19 namespace cc {
20
21 namespace {
22
23 const int kDefaultRecordRepeatCount = 100;
24
Now()25 base::TimeTicks Now() {
26 return base::TimeTicks::IsThreadNowSupported()
27 ? base::TimeTicks::ThreadNow()
28 : base::TimeTicks::HighResNow();
29 }
30
31 } // namespace
32
RasterizeAndRecordBenchmark(scoped_ptr<base::Value> value,const MicroBenchmark::DoneCallback & callback)33 RasterizeAndRecordBenchmark::RasterizeAndRecordBenchmark(
34 scoped_ptr<base::Value> value,
35 const MicroBenchmark::DoneCallback& callback)
36 : MicroBenchmark(callback),
37 record_repeat_count_(kDefaultRecordRepeatCount),
38 settings_(value.Pass()),
39 main_thread_benchmark_done_(false),
40 host_(NULL),
41 weak_ptr_factory_(this) {
42 base::DictionaryValue* settings = NULL;
43 settings_->GetAsDictionary(&settings);
44 if (!settings)
45 return;
46
47 if (settings->HasKey("record_repeat_count"))
48 settings->GetInteger("record_repeat_count", &record_repeat_count_);
49 }
50
~RasterizeAndRecordBenchmark()51 RasterizeAndRecordBenchmark::~RasterizeAndRecordBenchmark() {
52 weak_ptr_factory_.InvalidateWeakPtrs();
53 }
54
DidUpdateLayers(LayerTreeHost * host)55 void RasterizeAndRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) {
56 host_ = host;
57 LayerTreeHostCommon::CallFunctionForSubtree(
58 host->root_layer(),
59 base::Bind(&RasterizeAndRecordBenchmark::Run, base::Unretained(this)));
60
61 DCHECK(!results_.get());
62 results_ = make_scoped_ptr(new base::DictionaryValue);
63 results_->SetInteger("pixels_recorded", record_results_.pixels_recorded);
64 results_->SetDouble("record_time_ms",
65 record_results_.total_best_time.InMillisecondsF());
66 main_thread_benchmark_done_ = true;
67 }
68
RecordRasterResults(scoped_ptr<base::Value> results_value)69 void RasterizeAndRecordBenchmark::RecordRasterResults(
70 scoped_ptr<base::Value> results_value) {
71 DCHECK(main_thread_benchmark_done_);
72
73 base::DictionaryValue* results = NULL;
74 results_value->GetAsDictionary(&results);
75
76 DCHECK(results);
77 DCHECK(results->HasKey("pixels_rasterized"));
78 DCHECK(results->HasKey("rasterize_time_ms"));
79
80 int pixels_rasterized;
81 results->GetInteger("pixels_rasterized", &pixels_rasterized);
82 double rasterize_time_ms;
83 results->GetDouble("rasterize_time_ms", &rasterize_time_ms);
84
85 results_->SetInteger("pixels_rasterized", pixels_rasterized);
86 results_->SetDouble("rasterize_time_ms", rasterize_time_ms);
87
88 NotifyDone(results_.PassAs<base::Value>());
89 }
90
CreateBenchmarkImpl(scoped_refptr<base::MessageLoopProxy> origin_loop)91 scoped_ptr<MicroBenchmarkImpl> RasterizeAndRecordBenchmark::CreateBenchmarkImpl(
92 scoped_refptr<base::MessageLoopProxy> origin_loop) {
93 return scoped_ptr<MicroBenchmarkImpl>(new RasterizeAndRecordBenchmarkImpl(
94 origin_loop,
95 settings_.get(),
96 base::Bind(&RasterizeAndRecordBenchmark::RecordRasterResults,
97 weak_ptr_factory_.GetWeakPtr())));
98 }
99
Run(Layer * layer)100 void RasterizeAndRecordBenchmark::Run(Layer* layer) {
101 layer->RunMicroBenchmark(this);
102 }
103
RunOnLayer(PictureLayer * layer)104 void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) {
105 ContentLayerClient* painter = layer->client();
106 gfx::Size content_bounds = layer->content_bounds();
107
108 DCHECK(host_);
109 gfx::Size tile_grid_size = host_->settings().default_tile_size;
110
111 SkTileGridPicture::TileGridInfo tile_grid_info;
112 PicturePileBase::ComputeTileGridInfo(tile_grid_size, &tile_grid_info);
113
114 gfx::Rect visible_content_rect = gfx::ScaleToEnclosingRect(
115 layer->visible_content_rect(), 1.f / layer->contents_scale_x());
116 if (visible_content_rect.IsEmpty())
117 return;
118
119 scoped_refptr<Picture> picture = Picture::Create(visible_content_rect);
120
121 base::TimeDelta min_time =
122 base::TimeDelta::FromInternalValue(std::numeric_limits<int64>::max());
123 for (int i = 0; i < record_repeat_count_; ++i) {
124 base::TimeTicks start = Now();
125 picture->Record(painter, tile_grid_info);
126 base::TimeTicks end = Now();
127 base::TimeDelta duration = end - start;
128 if (duration < min_time)
129 min_time = duration;
130 }
131
132 record_results_.pixels_recorded +=
133 visible_content_rect.width() * visible_content_rect.height();
134 record_results_.total_best_time += min_time;
135 }
136
RecordResults()137 RasterizeAndRecordBenchmark::RecordResults::RecordResults()
138 : pixels_recorded(0) {}
139
~RecordResults()140 RasterizeAndRecordBenchmark::RecordResults::~RecordResults() {}
141
142 } // namespace cc
143