| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 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/tile_priority.h" | |
| 6 | |
| 7 #include "base/values.h" | |
| 8 #include "cc/base/math_util.h" | |
| 9 | |
| 10 namespace { | |
| 11 | |
| 12 // TODO(qinmin): modify ui/range/Range.h to support template so that we | |
| 13 // don't need to define this. | |
| 14 struct Range { | |
| 15 Range(float start, float end) : start_(start), end_(end) {} | |
| 16 bool IsEmpty(); | |
| 17 float start_; | |
| 18 float end_; | |
| 19 }; | |
| 20 | |
| 21 inline bool Intersects(const Range& a, const Range& b) { | |
| 22 return a.start_ < b.end_ && b.start_ < a.end_; | |
| 23 } | |
| 24 | |
| 25 inline Range Intersect(const Range& a, const Range& b) { | |
| 26 return Range(std::max(a.start_, b.start_), std::min(a.end_, b.end_)); | |
| 27 } | |
| 28 | |
| 29 bool Range::IsEmpty() { | |
| 30 return start_ >= end_; | |
| 31 } | |
| 32 | |
| 33 inline void IntersectNegativeHalfplane(Range& out, float previous, | |
| 34 float current, float target, float time_delta) { | |
| 35 float time_per_dist = time_delta / (current - previous); | |
| 36 float t = (target - current) * time_per_dist; | |
| 37 if (time_per_dist > 0.0f) | |
| 38 out.start_ = std::max(out.start_, t); | |
| 39 else | |
| 40 out.end_ = std::min(out.end_, t); | |
| 41 } | |
| 42 | |
| 43 inline void IntersectPositiveHalfplane(Range& out, float previous, | |
| 44 float current, float target, float time_delta) { | |
| 45 float time_per_dist = time_delta / (current - previous); | |
| 46 float t = (target - current) * time_per_dist; | |
| 47 if (time_per_dist < 0.0f) | |
| 48 out.start_ = std::max(out.start_, t); | |
| 49 else | |
| 50 out.end_ = std::min(out.end_, t); | |
| 51 } | |
| 52 | |
| 53 } // namespace | |
| 54 | |
| 55 namespace cc { | |
| 56 | |
| 57 const float TilePriority::kMaxDistanceInContentSpace = 4096.0f; | |
| 58 | |
| 59 // At 256x256 tiles, 128 tiles cover an area of 2048x4096 pixels. | |
| 60 const int64 TilePriority:: | |
| 61 kNumTilesToCoverWithInflatedViewportRectForPrioritization = 128; | |
| 62 | |
| 63 scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree) { | |
| 64 switch (tree) { | |
| 65 case ACTIVE_TREE: | |
| 66 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 67 "ACTIVE_TREE")); | |
| 68 case PENDING_TREE: | |
| 69 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 70 "PENDING_TREE")); | |
| 71 default: | |
| 72 DCHECK(false) << "Unrecognized WhichTree value " << tree; | |
| 73 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 74 "<unknown WhichTree value>")); | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 scoped_ptr<base::Value> TileResolutionAsValue( | |
| 79 TileResolution resolution) { | |
| 80 switch (resolution) { | |
| 81 case LOW_RESOLUTION: | |
| 82 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 83 "LOW_RESOLUTION")); | |
| 84 case HIGH_RESOLUTION: | |
| 85 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 86 "HIGH_RESOLUTION")); | |
| 87 case NON_IDEAL_RESOLUTION: | |
| 88 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 89 "NON_IDEAL_RESOLUTION")); | |
| 90 default: | |
| 91 DCHECK(false) << "Unrecognized TileResolution value " << resolution; | |
| 92 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 93 "<unknown TileResolution value>")); | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 scoped_ptr<base::Value> TilePriority::AsValue() const { | |
| 98 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | |
| 99 state->SetBoolean("is_live", is_live); | |
| 100 state->Set("resolution", TileResolutionAsValue(resolution).release()); | |
| 101 state->Set("time_to_visible_in_seconds", MathUtil::AsValueSafely(time_to_visib
le_in_seconds).release()); | |
| 102 state->Set("distance_to_visible_in_pixels", MathUtil::AsValueSafely(distance_t
o_visible_in_pixels).release()); | |
| 103 state->Set("current_screen_quad", MathUtil::AsValue(current_screen_quad).relea
se()); | |
| 104 return state.PassAs<base::Value>(); | |
| 105 } | |
| 106 | |
| 107 float TilePriority::TimeForBoundsToIntersect(const gfx::RectF& previous_bounds, | |
| 108 const gfx::RectF& current_bounds, | |
| 109 float time_delta, | |
| 110 const gfx::RectF& target_bounds) { | |
| 111 // Perform an intersection test explicitly between current and target. | |
| 112 if (current_bounds.x() < target_bounds.right() && | |
| 113 current_bounds.y() < target_bounds.bottom() && | |
| 114 target_bounds.x() < current_bounds.right() && | |
| 115 target_bounds.y() < current_bounds.bottom()) | |
| 116 return 0.0f; | |
| 117 | |
| 118 const float kMaxTimeToVisibleInSeconds = | |
| 119 std::numeric_limits<float>::infinity(); | |
| 120 | |
| 121 if (time_delta == 0.0f) | |
| 122 return kMaxTimeToVisibleInSeconds; | |
| 123 | |
| 124 // As we are trying to solve the case of both scaling and scrolling, using | |
| 125 // a single coordinate with velocity is not enough. The logic here is to | |
| 126 // calculate the velocity for each edge. Then we calculate the time range that | |
| 127 // each edge will stay on the same side of the target bounds. If there is an | |
| 128 // overlap between these time ranges, the bounds must have intersect with | |
| 129 // each other during that period of time. | |
| 130 Range range(0.0f, kMaxTimeToVisibleInSeconds); | |
| 131 IntersectPositiveHalfplane( | |
| 132 range, previous_bounds.x(), current_bounds.x(), | |
| 133 target_bounds.right(), time_delta); | |
| 134 IntersectNegativeHalfplane( | |
| 135 range, previous_bounds.right(), current_bounds.right(), | |
| 136 target_bounds.x(), time_delta); | |
| 137 IntersectPositiveHalfplane( | |
| 138 range, previous_bounds.y(), current_bounds.y(), | |
| 139 target_bounds.bottom(), time_delta); | |
| 140 IntersectNegativeHalfplane( | |
| 141 range, previous_bounds.bottom(), current_bounds.bottom(), | |
| 142 target_bounds.y(), time_delta); | |
| 143 return range.IsEmpty() ? kMaxTimeToVisibleInSeconds : range.start_; | |
| 144 } | |
| 145 | |
| 146 scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue( | |
| 147 TileMemoryLimitPolicy policy) { | |
| 148 switch (policy) { | |
| 149 case ALLOW_NOTHING: | |
| 150 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 151 "ALLOW_NOTHING")); | |
| 152 case ALLOW_ABSOLUTE_MINIMUM: | |
| 153 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 154 "ALLOW_ABSOLUTE_MINIMUM")); | |
| 155 case ALLOW_PREPAINT_ONLY: | |
| 156 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 157 "ALLOW_PREPAINT_ONLY")); | |
| 158 case ALLOW_ANYTHING: | |
| 159 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 160 "ALLOW_ANYTHING")); | |
| 161 default: | |
| 162 DCHECK(false) << "Unrecognized policy value"; | |
| 163 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 164 "<unknown>")); | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 scoped_ptr<base::Value> TreePriorityAsValue(TreePriority prio) { | |
| 169 switch (prio) { | |
| 170 case SAME_PRIORITY_FOR_BOTH_TREES: | |
| 171 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 172 "SAME_PRIORITY_FOR_BOTH_TREES")); | |
| 173 case SMOOTHNESS_TAKES_PRIORITY: | |
| 174 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 175 "SMOOTHNESS_TAKES_PRIORITY")); | |
| 176 case NEW_CONTENT_TAKES_PRIORITY: | |
| 177 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 178 "NEW_CONTENT_TAKES_PRIORITY")); | |
| 179 default: | |
| 180 DCHECK(false) << "Unrecognized priority value " << prio; | |
| 181 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | |
| 182 "<unknown>")); | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 scoped_ptr<base::Value> GlobalStateThatImpactsTilePriority::AsValue() const { | |
| 187 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | |
| 188 state->Set("memory_limit_policy", TileMemoryLimitPolicyAsValue(memory_limit_po
licy).release()); | |
| 189 state->SetInteger("memory_limit_in_bytes", memory_limit_in_bytes); | |
| 190 state->Set("tree_priority", TreePriorityAsValue(tree_priority).release()); | |
| 191 return state.PassAs<base::Value>(); | |
| 192 } | |
| 193 | |
| 194 | |
| 195 } // namespace cc | |
| OLD | NEW |