blob: cd5e8902b553c112344cd5910553a3b405ef7e7f [file] [log] [blame]
// Copyright 2013 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/eviction_tile_priority_queue.h"
#include "cc/resources/raster_tile_priority_queue.h"
#include "cc/resources/tile.h"
#include "cc/resources/tile_priority.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/fake_tile_manager.h"
#include "cc/test/impl_side_painting_settings.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_tile_priorities.h"
#include "cc/trees/layer_tree_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
namespace {
class LowResTilingsSettings : public ImplSidePaintingSettings {
public:
LowResTilingsSettings() { create_low_res_tiling = true; }
};
class TileManagerTilePriorityQueueTest : public testing::Test {
public:
TileManagerTilePriorityQueueTest()
: memory_limit_policy_(ALLOW_ANYTHING),
max_tiles_(10000),
ready_to_activate_(false),
id_(7),
proxy_(base::MessageLoopProxy::current()),
host_impl_(LowResTilingsSettings(), &proxy_, &shared_bitmap_manager_) {}
void SetTreePriority(TreePriority tree_priority) {
GlobalStateThatImpactsTilePriority state;
gfx::Size tile_size(256, 256);
state.soft_memory_limit_in_bytes = 100 * 1000 * 1000;
state.num_resources_limit = max_tiles_;
state.hard_memory_limit_in_bytes = state.soft_memory_limit_in_bytes * 2;
state.memory_limit_policy = memory_limit_policy_;
state.tree_priority = tree_priority;
global_state_ = state;
host_impl_.resource_pool()->SetResourceUsageLimits(
state.soft_memory_limit_in_bytes,
state.soft_memory_limit_in_bytes,
state.num_resources_limit);
host_impl_.tile_manager()->SetGlobalStateForTesting(state);
}
virtual void SetUp() override {
InitializeRenderer();
SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
}
virtual void InitializeRenderer() {
host_impl_.InitializeRenderer(FakeOutputSurface::Create3d());
}
void SetupDefaultTrees(const gfx::Size& layer_bounds) {
gfx::Size tile_size(100, 100);
scoped_refptr<FakePicturePileImpl> pending_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
scoped_refptr<FakePicturePileImpl> active_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
SetupTrees(pending_pile, active_pile);
}
void ActivateTree() {
host_impl_.ActivateSyncTree();
CHECK(!host_impl_.pending_tree());
pending_layer_ = NULL;
active_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.active_tree()->LayerById(id_));
}
void SetupDefaultTreesWithFixedTileSize(const gfx::Size& layer_bounds,
const gfx::Size& tile_size) {
SetupDefaultTrees(layer_bounds);
pending_layer_->set_fixed_tile_size(tile_size);
active_layer_->set_fixed_tile_size(tile_size);
}
void SetupTrees(scoped_refptr<PicturePileImpl> pending_pile,
scoped_refptr<PicturePileImpl> active_pile) {
SetupPendingTree(active_pile);
ActivateTree();
SetupPendingTree(pending_pile);
}
void SetupPendingTree(scoped_refptr<PicturePileImpl> pile) {
host_impl_.CreatePendingTree();
LayerTreeImpl* pending_tree = host_impl_.pending_tree();
// Steal from the recycled tree.
scoped_ptr<LayerImpl> old_pending_root = pending_tree->DetachLayerTree();
DCHECK_IMPLIES(old_pending_root, old_pending_root->id() == id_);
scoped_ptr<FakePictureLayerImpl> pending_layer;
if (old_pending_root) {
pending_layer.reset(
static_cast<FakePictureLayerImpl*>(old_pending_root.release()));
pending_layer->SetPile(pile);
} else {
pending_layer =
FakePictureLayerImpl::CreateWithPile(pending_tree, id_, pile);
pending_layer->SetDrawsContent(true);
}
// The bounds() just mirror the pile size.
pending_layer->SetBounds(pending_layer->pile()->tiling_size());
pending_tree->SetRootLayer(pending_layer.Pass());
pending_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.pending_tree()->LayerById(id_));
pending_layer_->DoPostCommitInitializationIfNeeded();
}
void CreateHighLowResAndSetAllTilesVisible() {
// Active layer must get updated first so pending layer can share from it.
active_layer_->CreateDefaultTilingsAndTiles();
active_layer_->SetAllTilesVisible();
pending_layer_->CreateDefaultTilingsAndTiles();
pending_layer_->SetAllTilesVisible();
}
TileManager* tile_manager() { return host_impl_.tile_manager(); }
protected:
GlobalStateThatImpactsTilePriority global_state_;
TestSharedBitmapManager shared_bitmap_manager_;
TileMemoryLimitPolicy memory_limit_policy_;
int max_tiles_;
bool ready_to_activate_;
int id_;
FakeImplProxy proxy_;
FakeLayerTreeHostImpl host_impl_;
FakePictureLayerImpl* pending_layer_;
FakePictureLayerImpl* active_layer_;
};
TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueue) {
const gfx::Size layer_bounds(1000, 1000);
host_impl_.SetViewportSize(layer_bounds);
SetupDefaultTrees(layer_bounds);
active_layer_->CreateDefaultTilingsAndTiles();
pending_layer_->CreateDefaultTilingsAndTiles();
RasterTilePriorityQueue queue;
host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES);
EXPECT_FALSE(queue.IsEmpty());
size_t tile_count = 0;
std::set<Tile*> all_tiles;
while (!queue.IsEmpty()) {
EXPECT_TRUE(queue.Top());
all_tiles.insert(queue.Top());
++tile_count;
queue.Pop();
}
EXPECT_EQ(tile_count, all_tiles.size());
EXPECT_EQ(16u, tile_count);
// Sanity check, all tiles should be visible.
std::set<Tile*> smoothness_tiles;
queue.Reset();
host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
bool had_low_res = false;
while (!queue.IsEmpty()) {
Tile* tile = queue.Top();
EXPECT_TRUE(tile);
EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin);
EXPECT_EQ(TilePriority::NOW, tile->priority(PENDING_TREE).priority_bin);
if (tile->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION)
had_low_res = true;
else
smoothness_tiles.insert(tile);
queue.Pop();
}
EXPECT_EQ(all_tiles, smoothness_tiles);
EXPECT_TRUE(had_low_res);
Region invalidation(gfx::Rect(0, 0, 500, 500));
// Invalidate the pending tree.
pending_layer_->set_invalidation(invalidation);
pending_layer_->HighResTiling()->UpdateTilesToCurrentPile(
invalidation, gfx::Size(1000, 1000));
pending_layer_->LowResTiling()->UpdateTilesToCurrentPile(
invalidation, gfx::Size(1000, 1000));
active_layer_->ResetAllTilesPriorities();
pending_layer_->ResetAllTilesPriorities();
// Renew all of the tile priorities.
gfx::Rect viewport(50, 50, 100, 100);
pending_layer_->HighResTiling()->ComputeTilePriorityRects(
PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
pending_layer_->LowResTiling()->ComputeTilePriorityRects(
PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
active_layer_->HighResTiling()->ComputeTilePriorityRects(
ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
active_layer_->LowResTiling()->ComputeTilePriorityRects(
ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
// Populate all tiles directly from the tilings.
all_tiles.clear();
std::set<Tile*> high_res_tiles;
std::vector<Tile*> pending_high_res_tiles =
pending_layer_->HighResTiling()->AllTilesForTesting();
for (size_t i = 0; i < pending_high_res_tiles.size(); ++i) {
all_tiles.insert(pending_high_res_tiles[i]);
high_res_tiles.insert(pending_high_res_tiles[i]);
}
std::vector<Tile*> pending_low_res_tiles =
pending_layer_->LowResTiling()->AllTilesForTesting();
for (size_t i = 0; i < pending_low_res_tiles.size(); ++i)
all_tiles.insert(pending_low_res_tiles[i]);
std::vector<Tile*> active_high_res_tiles =
active_layer_->HighResTiling()->AllTilesForTesting();
for (size_t i = 0; i < active_high_res_tiles.size(); ++i) {
all_tiles.insert(active_high_res_tiles[i]);
high_res_tiles.insert(active_high_res_tiles[i]);
}
std::vector<Tile*> active_low_res_tiles =
active_layer_->LowResTiling()->AllTilesForTesting();
for (size_t i = 0; i < active_low_res_tiles.size(); ++i)
all_tiles.insert(active_low_res_tiles[i]);
Tile* last_tile = NULL;
smoothness_tiles.clear();
tile_count = 0;
size_t correct_order_tiles = 0u;
// Here we expect to get increasing ACTIVE_TREE priority_bin.
queue.Reset();
host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
while (!queue.IsEmpty()) {
Tile* tile = queue.Top();
EXPECT_TRUE(tile);
if (!last_tile)
last_tile = tile;
EXPECT_LE(last_tile->priority(ACTIVE_TREE).priority_bin,
tile->priority(ACTIVE_TREE).priority_bin);
bool skip_updating_last_tile = false;
if (last_tile->priority(ACTIVE_TREE).priority_bin ==
tile->priority(ACTIVE_TREE).priority_bin) {
correct_order_tiles +=
last_tile->priority(ACTIVE_TREE).distance_to_visible <=
tile->priority(ACTIVE_TREE).distance_to_visible;
} else if (tile->priority(ACTIVE_TREE).priority_bin ==
TilePriority::EVENTUALLY &&
tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW) {
// Since we'd return pending tree now tiles before the eventually tiles on
// the active tree, update the value.
++correct_order_tiles;
skip_updating_last_tile = true;
}
if (tile->priority(ACTIVE_TREE).priority_bin == TilePriority::NOW &&
last_tile->priority(ACTIVE_TREE).resolution !=
tile->priority(ACTIVE_TREE).resolution) {
// Low resolution should come first.
EXPECT_EQ(LOW_RESOLUTION, last_tile->priority(ACTIVE_TREE).resolution);
}
if (!skip_updating_last_tile)
last_tile = tile;
++tile_count;
smoothness_tiles.insert(tile);
queue.Pop();
}
EXPECT_EQ(tile_count, smoothness_tiles.size());
EXPECT_EQ(all_tiles, smoothness_tiles);
// Since we don't guarantee increasing distance due to spiral iterator, we
// should check that we're _mostly_ right.
EXPECT_GT(correct_order_tiles, 3 * tile_count / 4);
std::set<Tile*> new_content_tiles;
last_tile = NULL;
size_t increasing_distance_tiles = 0u;
// Here we expect to get increasing PENDING_TREE priority_bin.
queue.Reset();
host_impl_.BuildRasterQueue(&queue, NEW_CONTENT_TAKES_PRIORITY);
tile_count = 0;
while (!queue.IsEmpty()) {
Tile* tile = queue.Top();
EXPECT_TRUE(tile);
if (!last_tile)
last_tile = tile;
EXPECT_LE(last_tile->priority(PENDING_TREE).priority_bin,
tile->priority(PENDING_TREE).priority_bin);
if (last_tile->priority(PENDING_TREE).priority_bin ==
tile->priority(PENDING_TREE).priority_bin) {
increasing_distance_tiles +=
last_tile->priority(PENDING_TREE).distance_to_visible <=
tile->priority(PENDING_TREE).distance_to_visible;
}
if (tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW &&
last_tile->priority(PENDING_TREE).resolution !=
tile->priority(PENDING_TREE).resolution) {
// High resolution should come first.
EXPECT_EQ(HIGH_RESOLUTION, last_tile->priority(PENDING_TREE).resolution);
}
last_tile = tile;
new_content_tiles.insert(tile);
++tile_count;
queue.Pop();
}
EXPECT_EQ(tile_count, new_content_tiles.size());
EXPECT_EQ(high_res_tiles, new_content_tiles);
// Since we don't guarantee increasing distance due to spiral iterator, we
// should check that we're _mostly_ right.
EXPECT_GE(increasing_distance_tiles, 3 * tile_count / 4);
}
TEST_F(TileManagerTilePriorityQueueTest, ActivationComesBeforeEventually) {
SetupDefaultTrees(gfx::Size(1000, 1000));
active_layer_->CreateDefaultTilingsAndTiles();
pending_layer_->CreateDefaultTilingsAndTiles();
// Create a pending child layer.
gfx::Size tile_size(256, 256);
scoped_refptr<FakePicturePileImpl> pending_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(1000, 1000));
scoped_ptr<FakePictureLayerImpl> pending_child =
FakePictureLayerImpl::CreateWithPile(
host_impl_.pending_tree(), id_ + 1, pending_pile);
pending_layer_->AddChild(pending_child.Pass());
FakePictureLayerImpl* pending_child_raw = static_cast<FakePictureLayerImpl*>(
host_impl_.pending_tree()->LayerById(id_ + 1));
ASSERT_TRUE(pending_child_raw);
pending_child_raw->SetDrawsContent(true);
pending_child_raw->DoPostCommitInitializationIfNeeded();
pending_child_raw->CreateDefaultTilingsAndTiles();
ASSERT_TRUE(pending_child_raw->HighResTiling());
// Set a small viewport, so we have soon and eventually tiles.
gfx::Rect viewport(200, 200);
active_layer_->draw_properties().visible_content_rect = viewport;
active_layer_->UpdateTiles(Occlusion(), false);
pending_layer_->draw_properties().visible_content_rect = viewport;
pending_layer_->UpdateTiles(Occlusion(), false);
pending_child_raw->draw_properties().visible_content_rect = viewport;
pending_child_raw->UpdateTiles(Occlusion(), false);
RasterTilePriorityQueue queue;
host_impl_.SetRequiresHighResToDraw();
host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
EXPECT_FALSE(queue.IsEmpty());
// Get all the tiles that are NOW or SOON and make sure they are ready to
// draw.
std::vector<Tile*> all_tiles;
while (!queue.IsEmpty()) {
Tile* tile = queue.Top();
if (tile->combined_priority().priority_bin >= TilePriority::EVENTUALLY)
break;
all_tiles.push_back(tile);
queue.Pop();
}
tile_manager()->InitializeTilesWithResourcesForTesting(
std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
// Ensure we can activate.
EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
EXPECT_TRUE(pending_child_raw->AllTilesRequiredForActivationAreReadyToDraw());
}
TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
const gfx::Size layer_bounds(1000, 1000);
host_impl_.SetViewportSize(layer_bounds);
SetupDefaultTrees(layer_bounds);
active_layer_->CreateDefaultTilingsAndTiles();
pending_layer_->CreateDefaultTilingsAndTiles();
EvictionTilePriorityQueue empty_queue;
host_impl_.BuildEvictionQueue(&empty_queue, SAME_PRIORITY_FOR_BOTH_TREES);
EXPECT_TRUE(empty_queue.IsEmpty());
std::set<Tile*> all_tiles;
size_t tile_count = 0;
RasterTilePriorityQueue raster_queue;
host_impl_.BuildRasterQueue(&raster_queue, SAME_PRIORITY_FOR_BOTH_TREES);
while (!raster_queue.IsEmpty()) {
++tile_count;
EXPECT_TRUE(raster_queue.Top());
all_tiles.insert(raster_queue.Top());
raster_queue.Pop();
}
EXPECT_EQ(tile_count, all_tiles.size());
EXPECT_EQ(16u, tile_count);
tile_manager()->InitializeTilesWithResourcesForTesting(
std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
EvictionTilePriorityQueue queue;
host_impl_.BuildEvictionQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
EXPECT_FALSE(queue.IsEmpty());
// Sanity check, all tiles should be visible.
std::set<Tile*> smoothness_tiles;
while (!queue.IsEmpty()) {
Tile* tile = queue.Top();
EXPECT_TRUE(tile);
EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin);
EXPECT_EQ(TilePriority::NOW, tile->priority(PENDING_TREE).priority_bin);
EXPECT_TRUE(tile->HasResources());
smoothness_tiles.insert(tile);
queue.Pop();
}
EXPECT_EQ(all_tiles, smoothness_tiles);
tile_manager()->ReleaseTileResourcesForTesting(
std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
Region invalidation(gfx::Rect(0, 0, 500, 500));
// Invalidate the pending tree.
pending_layer_->set_invalidation(invalidation);
pending_layer_->HighResTiling()->UpdateTilesToCurrentPile(
invalidation, gfx::Size(1000, 1000));
pending_layer_->LowResTiling()->UpdateTilesToCurrentPile(
invalidation, gfx::Size(1000, 1000));
active_layer_->ResetAllTilesPriorities();
pending_layer_->ResetAllTilesPriorities();
// Renew all of the tile priorities.
gfx::Rect viewport(50, 50, 100, 100);
pending_layer_->HighResTiling()->ComputeTilePriorityRects(
PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
pending_layer_->LowResTiling()->ComputeTilePriorityRects(
PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
active_layer_->HighResTiling()->ComputeTilePriorityRects(
ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
active_layer_->LowResTiling()->ComputeTilePriorityRects(
ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
// Populate all tiles directly from the tilings.
all_tiles.clear();
std::vector<Tile*> pending_high_res_tiles =
pending_layer_->HighResTiling()->AllTilesForTesting();
for (size_t i = 0; i < pending_high_res_tiles.size(); ++i)
all_tiles.insert(pending_high_res_tiles[i]);
std::vector<Tile*> pending_low_res_tiles =
pending_layer_->LowResTiling()->AllTilesForTesting();
for (size_t i = 0; i < pending_low_res_tiles.size(); ++i)
all_tiles.insert(pending_low_res_tiles[i]);
std::vector<Tile*> active_high_res_tiles =
active_layer_->HighResTiling()->AllTilesForTesting();
for (size_t i = 0; i < active_high_res_tiles.size(); ++i)
all_tiles.insert(active_high_res_tiles[i]);
std::vector<Tile*> active_low_res_tiles =
active_layer_->LowResTiling()->AllTilesForTesting();
for (size_t i = 0; i < active_low_res_tiles.size(); ++i)
all_tiles.insert(active_low_res_tiles[i]);
tile_manager()->InitializeTilesWithResourcesForTesting(
std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
Tile* last_tile = NULL;
smoothness_tiles.clear();
tile_count = 0;
// Here we expect to get increasing ACTIVE_TREE priority_bin.
queue.Reset();
host_impl_.BuildEvictionQueue(&queue, SMOOTHNESS_TAKES_PRIORITY);
while (!queue.IsEmpty()) {
Tile* tile = queue.Top();
EXPECT_TRUE(tile);
EXPECT_TRUE(tile->HasResources());
if (!last_tile)
last_tile = tile;
EXPECT_GE(last_tile->priority(ACTIVE_TREE).priority_bin,
tile->priority(ACTIVE_TREE).priority_bin);
if (last_tile->priority(ACTIVE_TREE).priority_bin ==
tile->priority(ACTIVE_TREE).priority_bin) {
EXPECT_LE(last_tile->required_for_activation(),
tile->required_for_activation());
if (last_tile->required_for_activation() ==
tile->required_for_activation()) {
EXPECT_GE(last_tile->priority(ACTIVE_TREE).distance_to_visible,
tile->priority(ACTIVE_TREE).distance_to_visible);
}
}
last_tile = tile;
++tile_count;
smoothness_tiles.insert(tile);
queue.Pop();
}
EXPECT_EQ(tile_count, smoothness_tiles.size());
EXPECT_EQ(all_tiles, smoothness_tiles);
std::set<Tile*> new_content_tiles;
last_tile = NULL;
// Here we expect to get increasing PENDING_TREE priority_bin.
queue.Reset();
host_impl_.BuildEvictionQueue(&queue, NEW_CONTENT_TAKES_PRIORITY);
while (!queue.IsEmpty()) {
Tile* tile = queue.Top();
EXPECT_TRUE(tile);
if (!last_tile)
last_tile = tile;
EXPECT_GE(last_tile->priority(PENDING_TREE).priority_bin,
tile->priority(PENDING_TREE).priority_bin);
if (last_tile->priority(PENDING_TREE).priority_bin ==
tile->priority(PENDING_TREE).priority_bin) {
EXPECT_LE(last_tile->required_for_activation(),
tile->required_for_activation());
if (last_tile->required_for_activation() ==
tile->required_for_activation()) {
EXPECT_GE(last_tile->priority(PENDING_TREE).distance_to_visible,
tile->priority(PENDING_TREE).distance_to_visible);
}
}
last_tile = tile;
new_content_tiles.insert(tile);
queue.Pop();
}
EXPECT_EQ(tile_count, new_content_tiles.size());
EXPECT_EQ(all_tiles, new_content_tiles);
}
TEST_F(TileManagerTilePriorityQueueTest,
EvictionTilePriorityQueueWithOcclusion) {
gfx::Size tile_size(102, 102);
gfx::Size layer_bounds(1000, 1000);
host_impl_.SetViewportSize(layer_bounds);
scoped_refptr<FakePicturePileImpl> pending_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
SetupPendingTree(pending_pile);
pending_layer_->CreateDefaultTilingsAndTiles();
scoped_ptr<FakePictureLayerImpl> pending_child =
FakePictureLayerImpl::CreateWithPile(
host_impl_.pending_tree(), 2, pending_pile);
pending_layer_->AddChild(pending_child.Pass());
FakePictureLayerImpl* pending_child_layer =
static_cast<FakePictureLayerImpl*>(pending_layer_->children()[0]);
pending_child_layer->SetDrawsContent(true);
pending_child_layer->DoPostCommitInitializationIfNeeded();
pending_child_layer->CreateDefaultTilingsAndTiles();
std::set<Tile*> all_tiles;
size_t tile_count = 0;
RasterTilePriorityQueue raster_queue;
host_impl_.BuildRasterQueue(&raster_queue, SAME_PRIORITY_FOR_BOTH_TREES);
while (!raster_queue.IsEmpty()) {
++tile_count;
EXPECT_TRUE(raster_queue.Top());
all_tiles.insert(raster_queue.Top());
raster_queue.Pop();
}
EXPECT_EQ(tile_count, all_tiles.size());
EXPECT_EQ(32u, tile_count);
pending_layer_->ResetAllTilesPriorities();
// Renew all of the tile priorities.
gfx::Rect viewport(layer_bounds);
pending_layer_->HighResTiling()->ComputeTilePriorityRects(
PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
pending_layer_->LowResTiling()->ComputeTilePriorityRects(
PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
pending_child_layer->HighResTiling()->ComputeTilePriorityRects(
PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
pending_child_layer->LowResTiling()->ComputeTilePriorityRects(
PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
// Populate all tiles directly from the tilings.
all_tiles.clear();
std::vector<Tile*> pending_high_res_tiles =
pending_layer_->HighResTiling()->AllTilesForTesting();
all_tiles.insert(pending_high_res_tiles.begin(),
pending_high_res_tiles.end());
std::vector<Tile*> pending_low_res_tiles =
pending_layer_->LowResTiling()->AllTilesForTesting();
all_tiles.insert(pending_low_res_tiles.begin(), pending_low_res_tiles.end());
// Set all tiles on the pending_child_layer as occluded on the pending tree.
std::vector<Tile*> pending_child_high_res_tiles =
pending_child_layer->HighResTiling()->AllTilesForTesting();
pending_child_layer->HighResTiling()->SetAllTilesOccludedForTesting();
all_tiles.insert(pending_child_high_res_tiles.begin(),
pending_child_high_res_tiles.end());
std::vector<Tile*> pending_child_low_res_tiles =
pending_child_layer->LowResTiling()->AllTilesForTesting();
pending_child_layer->LowResTiling()->SetAllTilesOccludedForTesting();
all_tiles.insert(pending_child_low_res_tiles.begin(),
pending_child_low_res_tiles.end());
tile_manager()->InitializeTilesWithResourcesForTesting(
std::vector<Tile*>(all_tiles.begin(), all_tiles.end()));
// Verify occlusion is considered by EvictionTilePriorityQueue.
TreePriority tree_priority = NEW_CONTENT_TAKES_PRIORITY;
size_t occluded_count = 0u;
Tile* last_tile = NULL;
EvictionTilePriorityQueue queue;
host_impl_.BuildEvictionQueue(&queue, tree_priority);
while (!queue.IsEmpty()) {
Tile* tile = queue.Top();
if (!last_tile)
last_tile = tile;
bool tile_is_occluded = tile->is_occluded_for_tree_priority(tree_priority);
// The only way we will encounter an occluded tile after an unoccluded
// tile is if the priorty bin decreased, the tile is required for
// activation, or the scale changed.
if (tile_is_occluded) {
occluded_count++;
bool last_tile_is_occluded =
last_tile->is_occluded_for_tree_priority(tree_priority);
if (!last_tile_is_occluded) {
TilePriority::PriorityBin tile_priority_bin =
tile->priority_for_tree_priority(tree_priority).priority_bin;
TilePriority::PriorityBin last_tile_priority_bin =
last_tile->priority_for_tree_priority(tree_priority).priority_bin;
EXPECT_TRUE((tile_priority_bin < last_tile_priority_bin) ||
tile->required_for_activation() ||
(tile->contents_scale() != last_tile->contents_scale()));
}
}
last_tile = tile;
queue.Pop();
}
size_t expected_occluded_count =
pending_child_high_res_tiles.size() + pending_child_low_res_tiles.size();
EXPECT_EQ(expected_occluded_count, occluded_count);
}
TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueueEmptyLayers) {
const gfx::Size layer_bounds(1000, 1000);
host_impl_.SetViewportSize(layer_bounds);
SetupDefaultTrees(layer_bounds);
active_layer_->CreateDefaultTilingsAndTiles();
pending_layer_->CreateDefaultTilingsAndTiles();
RasterTilePriorityQueue queue;
host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES);
EXPECT_FALSE(queue.IsEmpty());
size_t tile_count = 0;
std::set<Tile*> all_tiles;
while (!queue.IsEmpty()) {
EXPECT_TRUE(queue.Top());
all_tiles.insert(queue.Top());
++tile_count;
queue.Pop();
}
EXPECT_EQ(tile_count, all_tiles.size());
EXPECT_EQ(16u, tile_count);
queue.Reset();
for (int i = 1; i < 10; ++i) {
scoped_ptr<FakePictureLayerImpl> pending_layer =
FakePictureLayerImpl::Create(host_impl_.pending_tree(), id_ + i);
pending_layer->SetDrawsContent(true);
pending_layer->DoPostCommitInitializationIfNeeded();
pending_layer->set_has_valid_tile_priorities(true);
pending_layer_->AddChild(pending_layer.Pass());
}
host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES);
EXPECT_FALSE(queue.IsEmpty());
tile_count = 0;
all_tiles.clear();
while (!queue.IsEmpty()) {
EXPECT_TRUE(queue.Top());
all_tiles.insert(queue.Top());
++tile_count;
queue.Pop();
}
EXPECT_EQ(tile_count, all_tiles.size());
EXPECT_EQ(16u, tile_count);
}
TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueueEmptyLayers) {
const gfx::Size layer_bounds(1000, 1000);
host_impl_.SetViewportSize(layer_bounds);
SetupDefaultTrees(layer_bounds);
active_layer_->CreateDefaultTilingsAndTiles();
pending_layer_->CreateDefaultTilingsAndTiles();
RasterTilePriorityQueue raster_queue;
host_impl_.BuildRasterQueue(&raster_queue, SAME_PRIORITY_FOR_BOTH_TREES);
EXPECT_FALSE(raster_queue.IsEmpty());
size_t tile_count = 0;
std::set<Tile*> all_tiles;
while (!raster_queue.IsEmpty()) {
EXPECT_TRUE(raster_queue.Top());
all_tiles.insert(raster_queue.Top());
++tile_count;
raster_queue.Pop();
}
EXPECT_EQ(tile_count, all_tiles.size());
EXPECT_EQ(16u, tile_count);
std::vector<Tile*> tiles(all_tiles.begin(), all_tiles.end());
host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
EvictionTilePriorityQueue queue;
for (int i = 1; i < 10; ++i) {
scoped_ptr<FakePictureLayerImpl> pending_layer =
FakePictureLayerImpl::Create(host_impl_.pending_tree(), id_ + i);
pending_layer->SetDrawsContent(true);
pending_layer->DoPostCommitInitializationIfNeeded();
pending_layer->set_has_valid_tile_priorities(true);
pending_layer_->AddChild(pending_layer.Pass());
}
host_impl_.BuildEvictionQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES);
EXPECT_FALSE(queue.IsEmpty());
tile_count = 0;
all_tiles.clear();
while (!queue.IsEmpty()) {
EXPECT_TRUE(queue.Top());
all_tiles.insert(queue.Top());
++tile_count;
queue.Pop();
}
EXPECT_EQ(tile_count, all_tiles.size());
EXPECT_EQ(16u, tile_count);
}
} // namespace
} // namespace cc