Index: cc/picture_layer_tiling.cc |
diff --git a/cc/picture_layer_tiling.cc b/cc/picture_layer_tiling.cc |
index 95be306169e327fa4b7f8685d86fc3c0fc979e18..398b26e347a621e7a322c01ec2fe17169c8fe546 100644 |
--- a/cc/picture_layer_tiling.cc |
+++ b/cc/picture_layer_tiling.cc |
@@ -4,6 +4,8 @@ |
#include "cc/picture_layer_tiling.h" |
+#include <cmath> |
+ |
#include "base/debug/trace_event.h" |
#include "cc/math_util.h" |
#include "ui/gfx/point_conversions.h" |
@@ -391,21 +393,24 @@ void PictureLayerTiling::UpdateTilePriorities( |
gfx::Rect viewport_in_content_space = |
gfx::ToEnclosingRect(gfx::ScaleRect(viewport_in_layer_space, |
contents_scale_)); |
- gfx::Rect inflated_rect = viewport_in_content_space; |
- float adjusted_inset = TilePriority::kMaxDistanceInContentSpace / |
- std::max(contents_scale_, 1.f); |
- inflated_rect.Inset( |
- -adjusted_inset, |
- -adjusted_inset, |
- -adjusted_inset, |
- -adjusted_inset); |
- inflated_rect.Intersect(ContentRect()); |
+ |
+ static const int64 kMaxTilesForPrioritizedRect = 80; |
nduca
2013/02/16 22:30:59
Should we put this by where the old constant lived
danakj
2013/02/18 19:26:20
Right, I feel like asking 3 people would get you 3
|
+ |
+ gfx::Size tile_size = tiling_data_.max_texture_size(); |
+ int64 prioritized_rect_area = kMaxTilesForPrioritizedRect * |
+ tile_size.width() * tile_size.height(); |
+ |
+ gfx::Rect prioritized_rect = ExpandRectEquallyToAreaBoundedBy( |
+ viewport_in_content_space, |
+ prioritized_rect_area, |
+ ContentRect()); |
+ DCHECK(ContentRect().Contains(prioritized_rect)); |
// Iterate through all of the tiles that were live last frame but will |
// not be live this frame, and mark them as being dead. |
for (TilingData::DifferenceIterator iter(&tiling_data_, |
last_prioritized_rect_, |
- inflated_rect); |
+ prioritized_rect); |
iter; |
++iter) { |
TileMap::iterator find = tiles_.find(iter.index()); |
@@ -417,7 +422,7 @@ void PictureLayerTiling::UpdateTilePriorities( |
Tile* tile = find->second.get(); |
tile->set_priority(tree, priority); |
} |
- last_prioritized_rect_ = inflated_rect; |
+ last_prioritized_rect_ = prioritized_rect; |
gfx::Rect view_rect(device_viewport); |
float current_scale = current_layer_contents_scale / contents_scale_; |
@@ -434,7 +439,7 @@ void PictureLayerTiling::UpdateTilePriorities( |
last_screen_transform.matrix().get(0, 3), |
last_screen_transform.matrix().get(1, 3)); |
- for (TilingData::Iterator iter(&tiling_data_, inflated_rect); |
+ for (TilingData::Iterator iter(&tiling_data_, prioritized_rect); |
iter; ++iter) { |
TileMap::iterator find = tiles_.find(iter.index()); |
if (find == tiles_.end()) |
@@ -467,7 +472,7 @@ void PictureLayerTiling::UpdateTilePriorities( |
tile->set_priority(tree, priority); |
} |
} else { |
- for (TilingData::Iterator iter(&tiling_data_, inflated_rect); |
+ for (TilingData::Iterator iter(&tiling_data_, prioritized_rect); |
iter; ++iter) { |
TileMap::iterator find = tiles_.find(iter.index()); |
if (find == tiles_.end()) |
@@ -539,4 +544,213 @@ scoped_ptr<base::Value> PictureLayerTiling::AsValue() const { |
return state.PassAs<base::Value>(); |
} |
+namespace { |
+ |
+int ComputeOffsetToExpand4EdgesEqually(int old_width, |
+ int old_height, |
+ int64 target_area) { |
+ // We need to expand the rect in 4 directions, we can compute the |
+ // amount to expand along each axis with a quadratic equation: |
+ // (old_w + add) * (old_h + add) = target_area |
+ // old_w * old_h + old_w * add + add * old_h + add * add = target_area |
+ // add^2 + add * (old_w + old_h) - target_area + old_w * old_h = 0 |
+ // Therefore, we solve the quadratic equation with: |
+ // a = 1 |
+ // b = old_w + old_h |
+ // c = -target_area + old_w * old_h |
+ int a = 1; |
+ int64 b = old_width + old_height; |
+ int64 c = -target_area + old_width * old_height; |
+ int sqrt_part = std::sqrt(b * b - 4.0 * a * c); |
+ int add_each_axis = (-b + sqrt_part) / 2 / a; |
+ return add_each_axis / 2; |
+} |
+ |
+int ComputeOffsetToExpand3EdgesEqually(int old_width, |
+ int old_height, |
+ int64 target_area, |
+ bool left_complete, |
+ bool top_complete, |
+ bool right_complete, |
+ bool bottom_complete) { |
+ // We need to expand the rect in three directions, so we will have to |
+ // expand along one axis twice as much as the other. Otherwise, this |
+ // is very similar to the case where we expand in all 4 directions. |
+ |
+ if (left_complete || right_complete) { |
+ // Expanding twice as much vertically as horizontally. |
+ // (old_w + add) * (old_h + add*2) = target_area |
+ // old_w * old_h + old_w * add*2 + add * old_h + add * add*2 = target_area |
+ // (add^2)*2 + add * (old_w*2 + old_h) - target_area + old_w * old_h = 0 |
+ // Therefore, we solve the quadratic equation with: |
+ // a = 2 |
+ // b = old_w*2 + old_h |
+ // c = -target_area + old_w * old_h |
+ int a = 2; |
+ int64 b = old_width * 2 + old_height; |
+ int64 c = -target_area + old_width * old_height; |
+ int sqrt_part = std::sqrt(b * b - 4.0 * a * c); |
+ int add_each_direction = (-b + sqrt_part) / 2 / a; |
+ return add_each_direction; |
+ } else { |
+ // Expanding twice as much horizontally as vertically. |
+ // (old_w + add*2) * (old_h + add) = target_area |
+ // old_w * old_h + old_w * add + add*2 * old_h + add*2 * add = target_area |
+ // (add^2)*2 + add * (old_w + old_h*2) - target_area + old_w * old_h = 0 |
+ // Therefore, we solve the quadratic equation with: |
+ // a = 2 |
+ // b = old_w + old_h*2 |
+ // c = -target_area + old_w * old_h |
+ int a = 2; |
+ int64 b = old_width + old_height * 2; |
+ int64 c = -target_area + old_width * old_height; |
+ int sqrt_part = std::sqrt(b * b - 4.0 * a * c); |
+ int add_each_direction = (-b + sqrt_part) / 2 / a; |
+ return add_each_direction; |
+ } |
+} |
+ |
+int ComputeOffsetToExpand2EdgesEqually(int old_width, |
+ int old_height, |
+ int64 target_area, |
+ bool left_complete, |
+ bool top_complete, |
+ bool right_complete, |
+ bool bottom_complete) { |
+ // We need to expand the rect along two directions. If the two directions |
+ // are opposite from each other then we only need to compute a distance |
+ // along a single axis. |
+ if (left_complete && right_complete) { |
+ // Expanding along the vertical axis only: |
+ // old_w * (old_h + add) = target_area |
+ // old_w * old_h + old_w * add = target_area |
+ // add_vertically = (target_area - old_w * old_h) / old_w |
+ int add_vertically = target_area / old_width - old_height; |
+ return add_vertically / 2; |
+ } else if (top_complete && bottom_complete) { |
+ // Expanding along the horizontal axis only: |
+ // (old_w + add) * old_h = target_area |
+ // old_w * old_h + add * old_h = target_area |
+ // add_horizontally = (target_area - old_w * old_h) / old_h |
+ int add_horizontally = target_area / old_height - old_width; |
+ return add_horizontally / 2; |
+ } else { |
+ // If we need to expand along both horizontal and vertical axes, we can use |
+ // the same result as if we were expanding all four edges. But we apply the |
+ // offset computed for opposing edges to a single edge. |
+ int add_each_direction = ComputeOffsetToExpand4EdgesEqually( |
+ old_width, old_height, target_area); |
+ return add_each_direction * 2; |
+ } |
+} |
+ |
+int ComputeOffsetToExpand1Edge(int old_width, |
+ int old_height, |
+ int64 target_area, |
+ bool left_complete, |
+ bool top_complete, |
+ bool right_complete, |
+ bool bottom_complete) { |
+ // We need to expand the rect in a single direction, so we are either |
+ // moving just a verical edge, or just a horizontal edge. |
+ if (!top_complete || !bottom_complete) { |
+ // Moving a vertical edge: |
+ // old_w * (old_h + add) = target_area |
+ // old_w * old_h + old_w * add = target_area |
+ // add_vertically = (target_area - old_w * old_h) / old_w |
+ int add_vertically = target_area / old_width - old_height; |
+ return add_vertically; |
+ } else { |
+ // Moving a horizontal edge: |
+ // (old_w + add) * old_h = target_area |
+ // old_w * old_h + add * old_h = target_area |
+ // add_horizontally = (target_area - old_w * old_h) / old_h |
+ int add_horizontally = target_area / old_height - old_width; |
+ return add_horizontally; |
+ } |
+} |
+ |
+} // namespace |
+ |
+// static |
+gfx::Rect PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy( |
+ gfx::Rect starting_rect, |
+ int64 target_area, |
+ gfx::Rect bounding_rect) { |
+ |
+ bool left_complete = false; |
+ bool top_complete = false; |
+ bool right_complete = false; |
+ bool bottom_complete = false; |
+ int num_edges_complete = 0; |
+ |
+ gfx::Rect working_rect = starting_rect; |
+ for (int i = 0; i < 4; ++i) { |
+ if (num_edges_complete != i) |
+ continue; |
+ int offset_for_each_edge = 0; |
+ switch (num_edges_complete) { |
+ case 0: |
+ offset_for_each_edge = ComputeOffsetToExpand4EdgesEqually( |
+ working_rect.width(), |
+ working_rect.height(), |
+ target_area); |
+ break; |
+ case 1: |
+ offset_for_each_edge = ComputeOffsetToExpand3EdgesEqually( |
+ working_rect.width(), |
+ working_rect.height(), |
+ target_area, |
+ left_complete, |
+ top_complete, |
+ right_complete, |
+ bottom_complete); |
+ break; |
+ case 2: |
+ offset_for_each_edge = ComputeOffsetToExpand2EdgesEqually( |
+ working_rect.width(), |
+ working_rect.height(), |
+ target_area, |
+ left_complete, |
+ top_complete, |
+ right_complete, |
+ bottom_complete); |
+ break; |
+ case 3: |
+ offset_for_each_edge = ComputeOffsetToExpand1Edge( |
+ working_rect.width(), |
+ working_rect.height(), |
+ target_area, |
+ left_complete, |
+ top_complete, |
+ right_complete, |
+ bottom_complete); |
+ } |
+ |
+ working_rect.Inset((left_complete ? 0 : -offset_for_each_edge), |
+ (top_complete ? 0 : -offset_for_each_edge), |
+ (right_complete ? 0 : -offset_for_each_edge), |
+ (bottom_complete ? 0 : -offset_for_each_edge)); |
+ |
+ if (bounding_rect.Contains(working_rect)) |
+ return working_rect; |
+ working_rect.Intersect(bounding_rect); |
+ |
+ if (working_rect.x() == bounding_rect.x()) left_complete = true; |
+ if (working_rect.y() == bounding_rect.y()) top_complete = true; |
+ if (working_rect.right() == bounding_rect.right()) right_complete = true; |
+ if (working_rect.bottom() == bounding_rect.bottom()) bottom_complete = true; |
+ |
+ num_edges_complete = (left_complete ? 1 : 0) + |
+ (top_complete ? 1 : 0) + |
+ (right_complete ? 1 : 0) + |
+ (bottom_complete ? 1 : 0); |
+ if (num_edges_complete == 4) |
+ return working_rect; |
+ } |
+ |
+ NOTREACHED(); |
+ return starting_rect; |
+} |
+ |
} // namespace cc |