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_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/raster_worker_pool.h"
     16 #include "cc/trees/layer_tree_host_common.h"
     17 #include "cc/trees/layer_tree_host_impl.h"
     18 #include "ui/gfx/rect.h"
     19 
     20 namespace cc {
     21 
     22 namespace {
     23 
     24 const int kDefaultRasterizeRepeatCount = 100;
     25 
     26 class BenchmarkRasterTask : public Task {
     27  public:
     28   BenchmarkRasterTask(PicturePileImpl* picture_pile,
     29                       const gfx::Rect& content_rect,
     30                       float contents_scale,
     31                       size_t repeat_count)
     32       : picture_pile_(picture_pile),
     33         content_rect_(content_rect),
     34         contents_scale_(contents_scale),
     35         repeat_count_(repeat_count),
     36         is_solid_color_(false),
     37         best_time_(base::TimeDelta::Max()) {}
     38 
     39   // Overridden from Task:
     40   virtual void RunOnWorkerThread() OVERRIDE {
     41     PicturePileImpl* picture_pile = picture_pile_->GetCloneForDrawingOnThread(
     42         RasterWorkerPool::GetPictureCloneIndexForCurrentThread());
     43 
     44     // Parameters for LapTimer.
     45     const int kTimeLimitMillis = 1;
     46     const int kWarmupRuns = 0;
     47     const int kTimeCheckInterval = 1;
     48 
     49     for (size_t i = 0; i < repeat_count_; ++i) {
     50       // Run for a minimum amount of time to avoid problems with timer
     51       // quantization when the layer is very small.
     52       LapTimer timer(kWarmupRuns,
     53                      base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
     54                      kTimeCheckInterval);
     55       do {
     56         SkBitmap bitmap;
     57         bitmap.allocPixels(SkImageInfo::MakeN32Premul(content_rect_.width(),
     58                                                       content_rect_.height()));
     59         SkCanvas canvas(bitmap);
     60         PicturePileImpl::Analysis analysis;
     61 
     62         picture_pile->AnalyzeInRect(
     63             content_rect_, contents_scale_, &analysis, NULL);
     64         picture_pile->RasterToBitmap(
     65             &canvas, content_rect_, contents_scale_, NULL);
     66 
     67         is_solid_color_ = analysis.is_solid_color;
     68 
     69         timer.NextLap();
     70       } while (!timer.HasTimeLimitExpired());
     71       base::TimeDelta duration =
     72           base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
     73       if (duration < best_time_)
     74         best_time_ = duration;
     75 
     76     }
     77   }
     78 
     79   bool IsSolidColor() const { return is_solid_color_; }
     80   base::TimeDelta GetBestTime() const { return best_time_; }
     81 
     82  private:
     83   virtual ~BenchmarkRasterTask() {}
     84 
     85   PicturePileImpl* picture_pile_;
     86   gfx::Rect content_rect_;
     87   float contents_scale_;
     88   size_t repeat_count_;
     89   bool is_solid_color_;
     90   base::TimeDelta best_time_;
     91 };
     92 
     93 }  // namespace
     94 
     95 RasterizeAndRecordBenchmarkImpl::RasterizeAndRecordBenchmarkImpl(
     96     scoped_refptr<base::MessageLoopProxy> origin_loop,
     97     base::Value* value,
     98     const MicroBenchmarkImpl::DoneCallback& callback)
     99     : MicroBenchmarkImpl(callback, origin_loop),
    100       rasterize_repeat_count_(kDefaultRasterizeRepeatCount) {
    101   base::DictionaryValue* settings = NULL;
    102   value->GetAsDictionary(&settings);
    103   if (!settings)
    104     return;
    105 
    106   if (settings->HasKey("rasterize_repeat_count"))
    107     settings->GetInteger("rasterize_repeat_count", &rasterize_repeat_count_);
    108 }
    109 
    110 RasterizeAndRecordBenchmarkImpl::~RasterizeAndRecordBenchmarkImpl() {}
    111 
    112 void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit(
    113     LayerTreeHostImpl* host) {
    114   LayerTreeHostCommon::CallFunctionForSubtree(
    115       host->RootLayer(),
    116       base::Bind(&RasterizeAndRecordBenchmarkImpl::Run,
    117                  base::Unretained(this)));
    118 
    119   scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
    120   result->SetDouble("rasterize_time_ms",
    121                     rasterize_results_.total_best_time.InMillisecondsF());
    122   result->SetInteger("pixels_rasterized", rasterize_results_.pixels_rasterized);
    123   result->SetInteger("pixels_rasterized_with_non_solid_color",
    124                      rasterize_results_.pixels_rasterized_with_non_solid_color);
    125   result->SetInteger("pixels_rasterized_as_opaque",
    126                      rasterize_results_.pixels_rasterized_as_opaque);
    127   result->SetInteger("total_layers", rasterize_results_.total_layers);
    128   result->SetInteger("total_picture_layers",
    129                      rasterize_results_.total_picture_layers);
    130   result->SetInteger("total_picture_layers_with_no_content",
    131                      rasterize_results_.total_picture_layers_with_no_content);
    132   result->SetInteger("total_picture_layers_off_screen",
    133                      rasterize_results_.total_picture_layers_off_screen);
    134 
    135   NotifyDone(result.PassAs<base::Value>());
    136 }
    137 
    138 void RasterizeAndRecordBenchmarkImpl::Run(LayerImpl* layer) {
    139   rasterize_results_.total_layers++;
    140   layer->RunMicroBenchmark(this);
    141 }
    142 
    143 void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {
    144   rasterize_results_.total_picture_layers++;
    145   if (!layer->DrawsContent()) {
    146     rasterize_results_.total_picture_layers_with_no_content++;
    147     return;
    148   }
    149   if (layer->visible_content_rect().IsEmpty()) {
    150     rasterize_results_.total_picture_layers_off_screen++;
    151     return;
    152   }
    153 
    154   TaskGraphRunner* task_graph_runner = RasterWorkerPool::GetTaskGraphRunner();
    155   DCHECK(task_graph_runner);
    156 
    157   if (!task_namespace_.IsValid())
    158     task_namespace_ = task_graph_runner->GetNamespaceToken();
    159 
    160   PictureLayerTilingSet tiling_set(layer, layer->content_bounds());
    161 
    162   PictureLayerTiling* tiling = tiling_set.AddTiling(layer->contents_scale_x());
    163   tiling->CreateAllTilesForTesting();
    164   for (PictureLayerTiling::CoverageIterator it(
    165            tiling, layer->contents_scale_x(), layer->visible_content_rect());
    166        it;
    167        ++it) {
    168     DCHECK(*it);
    169 
    170     PicturePileImpl* picture_pile = (*it)->picture_pile();
    171     gfx::Rect content_rect = (*it)->content_rect();
    172     float contents_scale = (*it)->contents_scale();
    173 
    174     scoped_refptr<BenchmarkRasterTask> benchmark_raster_task(
    175         new BenchmarkRasterTask(picture_pile,
    176                                 content_rect,
    177                                 contents_scale,
    178                                 rasterize_repeat_count_));
    179 
    180     TaskGraph graph;
    181 
    182     graph.nodes.push_back(
    183         TaskGraph::Node(benchmark_raster_task,
    184                         RasterWorkerPool::kBenchmarkRasterTaskPriority,
    185                         0u));
    186 
    187     task_graph_runner->ScheduleTasks(task_namespace_, &graph);
    188     task_graph_runner->WaitForTasksToFinishRunning(task_namespace_);
    189 
    190     Task::Vector completed_tasks;
    191     task_graph_runner->CollectCompletedTasks(task_namespace_, &completed_tasks);
    192     DCHECK_EQ(1u, completed_tasks.size());
    193     DCHECK_EQ(completed_tasks[0], benchmark_raster_task);
    194 
    195     int tile_size = content_rect.width() * content_rect.height();
    196     base::TimeDelta min_time = benchmark_raster_task->GetBestTime();
    197     bool is_solid_color = benchmark_raster_task->IsSolidColor();
    198 
    199     if (layer->contents_opaque())
    200       rasterize_results_.pixels_rasterized_as_opaque += tile_size;
    201 
    202     if (!is_solid_color) {
    203       rasterize_results_.pixels_rasterized_with_non_solid_color += tile_size;
    204     }
    205 
    206     rasterize_results_.pixels_rasterized += tile_size;
    207     rasterize_results_.total_best_time += min_time;
    208   }
    209 }
    210 
    211 RasterizeAndRecordBenchmarkImpl::RasterizeResults::RasterizeResults()
    212     : pixels_rasterized(0),
    213       pixels_rasterized_with_non_solid_color(0),
    214       pixels_rasterized_as_opaque(0),
    215       total_layers(0),
    216       total_picture_layers(0),
    217       total_picture_layers_with_no_content(0),
    218       total_picture_layers_off_screen(0) {}
    219 
    220 RasterizeAndRecordBenchmarkImpl::RasterizeResults::~RasterizeResults() {}
    221 
    222 }  // namespace cc
    223