OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/tile_priority.h" | 5 #include "cc/tile_priority.h" |
6 | 6 |
7 #include "base/values.h" | 7 #include "base/values.h" |
8 | 8 |
9 namespace { | 9 namespace { |
10 | 10 |
11 // TODO(qinmin): modify ui/range/Range.h to support template so that we | 11 // TODO(qinmin): modify ui/range/Range.h to support template so that we |
12 // don't need to define this. | 12 // don't need to define this. |
13 struct Range { | 13 struct Range { |
14 Range(double start, double end) : start_(start), end_(end) {} | 14 Range(float start, float end) : start_(start), end_(end) {} |
15 Range Intersects(const Range& other); | |
16 bool IsEmpty(); | 15 bool IsEmpty(); |
17 double start_; | 16 float start_; |
18 double end_; | 17 float end_; |
19 }; | 18 }; |
20 | 19 |
21 Range Range::Intersects(const Range& other) { | 20 inline bool Intersects(const Range& a, const Range& b) { |
22 start_ = std::max(start_, other.start_); | 21 return a.start_ < b.end_ && b.start_ < a.end_; |
23 end_ = std::min(end_, other.end_); | 22 } |
24 return Range(start_, end_); | 23 |
| 24 inline Range Intersect(const Range& a, const Range& b) { |
| 25 return Range(std::max(a.start_, b.start_), std::min(a.end_, b.end_)); |
25 } | 26 } |
26 | 27 |
27 bool Range::IsEmpty() { | 28 bool Range::IsEmpty() { |
28 return start_ >= end_; | 29 return start_ >= end_; |
29 } | 30 } |
30 | 31 |
31 // Calculate a time range that |value| will be larger than |threshold| | 32 inline void IntersectNegativeHalfplane(Range& out, float previous, |
32 // given the velocity of its change. | 33 float current, float target, float time_delta) { |
33 Range TimeRangeValueLargerThanThreshold( | 34 float time_per_dist = time_delta / (current - previous); |
34 int value, int threshold, double velocity) { | 35 float t = (target - current) * time_per_dist; |
35 double minimum_time = 0; | 36 if (time_per_dist > 0.0f) |
36 double maximum_time = cc::TilePriority::kMaxTimeToVisibleInSeconds; | 37 out.start_ = std::max(out.start_, t); |
| 38 else |
| 39 out.end_ = std::min(out.end_, t); |
| 40 } |
37 | 41 |
38 if (velocity > 0) { | 42 inline void IntersectPositiveHalfplane(Range& out, float previous, |
39 if (value < threshold) | 43 float current, float target, float time_delta) { |
40 minimum_time = std::min(cc::TilePriority::kMaxTimeToVisibleInSeconds, | 44 float time_per_dist = time_delta / (current - previous); |
41 (threshold - value) / velocity); | 45 float t = (target - current) * time_per_dist; |
42 } else if (velocity <= 0) { | 46 if (time_per_dist < 0.0f) |
43 if (value < threshold) | 47 out.start_ = std::max(out.start_, t); |
44 minimum_time = cc::TilePriority::kMaxTimeToVisibleInSeconds; | 48 else |
45 else if (velocity != 0) | 49 out.end_ = std::min(out.end_, t); |
46 maximum_time = std::min(maximum_time, (threshold - value) / velocity); | |
47 } | |
48 | |
49 return Range(minimum_time, maximum_time); | |
50 } | 50 } |
51 | 51 |
52 } // namespace | 52 } // namespace |
53 | 53 |
54 namespace cc { | 54 namespace cc { |
55 | 55 |
56 const double TilePriority::kMaxTimeToVisibleInSeconds = 1000.0; | 56 const float TilePriority::kMaxDistanceInContentSpace = 4096.0f; |
57 const double TilePriority::kMaxDistanceInContentSpace = 4096.0; | |
58 | 57 |
59 scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree) { | 58 scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree) { |
60 switch (tree) { | 59 switch (tree) { |
61 case ACTIVE_TREE: | 60 case ACTIVE_TREE: |
62 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | 61 return scoped_ptr<base::Value>(base::Value::CreateStringValue( |
63 "ACTIVE_TREE")); | 62 "ACTIVE_TREE")); |
64 case PENDING_TREE: | 63 case PENDING_TREE: |
65 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | 64 return scoped_ptr<base::Value>(base::Value::CreateStringValue( |
66 "PENDING_TREE")); | 65 "PENDING_TREE")); |
67 default: | 66 default: |
68 DCHECK(false) << "Unrecognized WhichTree value"; | 67 DCHECK(false) << "Unrecognized WhichTree value"; |
69 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | 68 return scoped_ptr<base::Value>(base::Value::CreateStringValue( |
70 "<unknown WhichTree value>")); | 69 "<unknown WhichTree value>")); |
71 } | 70 } |
72 } | 71 } |
73 | 72 |
74 int TilePriority::manhattanDistance(const gfx::RectF& a, const gfx::RectF& b) { | |
75 gfx::RectF c = gfx::UnionRects(a, b); | |
76 // Rects touching the edge of the screen should not be considered visible. | |
77 // So we add 1 pixel here to avoid that situation. | |
78 int x = static_cast<int>( | |
79 std::max(0.0f, c.width() - a.width() - b.width() + 1)); | |
80 int y = static_cast<int>( | |
81 std::max(0.0f, c.height() - a.height() - b.height() + 1)); | |
82 return (x + y); | |
83 } | |
84 | 73 |
85 double TilePriority::TimeForBoundsToIntersect(gfx::RectF previous_bounds, | 74 float TilePriority::TimeForBoundsToIntersect(const gfx::RectF& previous_bounds, |
86 gfx::RectF current_bounds, | 75 const gfx::RectF& current_bounds, |
87 double time_delta, | 76 float time_delta, |
88 gfx::RectF target_bounds) { | 77 const gfx::RectF& target_bounds) { |
89 if (current_bounds.Intersects(target_bounds)) | 78 // Perform an intersection test explicitly between current and target. |
90 return 0; | 79 if (current_bounds.x() < target_bounds.right() && |
| 80 current_bounds.y() < target_bounds.bottom() && |
| 81 target_bounds.x() < current_bounds.right() && |
| 82 target_bounds.y() < current_bounds.bottom()) |
| 83 return 0.0f; |
91 | 84 |
92 if (previous_bounds.Intersects(target_bounds) || time_delta == 0) | 85 const float kMaxTimeToVisibleInSeconds = |
| 86 std::numeric_limits<float>::infinity(); |
| 87 |
| 88 if (time_delta == 0.0f) |
93 return kMaxTimeToVisibleInSeconds; | 89 return kMaxTimeToVisibleInSeconds; |
94 | 90 |
95 // As we are trying to solve the case of both scaling and scrolling, using | 91 // As we are trying to solve the case of both scaling and scrolling, using |
96 // a single coordinate with velocity is not enough. The logic here is to | 92 // a single coordinate with velocity is not enough. The logic here is to |
97 // calculate the velocity for each edge. Then we calculate the time range that | 93 // calculate the velocity for each edge. Then we calculate the time range that |
98 // each edge will stay on the same side of the target bounds. If there is an | 94 // each edge will stay on the same side of the target bounds. If there is an |
99 // overlap between these time ranges, the bounds must have intersect with | 95 // overlap between these time ranges, the bounds must have intersect with |
100 // each other during that period of time. | 96 // each other during that period of time. |
101 double velocity = | 97 Range range(0.0f, kMaxTimeToVisibleInSeconds); |
102 (current_bounds.right() - previous_bounds.right()) / time_delta; | 98 IntersectPositiveHalfplane( |
103 Range range = TimeRangeValueLargerThanThreshold( | 99 range, previous_bounds.x(), current_bounds.x(), |
104 current_bounds.right(), target_bounds.x(), velocity); | 100 target_bounds.right(), time_delta); |
105 | 101 IntersectNegativeHalfplane( |
106 velocity = (current_bounds.x() - previous_bounds.x()) / time_delta; | 102 range, previous_bounds.right(), current_bounds.right(), |
107 range = range.Intersects(TimeRangeValueLargerThanThreshold( | 103 target_bounds.x(), time_delta); |
108 -current_bounds.x(), -target_bounds.right(), -velocity)); | 104 IntersectPositiveHalfplane( |
109 | 105 range, previous_bounds.y(), current_bounds.y(), |
110 | 106 target_bounds.bottom(), time_delta); |
111 velocity = (current_bounds.y() - previous_bounds.y()) / time_delta; | 107 IntersectNegativeHalfplane( |
112 range = range.Intersects(TimeRangeValueLargerThanThreshold( | 108 range, previous_bounds.bottom(), current_bounds.bottom(), |
113 -current_bounds.y(), -target_bounds.bottom(), -velocity)); | 109 target_bounds.y(), time_delta); |
114 | |
115 velocity = (current_bounds.bottom() - previous_bounds.bottom()) / time_delta; | |
116 range = range.Intersects(TimeRangeValueLargerThanThreshold( | |
117 current_bounds.bottom(), target_bounds.y(), velocity)); | |
118 | |
119 return range.IsEmpty() ? kMaxTimeToVisibleInSeconds : range.start_; | 110 return range.IsEmpty() ? kMaxTimeToVisibleInSeconds : range.start_; |
120 } | 111 } |
121 | 112 |
122 scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue( | 113 scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue( |
123 TileMemoryLimitPolicy policy) { | 114 TileMemoryLimitPolicy policy) { |
124 switch (policy) { | 115 switch (policy) { |
125 case ALLOW_NOTHING: | 116 case ALLOW_NOTHING: |
126 return scoped_ptr<base::Value>(base::Value::CreateStringValue( | 117 return scoped_ptr<base::Value>(base::Value::CreateStringValue( |
127 "ALLOW_NOTHING")); | 118 "ALLOW_NOTHING")); |
128 case ALLOW_ABSOLUTE_MINIMUM: | 119 case ALLOW_ABSOLUTE_MINIMUM: |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 scoped_ptr<base::Value> GlobalStateThatImpactsTilePriority::AsValue() const { | 153 scoped_ptr<base::Value> GlobalStateThatImpactsTilePriority::AsValue() const { |
163 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | 154 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
164 state->Set("memory_limit_policy", TileMemoryLimitPolicyAsValue(memory_limit_po
licy).release()); | 155 state->Set("memory_limit_policy", TileMemoryLimitPolicyAsValue(memory_limit_po
licy).release()); |
165 state->SetInteger("memory_limit_in_bytes", memory_limit_in_bytes); | 156 state->SetInteger("memory_limit_in_bytes", memory_limit_in_bytes); |
166 state->Set("tree_priority", TreePriorityAsValue(tree_priority).release()); | 157 state->Set("tree_priority", TreePriorityAsValue(tree_priority).release()); |
167 return state.PassAs<base::Value>(); | 158 return state.PassAs<base::Value>(); |
168 } | 159 } |
169 | 160 |
170 | 161 |
171 } // namespace cc | 162 } // namespace cc |
OLD | NEW |