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.
5 #include "cc/resources/tile_priority.h"
7 #include "base/values.h"
8 #include "cc/base/math_util.h"
12 // TODO(qinmin): modify ui/gfx/range/range.h to support template so that we
13 // don't need to define this.
15 Range(float start, float end) : start_(start), end_(end) {}
21 bool Range::IsEmpty() {
22 return start_ >= end_;
25 inline void IntersectNegativeHalfplane(Range* out,
30 float time_per_dist = time_delta / (current - previous);
31 float t = (target - current) * time_per_dist;
32 if (time_per_dist > 0.0f)
33 out->start_ = std::max(out->start_, t);
35 out->end_ = std::min(out->end_, t);
38 inline void IntersectPositiveHalfplane(Range* out,
43 float time_per_dist = time_delta / (current - previous);
44 float t = (target - current) * time_per_dist;
45 if (time_per_dist < 0.0f)
46 out->start_ = std::max(out->start_, t);
48 out->end_ = std::min(out->end_, t);
55 scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree) {
58 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
61 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
64 DCHECK(false) << "Unrecognized WhichTree value " << tree;
65 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
66 "<unknown WhichTree value>"));
70 scoped_ptr<base::Value> TileResolutionAsValue(
71 TileResolution resolution) {
74 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
77 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
79 case NON_IDEAL_RESOLUTION:
80 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
81 "NON_IDEAL_RESOLUTION"));
83 DCHECK(false) << "Unrecognized TileResolution value " << resolution;
84 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
85 "<unknown TileResolution value>"));
88 scoped_ptr<base::Value> TilePriority::AsValue() const {
89 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
90 state->Set("resolution", TileResolutionAsValue(resolution).release());
91 state->Set("time_to_visible_in_seconds",
92 MathUtil::AsValueSafely(time_to_visible_in_seconds).release());
93 state->Set("distance_to_visible_in_pixels",
94 MathUtil::AsValueSafely(distance_to_visible_in_pixels).release());
95 return state.PassAs<base::Value>();
98 float TilePriority::TimeForBoundsToIntersect(const gfx::RectF& previous_bounds,
99 const gfx::RectF& current_bounds,
101 const gfx::RectF& target_bounds) {
102 // Perform an intersection test explicitly between current and target.
103 if (current_bounds.x() < target_bounds.right() &&
104 current_bounds.y() < target_bounds.bottom() &&
105 target_bounds.x() < current_bounds.right() &&
106 target_bounds.y() < current_bounds.bottom())
109 const float kMaxTimeToVisibleInSeconds =
110 std::numeric_limits<float>::infinity();
112 if (time_delta == 0.0f)
113 return kMaxTimeToVisibleInSeconds;
115 // As we are trying to solve the case of both scaling and scrolling, using
116 // a single coordinate with velocity is not enough. The logic here is to
117 // calculate the velocity for each edge. Then we calculate the time range that
118 // each edge will stay on the same side of the target bounds. If there is an
119 // overlap between these time ranges, the bounds must have intersect with
120 // each other during that period of time.
121 Range range(0.0f, kMaxTimeToVisibleInSeconds);
122 IntersectPositiveHalfplane(
123 &range, previous_bounds.x(), current_bounds.x(),
124 target_bounds.right(), time_delta);
125 IntersectNegativeHalfplane(
126 &range, previous_bounds.right(), current_bounds.right(),
127 target_bounds.x(), time_delta);
128 IntersectPositiveHalfplane(
129 &range, previous_bounds.y(), current_bounds.y(),
130 target_bounds.bottom(), time_delta);
131 IntersectNegativeHalfplane(
132 &range, previous_bounds.bottom(), current_bounds.bottom(),
133 target_bounds.y(), time_delta);
134 return range.IsEmpty() ? kMaxTimeToVisibleInSeconds : range.start_;
137 scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue(
138 TileMemoryLimitPolicy policy) {
141 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
143 case ALLOW_ABSOLUTE_MINIMUM:
144 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
145 "ALLOW_ABSOLUTE_MINIMUM"));
146 case ALLOW_PREPAINT_ONLY:
147 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
148 "ALLOW_PREPAINT_ONLY"));
150 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
153 DCHECK(false) << "Unrecognized policy value";
154 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
159 scoped_ptr<base::Value> TreePriorityAsValue(TreePriority prio) {
161 case SAME_PRIORITY_FOR_BOTH_TREES:
162 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
163 "SAME_PRIORITY_FOR_BOTH_TREES"));
164 case SMOOTHNESS_TAKES_PRIORITY:
165 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
166 "SMOOTHNESS_TAKES_PRIORITY"));
167 case NEW_CONTENT_TAKES_PRIORITY:
168 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
169 "NEW_CONTENT_TAKES_PRIORITY"));
171 DCHECK(false) << "Unrecognized priority value " << prio;
172 return scoped_ptr<base::Value>(base::Value::CreateStringValue(
176 scoped_ptr<base::Value> GlobalStateThatImpactsTilePriority::AsValue() const {
177 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
178 state->Set("memory_limit_policy",
179 TileMemoryLimitPolicyAsValue(memory_limit_policy).release());
180 state->SetInteger("memory_limit_in_bytes", memory_limit_in_bytes);
181 state->SetInteger("unused_memory_limit_in_bytes",
182 unused_memory_limit_in_bytes);
183 state->SetInteger("num_resources_limit", num_resources_limit);
184 state->Set("tree_priority", TreePriorityAsValue(tree_priority).release());
185 return state.PassAs<base::Value>();