Home | History | Annotate | Download | only in debug
      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