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 |