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"
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/rect.h"
24 const int kDefaultRasterizeRepeatCount
= 100;
26 class BenchmarkRasterTask
: public Task
{
28 BenchmarkRasterTask(PicturePileImpl
* picture_pile
,
29 const gfx::Rect
& content_rect
,
32 : picture_pile_(picture_pile
),
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 virtual 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
),
54 bitmap
.allocPixels(SkImageInfo::MakeN32Premul(content_rect_
.width(),
55 content_rect_
.height()));
56 SkCanvas
canvas(bitmap
);
57 PicturePileImpl::Analysis analysis
;
59 picture_pile_
->AnalyzeInRect(
60 content_rect_
, contents_scale_
, &analysis
, NULL
);
61 picture_pile_
->RasterToBitmap(
62 &canvas
, content_rect_
, contents_scale_
, NULL
);
64 is_solid_color_
= analysis
.is_solid_color
;
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_
; }
79 virtual ~BenchmarkRasterTask() {}
81 PicturePileImpl
* picture_pile_
;
82 gfx::Rect content_rect_
;
83 float contents_scale_
;
86 base::TimeDelta best_time_
;
89 class FixedInvalidationPictureLayerTilingClient
90 : public PictureLayerTilingClient
{
92 FixedInvalidationPictureLayerTilingClient(
93 PictureLayerTilingClient
* base_client
,
94 const Region invalidation
)
95 : base_client_(base_client
), invalidation_(invalidation
) {}
97 virtual scoped_refptr
<Tile
> CreateTile(
98 PictureLayerTiling
* tiling
,
99 const gfx::Rect
& content_rect
) OVERRIDE
{
100 return base_client_
->CreateTile(tiling
, content_rect
);
103 virtual PicturePileImpl
* GetPile() OVERRIDE
{
104 return base_client_
->GetPile();
107 virtual gfx::Size
CalculateTileSize(
108 const gfx::Size
& content_bounds
) const OVERRIDE
{
109 return base_client_
->CalculateTileSize(content_bounds
);
112 // This is the only function that returns something different from the base
114 virtual const Region
* GetInvalidation() OVERRIDE
{ return &invalidation_
; }
116 virtual const PictureLayerTiling
* GetTwinTiling(
117 const PictureLayerTiling
* tiling
) const OVERRIDE
{
118 return base_client_
->GetTwinTiling(tiling
);
121 virtual PictureLayerTiling
* GetRecycledTwinTiling(
122 const PictureLayerTiling
* tiling
) OVERRIDE
{
123 return base_client_
->GetRecycledTwinTiling(tiling
);
126 virtual size_t GetMaxTilesForInterestArea() const OVERRIDE
{
127 return base_client_
->GetMaxTilesForInterestArea();
130 virtual float GetSkewportTargetTimeInSeconds() const OVERRIDE
{
131 return base_client_
->GetSkewportTargetTimeInSeconds();
134 virtual int GetSkewportExtrapolationLimitInContentPixels() const OVERRIDE
{
135 return base_client_
->GetSkewportExtrapolationLimitInContentPixels();
138 virtual WhichTree
GetTree() const OVERRIDE
{ return base_client_
->GetTree(); }
141 PictureLayerTilingClient
* base_client_
;
142 Region invalidation_
;
147 RasterizeAndRecordBenchmarkImpl::RasterizeAndRecordBenchmarkImpl(
148 scoped_refptr
<base::MessageLoopProxy
> origin_loop
,
150 const MicroBenchmarkImpl::DoneCallback
& callback
)
151 : MicroBenchmarkImpl(callback
, origin_loop
),
152 rasterize_repeat_count_(kDefaultRasterizeRepeatCount
) {
153 base::DictionaryValue
* settings
= NULL
;
154 value
->GetAsDictionary(&settings
);
158 if (settings
->HasKey("rasterize_repeat_count"))
159 settings
->GetInteger("rasterize_repeat_count", &rasterize_repeat_count_
);
162 RasterizeAndRecordBenchmarkImpl::~RasterizeAndRecordBenchmarkImpl() {}
164 void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit(
165 LayerTreeHostImpl
* host
) {
166 LayerTreeHostCommon::CallFunctionForSubtree(
168 base::Bind(&RasterizeAndRecordBenchmarkImpl::Run
,
169 base::Unretained(this)));
171 scoped_ptr
<base::DictionaryValue
> result(new base::DictionaryValue());
172 result
->SetDouble("rasterize_time_ms",
173 rasterize_results_
.total_best_time
.InMillisecondsF());
174 result
->SetInteger("pixels_rasterized", rasterize_results_
.pixels_rasterized
);
175 result
->SetInteger("pixels_rasterized_with_non_solid_color",
176 rasterize_results_
.pixels_rasterized_with_non_solid_color
);
177 result
->SetInteger("pixels_rasterized_as_opaque",
178 rasterize_results_
.pixels_rasterized_as_opaque
);
179 result
->SetInteger("total_layers", rasterize_results_
.total_layers
);
180 result
->SetInteger("total_picture_layers",
181 rasterize_results_
.total_picture_layers
);
182 result
->SetInteger("total_picture_layers_with_no_content",
183 rasterize_results_
.total_picture_layers_with_no_content
);
184 result
->SetInteger("total_picture_layers_off_screen",
185 rasterize_results_
.total_picture_layers_off_screen
);
187 NotifyDone(result
.PassAs
<base::Value
>());
190 void RasterizeAndRecordBenchmarkImpl::Run(LayerImpl
* layer
) {
191 rasterize_results_
.total_layers
++;
192 layer
->RunMicroBenchmark(this);
195 void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl
* layer
) {
196 rasterize_results_
.total_picture_layers
++;
197 if (!layer
->DrawsContent()) {
198 rasterize_results_
.total_picture_layers_with_no_content
++;
201 if (layer
->visible_content_rect().IsEmpty()) {
202 rasterize_results_
.total_picture_layers_off_screen
++;
206 TaskGraphRunner
* task_graph_runner
= RasterWorkerPool::GetTaskGraphRunner();
207 DCHECK(task_graph_runner
);
209 if (!task_namespace_
.IsValid())
210 task_namespace_
= task_graph_runner
->GetNamespaceToken();
212 FixedInvalidationPictureLayerTilingClient
client(
213 layer
, gfx::Rect(layer
->content_bounds()));
214 PictureLayerTilingSet
tiling_set(&client
, layer
->content_bounds());
216 PictureLayerTiling
* tiling
= tiling_set
.AddTiling(layer
->contents_scale_x());
217 tiling
->CreateAllTilesForTesting();
218 for (PictureLayerTiling::CoverageIterator
it(
219 tiling
, layer
->contents_scale_x(), layer
->visible_content_rect());
224 PicturePileImpl
* picture_pile
= (*it
)->picture_pile();
225 gfx::Rect content_rect
= (*it
)->content_rect();
226 float contents_scale
= (*it
)->contents_scale();
228 scoped_refptr
<BenchmarkRasterTask
> benchmark_raster_task(
229 new BenchmarkRasterTask(picture_pile
,
232 rasterize_repeat_count_
));
236 graph
.nodes
.push_back(
237 TaskGraph::Node(benchmark_raster_task
.get(),
238 RasterWorkerPool::kBenchmarkRasterTaskPriority
,
241 task_graph_runner
->ScheduleTasks(task_namespace_
, &graph
);
242 task_graph_runner
->WaitForTasksToFinishRunning(task_namespace_
);
244 Task::Vector completed_tasks
;
245 task_graph_runner
->CollectCompletedTasks(task_namespace_
, &completed_tasks
);
246 DCHECK_EQ(1u, completed_tasks
.size());
247 DCHECK_EQ(completed_tasks
[0], benchmark_raster_task
);
249 int tile_size
= content_rect
.width() * content_rect
.height();
250 base::TimeDelta min_time
= benchmark_raster_task
->GetBestTime();
251 bool is_solid_color
= benchmark_raster_task
->IsSolidColor();
253 if (layer
->contents_opaque())
254 rasterize_results_
.pixels_rasterized_as_opaque
+= tile_size
;
256 if (!is_solid_color
) {
257 rasterize_results_
.pixels_rasterized_with_non_solid_color
+= tile_size
;
260 rasterize_results_
.pixels_rasterized
+= tile_size
;
261 rasterize_results_
.total_best_time
+= min_time
;
265 RasterizeAndRecordBenchmarkImpl::RasterizeResults::RasterizeResults()
266 : pixels_rasterized(0),
267 pixels_rasterized_with_non_solid_color(0),
268 pixels_rasterized_as_opaque(0),
270 total_picture_layers(0),
271 total_picture_layers_with_no_content(0),
272 total_picture_layers_off_screen(0) {}
274 RasterizeAndRecordBenchmarkImpl::RasterizeResults::~RasterizeResults() {}