diff options
Diffstat (limited to 'chromium/cc/resources/tile_priority.cc')
-rw-r--r-- | chromium/cc/resources/tile_priority.cc | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/chromium/cc/resources/tile_priority.cc b/chromium/cc/resources/tile_priority.cc new file mode 100644 index 00000000000..970ea1d81a5 --- /dev/null +++ b/chromium/cc/resources/tile_priority.cc @@ -0,0 +1,198 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/tile_priority.h" + +#include "base/values.h" +#include "cc/base/math_util.h" + +namespace { + +// TODO(qinmin): modify ui/range/Range.h to support template so that we +// don't need to define this. +struct Range { + Range(float start, float end) : start_(start), end_(end) {} + bool IsEmpty(); + float start_; + float end_; +}; + +inline bool Intersects(const Range& a, const Range& b) { + return a.start_ < b.end_ && b.start_ < a.end_; +} + +inline Range Intersect(const Range& a, const Range& b) { + return Range(std::max(a.start_, b.start_), std::min(a.end_, b.end_)); +} + +bool Range::IsEmpty() { + return start_ >= end_; +} + +inline void IntersectNegativeHalfplane(Range* out, + float previous, + float current, + float target, + float time_delta) { + float time_per_dist = time_delta / (current - previous); + float t = (target - current) * time_per_dist; + if (time_per_dist > 0.0f) + out->start_ = std::max(out->start_, t); + else + out->end_ = std::min(out->end_, t); +} + +inline void IntersectPositiveHalfplane(Range* out, + float previous, + float current, + float target, + float time_delta) { + float time_per_dist = time_delta / (current - previous); + float t = (target - current) * time_per_dist; + if (time_per_dist < 0.0f) + out->start_ = std::max(out->start_, t); + else + out->end_ = std::min(out->end_, t); +} + +} // namespace + +namespace cc { + +scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree) { + switch (tree) { + case ACTIVE_TREE: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "ACTIVE_TREE")); + case PENDING_TREE: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "PENDING_TREE")); + default: + DCHECK(false) << "Unrecognized WhichTree value " << tree; + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "<unknown WhichTree value>")); + } +} + +scoped_ptr<base::Value> TileResolutionAsValue( + TileResolution resolution) { + switch (resolution) { + case LOW_RESOLUTION: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "LOW_RESOLUTION")); + case HIGH_RESOLUTION: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "HIGH_RESOLUTION")); + case NON_IDEAL_RESOLUTION: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "NON_IDEAL_RESOLUTION")); + default: + DCHECK(false) << "Unrecognized TileResolution value " << resolution; + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "<unknown TileResolution value>")); + } +} + +scoped_ptr<base::Value> TilePriority::AsValue() const { + scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); + state->Set("resolution", TileResolutionAsValue(resolution).release()); + state->Set("time_to_visible_in_seconds", + MathUtil::AsValueSafely(time_to_visible_in_seconds).release()); + state->Set("distance_to_visible_in_pixels", + MathUtil::AsValueSafely(distance_to_visible_in_pixels).release()); + return state.PassAs<base::Value>(); +} + +float TilePriority::TimeForBoundsToIntersect(const gfx::RectF& previous_bounds, + const gfx::RectF& current_bounds, + float time_delta, + const gfx::RectF& target_bounds) { + // Perform an intersection test explicitly between current and target. + if (current_bounds.x() < target_bounds.right() && + current_bounds.y() < target_bounds.bottom() && + target_bounds.x() < current_bounds.right() && + target_bounds.y() < current_bounds.bottom()) + return 0.0f; + + const float kMaxTimeToVisibleInSeconds = + std::numeric_limits<float>::infinity(); + + if (time_delta == 0.0f) + return kMaxTimeToVisibleInSeconds; + + // As we are trying to solve the case of both scaling and scrolling, using + // a single coordinate with velocity is not enough. The logic here is to + // calculate the velocity for each edge. Then we calculate the time range that + // each edge will stay on the same side of the target bounds. If there is an + // overlap between these time ranges, the bounds must have intersect with + // each other during that period of time. + Range range(0.0f, kMaxTimeToVisibleInSeconds); + IntersectPositiveHalfplane( + &range, previous_bounds.x(), current_bounds.x(), + target_bounds.right(), time_delta); + IntersectNegativeHalfplane( + &range, previous_bounds.right(), current_bounds.right(), + target_bounds.x(), time_delta); + IntersectPositiveHalfplane( + &range, previous_bounds.y(), current_bounds.y(), + target_bounds.bottom(), time_delta); + IntersectNegativeHalfplane( + &range, previous_bounds.bottom(), current_bounds.bottom(), + target_bounds.y(), time_delta); + return range.IsEmpty() ? kMaxTimeToVisibleInSeconds : range.start_; +} + +scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue( + TileMemoryLimitPolicy policy) { + switch (policy) { + case ALLOW_NOTHING: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "ALLOW_NOTHING")); + case ALLOW_ABSOLUTE_MINIMUM: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "ALLOW_ABSOLUTE_MINIMUM")); + case ALLOW_PREPAINT_ONLY: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "ALLOW_PREPAINT_ONLY")); + case ALLOW_ANYTHING: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "ALLOW_ANYTHING")); + default: + DCHECK(false) << "Unrecognized policy value"; + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "<unknown>")); + } +} + +scoped_ptr<base::Value> TreePriorityAsValue(TreePriority prio) { + switch (prio) { + case SAME_PRIORITY_FOR_BOTH_TREES: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "SAME_PRIORITY_FOR_BOTH_TREES")); + case SMOOTHNESS_TAKES_PRIORITY: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "SMOOTHNESS_TAKES_PRIORITY")); + case NEW_CONTENT_TAKES_PRIORITY: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "NEW_CONTENT_TAKES_PRIORITY")); + default: + DCHECK(false) << "Unrecognized priority value " << prio; + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "<unknown>")); + } +} + +scoped_ptr<base::Value> GlobalStateThatImpactsTilePriority::AsValue() const { + scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); + state->Set("memory_limit_policy", + TileMemoryLimitPolicyAsValue(memory_limit_policy).release()); + state->SetInteger("memory_limit_in_bytes", memory_limit_in_bytes); + state->SetInteger("unused_memory_limit_in_bytes", + unused_memory_limit_in_bytes); + state->SetInteger("num_resources_limit", num_resources_limit); + state->Set("tree_priority", TreePriorityAsValue(tree_priority).release()); + return state.PassAs<base::Value>(); +} + +} // namespace cc |