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 #include <string> 10 11 #include "base/basictypes.h" 12 #include "base/strings/stringprintf.h" 13 #include "base/values.h" 14 #include "cc/debug/lap_timer.h" 15 #include "cc/debug/rasterize_and_record_benchmark_impl.h" 16 #include "cc/layers/layer.h" 17 #include "cc/layers/picture_layer.h" 18 #include "cc/trees/layer_tree_host.h" 19 #include "cc/trees/layer_tree_host_common.h" 20 #include "ui/gfx/rect.h" 21 22 namespace cc { 23 24 namespace { 25 26 const int kDefaultRecordRepeatCount = 100; 27 28 const char* kModeSuffixes[Picture::RECORDING_MODE_COUNT] = { 29 "", "_sk_null_canvas", "_painting_disabled", "_skrecord"}; 30 31 } // namespace 32 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 51 RasterizeAndRecordBenchmark::~RasterizeAndRecordBenchmark() { 52 weak_ptr_factory_.InvalidateWeakPtrs(); 53 } 54 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 65 for (int i = 0; i < Picture::RECORDING_MODE_COUNT; i++) { 66 std::string name = base::StringPrintf("record_time%s_ms", kModeSuffixes[i]); 67 results_->SetDouble(name, 68 record_results_.total_best_time[i].InMillisecondsF()); 69 } 70 main_thread_benchmark_done_ = true; 71 } 72 73 void RasterizeAndRecordBenchmark::RecordRasterResults( 74 scoped_ptr<base::Value> results_value) { 75 DCHECK(main_thread_benchmark_done_); 76 77 base::DictionaryValue* results = NULL; 78 results_value->GetAsDictionary(&results); 79 DCHECK(results); 80 81 results_->MergeDictionary(results); 82 83 NotifyDone(results_.PassAs<base::Value>()); 84 } 85 86 scoped_ptr<MicroBenchmarkImpl> RasterizeAndRecordBenchmark::CreateBenchmarkImpl( 87 scoped_refptr<base::MessageLoopProxy> origin_loop) { 88 return scoped_ptr<MicroBenchmarkImpl>(new RasterizeAndRecordBenchmarkImpl( 89 origin_loop, 90 settings_.get(), 91 base::Bind(&RasterizeAndRecordBenchmark::RecordRasterResults, 92 weak_ptr_factory_.GetWeakPtr()))); 93 } 94 95 void RasterizeAndRecordBenchmark::Run(Layer* layer) { 96 layer->RunMicroBenchmark(this); 97 } 98 99 void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) { 100 ContentLayerClient* painter = layer->client(); 101 gfx::Size content_bounds = layer->content_bounds(); 102 103 DCHECK(host_); 104 gfx::Size tile_grid_size = host_->settings().default_tile_size; 105 106 SkTileGridFactory::TileGridInfo tile_grid_info; 107 PicturePileBase::ComputeTileGridInfo(tile_grid_size, &tile_grid_info); 108 109 gfx::Rect visible_content_rect = gfx::ScaleToEnclosingRect( 110 layer->visible_content_rect(), 1.f / layer->contents_scale_x()); 111 if (visible_content_rect.IsEmpty()) 112 return; 113 114 for (int mode_index = 0; mode_index < Picture::RECORDING_MODE_COUNT; 115 mode_index++) { 116 Picture::RecordingMode mode = 117 static_cast<Picture::RecordingMode>(mode_index); 118 base::TimeDelta min_time = base::TimeDelta::Max(); 119 120 // Parameters for LapTimer. 121 const int kTimeLimitMillis = 1; 122 const int kWarmupRuns = 0; 123 const int kTimeCheckInterval = 1; 124 125 for (int i = 0; i < record_repeat_count_; ++i) { 126 // Run for a minimum amount of time to avoid problems with timer 127 // quantization when the layer is very small. 128 LapTimer timer(kWarmupRuns, 129 base::TimeDelta::FromMilliseconds(kTimeLimitMillis), 130 kTimeCheckInterval); 131 do { 132 scoped_refptr<Picture> picture = Picture::Create( 133 visible_content_rect, painter, tile_grid_info, false, mode); 134 timer.NextLap(); 135 } while (!timer.HasTimeLimitExpired()); 136 base::TimeDelta duration = 137 base::TimeDelta::FromMillisecondsD(timer.MsPerLap()); 138 if (duration < min_time) 139 min_time = duration; 140 } 141 142 if (mode == Picture::RECORD_NORMALLY) { 143 record_results_.pixels_recorded += 144 visible_content_rect.width() * visible_content_rect.height(); 145 } 146 record_results_.total_best_time[mode_index] += min_time; 147 } 148 } 149 150 RasterizeAndRecordBenchmark::RecordResults::RecordResults() 151 : pixels_recorded(0) {} 152 153 RasterizeAndRecordBenchmark::RecordResults::~RecordResults() {} 154 155 } // namespace cc 156