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/resources/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 bool Range::IsEmpty() { 22 return start_ >= end_; 23 } 24 25 inline void IntersectNegativeHalfplane(Range* out, 26 float previous, 27 float current, 28 float target, 29 float time_delta) { 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); 34 else 35 out->end_ = std::min(out->end_, t); 36 } 37 38 inline void IntersectPositiveHalfplane(Range* out, 39 float previous, 40 float current, 41 float target, 42 float time_delta) { 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); 47 else 48 out->end_ = std::min(out->end_, t); 49 } 50 51 } // namespace 52 53 namespace cc { 54 55 scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree) { 56 switch (tree) { 57 case ACTIVE_TREE: 58 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 59 "ACTIVE_TREE")); 60 case PENDING_TREE: 61 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 62 "PENDING_TREE")); 63 default: 64 DCHECK(false) << "Unrecognized WhichTree value " << tree; 65 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 66 "<unknown WhichTree value>")); 67 } 68 } 69 70 scoped_ptr<base::Value> TileResolutionAsValue( 71 TileResolution resolution) { 72 switch (resolution) { 73 case LOW_RESOLUTION: 74 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 75 "LOW_RESOLUTION")); 76 case HIGH_RESOLUTION: 77 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 78 "HIGH_RESOLUTION")); 79 case NON_IDEAL_RESOLUTION: 80 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 81 "NON_IDEAL_RESOLUTION")); 82 } 83 DCHECK(false) << "Unrecognized TileResolution value " << resolution; 84 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 85 "<unknown TileResolution value>")); 86 } 87 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>(); 96 } 97 98 float TilePriority::TimeForBoundsToIntersect(const gfx::RectF& previous_bounds, 99 const gfx::RectF& current_bounds, 100 float time_delta, 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()) 107 return 0.0f; 108 109 const float kMaxTimeToVisibleInSeconds = 110 std::numeric_limits<float>::infinity(); 111 112 if (time_delta == 0.0f) 113 return kMaxTimeToVisibleInSeconds; 114 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_; 135 } 136 137 scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue( 138 TileMemoryLimitPolicy policy) { 139 switch (policy) { 140 case ALLOW_NOTHING: 141 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 142 "ALLOW_NOTHING")); 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")); 149 case ALLOW_ANYTHING: 150 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 151 "ALLOW_ANYTHING")); 152 default: 153 DCHECK(false) << "Unrecognized policy value"; 154 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 155 "<unknown>")); 156 } 157 } 158 159 scoped_ptr<base::Value> TreePriorityAsValue(TreePriority prio) { 160 switch (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")); 170 } 171 DCHECK(false) << "Unrecognized priority value " << prio; 172 return scoped_ptr<base::Value>(base::Value::CreateStringValue( 173 "<unknown>")); 174 } 175 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>(); 186 } 187 188 } // namespace cc 189