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     // Parameters for LapTimer.
     42     const int kTimeLimitMillis = 1;
     43     const int kWarmupRuns = 0;
     44     const int kTimeCheckInterval = 1;
     45 
     46     for (size_t i = 0; i < repeat_count_; ++i) {
     47       // Run for a minimum amount of time to avoid problems with timer
     48       // quantization when the layer is very small.
     49       LapTimer timer(kWarmupRuns,
     50                      base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
     51                      kTimeCheckInterval);
     52       do {
     53         SkBitmap bitmap;
     54         bitmap.allocPixels(SkImageInfo::MakeN32Premul(content_rect_.width(),
     55                                                       content_rect_.height()));
     56         SkCanvas canvas(bitmap);
     57         PicturePileImpl::Analysis analysis;
     58 
     59         picture_pile_->AnalyzeInRect(
     60             content_rect_, contents_scale_, &analysis, NULL);
     61         picture_pile_->RasterToBitmap(
     62             &canvas, content_rect_, contents_scale_, NULL);
     63 
     64         is_solid_color_ = analysis.is_solid_color;
     65 
     66         timer.NextLap();
     67       } while (!timer.HasTimeLimitExpired());
     68       base::TimeDelta duration =
     69           base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
     70       if (duration < best_time_)
     71         best_time_ = duration;
     72     }
     73   }
     74 
     75   bool IsSolidColor() const { return is_solid_color_; }
     76   base::TimeDelta GetBestTime() const { return best_time_; }
     77 
     78  private:
     79   virtual ~BenchmarkRasterTask() {}
     80 
     81   PicturePileImpl* picture_pile_;
     82   gfx::Rect content_rect_;
     83   float contents_scale_;
     84   size_t repeat_count_;
     85   bool is_solid_color_;
     86   base::TimeDelta best_time_;
     87 };
     88 
     89 class FixedInvalidationPictureLayerTilingClient
     90     : public PictureLayerTilingClient {
     91  public:
     92   FixedInvalidationPictureLayerTilingClient(
     93       PictureLayerTilingClient* base_client,
     94       const Region invalidation)
     95       : base_client_(base_client), invalidation_(invalidation) {}
     96 
     97   virtual scoped_refptr<Tile> CreateTile(
     98       PictureLayerTiling* tiling,
     99       const gfx::Rect& content_rect) OVERRIDE {
    100     return base_client_->CreateTile(tiling, content_rect);
    101   }
    102 
    103   virtual PicturePileImpl* GetPile() OVERRIDE {
    104     return base_client_->GetPile();
    105   }
    106 
    107   virtual gfx::Size CalculateTileSize(
    108       const gfx::Size& content_bounds) const OVERRIDE {
    109     return base_client_->CalculateTileSize(content_bounds);
    110   }
    111 
    112   // This is the only function that returns something different from the base
    113   // client.
    114   virtual const Region* GetInvalidation() OVERRIDE { return &invalidation_; }
    115 
    116   virtual const PictureLayerTiling* GetTwinTiling(
    117       const PictureLayerTiling* tiling) const OVERRIDE {
    118     return base_client_->GetTwinTiling(tiling);
    119   }
    120 
    121   virtual PictureLayerTiling* GetRecycledTwinTiling(
    122       const PictureLayerTiling* tiling) OVERRIDE {
    123     return base_client_->GetRecycledTwinTiling(tiling);
    124   }
    125 
    126   virtual size_t GetMaxTilesForInterestArea() const OVERRIDE {
    127     return base_client_->GetMaxTilesForInterestArea();
    128   }
    129 
    130   virtual float GetSkewportTargetTimeInSeconds() const OVERRIDE {
    131     return base_client_->GetSkewportTargetTimeInSeconds();
    132   }
    133 
    134   virtual int GetSkewportExtrapolationLimitInContentPixels() const OVERRIDE {
    135     return base_client_->GetSkewportExtrapolationLimitInContentPixels();
    136   }
    137 
    138   virtual WhichTree GetTree() const OVERRIDE { return base_client_->GetTree(); }
    139 
    140  private:
    141   PictureLayerTilingClient* base_client_;
    142   Region invalidation_;
    143 };
    144 
    145 }  // namespace
    146 
    147 RasterizeAndRecordBenchmarkImpl::RasterizeAndRecordBenchmarkImpl(
    148     scoped_refptr<base::MessageLoopProxy> origin_loop,
    149     base::Value* value,
    150     const MicroBenchmarkImpl::DoneCallback& callback)
    151     : MicroBenchmarkImpl(callback, origin_loop),
    152       rasterize_repeat_count_(kDefaultRasterizeRepeatCount) {
    153   base::DictionaryValue* settings = NULL;
    154   value->GetAsDictionary(&settings);
    155   if (!settings)
    156     return;
    157 
    158   if (settings->HasKey("rasterize_repeat_count"))
    159     settings->GetInteger("rasterize_repeat_count", &rasterize_repeat_count_);
    160 }
    161 
    162 RasterizeAndRecordBenchmarkImpl::~RasterizeAndRecordBenchmarkImpl() {}
    163 
    164 void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit(
    165     LayerTreeHostImpl* host) {
    166   LayerTreeHostCommon::CallFunctionForSubtree(
    167       host->RootLayer(),
    168       base::Bind(&RasterizeAndRecordBenchmarkImpl::Run,
    169                  base::Unretained(this)));
    170 
    171   scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
    172   result->SetDouble("rasterize_time_ms",
    173                     rasterize_results_.total_best_time.InMillisecondsF());
    174   result->SetInteger("pixels_rasterized", rasterize_results_.pixels_rasterized);
    175   result->SetInteger("pixels_rasterized_with_non_solid_color",
    176                      rasterize_results_.pixels_rasterized_with_non_solid_color);
    177   result->SetInteger("pixels_rasterized_as_opaque",
    178                      rasterize_results_.pixels_rasterized_as_opaque);
    179   result->SetInteger("total_layers", rasterize_results_.total_layers);
    180   result->SetInteger("total_picture_layers",
    181                      rasterize_results_.total_picture_layers);
    182   result->SetInteger("total_picture_layers_with_no_content",
    183                      rasterize_results_.total_picture_layers_with_no_content);
    184   result->SetInteger("total_picture_layers_off_screen",
    185                      rasterize_results_.total_picture_layers_off_screen);
    186 
    187   NotifyDone(result.PassAs<base::Value>());
    188 }
    189 
    190 void RasterizeAndRecordBenchmarkImpl::Run(LayerImpl* layer) {
    191   rasterize_results_.total_layers++;
    192   layer->RunMicroBenchmark(this);
    193 }
    194 
    195 void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {
    196   rasterize_results_.total_picture_layers++;
    197   if (!layer->DrawsContent()) {
    198     rasterize_results_.total_picture_layers_with_no_content++;
    199     return;
    200   }
    201   if (layer->visible_content_rect().IsEmpty()) {
    202     rasterize_results_.total_picture_layers_off_screen++;
    203     return;
    204   }
    205 
    206   TaskGraphRunner* task_graph_runner = RasterWorkerPool::GetTaskGraphRunner();
    207   DCHECK(task_graph_runner);
    208 
    209   if (!task_namespace_.IsValid())
    210     task_namespace_ = task_graph_runner->GetNamespaceToken();
    211 
    212   FixedInvalidationPictureLayerTilingClient client(
    213       layer, gfx::Rect(layer->content_bounds()));
    214   PictureLayerTilingSet tiling_set(&client, layer->content_bounds());
    215 
    216   PictureLayerTiling* tiling = tiling_set.AddTiling(layer->contents_scale_x());
    217   tiling->CreateAllTilesForTesting();
    218   for (PictureLayerTiling::CoverageIterator it(
    219            tiling, layer->contents_scale_x(), layer->visible_content_rect());
    220        it;
    221        ++it) {
    222     DCHECK(*it);
    223 
    224     PicturePileImpl* picture_pile = (*it)->picture_pile();
    225     gfx::Rect content_rect = (*it)->content_rect();
    226     float contents_scale = (*it)->contents_scale();
    227 
    228     scoped_refptr<BenchmarkRasterTask> benchmark_raster_task(
    229         new BenchmarkRasterTask(picture_pile,
    230                                 content_rect,
    231                                 contents_scale,
    232                                 rasterize_repeat_count_));
    233 
    234     TaskGraph graph;
    235 
    236     graph.nodes.push_back(
    237         TaskGraph::Node(benchmark_raster_task.get(),
    238                         RasterWorkerPool::kBenchmarkRasterTaskPriority,
    239                         0u));
    240 
    241     task_graph_runner->ScheduleTasks(task_namespace_, &graph);
    242     task_graph_runner->WaitForTasksToFinishRunning(task_namespace_);
    243 
    244     Task::Vector completed_tasks;
    245     task_graph_runner->CollectCompletedTasks(task_namespace_, &completed_tasks);
    246     DCHECK_EQ(1u, completed_tasks.size());
    247     DCHECK_EQ(completed_tasks[0], benchmark_raster_task);
    248 
    249     int tile_size = content_rect.width() * content_rect.height();
    250     base::TimeDelta min_time = benchmark_raster_task->GetBestTime();
    251     bool is_solid_color = benchmark_raster_task->IsSolidColor();
    252 
    253     if (layer->contents_opaque())
    254       rasterize_results_.pixels_rasterized_as_opaque += tile_size;
    255 
    256     if (!is_solid_color) {
    257       rasterize_results_.pixels_rasterized_with_non_solid_color += tile_size;
    258     }
    259 
    260     rasterize_results_.pixels_rasterized += tile_size;
    261     rasterize_results_.total_best_time += min_time;
    262   }
    263 }
    264 
    265 RasterizeAndRecordBenchmarkImpl::RasterizeResults::RasterizeResults()
    266     : pixels_rasterized(0),
    267       pixels_rasterized_with_non_solid_color(0),
    268       pixels_rasterized_as_opaque(0),
    269       total_layers(0),
    270       total_picture_layers(0),
    271       total_picture_layers_with_no_content(0),
    272       total_picture_layers_off_screen(0) {}
    273 
    274 RasterizeAndRecordBenchmarkImpl::RasterizeResults::~RasterizeResults() {}
    275 
    276 }  // namespace cc
    277