Commit e3b7da9e authored by Dana Jansens's avatar Dana Jansens

cc: Remove and Create the correct tiles when resizing live tiles rect

When removing tiles, we need to remove everything outside the live
tiles rect even if it has borders inside the live tiles rect. The
DifferenceIterator includes borders when deciding if a tile is in the
included rect, so tiles that are only in the included rect with a border
were not being removed from the tiling. This lead to us having tiles
outside the rect, and to creating a tile that already existed.

When adding tiles, the same problem existed. The DifferenceIterator
includes borders when deciding which tiles are to be excluded, so a
tile that was inside the old live tiles rect with borders only would
not have existed, but it would be excluded by the DifferenceIterator.
This prevented us from making tiles that were inside the live tiles
rect.

Depends on: https://codereview.chromium.org/513903002/

R=enne@chromium.org, vmpstr@chromium.org, enne, vmpstr
BUG=405427

Review URL: https://codereview.chromium.org/505913003

Cr-Commit-Position: refs/heads/master@{#292417}
parent a1733ee3
......@@ -126,7 +126,7 @@ int TilingData::LastBorderTileYIndexFromSrcCoord(int src_position) const {
return std::min(std::max(y, 0), num_tiles_y_ - 1);
}
gfx::Rect TilingData::ExpandRectIgnoringBordersToTileBoundsWithBorders(
gfx::Rect TilingData::ExpandRectIgnoringBordersToTileBounds(
const gfx::Rect& rect) const {
if (rect.IsEmpty() || has_empty_bounds())
return gfx::Rect();
......@@ -137,8 +137,8 @@ gfx::Rect TilingData::ExpandRectIgnoringBordersToTileBoundsWithBorders(
int index_right = TileXIndexFromSrcCoord(rect.right() - 1);
int index_bottom = TileYIndexFromSrcCoord(rect.bottom() - 1);
gfx::Rect rect_top_left(TileBoundsWithBorder(index_x, index_y));
gfx::Rect rect_bottom_right(TileBoundsWithBorder(index_right, index_bottom));
gfx::Rect rect_top_left(TileBounds(index_x, index_y));
gfx::Rect rect_bottom_right(TileBounds(index_right, index_bottom));
return gfx::UnionRects(rect_top_left, rect_bottom_right);
}
......@@ -379,24 +379,17 @@ TilingData::DifferenceIterator::DifferenceIterator(
return;
}
consider_left_ =
tiling_data_->FirstBorderTileXIndexFromSrcCoord(consider.x());
consider_top_ =
tiling_data_->FirstBorderTileYIndexFromSrcCoord(consider.y());
consider_right_ =
tiling_data_->LastBorderTileXIndexFromSrcCoord(consider.right() - 1);
consider_left_ = tiling_data_->TileXIndexFromSrcCoord(consider.x());
consider_top_ = tiling_data_->TileYIndexFromSrcCoord(consider.y());
consider_right_ = tiling_data_->TileXIndexFromSrcCoord(consider.right() - 1);
consider_bottom_ =
tiling_data_->LastBorderTileYIndexFromSrcCoord(consider.bottom() - 1);
tiling_data_->TileYIndexFromSrcCoord(consider.bottom() - 1);
if (!ignore.IsEmpty()) {
ignore_left_ =
tiling_data_->FirstBorderTileXIndexFromSrcCoord(ignore.x());
ignore_top_ =
tiling_data_->FirstBorderTileYIndexFromSrcCoord(ignore.y());
ignore_right_ =
tiling_data_->LastBorderTileXIndexFromSrcCoord(ignore.right() - 1);
ignore_bottom_ =
tiling_data_->LastBorderTileYIndexFromSrcCoord(ignore.bottom() - 1);
ignore_left_ = tiling_data_->TileXIndexFromSrcCoord(ignore.x());
ignore_top_ = tiling_data_->TileYIndexFromSrcCoord(ignore.y());
ignore_right_ = tiling_data_->TileXIndexFromSrcCoord(ignore.right() - 1);
ignore_bottom_ = tiling_data_->TileYIndexFromSrcCoord(ignore.bottom() - 1);
// Clamp ignore indices to consider indices.
ignore_left_ = std::max(ignore_left_, consider_left_);
......@@ -488,21 +481,17 @@ TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator(
return;
}
consider_left_ =
tiling_data_->FirstBorderTileXIndexFromSrcCoord(consider.x());
consider_top_ = tiling_data_->FirstBorderTileYIndexFromSrcCoord(consider.y());
consider_right_ =
tiling_data_->LastBorderTileXIndexFromSrcCoord(consider.right() - 1);
consider_left_ = tiling_data_->TileXIndexFromSrcCoord(consider.x());
consider_top_ = tiling_data_->TileYIndexFromSrcCoord(consider.y());
consider_right_ = tiling_data_->TileXIndexFromSrcCoord(consider.right() - 1);
consider_bottom_ =
tiling_data_->LastBorderTileYIndexFromSrcCoord(consider.bottom() - 1);
tiling_data_->TileYIndexFromSrcCoord(consider.bottom() - 1);
if (!ignore.IsEmpty()) {
ignore_left_ = tiling_data_->FirstBorderTileXIndexFromSrcCoord(ignore.x());
ignore_top_ = tiling_data_->FirstBorderTileYIndexFromSrcCoord(ignore.y());
ignore_right_ =
tiling_data_->LastBorderTileXIndexFromSrcCoord(ignore.right() - 1);
ignore_bottom_ =
tiling_data_->LastBorderTileYIndexFromSrcCoord(ignore.bottom() - 1);
ignore_left_ = tiling_data_->TileXIndexFromSrcCoord(ignore.x());
ignore_top_ = tiling_data_->TileYIndexFromSrcCoord(ignore.y());
ignore_right_ = tiling_data_->TileXIndexFromSrcCoord(ignore.right() - 1);
ignore_bottom_ = tiling_data_->TileYIndexFromSrcCoord(ignore.bottom() - 1);
// Clamp ignore indices to consider indices.
ignore_left_ = std::max(ignore_left_, consider_left_);
......@@ -524,7 +513,7 @@ TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator(
else if (center.x() > tiling_data->tiling_size().width())
around_left = tiling_data->num_tiles_x();
else
around_left = tiling_data->FirstBorderTileXIndexFromSrcCoord(center.x());
around_left = tiling_data->TileXIndexFromSrcCoord(center.x());
// Determine around top, such that it is between -1 and num_tiles_y.
int around_top = 0;
......@@ -533,7 +522,7 @@ TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator(
else if (center.y() > tiling_data->tiling_size().height())
around_top = tiling_data->num_tiles_y();
else
around_top = tiling_data->FirstBorderTileYIndexFromSrcCoord(center.y());
around_top = tiling_data->TileYIndexFromSrcCoord(center.y());
// Determine around right, such that it is between -1 and num_tiles_x.
int right_src_coord = center.right() - 1;
......@@ -543,8 +532,7 @@ TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator(
} else if (right_src_coord > tiling_data->tiling_size().width()) {
around_right = tiling_data->num_tiles_x();
} else {
around_right =
tiling_data->LastBorderTileXIndexFromSrcCoord(right_src_coord);
around_right = tiling_data->TileXIndexFromSrcCoord(right_src_coord);
}
// Determine around bottom, such that it is between -1 and num_tiles_y.
......@@ -555,8 +543,7 @@ TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator(
} else if (bottom_src_coord > tiling_data->tiling_size().height()) {
around_bottom = tiling_data->num_tiles_y();
} else {
around_bottom =
tiling_data->LastBorderTileYIndexFromSrcCoord(bottom_src_coord);
around_bottom = tiling_data->TileYIndexFromSrcCoord(bottom_src_coord);
}
vertical_step_count_ = around_bottom - around_top + 1;
......
......@@ -52,8 +52,7 @@ class CC_EXPORT TilingData {
int LastBorderTileXIndexFromSrcCoord(int src_position) const;
int LastBorderTileYIndexFromSrcCoord(int src_position) const;
gfx::Rect ExpandRectIgnoringBordersToTileBoundsWithBorders(
const gfx::Rect& rect) const;
gfx::Rect ExpandRectIgnoringBordersToTileBounds(const gfx::Rect& rect) const;
gfx::Rect ExpandRectToTileBounds(const gfx::Rect& rect) const;
gfx::Rect TileBounds(int i, int j) const;
......@@ -103,14 +102,13 @@ class CC_EXPORT TilingData {
int bottom_;
};
// Iterate through all indices whose bounds + border intersect with
// |consider| but which also do not intersect with |ignore|.
// Iterate through all indices whose bounds (not including borders) intersect
// with |consider| but which also do not intersect with |ignore|.
class CC_EXPORT DifferenceIterator : public BaseIterator {
public:
DifferenceIterator(
const TilingData* tiling_data,
const gfx::Rect& consider_rect,
const gfx::Rect& ignore_rect);
DifferenceIterator(const TilingData* tiling_data,
const gfx::Rect& consider_rect,
const gfx::Rect& ignore_rect);
DifferenceIterator& operator++();
private:
......
......@@ -773,92 +773,82 @@ TEST(TilingDataTest, SetMaxTextureSizeBorders) {
EXPECT_EQ(10, data.num_tiles_y());
}
TEST(TilingDataTest, ExpandRectIgnoringBordersToTileBoundsWithBordersEmpty) {
TEST(TilingDataTest, ExpandRectIgnoringBordersToTileBoundsEmpty) {
TilingData empty_total_size(gfx::Size(0, 0), gfx::Size(8, 8), true);
EXPECT_RECT_EQ(
gfx::Rect(),
empty_total_size.ExpandRectIgnoringBordersToTileBoundsWithBorders(
gfx::Rect()));
EXPECT_RECT_EQ(
gfx::Rect(),
empty_total_size.ExpandRectIgnoringBordersToTileBoundsWithBorders(
gfx::Rect(100, 100, 100, 100)));
EXPECT_RECT_EQ(
gfx::Rect(),
empty_total_size.ExpandRectIgnoringBordersToTileBoundsWithBorders(
gfx::Rect(100, 100)));
empty_total_size.ExpandRectIgnoringBordersToTileBounds(gfx::Rect()));
EXPECT_RECT_EQ(gfx::Rect(),
empty_total_size.ExpandRectIgnoringBordersToTileBounds(
gfx::Rect(100, 100, 100, 100)));
EXPECT_RECT_EQ(gfx::Rect(),
empty_total_size.ExpandRectIgnoringBordersToTileBounds(
gfx::Rect(100, 100)));
TilingData empty_max_texture_size(gfx::Size(8, 8), gfx::Size(0, 0), true);
EXPECT_RECT_EQ(
gfx::Rect(),
empty_max_texture_size.ExpandRectIgnoringBordersToTileBoundsWithBorders(
gfx::Rect()));
EXPECT_RECT_EQ(
gfx::Rect(),
empty_max_texture_size.ExpandRectIgnoringBordersToTileBoundsWithBorders(
gfx::Rect(100, 100, 100, 100)));
EXPECT_RECT_EQ(
gfx::Rect(),
empty_max_texture_size.ExpandRectIgnoringBordersToTileBoundsWithBorders(
gfx::Rect(100, 100)));
EXPECT_RECT_EQ(gfx::Rect(),
empty_max_texture_size.ExpandRectIgnoringBordersToTileBounds(
gfx::Rect()));
EXPECT_RECT_EQ(gfx::Rect(),
empty_max_texture_size.ExpandRectIgnoringBordersToTileBounds(
gfx::Rect(100, 100, 100, 100)));
EXPECT_RECT_EQ(gfx::Rect(),
empty_max_texture_size.ExpandRectIgnoringBordersToTileBounds(
gfx::Rect(100, 100)));
}
TEST(TilingDataTest, ExpandRectIgnoringBordersToTileBoundsWithBorders) {
TEST(TilingDataTest, ExpandRectIgnoringBordersToTileBounds) {
TilingData data(gfx::Size(4, 4), gfx::Size(16, 32), true);
// Small rect at origin rounds up to tile 0, 0.
gfx::Rect at_origin_src(1, 1);
gfx::Rect at_origin_result(data.TileBoundsWithBorder(0, 0));
gfx::Rect at_origin_result(data.TileBounds(0, 0));
EXPECT_NE(at_origin_src, at_origin_result);
EXPECT_RECT_EQ(
at_origin_result,
data.ExpandRectIgnoringBordersToTileBoundsWithBorders(at_origin_src));
EXPECT_RECT_EQ(at_origin_result,
data.ExpandRectIgnoringBordersToTileBounds(at_origin_src));
// Arbitrary internal rect.
gfx::Rect rect_src(6, 6, 1, 3);
// Tile 2, 2 => gfx::Rect(4, 4, 4, 4)
// Tile 2, 3 => gfx::Rect(4, 6, 4, 4)
gfx::Rect rect_result(gfx::UnionRects(data.TileBoundsWithBorder(2, 2),
data.TileBoundsWithBorder(2, 3)));
gfx::Rect rect_result(
gfx::UnionRects(data.TileBounds(2, 2), data.TileBounds(2, 3)));
EXPECT_NE(rect_src, rect_result);
EXPECT_RECT_EQ(
rect_result,
data.ExpandRectIgnoringBordersToTileBoundsWithBorders(rect_src));
EXPECT_RECT_EQ(rect_result,
data.ExpandRectIgnoringBordersToTileBounds(rect_src));
// On tile bounds does not round up to next tile (ignores the border).
gfx::Rect border_rect_src(
gfx::UnionRects(data.TileBounds(1, 2), data.TileBounds(3, 4)));
gfx::Rect border_rect_result(gfx::UnionRects(
data.TileBoundsWithBorder(1, 2), data.TileBoundsWithBorder(3, 4)));
EXPECT_RECT_EQ(
border_rect_result,
data.ExpandRectIgnoringBordersToTileBoundsWithBorders(border_rect_src));
gfx::Rect border_rect_result(
gfx::UnionRects(data.TileBounds(1, 2), data.TileBounds(3, 4)));
EXPECT_RECT_EQ(border_rect_result,
data.ExpandRectIgnoringBordersToTileBounds(border_rect_src));
// Equal to tiling rect.
EXPECT_RECT_EQ(gfx::Rect(data.tiling_size()),
data.ExpandRectIgnoringBordersToTileBoundsWithBorders(
data.ExpandRectIgnoringBordersToTileBounds(
gfx::Rect(data.tiling_size())));
// Containing, but larger than tiling rect.
EXPECT_RECT_EQ(gfx::Rect(data.tiling_size()),
data.ExpandRectIgnoringBordersToTileBoundsWithBorders(
gfx::Rect(100, 100)));
EXPECT_RECT_EQ(
gfx::Rect(data.tiling_size()),
data.ExpandRectIgnoringBordersToTileBounds(gfx::Rect(100, 100)));
// Non-intersecting with tiling rect.
gfx::Rect non_intersect(200, 200, 100, 100);
EXPECT_FALSE(non_intersect.Intersects(gfx::Rect(data.tiling_size())));
EXPECT_RECT_EQ(
gfx::Rect(),
data.ExpandRectIgnoringBordersToTileBoundsWithBorders(non_intersect));
EXPECT_RECT_EQ(gfx::Rect(),
data.ExpandRectIgnoringBordersToTileBounds(non_intersect));
TilingData data2(gfx::Size(8, 8), gfx::Size(32, 64), true);
// Inside other tile border texels doesn't include other tiles.
gfx::Rect inner_rect_src(data2.TileBounds(1, 1));
inner_rect_src.Inset(data2.border_texels(), data.border_texels());
gfx::Rect inner_rect_result(data2.TileBoundsWithBorder(1, 1));
gfx::Rect inner_rect_result(data2.TileBounds(1, 1));
gfx::Rect expanded =
data2.ExpandRectIgnoringBordersToTileBoundsWithBorders(inner_rect_src);
data2.ExpandRectIgnoringBordersToTileBounds(inner_rect_src);
EXPECT_EQ(inner_rect_result.ToString(), expanded.ToString());
}
......@@ -1086,11 +1076,11 @@ void TestIterate(const TilingData& data,
}
// Make sure this also works with a difference iterator and an empty ignore.
// The difference iterator always includes borders, so ignore it otherwise.
if (include_borders) {
// The difference iterator never includes borders, so ignore it otherwise.
if (!include_borders) {
std::vector<std::pair<int, int> > expected = original_expected;
for (TilingData::DifferenceIterator iter(&data, rect, gfx::Rect());
iter; ++iter) {
for (TilingData::DifferenceIterator iter(&data, rect, gfx::Rect()); iter;
++iter) {
bool found = false;
for (size_t i = 0; i < expected.size(); ++i) {
if (expected[i] == iter.index()) {
......@@ -1250,16 +1240,14 @@ TEST(TilingDataTest, IteratorNoTiles) {
TestIterateAll(data, gfx::Rect(100, 100), 0, 0, -1, -1);
}
void TestDiff(
const TilingData& data,
gfx::Rect consider,
gfx::Rect ignore,
size_t num_tiles) {
void TestDiff(const TilingData& data,
gfx::Rect consider,
gfx::Rect ignore,
size_t num_tiles) {
std::vector<std::pair<int, int> > expected;
for (int y = 0; y < data.num_tiles_y(); ++y) {
for (int x = 0; x < data.num_tiles_x(); ++x) {
gfx::Rect bounds = data.TileBoundsWithBorder(x, y);
gfx::Rect bounds = data.TileBounds(x, y);
if (bounds.Intersects(consider) && !bounds.Intersects(ignore))
expected.push_back(std::make_pair(x, y));
}
......@@ -1268,8 +1256,8 @@ void TestDiff(
// Sanity check the test.
EXPECT_EQ(num_tiles, expected.size());
for (TilingData::DifferenceIterator iter(&data, consider, ignore);
iter; ++iter) {
for (TilingData::DifferenceIterator iter(&data, consider, ignore); iter;
++iter) {
bool found = false;
for (size_t i = 0; i < expected.size(); ++i) {
if (expected[i] == iter.index()) {
......@@ -1339,16 +1327,26 @@ TEST(TilingDataTest, DifferenceIteratorIgnoreGeometry) {
TEST(TilingDataTest, DifferenceIteratorManyBorderTexels) {
// X border index by src coord: [0-50), [10-60), [20-65)
// Y border index by src coord: [0-60), [20-80), [40-100), [60-110)
// X tile bounds by src coord: [0-30), [30-40), [40-65)
// Y tile bounds by src coord: [0-40), [40-60), [60-80), [80-110)
TilingData data(gfx::Size(50, 60), gfx::Size(65, 110), 20);
// Ignore one column, three rows
TestDiff(data, gfx::Rect(0, 30, 55, 80), gfx::Rect(5, 30, 5, 15), 9);
// Knock out two rows, but not the left column.
TestDiff(data, gfx::Rect(10, 30, 55, 80), gfx::Rect(30, 59, 20, 2), 8);
// Knock out three columns, leaving only one.
TestDiff(data, gfx::Rect(10, 30, 55, 80), gfx::Rect(30, 59, 20, 1), 3);
// Knock out one row.
TestDiff(data, gfx::Rect(10, 30, 55, 80), gfx::Rect(29, 59, 20, 1), 9);
// Overlap all tiles with ignore rect.
TestDiff(data, gfx::Rect(65, 110), gfx::Rect(30, 59, 1, 2), 0);
TestDiff(data, gfx::Rect(65, 110), gfx::Rect(29, 39, 12, 42), 0);
gfx::Rect tile = data.TileBounds(1, 1);
// Ignore one tile.
TestDiff(data, gfx::Rect(20, 30, 45, 80), tile, 11);
// Include one tile.
TestDiff(data, tile, gfx::Rect(), 1);
}
TEST(TilingDataTest, DifferenceIteratorOneTile) {
......
......@@ -11,6 +11,7 @@
#include "base/debug/trace_event.h"
#include "base/debug/trace_event_argument.h"
#include "base/logging.h"
#include "cc/base/math_util.h"
#include "cc/resources/tile.h"
#include "cc/resources/tile_priority.h"
......@@ -147,7 +148,7 @@ Tile* PictureLayerTiling::CreateTile(int i,
void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() {
const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this);
bool include_borders = true;
bool include_borders = false;
for (TilingData::Iterator iter(
&tiling_data_, live_tiles_rect_, include_borders);
iter;
......@@ -158,6 +159,8 @@ void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() {
continue;
CreateTile(key.first, key.second, twin_tiling);
}
VerifyLiveTilesRect();
}
void PictureLayerTiling::UpdateTilesToCurrentPile(
......@@ -173,10 +176,60 @@ void PictureLayerTiling::UpdateTilesToCurrentPile(
gfx::Size tile_size = tiling_data_.max_texture_size();
if (layer_bounds_ != old_layer_bounds) {
// Drop tiles outside the new layer bounds if the layer shrank.
SetLiveTilesRect(
gfx::IntersectRects(live_tiles_rect_, gfx::Rect(content_bounds)));
// The SetLiveTilesRect() method would drop tiles outside the new bounds,
// but may do so incorrectly if resizing the tiling causes the number of
// tiles in the tiling_data_ to change.
gfx::Rect content_rect(content_bounds);
int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x());
int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y());
int before_right =
tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1);
int before_bottom =
tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1);
// The live_tiles_rect_ is clamped to stay within the tiling size as we
// change it.
live_tiles_rect_.Intersect(content_rect);
tiling_data_.SetTilingSize(content_bounds);
int after_right = -1;
int after_bottom = -1;
if (!live_tiles_rect_.IsEmpty()) {
after_right =
tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1);
after_bottom =
tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1);
}
// There is no recycled twin since this is run on the pending tiling.
PictureLayerTiling* recycled_twin = NULL;
DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this));
DCHECK_EQ(PENDING_TREE, client_->GetTree());
// Drop tiles outside the new layer bounds if the layer shrank.
for (int i = after_right + 1; i <= before_right; ++i) {
for (int j = before_top; j <= before_bottom; ++j)
RemoveTileAt(i, j, recycled_twin);
}
for (int i = before_left; i <= after_right; ++i) {
for (int j = after_bottom + 1; j <= before_bottom; ++j)
RemoveTileAt(i, j, recycled_twin);
}
// If the layer grew, the live_tiles_rect_ is not changed, but a new row
// and/or column of tiles may now exist inside the same live_tiles_rect_.
const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this);
if (after_right > before_right) {
DCHECK_EQ(after_right, before_right + 1);
for (int j = before_top; j <= after_bottom; ++j)
CreateTile(after_right, j, twin_tiling);
}
if (after_bottom > before_bottom) {
DCHECK_EQ(after_bottom, before_bottom + 1);
for (int i = before_left; i <= before_right; ++i)
CreateTile(i, after_bottom, twin_tiling);
}
tile_size = client_->CalculateTileSize(content_bounds);
}
......@@ -192,6 +245,7 @@ void PictureLayerTiling::UpdateTilesToCurrentPile(
PicturePileImpl* pile = client_->GetPile();
for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
it->second->set_picture_pile(pile);
VerifyLiveTilesRect();
}
void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_region) {
......@@ -208,18 +262,24 @@ void PictureLayerTiling::DoInvalidate(const Region& layer_region,
bool recreate_invalidated_tiles) {
std::vector<TileMapKey> new_tile_keys;
gfx::Rect expanded_live_tiles_rect =
tiling_data_.ExpandRectIgnoringBordersToTileBoundsWithBorders(
live_tiles_rect_);
tiling_data_.ExpandRectIgnoringBordersToTileBounds(live_tiles_rect_);
for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) {
gfx::Rect layer_rect = iter.rect();
gfx::Rect content_rect =
gfx::ScaleToEnclosingRect(layer_rect, contents_scale_);
// Consider tiles inside the live tiles rect even if only their border
// pixels intersect the invalidation. But don't consider tiles outside
// the live tiles rect with the same conditions, as they won't exist.
int border_pixels = tiling_data_.border_texels();
content_rect.Inset(-border_pixels, -border_pixels);
// Avoid needless work by not bothering to invalidate where there aren't
// tiles.
content_rect.Intersect(expanded_live_tiles_rect);
if (content_rect.IsEmpty())
continue;
bool include_borders = true;
// Since the content_rect includes border pixels already, don't include
// borders when iterating to avoid double counting them.
bool include_borders = false;
for (TilingData::Iterator iter(
&tiling_data_, content_rect, include_borders);
iter;
......@@ -522,7 +582,7 @@ void PictureLayerTiling::UpdateTilePriorities(
float content_to_screen_scale = ideal_contents_scale / contents_scale_;
// Assign now priority to all visible tiles.
bool include_borders = true;
bool include_borders = false;
has_visible_rect_tiles_ = false;
for (TilingData::Iterator iter(
&tiling_data_, visible_rect_in_content_space, include_borders);
......@@ -656,6 +716,30 @@ void PictureLayerTiling::SetLiveTilesRect(
}
live_tiles_rect_ = new_live_tiles_rect;
VerifyLiveTilesRect();
}
void PictureLayerTiling::VerifyLiveTilesRect() {
#if DCHECK_IS_ON
for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
if (!it->second.get())
continue;
DCHECK(it->first.first < tiling_data_.num_tiles_x())
<< this << " " << it->first.first << "," << it->first.second
<< " num_tiles_x " << tiling_data_.num_tiles_x() << " live_tiles_rect "
<< live_tiles_rect_.ToString();
DCHECK(it->first.second < tiling_data_.num_tiles_y())
<< this << " " << it->first.first << "," << it->first.second
<< " num_tiles_y " << tiling_data_.num_tiles_y() << " live_tiles_rect "
<< live_tiles_rect_.ToString();
DCHECK(tiling_data_.TileBounds(it->first.first, it->first.second)
.Intersects(live_tiles_rect_))
<< this << " " << it->first.first << "," << it->first.second
<< " tile bounds "
<< tiling_data_.TileBounds(it->first.first, it->first.second).ToString()
<< " live_tiles_rect " << live_tiles_rect_.ToString();
}
#endif
}
void PictureLayerTiling::DidBecomeRecycled() {
......@@ -956,7 +1040,7 @@ PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator(
visible_iterator_ = TilingData::Iterator(&tiling_->tiling_data_,
tiling_->current_visible_rect_,
true /* include_borders */);
false /* include_borders */);
if (!visible_iterator_) {
AdvancePhase();
return;
......
......@@ -298,6 +298,7 @@ class CC_EXPORT PictureLayerTiling {
const gfx::Size& layer_bounds,
PictureLayerTilingClient* client);
void SetLiveTilesRect(const gfx::Rect& live_tiles_rect);
void VerifyLiveTilesRect();
Tile* CreateTile(int i, int j, const PictureLayerTiling* twin_tiling);
// Returns true if the Tile existed and was removed from the tiling.
bool RemoveTileAt(int i, int j, PictureLayerTiling* recycled_twin);
......
......@@ -65,6 +65,8 @@ class TestablePictureLayerTiling : public PictureLayerTiling {
client));
}
gfx::Rect live_tiles_rect() const { return live_tiles_rect_; }
using PictureLayerTiling::ComputeSkewport;
protected:
......@@ -210,6 +212,196 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) {
EXPECT_FALSE(tiling_->TileAt(0, 0));
}
TEST_F(PictureLayerTilingIteratorTest, CreateMissingTilesStaysInsideLiveRect) {
// The tiling has three rows and columns.
Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 250));
EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_y());
// The live tiles rect is at the very edge of the right-most and
// bottom-most tiles. Their border pixels would still be inside the live
// tiles rect, but the tiles should not exist just for that.
int right = tiling_->TilingDataForTesting().TileBounds(2, 2).x();
int bottom = tiling_->TilingDataForTesting().TileBounds(2, 2).y();
SetLiveRectAndVerifyTiles(gfx::Rect(right, bottom));
EXPECT_FALSE(tiling_->TileAt(2, 0));
EXPECT_FALSE(tiling_->TileAt(2, 1));
EXPECT_FALSE(tiling_->TileAt(2, 2));
EXPECT_FALSE(tiling_->TileAt(1, 2));
EXPECT_FALSE(tiling_->TileAt(0, 2));
// Verify CreateMissingTilesInLiveTilesRect respects this.
tiling_->CreateMissingTilesInLiveTilesRect();
EXPECT_FALSE(tiling_->TileAt(2, 0));
EXPECT_FALSE(tiling_->TileAt(2, 1));
EXPECT_FALSE(tiling_->TileAt(2, 2));
EXPECT_FALSE(tiling_->TileAt(1, 2));
EXPECT_FALSE(tiling_->TileAt(0, 2));
}
TEST_F(PictureLayerTilingIteratorTest, ResizeTilingOverTileBorders) {
// The tiling has four rows and three columns.
Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 350));
EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());
// The live tiles rect covers the whole tiling.
SetLiveRectAndVerifyTiles(gfx::Rect(250, 350));
// Tiles in the bottom row and right column exist.
EXPECT_TRUE(tiling_->TileAt(2, 0));
EXPECT_TRUE(tiling_->TileAt(2, 1));
EXPECT_TRUE(tiling_->TileAt(2, 2));
EXPECT_TRUE(tiling_->TileAt(2, 3));
EXPECT_TRUE(tiling_->TileAt(1, 3));
EXPECT_TRUE(tiling_->TileAt(0, 3));
int right = tiling_->TilingDataForTesting().TileBounds(2, 2).x();
int bottom = tiling_->TilingDataForTesting().TileBounds(2, 3).y();
// Shrink the tiling so that the last tile row/column is entirely in the
// border pixels of the interior tiles. That row/column is removed.
Region invalidation;
tiling_->UpdateTilesToCurrentPile(invalidation,
gfx::Size(right + 1, bottom + 1));
EXPECT_EQ(2, tiling_->TilingDataForTesting().num_tiles_x());
EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_y());
// The live tiles rect was clamped to the pile size.
EXPECT_EQ(gfx::Rect(right + 1, bottom + 1), tiling_->live_tiles_rect());
// Since the row/column is gone, the tiles should be gone too.
EXPECT_FALSE(tiling_->TileAt(2, 0));
EXPECT_FALSE(tiling_->TileAt(2, 1));
EXPECT_FALSE(tiling_->TileAt(2, 2));
EXPECT_FALSE(tiling_->TileAt(2, 3));
EXPECT_FALSE(tiling_->TileAt(1, 3));
EXPECT_FALSE(tiling_->TileAt(0, 3));
// Growing outside the current right/bottom tiles border pixels should create
// the tiles again, even though the live rect has not changed size.
tiling_->UpdateTilesToCurrentPile(invalidation,
gfx::Size(right + 2, bottom + 2));
EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());
// Not changed.
EXPECT_EQ(gfx::Rect(right + 1, bottom + 1), tiling_->live_tiles_rect());
// The last row/column tiles are inside the live tiles rect.
EXPECT_TRUE(gfx::Rect(right + 1, bottom + 1).Intersects(
tiling_->TilingDataForTesting().TileBounds(2, 0)));
EXPECT_TRUE(gfx::Rect(right + 1, bottom + 1).Intersects(
tiling_->TilingDataForTesting().TileBounds(0, 3)));
EXPECT_TRUE(tiling_->TileAt(2, 0));
EXPECT_TRUE(tiling_->TileAt(2, 1));
EXPECT_TRUE(tiling_->TileAt(2, 2));
EXPECT_TRUE(tiling_->TileAt(2, 3));
EXPECT_TRUE(tiling_->TileAt(1, 3));
EXPECT_TRUE(tiling_->TileAt(0, 3));
}
TEST_F(PictureLayerTilingIteratorTest, ResizeLiveTileRectOverTileBorders) {
// The tiling has three rows and columns.
Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 350));
EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());
// The live tiles rect covers the whole tiling.
SetLiveRectAndVerifyTiles(gfx::Rect(250, 350));
// Tiles in the bottom row and right column exist.
EXPECT_TRUE(tiling_->TileAt(2, 0));
EXPECT_TRUE(tiling_->TileAt(2, 1));
EXPECT_TRUE(tiling_->TileAt(2, 2));
EXPECT_TRUE(tiling_->TileAt(2, 3));
EXPECT_TRUE(tiling_->TileAt(1, 3));
EXPECT_TRUE(tiling_->TileAt(0, 3));
// Shrink the live tiles rect to the very edge of the right-most and
// bottom-most tiles. Their border pixels would still be inside the live
// tiles rect, but the tiles should not exist just for that.
int right = tiling_->TilingDataForTesting().TileBounds(2, 3).x();
int bottom = tiling_->TilingDataForTesting().TileBounds(2, 3).y();
SetLiveRectAndVerifyTiles(gfx::Rect(right, bottom));
EXPECT_FALSE(tiling_->TileAt(2, 0));
EXPECT_FALSE(tiling_->TileAt(2, 1));
EXPECT_FALSE(tiling_->TileAt(2, 2));
EXPECT_FALSE(tiling_->TileAt(2, 3));
EXPECT_FALSE(tiling_->TileAt(1, 3));
EXPECT_FALSE(tiling_->TileAt(0, 3));
// Including the bottom row and right column again, should create the tiles.
SetLiveRectAndVerifyTiles(gfx::Rect(right + 1, bottom + 1));
EXPECT_TRUE(tiling_->TileAt(2, 0));
EXPECT_TRUE(tiling_->TileAt(2, 1));
EXPECT_TRUE(tiling_->TileAt(2, 2));
EXPECT_TRUE(tiling_->TileAt(2, 3));
EXPECT_TRUE(tiling_->TileAt(1, 2));
EXPECT_TRUE(tiling_->TileAt(0, 2));
// Shrink the live tiles rect to the very edge of the left-most and
// top-most tiles. Their border pixels would still be inside the live
// tiles rect, but the tiles should not exist just for that.
int left = tiling_->TilingDataForTesting().TileBounds(0, 0).right();
int top = tiling_->TilingDataForTesting().TileBounds(0, 0).bottom();
SetLiveRectAndVerifyTiles(gfx::Rect(left, top, 250 - left, 350 - top));
EXPECT_FALSE(tiling_->TileAt(0, 3));
EXPECT_FALSE(tiling_->TileAt(0, 2));
EXPECT_FALSE(tiling_->TileAt(0, 1));
EXPECT_FALSE(tiling_->TileAt(0, 0));
EXPECT_FALSE(tiling_->TileAt(1, 0));
EXPECT_FALSE(tiling_->TileAt(2, 0));
// Including the top row and left column again, should create the tiles.
SetLiveRectAndVerifyTiles(
gfx::Rect(left - 1, top - 1, 250 - left, 350 - top));
EXPECT_TRUE(tiling_->TileAt(0, 3));
EXPECT_TRUE(tiling_->TileAt(0, 2));
EXPECT_TRUE(tiling_->TileAt(0, 1));
EXPECT_TRUE(tiling_->TileAt(0, 0));
EXPECT_TRUE(tiling_->TileAt(1, 0));
EXPECT_TRUE(tiling_->TileAt(2, 0));
}
TEST_F(PictureLayerTilingIteratorTest, ResizeLiveTileRectOverSameTiles) {
// The tiling has four rows and three columns.
Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 350));
EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x());
EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y());
// The live tiles rect covers the whole tiling.
SetLiveRectAndVerifyTiles(gfx::Rect(250, 350));
// All tiles exist.
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j)
EXPECT_TRUE(tiling_->TileAt(i, j)) << i << "," << j;
}
// Shrink the live tiles rect, but still cover all the tiles.
SetLiveRectAndVerifyTiles(gfx::Rect(1, 1, 249, 349));
// All tiles still exist.
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j)
EXPECT_TRUE(tiling_->TileAt(i, j)) << i << "," << j;
}
// Grow the live tiles rect, but still cover all the same tiles.
SetLiveRectAndVerifyTiles(gfx::Rect(0, 0, 250, 350));
// All tiles still exist.
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j)
EXPECT_TRUE(tiling_->TileAt(i, j)) << i << "," << j;
}
}
TEST_F(PictureLayerTilingIteratorTest, ResizeOverBorderPixelsDeletesTiles) {
// Verifies that a resize with invalidation for newly exposed pixels will
// deletes tiles that intersect that invalidation.
......@@ -513,11 +705,12 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
Tile* tile = tiling->TileAt(i, j);
TilePriority priority = tile->priority(ACTIVE_TREE);
if (viewport_in_content_space.Intersects(tile->content_rect())) {
gfx::Rect tile_rect = tiling->TilingDataForTesting().TileBounds(i, j);
if (viewport_in_content_space.Intersects(tile_rect)) {
EXPECT_EQ(TilePriority::NOW, priority.priority_bin);
EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
have_now = true;
} else if (soon_rect_in_content_space.Intersects(tile->content_rect())) {
} else if (soon_rect_in_content_space.Intersects(tile_rect)) {
EXPECT_EQ(TilePriority::SOON, priority.priority_bin);
have_soon = true;
} else {
......@@ -581,14 +774,15 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
Tile* tile = tiling->TileAt(i, j);
TilePriority priority = tile->priority(ACTIVE_TREE);
if (viewport_in_content_space.Intersects(tile->content_rect())) {
gfx::Rect tile_rect = tiling->TilingDataForTesting().TileBounds(i, j);
if (viewport_in_content_space.Intersects(tile_rect)) {
EXPECT_EQ(TilePriority::NOW, priority.priority_bin) << "i: " << i
<< " j: " << j;
EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible) << "i: " << i
<< " j: " << j;
have_now = true;
} else if (skewport.Intersects(tile->content_rect()) ||
soon_rect_in_content_space.Intersects(tile->content_rect())) {
} else if (skewport.Intersects(tile_rect) ||
soon_rect_in_content_space.Intersects(tile_rect)) {
EXPECT_EQ(TilePriority::SOON, priority.priority_bin) << "i: " << i
<< " j: " << j;
EXPECT_GT(priority.distance_to_visible, 0.f) << "i: " << i
......@@ -615,7 +809,7 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
EXPECT_FLOAT_EQ(28.f, priority.distance_to_visible);
priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
EXPECT_FLOAT_EQ(4.f, priority.distance_to_visible);
// Change the underlying layer scale.
tiling->UpdateTilePriorities(
......@@ -628,7 +822,7 @@ TEST(PictureLayerTilingTest, ViewportDistanceWithScale) {
EXPECT_FLOAT_EQ(56.f, priority.distance_to_visible);
priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
EXPECT_FLOAT_EQ(8.f, priority.distance_to_visible);
// Test additional scales.
tiling = TestablePictureLayerTiling::Create(0.2f, layer_bounds, &client);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment