#include "cc/layers/append_quads_data.h"
#include "cc/layers/picture_layer.h"
#include "cc/quads/draw_quad.h"
+#include "cc/quads/tile_draw_quad.h"
+#include "cc/test/begin_frame_args_test.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
std::vector<SkRect> rects_;
};
+class NoLowResTilingsSettings : public ImplSidePaintingSettings {};
+
+class LowResTilingsSettings : public ImplSidePaintingSettings {
+ public:
+ LowResTilingsSettings() { create_low_res_tiling = true; }
+};
+
class PictureLayerImplTest : public testing::Test {
public:
PictureLayerImplTest()
: proxy_(base::MessageLoopProxy::current()),
- host_impl_(ImplSidePaintingSettings(),
- &proxy_,
- &shared_bitmap_manager_),
+ host_impl_(LowResTilingsSettings(), &proxy_, &shared_bitmap_manager_),
id_(7),
pending_layer_(NULL),
old_pending_layer_(NULL),
maximum_animation_contents_scale;
layer->draw_properties().screen_space_transform_is_animating =
animating_transform_to_screen;
- layer->UpdateTiles(NULL);
+ layer->UpdateTiles(Occlusion());
}
static void VerifyAllTilesExistAndHavePile(
const PictureLayerTiling* tiling,
}
}
+ void TestQuadsForSolidColor(bool test_for_solid);
+
FakeImplProxy proxy_;
TestSharedBitmapManager shared_bitmap_manager_;
FakeLayerTreeHostImpl host_impl_;
TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
base::TimeTicks time_ticks;
time_ticks += base::TimeDelta::FromMilliseconds(1);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
// Update tiles with viewport for tile priority as (0, 0, 100, 100) and the
// identify transform for tile priority.
resourceless_software_draw);
active_layer_->draw_properties().visible_content_rect = viewport;
active_layer_->draw_properties().screen_space_transform = transform;
- active_layer_->UpdateTiles(NULL);
+ active_layer_->UpdateTiles(Occlusion());
gfx::Rect viewport_rect_for_tile_priority_in_view_space =
viewport_rect_for_tile_priority;
// rotated. The actual viewport for tile priority used by PictureLayerImpl
// should be (200, 200, 100, 100) applied with the said transform.
time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
viewport_rect_for_tile_priority = gfx::Rect(200, 200, 100, 100);
transform_for_tile_priority.Translate(100, 100);
resourceless_software_draw);
active_layer_->draw_properties().visible_content_rect = viewport;
active_layer_->draw_properties().screen_space_transform = transform;
- active_layer_->UpdateTiles(NULL);
+ active_layer_->UpdateTiles(Occlusion());
gfx::Transform screen_to_view(gfx::Transform::kSkipInitialization);
bool success = transform_for_tile_priority.GetInverse(&screen_to_view);
EXPECT_TRUE(success);
+ // Note that we don't clip this to the layer bounds, since it is expected that
+ // the rect will sometimes be outside of the layer bounds. If we clip to
+ // bounds, then tile priorities will end up being incorrect in cases of fully
+ // offscreen layer.
viewport_rect_for_tile_priority_in_view_space =
gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
screen_to_view, viewport_rect_for_tile_priority));
EXPECT_EQ(active_layer_->viewport_rect_for_tile_priority(),
viewport_rect_for_tile_priority_in_view_space);
- // Interset viewport_rect_for_tile_priority_in_view_space with the layer
- // bounds and the result should be used in PictureLayerTiling.
- viewport_rect_for_tile_priority_in_view_space.Intersect(
- gfx::Rect(layer_bounds));
tilings = active_layer_->tilings();
for (size_t i = 0; i < tilings->num_tilings(); i++) {
PictureLayerTiling* tiling = tilings->tiling_at(i);
}
}
-TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
+TEST_F(PictureLayerImplTest,
+ ResourcelessSoftwareDrawHasValidViewportForTilePriority) {
base::TimeTicks time_ticks;
time_ticks += base::TimeDelta::FromMilliseconds(1);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
// UpdateTiles with valid viewport. Should update tile viewport.
- // Note viewport is considered invalid if and only if in resourceless
- // software draw.
bool resourceless_software_draw = false;
gfx::Rect viewport = gfx::Rect(layer_bounds);
gfx::Transform transform;
resourceless_software_draw);
active_layer_->draw_properties().visible_content_rect = viewport;
active_layer_->draw_properties().screen_space_transform = transform;
- active_layer_->UpdateTiles(NULL);
+ active_layer_->UpdateTiles(Occlusion());
gfx::Rect visible_rect_for_tile_priority =
active_layer_->visible_rect_for_tile_priority();
gfx::Transform screen_space_transform_for_tile_priority =
active_layer_->screen_space_transform_for_tile_priority();
- // Expand viewport and set it as invalid for prioritizing tiles.
- // Should not update tile viewport.
+ // PictureLayerImpl does not make a special case for
+ // resource_less_software_draw, so the tile viewport and matrix should be
+ // respected.
time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
resourceless_software_draw = true;
viewport = gfx::ScaleToEnclosingRect(viewport, 2);
transform.Translate(1.f, 1.f);
viewport,
transform,
resourceless_software_draw);
- active_layer_->UpdateTiles(NULL);
+ active_layer_->UpdateTiles(Occlusion());
+ visible_rect_for_tile_priority =
+ gfx::ScaleToEnclosingRect(visible_rect_for_tile_priority, 2);
+ viewport_rect_for_tile_priority =
+ gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority, 2);
+ screen_space_transform_for_tile_priority = transform;
EXPECT_RECT_EQ(visible_rect_for_tile_priority,
active_layer_->visible_rect_for_tile_priority());
EXPECT_RECT_EQ(viewport_rect_for_tile_priority,
EXPECT_TRANSFORMATION_MATRIX_EQ(
screen_space_transform_for_tile_priority,
active_layer_->screen_space_transform_for_tile_priority());
-
- // Keep expanded viewport but mark it valid. Should update tile viewport.
- time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
- resourceless_software_draw = false;
- host_impl_.SetExternalDrawConstraints(transform,
- viewport,
- viewport,
- viewport,
- transform,
- resourceless_software_draw);
- active_layer_->UpdateTiles(NULL);
-
- EXPECT_FALSE(visible_rect_for_tile_priority ==
- active_layer_->visible_rect_for_tile_priority());
- EXPECT_FALSE(viewport_rect_for_tile_priority ==
- active_layer_->viewport_rect_for_tile_priority());
- EXPECT_FALSE(screen_space_transform_for_tile_priority ==
- active_layer_->screen_space_transform_for_tile_priority());
-}
-
-TEST_F(PictureLayerImplTest, InvalidViewportAfterReleaseResources) {
- gfx::Size tile_size(100, 100);
- gfx::Size layer_bounds(400, 400);
-
- 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);
-
- Region invalidation;
- AddDefaultTilingsWithInvalidation(invalidation);
-
- bool resourceless_software_draw = true;
- gfx::Rect viewport = gfx::Rect(layer_bounds);
- gfx::Transform identity = gfx::Transform();
- host_impl_.SetExternalDrawConstraints(identity,
- viewport,
- viewport,
- viewport,
- identity,
- resourceless_software_draw);
- ResetTilingsAndRasterScales();
- host_impl_.pending_tree()->UpdateDrawProperties();
- host_impl_.active_tree()->UpdateDrawProperties();
- EXPECT_TRUE(active_layer_->HighResTiling());
-
- size_t num_tilings = active_layer_->num_tilings();
- active_layer_->UpdateTiles(NULL);
- pending_layer_->AddTiling(0.5f);
- EXPECT_EQ(num_tilings + 1, active_layer_->num_tilings());
}
TEST_F(PictureLayerImplTest, ClonePartialInvalidation) {
EXPECT_TRUE(*iter);
EXPECT_FALSE(iter.geometry_rect().IsEmpty());
if (iter.geometry_rect().Intersects(content_invalidation))
- EXPECT_EQ(pending_pile, iter->picture_pile());
+ EXPECT_EQ(pending_pile.get(), iter->picture_pile());
else
- EXPECT_EQ(active_pile, iter->picture_pile());
+ EXPECT_EQ(active_pile.get(), iter->picture_pile());
}
}
}
iter.geometry_rect().bottom() >= active_content_bounds.height() ||
active_tiles[0]->content_rect().size() !=
pending_tiles[0]->content_rect().size()) {
- EXPECT_EQ(pending_pile, iter->picture_pile());
+ EXPECT_EQ(pending_pile.get(), iter->picture_pile());
} else {
- EXPECT_EQ(active_pile, iter->picture_pile());
+ EXPECT_EQ(active_pile.get(), iter->picture_pile());
}
}
}
iter.full_tile_geometry_rect());
if (in_pending && !in_active)
- EXPECT_EQ(pending_pile, iter->picture_pile());
+ EXPECT_EQ(pending_pile.get(), iter->picture_pile());
else if (in_active)
- EXPECT_EQ(active_pile, iter->picture_pile());
+ EXPECT_EQ(active_pile.get(), iter->picture_pile());
else
EXPECT_FALSE(*iter);
}
active_layer_->DidDraw(NULL);
ASSERT_EQ(1U, render_pass->quad_list.size());
- EXPECT_EQ(DrawQuad::PICTURE_CONTENT, render_pass->quad_list[0]->material);
+ EXPECT_EQ(DrawQuad::PICTURE_CONTENT,
+ render_pass->quad_list.front()->material);
}
TEST_F(PictureLayerImplTest, MarkRequiredNullTiles) {
TEST_F(PictureLayerImplTest, TileOutsideOfViewportForTilePriorityNotRequired) {
base::TimeTicks time_ticks;
time_ticks += base::TimeDelta::FromMilliseconds(1);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
// external_viewport_for_tile_priority.
pending_layer_->draw_properties().visible_content_rect = visible_content_rect;
time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
- pending_layer_->UpdateTiles(NULL);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
+ pending_layer_->UpdateTiles(Occlusion());
pending_layer_->MarkVisibleResourcesAsRequired();
EXPECT_EQ(0u, data.num_incomplete_tiles);
}
+TEST_F(PictureLayerImplTest, HighResTileIsComplete) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
+
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(200, 200);
+
+ host_impl_.SetViewportSize(layer_bounds);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ SetupPendingTree(pending_pile);
+ ActivateTree();
+
+ // All high res tiles have resources.
+ active_layer_->set_fixed_tile_size(tile_size);
+ host_impl_.active_tree()->UpdateDrawProperties();
+ std::vector<Tile*> tiles =
+ active_layer_->tilings()->tiling_at(0)->AllTilesForTesting();
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
+
+ MockOcclusionTracker<LayerImpl> occlusion_tracker;
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ AppendQuadsData data;
+ active_layer_->WillDraw(DRAW_MODE_SOFTWARE, NULL);
+ active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
+ active_layer_->DidDraw(NULL);
+
+ // All high res tiles drew, nothing was incomplete.
+ EXPECT_EQ(9u, render_pass->quad_list.size());
+ EXPECT_EQ(0u, data.num_missing_tiles);
+ EXPECT_EQ(0u, data.num_incomplete_tiles);
+}
+
+TEST_F(PictureLayerImplTest, LowResTileIsIncomplete) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
+
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(200, 200);
+
+ host_impl_.SetViewportSize(layer_bounds);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ SetupPendingTree(pending_pile);
+ ActivateTree();
+
+ // All high res tiles have resources except one.
+ active_layer_->set_fixed_tile_size(tile_size);
+ host_impl_.active_tree()->UpdateDrawProperties();
+ std::vector<Tile*> high_tiles =
+ active_layer_->tilings()->tiling_at(0)->AllTilesForTesting();
+ high_tiles.erase(high_tiles.begin());
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(high_tiles);
+
+ // All low res tiles have resources.
+ std::vector<Tile*> low_tiles =
+ active_layer_->tilings()->tiling_at(1)->AllTilesForTesting();
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(low_tiles);
+
+ MockOcclusionTracker<LayerImpl> occlusion_tracker;
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ AppendQuadsData data;
+ active_layer_->WillDraw(DRAW_MODE_SOFTWARE, NULL);
+ active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
+ active_layer_->DidDraw(NULL);
+
+ // The missing high res tile was replaced by a low res tile.
+ EXPECT_EQ(9u, render_pass->quad_list.size());
+ EXPECT_EQ(0u, data.num_missing_tiles);
+ EXPECT_EQ(1u, data.num_incomplete_tiles);
+}
+
+TEST_F(PictureLayerImplTest,
+ HighResAndIdealResTileIsCompleteWhenRasterScaleIsNotIdeal) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
+
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(200, 200);
+
+ host_impl_.SetViewportSize(layer_bounds);
+
+ 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);
+
+ active_layer_->set_fixed_tile_size(tile_size);
+
+ active_layer_->draw_properties().visible_content_rect =
+ gfx::Rect(layer_bounds);
+ SetupDrawPropertiesAndUpdateTiles(active_layer_, 2.f, 1.f, 1.f, 1.f, false);
+
+ // One ideal tile exists, this will get used when drawing.
+ std::vector<Tile*> ideal_tiles;
+ EXPECT_EQ(2.f, active_layer_->HighResTiling()->contents_scale());
+ ideal_tiles.push_back(active_layer_->HighResTiling()->TileAt(0, 0));
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(
+ ideal_tiles);
+
+ // Due to layer scale throttling, the raster contents scale is changed to 1,
+ // while the ideal is still 2.
+ SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
+ SetupDrawPropertiesAndUpdateTiles(active_layer_, 2.f, 1.f, 1.f, 1.f, false);
+
+ EXPECT_EQ(1.f, active_layer_->HighResTiling()->contents_scale());
+ EXPECT_EQ(1.f, active_layer_->raster_contents_scale());
+ EXPECT_EQ(2.f, active_layer_->ideal_contents_scale());
+
+ // Both tilings still exist.
+ EXPECT_EQ(2.f, active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_EQ(1.f, active_layer_->tilings()->tiling_at(1)->contents_scale());
+
+ // All high res tiles have resources.
+ std::vector<Tile*> high_tiles =
+ active_layer_->HighResTiling()->AllTilesForTesting();
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(high_tiles);
+
+ MockOcclusionTracker<LayerImpl> occlusion_tracker;
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ AppendQuadsData data;
+ active_layer_->WillDraw(DRAW_MODE_SOFTWARE, NULL);
+ active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
+ active_layer_->DidDraw(NULL);
+
+ // All high res tiles drew, and the one ideal res tile drew.
+ ASSERT_GT(render_pass->quad_list.size(), 9u);
+ EXPECT_EQ(gfx::SizeF(99.f, 99.f),
+ TileDrawQuad::MaterialCast(render_pass->quad_list.front())
+ ->tex_coord_rect.size());
+ EXPECT_EQ(gfx::SizeF(49.5f, 49.5f),
+ TileDrawQuad::MaterialCast(render_pass->quad_list.ElementAt(1))
+ ->tex_coord_rect.size());
+
+ // Neither the high res nor the ideal tiles were considered as incomplete.
+ EXPECT_EQ(0u, data.num_missing_tiles);
+ EXPECT_EQ(0u, data.num_incomplete_tiles);
+}
+
TEST_F(PictureLayerImplTest, HighResRequiredWhenUnsharedActiveAllReady) {
gfx::Size layer_bounds(400, 400);
gfx::Size tile_size(100, 100);
EXPECT_TRUE(pending_tiling->TileAt(1, 1));
EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
+ EXPECT_TRUE(active_tiling->TileAt(0, 0)->is_shared());
EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
+ EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared());
EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
+ EXPECT_TRUE(active_tiling->TileAt(0, 1)->is_shared());
EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
+ EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared());
}
}
EXPECT_TRUE(pending_tiling->TileAt(1, 1));
EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
+ EXPECT_TRUE(active_tiling->TileAt(0, 0)->is_shared());
EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
+ EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared());
EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
+ EXPECT_TRUE(active_tiling->TileAt(0, 1)->is_shared());
EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
+ EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared());
}
}
EXPECT_TRUE(pending_tiling->TileAt(1, 1));
EXPECT_NE(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
+ EXPECT_FALSE(active_tiling->TileAt(0, 0)->is_shared());
+ EXPECT_FALSE(pending_tiling->TileAt(0, 0)->is_shared());
EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
+ EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared());
EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
+ EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared());
EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
+ EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared());
}
}
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 11.f);
}
+TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForGpuRasterization) {
+ gfx::Size layer_bounds(100, 100);
+ gfx::Size viewport_size(1000, 1000);
+ SetupDefaultTrees(layer_bounds);
+ host_impl_.SetViewportSize(viewport_size);
+ host_impl_.SetUseGpuRasterization(true);
+
+ float contents_scale = 1.f;
+ float device_scale = 1.3f;
+ float page_scale = 1.4f;
+ float maximum_animation_scale = 1.f;
+ bool animating_transform = false;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
+
+ // Since we're GPU-rasterizing, starting an animation should cause tiling
+ // resolution to get set to the current contents scale.
+ animating_transform = true;
+ contents_scale = 2.f;
+ maximum_animation_scale = 4.f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
+
+ // Further changes to scale during the animation should cause a new high-res
+ // tiling to get created.
+ contents_scale = 3.f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
+
+ // Since we're re-rasterizing during the animation, scales smaller than 1
+ // should be respected.
+ contents_scale = 0.25f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 0.25f);
+
+ // Once we stop animating, a new high-res tiling should be created.
+ contents_scale = 4.f;
+ animating_transform = false;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
+
+ static_cast<FakePicturePileImpl*>(pending_layer_->pile())->set_has_text(true);
+ static_cast<FakePicturePileImpl*>(active_layer_->pile())->set_has_text(true);
+
+ // Since we're GPU-rasterizing but have text, starting an animation should
+ // cause tiling resolution to get set to the maximum animation scale.
+ animating_transform = true;
+ contents_scale = 2.f;
+ maximum_animation_scale = 3.f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
+
+ // Further changes to scale during the animation should not cause a new
+ // high-res tiling to get created.
+ contents_scale = 4.f;
+ maximum_animation_scale = 5.f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
+
+ // Once we stop animating, a new high-res tiling should be created.
+ animating_transform = false;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
+}
+
TEST_F(PictureLayerImplTest, LayerRasterTileIterator) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
+
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(1000, 1000);
EXPECT_EQ(low_res_tile_count + high_res_tile_count + non_ideal_tile_count,
unique_tiles.size());
+ // No NOW tiles.
+ time_ticks += base::TimeDelta::FromMilliseconds(200);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
+
+ pending_layer_->draw_properties().visible_content_rect =
+ gfx::Rect(1100, 1100, 500, 500);
+ pending_layer_->UpdateTiles(Occlusion());
+
+ unique_tiles.clear();
+ high_res_tile_count = 0u;
+ for (it = PictureLayerImpl::LayerRasterTileIterator(pending_layer_, false);
+ it;
+ ++it) {
+ Tile* tile = *it;
+ TilePriority priority = tile->priority(PENDING_TREE);
+
+ EXPECT_TRUE(tile);
+
+ // Non-high res tiles only get visible tiles.
+ EXPECT_EQ(HIGH_RESOLUTION, priority.resolution);
+ EXPECT_NE(TilePriority::NOW, priority.priority_bin);
+
+ high_res_tile_count += priority.resolution == HIGH_RESOLUTION;
+
+ unique_tiles.insert(tile);
+ }
+
+ EXPECT_EQ(16u, high_res_tile_count);
+ EXPECT_EQ(high_res_tile_count, unique_tiles.size());
+
+ time_ticks += base::TimeDelta::FromMilliseconds(200);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
+
+ pending_layer_->draw_properties().visible_content_rect =
+ gfx::Rect(0, 0, 500, 500);
+ pending_layer_->UpdateTiles(Occlusion());
+
std::vector<Tile*> high_res_tiles = high_res_tiling->AllTilesForTesting();
for (std::vector<Tile*>::iterator tile_it = high_res_tiles.begin();
tile_it != high_res_tiles.end();
impl.AppendQuadsWithOcclusion(active_layer_, occluded);
size_t partially_occluded_count = 0;
- LayerTestCommon::VerifyQuadsCoverRectWithOcclusion(
- impl.quad_list(),
- gfx::Rect(layer_bounds),
- occluded,
- &partially_occluded_count);
+ LayerTestCommon::VerifyQuadsAreOccluded(
+ impl.quad_list(), occluded, &partially_occluded_count);
// The layer outputs one quad, which is partially occluded.
EXPECT_EQ(100u - 10u, impl.quad_list().size());
EXPECT_EQ(10u + 10u, partially_occluded_count);
EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
}
-TEST_F(PictureLayerImplTest, HighResReadyToDrawNotEnoughToActivate) {
+TEST_F(PictureLayerImplTest, HighResReadyToDrawEnoughToActivate) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(1000, 1000);
// Initialize all high-res tiles.
pending_layer_->SetAllTilesReadyInTiling(pending_layer_->HighResTiling());
- // High-res tiles should not be enough.
- EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+ // High-res tiles should be enough, since they cover everything visible.
+ EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+}
- // Initialize remaining tiles.
- pending_layer_->SetAllTilesReady();
+TEST_F(PictureLayerImplTest,
+ SharedActiveHighResReadyAndPendingLowResReadyNotEnoughToActivate) {
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(1000, 1000);
+
+ SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
+
+ // Make sure some tiles are not shared.
+ pending_layer_->set_invalidation(gfx::Rect(gfx::Point(50, 50), tile_size));
+
+ CreateHighLowResAndSetAllTilesVisible();
+ // Initialize all high-res tiles in the active layer.
+ active_layer_->SetAllTilesReadyInTiling(active_layer_->HighResTiling());
+ // And all the low-res tiles in the pending layer.
+ pending_layer_->SetAllTilesReadyInTiling(pending_layer_->LowResTiling());
+
+ pending_layer_->MarkVisibleResourcesAsRequired();
+
+ // The unshared high-res tiles are not ready, so we cannot activate.
+ EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+
+ // When the unshared pending high-res tiles are ready, we can activate.
+ pending_layer_->SetAllTilesReadyInTiling(pending_layer_->HighResTiling());
EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
}
-class NoLowResTilingsSettings : public ImplSidePaintingSettings {
- public:
- NoLowResTilingsSettings() { create_low_res_tiling = false; }
-};
+TEST_F(PictureLayerImplTest, SharedActiveHighResReadyNotEnoughToActivate) {
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(1000, 1000);
+
+ SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
+
+ // Make sure some tiles are not shared.
+ pending_layer_->set_invalidation(gfx::Rect(gfx::Point(50, 50), tile_size));
+
+ CreateHighLowResAndSetAllTilesVisible();
+
+ // Initialize all high-res tiles in the active layer.
+ active_layer_->SetAllTilesReadyInTiling(active_layer_->HighResTiling());
+
+ pending_layer_->MarkVisibleResourcesAsRequired();
+
+ // The unshared high-res tiles are not ready, so we cannot activate.
+ EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+
+ // When the unshared pending high-res tiles are ready, we can activate.
+ pending_layer_->SetAllTilesReadyInTiling(pending_layer_->HighResTiling());
+ EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+}
class NoLowResPictureLayerImplTest : public PictureLayerImplTest {
public:
AssertNoTilesRequired(pending_layer_->LowResTiling());
}
-TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
+TEST_F(NoLowResPictureLayerImplTest,
+ ResourcelessSoftwareDrawHasValidViewportForTilePriority) {
base::TimeTicks time_ticks;
time_ticks += base::TimeDelta::FromMilliseconds(1);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
// UpdateTiles with valid viewport. Should update tile viewport.
- // Note viewport is considered invalid if and only if in resourceless
- // software draw.
bool resourceless_software_draw = false;
gfx::Rect viewport = gfx::Rect(layer_bounds);
gfx::Transform transform;
resourceless_software_draw);
active_layer_->draw_properties().visible_content_rect = viewport;
active_layer_->draw_properties().screen_space_transform = transform;
- active_layer_->UpdateTiles(NULL);
+ active_layer_->UpdateTiles(Occlusion());
gfx::Rect visible_rect_for_tile_priority =
active_layer_->visible_rect_for_tile_priority();
gfx::Transform screen_space_transform_for_tile_priority =
active_layer_->screen_space_transform_for_tile_priority();
- // Expand viewport and set it as invalid for prioritizing tiles.
- // Should not update tile viewport.
+ // PictureLayerImpl does not make a special case for
+ // resource_less_software_draw, so the tile viewport and matrix should be
+ // respected.
time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
resourceless_software_draw = true;
viewport = gfx::ScaleToEnclosingRect(viewport, 2);
transform.Translate(1.f, 1.f);
viewport,
transform,
resourceless_software_draw);
- active_layer_->UpdateTiles(NULL);
+ active_layer_->UpdateTiles(Occlusion());
+
+ visible_rect_for_tile_priority =
+ gfx::ScaleToEnclosingRect(visible_rect_for_tile_priority, 2);
+ viewport_rect_for_tile_priority =
+ gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority, 2);
+ screen_space_transform_for_tile_priority = transform;
EXPECT_RECT_EQ(visible_rect_for_tile_priority,
active_layer_->visible_rect_for_tile_priority());
EXPECT_TRANSFORMATION_MATRIX_EQ(
screen_space_transform_for_tile_priority,
active_layer_->screen_space_transform_for_tile_priority());
-
- // Keep expanded viewport but mark it valid. Should update tile viewport.
- time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
- resourceless_software_draw = false;
- host_impl_.SetExternalDrawConstraints(transform,
- viewport,
- viewport,
- viewport,
- transform,
- resourceless_software_draw);
- active_layer_->UpdateTiles(NULL);
-
- EXPECT_FALSE(visible_rect_for_tile_priority ==
- active_layer_->visible_rect_for_tile_priority());
- EXPECT_FALSE(viewport_rect_for_tile_priority ==
- active_layer_->viewport_rect_for_tile_priority());
- EXPECT_FALSE(screen_space_transform_for_tile_priority ==
- active_layer_->screen_space_transform_for_tile_priority());
-}
-
-TEST_F(NoLowResPictureLayerImplTest, InvalidViewportAfterReleaseResources) {
- gfx::Size tile_size(100, 100);
- gfx::Size layer_bounds(400, 400);
-
- 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);
-
- Region invalidation;
- AddDefaultTilingsWithInvalidation(invalidation);
-
- bool resourceless_software_draw = true;
- gfx::Rect viewport = gfx::Rect(layer_bounds);
- gfx::Transform identity = gfx::Transform();
- host_impl_.SetExternalDrawConstraints(identity,
- viewport,
- viewport,
- viewport,
- identity,
- resourceless_software_draw);
- ResetTilingsAndRasterScales();
- host_impl_.pending_tree()->UpdateDrawProperties();
- host_impl_.active_tree()->UpdateDrawProperties();
- EXPECT_TRUE(active_layer_->HighResTiling());
-
- size_t num_tilings = active_layer_->num_tilings();
- active_layer_->UpdateTiles(NULL);
- pending_layer_->AddTiling(0.5f);
- EXPECT_EQ(num_tilings + 1, active_layer_->num_tilings());
}
TEST_F(NoLowResPictureLayerImplTest, CleanUpTilings) {
render_pass->quad_list.back()->material);
}
-class OcclusionTrackingSettings : public ImplSidePaintingSettings {
+class OcclusionTrackingSettings : public LowResTilingsSettings {
public:
OcclusionTrackingSettings() { use_occlusion_for_tile_prioritization = true; }
};
OccludedTilesSkippedDuringRasterization) {
base::TimeTicks time_ticks;
time_ticks += base::TimeDelta::FromMilliseconds(1);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
gfx::Size tile_size(102, 102);
gfx::Size layer_bounds(1000, 1000);
layer1->SetPosition(occluding_layer_position);
time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
host_impl_.pending_tree()->UpdateDrawProperties();
unoccluded_tile_count = 0;
layer1->SetPosition(gfx::Point(0, 0));
time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
host_impl_.pending_tree()->UpdateDrawProperties();
unoccluded_tile_count = 0;
OccludedTilesNotMarkedAsRequired) {
base::TimeTicks time_ticks;
time_ticks += base::TimeDelta::FromMilliseconds(1);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
gfx::Size tile_size(102, 102);
gfx::Size layer_bounds(1000, 1000);
layer1->SetPosition(occluding_layer_position);
time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
host_impl_.pending_tree()->UpdateDrawProperties();
for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
layer1->SetPosition(gfx::PointF(0, 0));
time_ticks += base::TimeDelta::FromMilliseconds(200);
- host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
host_impl_.pending_tree()->UpdateDrawProperties();
for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
EXPECT_FALSE(active_layer_->GetRecycledTwinLayer());
}
+void PictureLayerImplTest::TestQuadsForSolidColor(bool test_for_solid) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
+
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(200, 200);
+ gfx::Rect layer_rect(layer_bounds);
+
+ FakeContentLayerClient client;
+ scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
+ FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+ scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&host_client);
+ host->SetRootLayer(layer);
+ PicturePile* pile = layer->GetPicturePileForTesting();
+
+ host_impl_.SetViewportSize(layer_bounds);
+
+ int frame_number = 0;
+ FakeRenderingStatsInstrumentation stats_instrumentation;
+
+ client.set_fill_with_nonsolid_color(!test_for_solid);
+
+ Region invalidation(layer_rect);
+ pile->UpdateAndExpandInvalidation(&client,
+ &invalidation,
+ SK_ColorWHITE,
+ false,
+ false,
+ layer_bounds,
+ layer_rect,
+ frame_number++,
+ Picture::RECORD_NORMALLY,
+ &stats_instrumentation);
+
+ scoped_refptr<PicturePileImpl> pending_pile =
+ PicturePileImpl::CreateFromOther(pile);
+
+ SetupPendingTree(pending_pile);
+ ActivateTree();
+
+ if (test_for_solid) {
+ EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+ } else {
+ ASSERT_TRUE(active_layer_->tilings());
+ active_layer_->set_fixed_tile_size(tile_size);
+ host_impl_.active_tree()->UpdateDrawProperties();
+ ASSERT_GT(active_layer_->tilings()->num_tilings(), 0u);
+ std::vector<Tile*> tiles =
+ active_layer_->tilings()->tiling_at(0)->AllTilesForTesting();
+ EXPECT_FALSE(tiles.empty());
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
+ }
+
+ MockOcclusionTracker<LayerImpl> occlusion_tracker;
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ AppendQuadsData data;
+ active_layer_->WillDraw(DRAW_MODE_SOFTWARE, NULL);
+ active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
+ active_layer_->DidDraw(NULL);
+
+ DrawQuad::Material expected = test_for_solid
+ ? DrawQuad::Material::SOLID_COLOR
+ : DrawQuad::Material::TILED_CONTENT;
+ EXPECT_EQ(expected, render_pass->quad_list.front()->material);
+}
+
+TEST_F(PictureLayerImplTest, DrawSolidQuads) {
+ TestQuadsForSolidColor(true);
+}
+
+TEST_F(PictureLayerImplTest, DrawNonSolidQuads) {
+ TestQuadsForSolidColor(false);
+}
+
+TEST_F(PictureLayerImplTest, NonSolidToSolidNoTilings) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentBeginFrameArgs(
+ CreateBeginFrameArgsForTesting(time_ticks));
+
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(200, 200);
+ gfx::Rect layer_rect(layer_bounds);
+
+ FakeContentLayerClient client;
+ scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
+ FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+ scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&host_client);
+ host->SetRootLayer(layer);
+ PicturePile* pile = layer->GetPicturePileForTesting();
+
+ host_impl_.SetViewportSize(layer_bounds);
+
+ int frame_number = 0;
+ FakeRenderingStatsInstrumentation stats_instrumentation;
+
+ client.set_fill_with_nonsolid_color(true);
+
+ Region invalidation1(layer_rect);
+ pile->UpdateAndExpandInvalidation(&client,
+ &invalidation1,
+ SK_ColorWHITE,
+ false,
+ false,
+ layer_bounds,
+ layer_rect,
+ frame_number++,
+ Picture::RECORD_NORMALLY,
+ &stats_instrumentation);
+
+ scoped_refptr<PicturePileImpl> pending_pile1 =
+ PicturePileImpl::CreateFromOther(pile);
+
+ SetupPendingTree(pending_pile1);
+ ActivateTree();
+ host_impl_.active_tree()->UpdateDrawProperties();
+
+ // We've started with a solid layer that contains some tilings.
+ ASSERT_TRUE(active_layer_->tilings());
+ EXPECT_NE(0u, active_layer_->tilings()->num_tilings());
+
+ client.set_fill_with_nonsolid_color(false);
+
+ Region invalidation2(layer_rect);
+ pile->UpdateAndExpandInvalidation(&client,
+ &invalidation2,
+ SK_ColorWHITE,
+ false,
+ false,
+ layer_bounds,
+ layer_rect,
+ frame_number++,
+ Picture::RECORD_NORMALLY,
+ &stats_instrumentation);
+
+ scoped_refptr<PicturePileImpl> pending_pile2 =
+ PicturePileImpl::CreateFromOther(pile);
+
+ SetupPendingTree(pending_pile2);
+ ActivateTree();
+
+ // We've switched to a solid color, so we should end up with no tilings.
+ ASSERT_TRUE(active_layer_->tilings());
+ EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+}
+
} // namespace
} // namespace cc