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/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"
25 const int kDefaultRasterizeRepeatCount
= 100;
27 class BenchmarkRasterTask
: public Task
{
29 BenchmarkRasterTask(RasterSource
* raster_source
,
30 const gfx::Rect
& content_rect
,
33 : raster_source_(raster_source
),
34 content_rect_(content_rect
),
35 contents_scale_(contents_scale
),
36 repeat_count_(repeat_count
),
37 is_solid_color_(false),
38 best_time_(base::TimeDelta::Max()) {}
40 // Overridden from Task:
41 void RunOnWorkerThread() override
{
42 // Parameters for LapTimer.
43 const int kTimeLimitMillis
= 1;
44 const int kWarmupRuns
= 0;
45 const int kTimeCheckInterval
= 1;
47 for (size_t i
= 0; i
< repeat_count_
; ++i
) {
48 // Run for a minimum amount of time to avoid problems with timer
49 // quantization when the layer is very small.
50 LapTimer
timer(kWarmupRuns
,
51 base::TimeDelta::FromMilliseconds(kTimeLimitMillis
),
55 bitmap
.allocPixels(SkImageInfo::MakeN32Premul(content_rect_
.width(),
56 content_rect_
.height()));
57 SkCanvas
canvas(bitmap
);
58 RasterSource::SolidColorAnalysis analysis
;
60 raster_source_
->PerformSolidColorAnalysis(content_rect_
,
61 contents_scale_
, &analysis
);
62 raster_source_
->PlaybackToCanvas(&canvas
, content_rect_
,
65 is_solid_color_
= analysis
.is_solid_color
;
68 } while (!timer
.HasTimeLimitExpired());
69 base::TimeDelta duration
=
70 base::TimeDelta::FromMillisecondsD(timer
.MsPerLap());
71 if (duration
< best_time_
)
72 best_time_
= duration
;
76 bool IsSolidColor() const { return is_solid_color_
; }
77 base::TimeDelta
GetBestTime() const { return best_time_
; }
80 ~BenchmarkRasterTask() override
{}
82 RasterSource
* raster_source_
;
83 gfx::Rect content_rect_
;
84 float contents_scale_
;
87 base::TimeDelta best_time_
;
90 class FixedInvalidationPictureLayerTilingClient
91 : public PictureLayerTilingClient
{
93 FixedInvalidationPictureLayerTilingClient(
94 PictureLayerTilingClient
* base_client
,
95 const Region invalidation
)
96 : base_client_(base_client
), invalidation_(invalidation
) {}
98 scoped_refptr
<Tile
> CreateTile(PictureLayerTiling
* tiling
,
99 const gfx::Rect
& content_rect
) override
{
100 return base_client_
->CreateTile(tiling
, content_rect
);
103 gfx::Size
CalculateTileSize(const gfx::Size
& content_bounds
) const override
{
104 return base_client_
->CalculateTileSize(content_bounds
);
107 // This is the only function that returns something different from the base
108 // client. Avoids sharing tiles in this area.
109 const Region
* GetPendingInvalidation() override
{ return &invalidation_
; }
111 const PictureLayerTiling
* GetPendingOrActiveTwinTiling(
112 const PictureLayerTiling
* tiling
) const override
{
113 return base_client_
->GetPendingOrActiveTwinTiling(tiling
);
116 PictureLayerTiling
* GetRecycledTwinTiling(
117 const PictureLayerTiling
* tiling
) override
{
118 return base_client_
->GetRecycledTwinTiling(tiling
);
121 TilePriority::PriorityBin
GetMaxTilePriorityBin() const override
{
122 return base_client_
->GetMaxTilePriorityBin();
125 WhichTree
GetTree() const override
{ return base_client_
->GetTree(); }
127 bool RequiresHighResToDraw() const override
{
128 return base_client_
->RequiresHighResToDraw();
132 PictureLayerTilingClient
* base_client_
;
133 Region invalidation_
;
138 RasterizeAndRecordBenchmarkImpl::RasterizeAndRecordBenchmarkImpl(
139 scoped_refptr
<base::MessageLoopProxy
> origin_loop
,
141 const MicroBenchmarkImpl::DoneCallback
& callback
)
142 : MicroBenchmarkImpl(callback
, origin_loop
),
143 rasterize_repeat_count_(kDefaultRasterizeRepeatCount
) {
144 base::DictionaryValue
* settings
= nullptr;
145 value
->GetAsDictionary(&settings
);
149 if (settings
->HasKey("rasterize_repeat_count"))
150 settings
->GetInteger("rasterize_repeat_count", &rasterize_repeat_count_
);
153 RasterizeAndRecordBenchmarkImpl::~RasterizeAndRecordBenchmarkImpl() {}
155 void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit(
156 LayerTreeHostImpl
* host
) {
157 LayerTreeHostCommon::CallFunctionForSubtree(
159 base::Bind(&RasterizeAndRecordBenchmarkImpl::Run
,
160 base::Unretained(this)));
162 scoped_ptr
<base::DictionaryValue
> result(new base::DictionaryValue());
163 result
->SetDouble("rasterize_time_ms",
164 rasterize_results_
.total_best_time
.InMillisecondsF());
165 result
->SetDouble("total_pictures_in_pile_size",
166 rasterize_results_
.total_memory_usage
);
167 result
->SetInteger("pixels_rasterized", rasterize_results_
.pixels_rasterized
);
168 result
->SetInteger("pixels_rasterized_with_non_solid_color",
169 rasterize_results_
.pixels_rasterized_with_non_solid_color
);
170 result
->SetInteger("pixels_rasterized_as_opaque",
171 rasterize_results_
.pixels_rasterized_as_opaque
);
172 result
->SetInteger("total_layers", rasterize_results_
.total_layers
);
173 result
->SetInteger("total_picture_layers",
174 rasterize_results_
.total_picture_layers
);
175 result
->SetInteger("total_picture_layers_with_no_content",
176 rasterize_results_
.total_picture_layers_with_no_content
);
177 result
->SetInteger("total_picture_layers_off_screen",
178 rasterize_results_
.total_picture_layers_off_screen
);
180 NotifyDone(result
.Pass());
183 void RasterizeAndRecordBenchmarkImpl::Run(LayerImpl
* layer
) {
184 rasterize_results_
.total_layers
++;
185 layer
->RunMicroBenchmark(this);
188 void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl
* layer
) {
189 rasterize_results_
.total_picture_layers
++;
190 if (!layer
->CanHaveTilings()) {
191 rasterize_results_
.total_picture_layers_with_no_content
++;
194 if (layer
->visible_content_rect().IsEmpty()) {
195 rasterize_results_
.total_picture_layers_off_screen
++;
199 TaskGraphRunner
* task_graph_runner
= TileTaskWorkerPool::GetTaskGraphRunner();
200 DCHECK(task_graph_runner
);
202 if (!task_namespace_
.IsValid())
203 task_namespace_
= task_graph_runner
->GetNamespaceToken();
205 FixedInvalidationPictureLayerTilingClient
client(
206 layer
, gfx::Rect(layer
->content_bounds()));
208 // In this benchmark, we will create a local tiling set and measure how long
209 // it takes to rasterize content. As such, the actual settings used here don't
211 const LayerTreeSettings
& settings
= layer
->layer_tree_impl()->settings();
212 auto tiling_set
= PictureLayerTilingSet::Create(
213 &client
, settings
.max_tiles_for_interest_area
,
214 settings
.skewport_target_time_in_seconds
,
215 settings
.skewport_extrapolation_limit_in_content_pixels
);
217 PictureLayerTiling
* tiling
=
218 tiling_set
->AddTiling(layer
->contents_scale_x(), layer
->bounds());
219 tiling
->CreateAllTilesForTesting();
220 for (PictureLayerTiling::CoverageIterator
it(
221 tiling
, layer
->contents_scale_x(), layer
->visible_content_rect());
226 RasterSource
* raster_source
= (*it
)->raster_source();
227 gfx::Rect content_rect
= (*it
)->content_rect();
228 float contents_scale
= (*it
)->contents_scale();
230 scoped_refptr
<BenchmarkRasterTask
> benchmark_raster_task(
231 new BenchmarkRasterTask(raster_source
,
234 rasterize_repeat_count_
));
238 graph
.nodes
.push_back(
239 TaskGraph::Node(benchmark_raster_task
.get(),
240 TileTaskWorkerPool::kBenchmarkTaskPriority
, 0u));
242 task_graph_runner
->ScheduleTasks(task_namespace_
, &graph
);
243 task_graph_runner
->WaitForTasksToFinishRunning(task_namespace_
);
245 Task::Vector completed_tasks
;
246 task_graph_runner
->CollectCompletedTasks(task_namespace_
, &completed_tasks
);
247 DCHECK_EQ(1u, completed_tasks
.size());
248 DCHECK_EQ(completed_tasks
[0], benchmark_raster_task
);
250 int tile_size
= content_rect
.width() * content_rect
.height();
251 base::TimeDelta min_time
= benchmark_raster_task
->GetBestTime();
252 bool is_solid_color
= benchmark_raster_task
->IsSolidColor();
254 if (layer
->contents_opaque())
255 rasterize_results_
.pixels_rasterized_as_opaque
+= tile_size
;
257 if (!is_solid_color
) {
258 rasterize_results_
.pixels_rasterized_with_non_solid_color
+= tile_size
;
261 rasterize_results_
.pixels_rasterized
+= tile_size
;
262 rasterize_results_
.total_best_time
+= min_time
;
265 const RasterSource
* layer_raster_source
= layer
->GetRasterSource();
266 rasterize_results_
.total_memory_usage
+=
267 layer_raster_source
->GetPictureMemoryUsage();
270 RasterizeAndRecordBenchmarkImpl::RasterizeResults::RasterizeResults()
271 : pixels_rasterized(0),
272 pixels_rasterized_with_non_solid_color(0),
273 pixels_rasterized_as_opaque(0),
274 total_memory_usage(0),
276 total_picture_layers(0),
277 total_picture_layers_with_no_content(0),
278 total_picture_layers_off_screen(0) {
281 RasterizeAndRecordBenchmarkImpl::RasterizeResults::~RasterizeResults() {}