| 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 |