[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 1 | // Copyright 2014 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 | |
chrishtr | 82b5d950 | 2017-03-20 18:25:33 | [diff] [blame] | 5 | #include "cc/benchmarks/invalidation_benchmark.h" |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 6 | |
avi | 02a4d17 | 2015-12-21 06:14:36 | [diff] [blame] | 7 | #include <stdint.h> |
| 8 | |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 9 | #include <algorithm> |
| 10 | #include <limits> |
| 11 | |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 12 | #include "base/rand_util.h" |
| 13 | #include "base/values.h" |
| 14 | #include "cc/layers/layer.h" |
| 15 | #include "cc/layers/picture_layer.h" |
jaydasika | 0f02fed | 2016-04-05 19:07:02 | [diff] [blame] | 16 | #include "cc/trees/draw_property_utils.h" |
khushalsagar | b69ba945 | 2017-01-27 22:20:07 | [diff] [blame] | 17 | #include "cc/trees/layer_tree_host.h" |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 18 | #include "cc/trees/layer_tree_host_common.h" |
heejin.r.chung | d28506ba | 2014-10-23 16:36:20 | [diff] [blame] | 19 | #include "ui/gfx/geometry/rect.h" |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 20 | |
| 21 | namespace cc { |
| 22 | |
| 23 | namespace { |
| 24 | |
| 25 | const char* kDefaultInvalidationMode = "viewport"; |
| 26 | |
| 27 | } // namespace |
| 28 | |
| 29 | InvalidationBenchmark::InvalidationBenchmark( |
danakj | 60bc3bc | 2016-04-09 00:24:48 | [diff] [blame] | 30 | std::unique_ptr<base::Value> value, |
Sadrul Habib Chowdhury | d7cc06cf7 | 2018-01-26 23:08:40 | [diff] [blame] | 31 | MicroBenchmark::DoneCallback callback) |
| 32 | : MicroBenchmark(std::move(callback)), seed_(0) { |
kulkarni.a | 4015690f1 | 2014-10-10 13:50:06 | [diff] [blame] | 33 | base::DictionaryValue* settings = nullptr; |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 34 | value->GetAsDictionary(&settings); |
| 35 | if (!settings) |
| 36 | return; |
| 37 | |
| 38 | std::string mode_string = kDefaultInvalidationMode; |
| 39 | |
| 40 | if (settings->HasKey("mode")) |
| 41 | settings->GetString("mode", &mode_string); |
| 42 | |
| 43 | if (mode_string == "fixed_size") { |
| 44 | mode_ = FIXED_SIZE; |
| 45 | CHECK(settings->HasKey("width")) |
| 46 | << "Must provide a width for fixed_size mode."; |
| 47 | CHECK(settings->HasKey("height")) |
| 48 | << "Must provide a height for fixed_size mode."; |
| 49 | settings->GetInteger("width", &width_); |
| 50 | settings->GetInteger("height", &height_); |
| 51 | } else if (mode_string == "layer") { |
| 52 | mode_ = LAYER; |
| 53 | } else if (mode_string == "random") { |
| 54 | mode_ = RANDOM; |
| 55 | } else if (mode_string == "viewport") { |
| 56 | mode_ = VIEWPORT; |
| 57 | } else { |
| 58 | CHECK(false) << "Invalid mode: " << mode_string |
| 59 | << ". One of {fixed_size, layer, viewport, random} expected."; |
| 60 | } |
| 61 | } |
| 62 | |
Chris Watkins | f635329 | 2017-12-04 02:36:05 | [diff] [blame] | 63 | InvalidationBenchmark::~InvalidationBenchmark() = default; |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 64 | |
khushalsagar | b69ba945 | 2017-01-27 22:20:07 | [diff] [blame] | 65 | void InvalidationBenchmark::DidUpdateLayers(LayerTreeHost* layer_tree_host) { |
jaydasika | 13c0506 | 2016-04-01 18:12:27 | [diff] [blame] | 66 | LayerTreeHostCommon::CallFunctionForEveryLayer( |
khushalsagar | b69ba945 | 2017-01-27 22:20:07 | [diff] [blame] | 67 | layer_tree_host, |
| 68 | [this](Layer* layer) { layer->RunMicroBenchmark(this); }); |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | void InvalidationBenchmark::RunOnLayer(PictureLayer* layer) { |
sunxd | 713aedbd | 2016-08-10 22:22:14 | [diff] [blame] | 72 | gfx::Rect visible_layer_rect = gfx::Rect(layer->bounds()); |
| 73 | gfx::Transform from_screen; |
xidachen | 41fb39b | 2017-04-11 21:40:25 | [diff] [blame] | 74 | bool invertible = layer->ScreenSpaceTransform().GetInverse(&from_screen); |
sunxd | 713aedbd | 2016-08-10 22:22:14 | [diff] [blame] | 75 | if (!invertible) |
| 76 | from_screen = gfx::Transform(); |
| 77 | gfx::Rect viewport_rect = MathUtil::ProjectEnclosingClippedRect( |
khushalsagar | b69ba945 | 2017-01-27 22:20:07 | [diff] [blame] | 78 | from_screen, gfx::Rect(layer->layer_tree_host()->device_viewport_size())); |
sunxd | 713aedbd | 2016-08-10 22:22:14 | [diff] [blame] | 79 | visible_layer_rect.Intersect(viewport_rect); |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 80 | switch (mode_) { |
| 81 | case FIXED_SIZE: { |
| 82 | // Invalidation with a random position and fixed size. |
danakj | 64767d90 | 2015-06-19 00:10:43 | [diff] [blame] | 83 | int x = LCGRandom() * (visible_layer_rect.width() - width_); |
| 84 | int y = LCGRandom() * (visible_layer_rect.height() - height_); |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 85 | gfx::Rect invalidation_rect(x, y, width_, height_); |
| 86 | layer->SetNeedsDisplayRect(invalidation_rect); |
| 87 | break; |
| 88 | } |
| 89 | case LAYER: { |
| 90 | // Invalidate entire layer. |
| 91 | layer->SetNeedsDisplay(); |
| 92 | break; |
| 93 | } |
| 94 | case RANDOM: { |
| 95 | // Random invalidation inside the viewport. |
danakj | 64767d90 | 2015-06-19 00:10:43 | [diff] [blame] | 96 | int x_min = LCGRandom() * visible_layer_rect.width(); |
| 97 | int x_max = LCGRandom() * visible_layer_rect.width(); |
| 98 | int y_min = LCGRandom() * visible_layer_rect.height(); |
| 99 | int y_max = LCGRandom() * visible_layer_rect.height(); |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 100 | if (x_min > x_max) |
| 101 | std::swap(x_min, x_max); |
| 102 | if (y_min > y_max) |
| 103 | std::swap(y_min, y_max); |
| 104 | gfx::Rect invalidation_rect(x_min, y_min, x_max - x_min, y_max - y_min); |
| 105 | layer->SetNeedsDisplayRect(invalidation_rect); |
| 106 | break; |
| 107 | } |
| 108 | case VIEWPORT: { |
| 109 | // Invalidate entire viewport. |
sunxd | 713aedbd | 2016-08-10 22:22:14 | [diff] [blame] | 110 | layer->SetNeedsDisplayRect(visible_layer_rect); |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 111 | break; |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | |
danakj | 60bc3bc | 2016-04-09 00:24:48 | [diff] [blame] | 116 | bool InvalidationBenchmark::ProcessMessage(std::unique_ptr<base::Value> value) { |
kulkarni.a | 4015690f1 | 2014-10-10 13:50:06 | [diff] [blame] | 117 | base::DictionaryValue* message = nullptr; |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 118 | value->GetAsDictionary(&message); |
| 119 | if (!message) |
| 120 | return false; |
| 121 | |
| 122 | bool notify_done; |
| 123 | if (message->HasKey("notify_done")) { |
| 124 | message->GetBoolean("notify_done", ¬ify_done); |
| 125 | if (notify_done) |
Jeremy Roman | 909d927b | 2017-08-27 18:34:09 | [diff] [blame] | 126 | NotifyDone(std::make_unique<base::Value>()); |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 127 | return true; |
| 128 | } |
| 129 | return false; |
| 130 | } |
| 131 | |
| 132 | // A simple linear congruential generator. The random numbers don't need to be |
| 133 | // high quality, but they need to be identical in each run. Therefore, we use a |
| 134 | // LCG and keep the state locally in the benchmark. |
| 135 | float InvalidationBenchmark::LCGRandom() { |
avi | 02a4d17 | 2015-12-21 06:14:36 | [diff] [blame] | 136 | const uint32_t a = 1664525; |
| 137 | const uint32_t c = 1013904223; |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 138 | seed_ = a * seed_ + c; |
avi | 02a4d17 | 2015-12-21 06:14:36 | [diff] [blame] | 139 | return static_cast<float>(seed_) / std::numeric_limits<uint32_t>::max(); |
[email protected] | 35805ad | 2014-05-31 22:17:19 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | } // namespace cc |