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/picture_record_benchmark.h" 6 7 #include <algorithm> 8 9 #include "base/basictypes.h" 10 #include "base/values.h" 11 #include "cc/layers/layer.h" 12 #include "cc/layers/picture_layer.h" 13 #include "cc/trees/layer_tree_host.h" 14 #include "cc/trees/layer_tree_host_common.h" 15 #include "ui/gfx/rect.h" 16 17 namespace cc { 18 19 namespace { 20 21 const int kPositionIncrement = 100; 22 const int kTileGridSize = 512; 23 const int kTileGridBorder = 1; 24 25 } // namespace 26 27 PictureRecordBenchmark::PictureRecordBenchmark( 28 scoped_ptr<base::Value> value, 29 const MicroBenchmark::DoneCallback& callback) 30 : MicroBenchmark(callback) { 31 if (!value) 32 return; 33 34 base::ListValue* list = NULL; 35 value->GetAsList(&list); 36 if (!list) 37 return; 38 39 for (base::ListValue::iterator it = list->begin(); it != list->end(); ++it) { 40 base::DictionaryValue* dictionary = NULL; 41 (*it)->GetAsDictionary(&dictionary); 42 if (!dictionary || 43 !dictionary->HasKey("width") || 44 !dictionary->HasKey("height")) 45 continue; 46 47 int width, height; 48 dictionary->GetInteger("width", &width); 49 dictionary->GetInteger("height", &height); 50 51 dimensions_.push_back(std::make_pair(width, height)); 52 } 53 } 54 55 PictureRecordBenchmark::~PictureRecordBenchmark() {} 56 57 void PictureRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) { 58 LayerTreeHostCommon::CallFunctionForSubtree( 59 host->root_layer(), 60 base::Bind(&PictureRecordBenchmark::Run, base::Unretained(this))); 61 62 scoped_ptr<base::ListValue> results(new base::ListValue()); 63 for (std::map<std::pair<int, int>, TotalTime>::iterator it = times_.begin(); 64 it != times_.end(); 65 ++it) { 66 std::pair<int, int> dimensions = it->first; 67 base::TimeDelta total_time = it->second.first; 68 unsigned total_count = it->second.second; 69 70 double average_time = 0.0; 71 if (total_count > 0) 72 average_time = total_time.InMillisecondsF() / total_count; 73 74 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); 75 result->SetInteger("width", dimensions.first); 76 result->SetInteger("height", dimensions.second); 77 result->SetInteger("samples_count", total_count); 78 result->SetDouble("time_ms", average_time); 79 80 results->Append(result.release()); 81 } 82 83 NotifyDone(results.PassAs<base::Value>()); 84 } 85 86 void PictureRecordBenchmark::Run(Layer* layer) { 87 layer->RunMicroBenchmark(this); 88 } 89 90 void PictureRecordBenchmark::RunOnLayer(PictureLayer* layer) { 91 ContentLayerClient* painter = layer->client(); 92 gfx::Size content_bounds = layer->content_bounds(); 93 94 SkTileGridFactory::TileGridInfo tile_grid_info; 95 tile_grid_info.fTileInterval.set(kTileGridSize - 2 * kTileGridBorder, 96 kTileGridSize - 2 * kTileGridBorder); 97 tile_grid_info.fMargin.set(kTileGridBorder, kTileGridBorder); 98 tile_grid_info.fOffset.set(-kTileGridBorder, -kTileGridBorder); 99 100 for (size_t i = 0; i < dimensions_.size(); ++i) { 101 std::pair<int, int> dimensions = dimensions_[i]; 102 int width = dimensions.first; 103 int height = dimensions.second; 104 105 int y_limit = std::max(1, content_bounds.height() - height); 106 int x_limit = std::max(1, content_bounds.width() - width); 107 for (int y = 0; y < y_limit; y += kPositionIncrement) { 108 for (int x = 0; x < x_limit; x += kPositionIncrement) { 109 gfx::Rect rect = gfx::Rect(x, y, width, height); 110 111 base::TimeTicks start = base::TimeTicks::HighResNow(); 112 113 scoped_refptr<Picture> picture = Picture::Create( 114 rect, painter, tile_grid_info, false, Picture::RECORD_NORMALLY); 115 116 base::TimeTicks end = base::TimeTicks::HighResNow(); 117 base::TimeDelta duration = end - start; 118 TotalTime& total_time = times_[dimensions]; 119 total_time.first += duration; 120 total_time.second++; 121 } 122 } 123 } 124 } 125 126 } // namespace cc 127