#include "cc/layers/picture_layer_impl.h"
+#include <algorithm>
+#include <limits>
#include <set>
#include <utility>
+#include "cc/base/math_util.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/picture_layer.h"
+#include "cc/quads/draw_quad.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"
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/fake_picture_pile_impl.h"
#include "cc/test/geometry_test_utils.h"
-#include "cc/test/gpu_rasterization_settings.h"
-#include "cc/test/hybrid_rasterization_settings.h"
#include "cc/test/impl_side_painting_settings.h"
-#include "cc/test/mock_quad_culler.h"
+#include "cc/test/layer_test_common.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/test_web_graphics_context_3d.h"
#include "cc/trees/layer_tree_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/size_conversions.h"
namespace cc {
namespace {
host_impl_(ImplSidePaintingSettings(),
&proxy_,
&shared_bitmap_manager_),
- id_(7) {}
+ id_(7),
+ pending_layer_(NULL),
+ old_pending_layer_(NULL),
+ active_layer_(NULL) {}
explicit PictureLayerImplTest(const LayerTreeSettings& settings)
: proxy_(base::MessageLoopProxy::current()),
}
void ActivateTree() {
- host_impl_.ActivatePendingTree();
+ host_impl_.ActivateSyncTree();
CHECK(!host_impl_.pending_tree());
+ CHECK(host_impl_.recycle_tree());
+ old_pending_layer_ = pending_layer_;
pending_layer_ = NULL;
active_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.active_tree()->LayerById(id_));
pending_layer_->tilings()->tiling_at(i)->CreateAllTilesForTesting();
}
- void SetupPendingTree(
- scoped_refptr<PicturePileImpl> pile) {
+ void SetupPendingTree(scoped_refptr<PicturePileImpl> pile) {
host_impl_.CreatePendingTree();
+ host_impl_.pending_tree()->SetPageScaleFactorAndLimits(1.f, 0.25f, 100.f);
LayerTreeImpl* pending_tree = host_impl_.pending_tree();
// Clear recycled tree.
pending_tree->DetachLayerTree();
pending_layer_->DoPostCommitInitializationIfNeeded();
}
+ void SetupDrawPropertiesAndUpdateTiles(FakePictureLayerImpl* layer,
+ float ideal_contents_scale,
+ float device_scale_factor,
+ float page_scale_factor,
+ float maximum_animation_contents_scale,
+ bool animating_transform_to_screen) {
+ layer->draw_properties().ideal_contents_scale = ideal_contents_scale;
+ layer->draw_properties().device_scale_factor = device_scale_factor;
+ layer->draw_properties().page_scale_factor = page_scale_factor;
+ layer->draw_properties().maximum_animation_contents_scale =
+ maximum_animation_contents_scale;
+ layer->draw_properties().screen_space_transform_is_animating =
+ animating_transform_to_screen;
+ layer->UpdateTiles(NULL);
+ }
static void VerifyAllTilesExistAndHavePile(
const PictureLayerTiling* tiling,
PicturePileImpl* pile) {
- for (PictureLayerTiling::CoverageIterator
- iter(tiling, tiling->contents_scale(), tiling->ContentRect());
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ tiling->contents_scale(),
+ gfx::Rect(tiling->tiling_size()));
iter;
++iter) {
EXPECT_TRUE(*iter);
void SetContentsScaleOnBothLayers(float contents_scale,
float device_scale_factor,
float page_scale_factor,
+ float maximum_animation_contents_scale,
bool animating_transform) {
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
- pending_layer_->CalculateContentsScale(
- contents_scale,
- device_scale_factor,
- page_scale_factor,
- animating_transform,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
- active_layer_->CalculateContentsScale(
- contents_scale,
- device_scale_factor,
- page_scale_factor,
- animating_transform,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ contents_scale,
+ device_scale_factor,
+ page_scale_factor,
+ maximum_animation_contents_scale,
+ animating_transform);
+
+ SetupDrawPropertiesAndUpdateTiles(active_layer_,
+ contents_scale,
+ device_scale_factor,
+ page_scale_factor,
+ maximum_animation_contents_scale,
+ animating_transform);
}
void ResetTilingsAndRasterScales() {
SetupTrees(pending_pile, active_pile);
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
- active_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
// Add 1x1 rects at the centers of each tile, then re-record pile contents
active_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting();
FakeLayerTreeHostImpl host_impl_;
int id_;
FakePictureLayerImpl* pending_layer_;
+ FakePictureLayerImpl* old_pending_layer_;
FakePictureLayerImpl* active_layer_;
private:
VerifyAllTilesExistAndHavePile(tilings->tiling_at(i), active_pile.get());
}
-TEST_F(PictureLayerImplTest, TileManagerRegisterUnregister) {
+TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
SetupTrees(pending_pile, active_pile);
- std::vector<TileManager::PairedPictureLayer> paired_layers;
- host_impl_.tile_manager()->GetPairedPictureLayers(&paired_layers);
- EXPECT_EQ(0u, paired_layers.size());
-
- // Update tile priorities will force the layer to register itself.
- float dummy_contents_scale_x;
- float dummy_contents_scale_y;
- gfx::Size dummy_content_bounds;
- active_layer_->CalculateContentsScale(1.f,
- 1.f,
- 1.f,
- false,
- &dummy_contents_scale_x,
- &dummy_contents_scale_y,
- &dummy_content_bounds);
- active_layer_->UpdateTilePriorities();
- host_impl_.pending_tree()->UpdateDrawProperties();
- pending_layer_->CalculateContentsScale(1.f,
- 1.f,
- 1.f,
- false,
- &dummy_contents_scale_x,
- &dummy_contents_scale_y,
- &dummy_content_bounds);
- pending_layer_->UpdateTilePriorities();
-
- host_impl_.tile_manager()->GetPairedPictureLayers(&paired_layers);
- EXPECT_EQ(1u, paired_layers.size());
- EXPECT_EQ(active_layer_, paired_layers[0].active_layer);
- EXPECT_EQ(pending_layer_, paired_layers[0].pending_layer);
-
- // Destroy and recreate tile manager.
- host_impl_.DidLoseOutputSurface();
- scoped_ptr<TestWebGraphicsContext3D> context =
- TestWebGraphicsContext3D::Create();
- host_impl_.InitializeRenderer(
- FakeOutputSurface::Create3d(context.Pass()).PassAs<OutputSurface>());
-
- host_impl_.tile_manager()->GetPairedPictureLayers(&paired_layers);
- EXPECT_EQ(0u, paired_layers.size());
-
- active_layer_->CalculateContentsScale(1.f,
- 1.f,
- 1.f,
- false,
- &dummy_contents_scale_x,
- &dummy_contents_scale_y,
- &dummy_content_bounds);
- active_layer_->UpdateTilePriorities();
- host_impl_.pending_tree()->UpdateDrawProperties();
- pending_layer_->CalculateContentsScale(1.f,
- 1.f,
- 1.f,
- false,
- &dummy_contents_scale_x,
- &dummy_contents_scale_y,
- &dummy_content_bounds);
- pending_layer_->UpdateTilePriorities();
-
- host_impl_.tile_manager()->GetPairedPictureLayers(&paired_layers);
- EXPECT_EQ(1u, paired_layers.size());
- EXPECT_EQ(active_layer_, paired_layers[0].active_layer);
- EXPECT_EQ(pending_layer_, paired_layers[0].pending_layer);
-}
-
-TEST_F(PictureLayerImplTest, SuppressUpdateTilePriorities) {
+ Region invalidation;
+ AddDefaultTilingsWithInvalidation(invalidation);
+ SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
+
+ time_ticks += base::TimeDelta::FromMilliseconds(200);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+
+ // Update tiles with viewport for tile priority as (0, 0, 100, 100) and the
+ // identify transform for tile priority.
+ bool resourceless_software_draw = false;
+ gfx::Rect viewport = gfx::Rect(layer_bounds),
+ viewport_rect_for_tile_priority = gfx::Rect(0, 0, 100, 100);
+ gfx::Transform transform, transform_for_tile_priority;
+
+ host_impl_.SetExternalDrawConstraints(transform,
+ viewport,
+ viewport,
+ viewport_rect_for_tile_priority,
+ 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);
+
+ gfx::Rect viewport_rect_for_tile_priority_in_view_space =
+ viewport_rect_for_tile_priority;
+
+ // Verify the viewport rect for tile priority is used in picture layer impl.
+ EXPECT_EQ(active_layer_->viewport_rect_for_tile_priority(),
+ viewport_rect_for_tile_priority_in_view_space);
+
+ // Verify the viewport rect for tile priority is used in picture layer tiling.
+ PictureLayerTilingSet* tilings = active_layer_->tilings();
+ for (size_t i = 0; i < tilings->num_tilings(); i++) {
+ PictureLayerTiling* tiling = tilings->tiling_at(i);
+ EXPECT_EQ(
+ tiling->GetCurrentVisibleRectForTesting(),
+ gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority_in_view_space,
+ tiling->contents_scale()));
+ }
+
+ // Update tiles with viewport for tile priority as (200, 200, 100, 100) in
+ // screen space and the transform for tile priority is translated and
+ // 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);
+
+ viewport_rect_for_tile_priority = gfx::Rect(200, 200, 100, 100);
+ transform_for_tile_priority.Translate(100, 100);
+ transform_for_tile_priority.Rotate(45);
+ host_impl_.SetExternalDrawConstraints(transform,
+ viewport,
+ viewport,
+ viewport_rect_for_tile_priority,
+ 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);
+
+ gfx::Transform screen_to_view(gfx::Transform::kSkipInitialization);
+ bool success = transform_for_tile_priority.GetInverse(&screen_to_view);
+ EXPECT_TRUE(success);
+
+ viewport_rect_for_tile_priority_in_view_space =
+ gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
+ screen_to_view, viewport_rect_for_tile_priority));
+
+ // Verify the viewport rect for tile priority is used in PictureLayerImpl.
+ 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);
+ EXPECT_EQ(
+ tiling->GetCurrentVisibleRectForTesting(),
+ gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority_in_view_space,
+ tiling->contents_scale()));
+ }
+}
+
+TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
host_impl_.SetCurrentFrameTimeTicks(time_ticks);
gfx::Size tile_size(100, 100);
Region invalidation;
AddDefaultTilingsWithInvalidation(invalidation);
- float dummy_contents_scale_x;
- float dummy_contents_scale_y;
- gfx::Size dummy_content_bounds;
- active_layer_->CalculateContentsScale(1.f,
- 1.f,
- 1.f,
- false,
- &dummy_contents_scale_x,
- &dummy_contents_scale_y,
- &dummy_content_bounds);
-
- EXPECT_TRUE(host_impl_.manage_tiles_needed());
- active_layer_->UpdateTilePriorities();
- host_impl_.ManageTiles();
- EXPECT_FALSE(host_impl_.manage_tiles_needed());
-
+ 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;
+ host_impl_.SetExternalDrawConstraints(transform,
+ viewport,
+ viewport,
+ viewport,
+ transform,
+ resourceless_software_draw);
+ active_layer_->draw_properties().visible_content_rect = viewport;
+ active_layer_->draw_properties().screen_space_transform = transform;
+ active_layer_->UpdateTiles(NULL);
+
+ gfx::Rect visible_rect_for_tile_priority =
+ active_layer_->visible_rect_for_tile_priority();
+ EXPECT_FALSE(visible_rect_for_tile_priority.IsEmpty());
+ gfx::Rect viewport_rect_for_tile_priority =
+ active_layer_->viewport_rect_for_tile_priority();
+ EXPECT_FALSE(viewport_rect_for_tile_priority.IsEmpty());
+ 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.
time_ticks += base::TimeDelta::FromMilliseconds(200);
host_impl_.SetCurrentFrameTimeTicks(time_ticks);
-
- // Setting this boolean should cause an early out in UpdateTilePriorities.
- bool valid_for_tile_management = false;
- host_impl_.SetExternalDrawConstraints(gfx::Transform(),
- gfx::Rect(layer_bounds),
- gfx::Rect(layer_bounds),
- valid_for_tile_management);
- active_layer_->UpdateTilePriorities();
- EXPECT_FALSE(host_impl_.manage_tiles_needed());
-
+ resourceless_software_draw = true;
+ viewport = gfx::ScaleToEnclosingRect(viewport, 2);
+ transform.Translate(1.f, 1.f);
+ active_layer_->draw_properties().visible_content_rect = viewport;
+ active_layer_->draw_properties().screen_space_transform = transform;
+ host_impl_.SetExternalDrawConstraints(transform,
+ viewport,
+ viewport,
+ viewport,
+ transform,
+ resourceless_software_draw);
+ active_layer_->UpdateTiles(NULL);
+
+ EXPECT_RECT_EQ(visible_rect_for_tile_priority,
+ active_layer_->visible_rect_for_tile_priority());
+ EXPECT_RECT_EQ(viewport_rect_for_tile_priority,
+ active_layer_->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());
- valid_for_tile_management = true;
- host_impl_.SetExternalDrawConstraints(gfx::Transform(),
- gfx::Rect(layer_bounds),
- gfx::Rect(layer_bounds),
- valid_for_tile_management);
- active_layer_->UpdateTilePriorities();
- EXPECT_TRUE(host_impl_.manage_tiles_needed());
+ 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) {
gfx::Rect content_invalidation = gfx::ScaleToEnclosingRect(
layer_invalidation,
tiling->contents_scale());
- for (PictureLayerTiling::CoverageIterator
- iter(tiling,
- tiling->contents_scale(),
- tiling->ContentRect());
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ tiling->contents_scale(),
+ gfx::Rect(tiling->tiling_size()));
iter;
++iter) {
EXPECT_TRUE(*iter);
gfx::Rect active_content_bounds = gfx::ScaleToEnclosingRect(
gfx::Rect(active_layer_bounds),
tiling->contents_scale());
- for (PictureLayerTiling::CoverageIterator
- iter(tiling,
- tiling->contents_scale(),
- tiling->ContentRect());
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ tiling->contents_scale(),
+ gfx::Rect(tiling->tiling_size()));
iter;
++iter) {
EXPECT_TRUE(*iter);
for (size_t i = 0; i < tilings->num_tilings(); ++i) {
const PictureLayerTiling* tiling = tilings->tiling_at(i);
- for (PictureLayerTiling::CoverageIterator
- iter(tiling,
- tiling->contents_scale(),
- tiling->ContentRect());
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ tiling->contents_scale(),
+ gfx::Rect(tiling->tiling_size()));
iter;
++iter) {
EXPECT_FALSE(iter.full_tile_geometry_rect().IsEmpty());
scoped_refptr<FakePicturePileImpl> active_pile =
FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds);
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
-
SetupTrees(pending_pile, active_pile);
- pending_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
}
scoped_refptr<FakePicturePileImpl> active_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
-
SetupTrees(pending_pile, active_pile);
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
EXPECT_LT(low_res_factor, 1.f);
- pending_layer_->CalculateContentsScale(1.3f, // ideal contents scale
- 1.7f, // device scale
- 3.2f, // page cale
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
- ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
- EXPECT_FLOAT_EQ(
- 1.3f,
- pending_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(
- 1.3f * low_res_factor,
- pending_layer_->tilings()->tiling_at(1)->contents_scale());
-
- // If we change the layer's CSS scale factor, then we should not get new
- // tilings.
- pending_layer_->CalculateContentsScale(1.8f, // ideal contents scale
- 1.7f, // device scale
- 3.2f, // page cale
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 6.f, // ideal contents scale
+ 3.f, // device scale
+ 2.f, // page scale
+ 1.f, // maximum animation scale
+ false);
ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
- EXPECT_FLOAT_EQ(
- 1.3f,
- pending_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(
- 1.3f * low_res_factor,
- pending_layer_->tilings()->tiling_at(1)->contents_scale());
+ EXPECT_FLOAT_EQ(6.f,
+ pending_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(6.f * low_res_factor,
+ pending_layer_->tilings()->tiling_at(1)->contents_scale());
// If we change the page scale factor, then we should get new tilings.
- pending_layer_->CalculateContentsScale(1.8f, // ideal contents scale
- 1.7f, // device scale
- 2.2f, // page cale
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 6.6f, // ideal contents scale
+ 3.f, // device scale
+ 2.2f, // page scale
+ 1.f, // maximum animation scale
+ false);
ASSERT_EQ(4u, pending_layer_->tilings()->num_tilings());
- EXPECT_FLOAT_EQ(
- 1.8f,
- pending_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(
- 1.8f * low_res_factor,
- pending_layer_->tilings()->tiling_at(2)->contents_scale());
+ EXPECT_FLOAT_EQ(6.6f,
+ pending_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(6.6f * low_res_factor,
+ pending_layer_->tilings()->tiling_at(2)->contents_scale());
// If we change the device scale factor, then we should get new tilings.
- pending_layer_->CalculateContentsScale(1.9f, // ideal contents scale
- 1.4f, // device scale
- 2.2f, // page cale
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 7.26f, // ideal contents scale
+ 3.3f, // device scale
+ 2.2f, // page scale
+ 1.f, // maximum animation scale
+ false);
ASSERT_EQ(6u, pending_layer_->tilings()->num_tilings());
- EXPECT_FLOAT_EQ(
- 1.9f,
- pending_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(
- 1.9f * low_res_factor,
- pending_layer_->tilings()->tiling_at(3)->contents_scale());
+ EXPECT_FLOAT_EQ(7.26f,
+ pending_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(7.26f * low_res_factor,
+ pending_layer_->tilings()->tiling_at(3)->contents_scale());
// If we change the device scale factor, but end up at the same total scale
// factor somehow, then we don't get new tilings.
- pending_layer_->CalculateContentsScale(1.9f, // ideal contents scale
- 2.2f, // device scale
- 1.4f, // page cale
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 7.26f, // ideal contents scale
+ 2.2f, // device scale
+ 3.3f, // page scale
+ 1.f, // maximum animation scale
+ false);
ASSERT_EQ(6u, pending_layer_->tilings()->num_tilings());
- EXPECT_FLOAT_EQ(
- 1.9f,
- pending_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(
- 1.9f * low_res_factor,
- pending_layer_->tilings()->tiling_at(3)->contents_scale());
+ EXPECT_FLOAT_EQ(7.26f,
+ pending_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(7.26f * low_res_factor,
+ pending_layer_->tilings()->tiling_at(3)->contents_scale());
}
TEST_F(PictureLayerImplTest, CreateTilingsEvenIfTwinHasNone) {
float low_res_scale = high_res_scale * low_res_factor;
float device_scale = 1.7f;
float page_scale = 3.2f;
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
+ float maximum_animation_scale = 1.f;
SetupPendingTree(valid_pile);
- pending_layer_->CalculateContentsScale(high_res_scale,
- device_scale,
- page_scale,
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ high_res_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ false);
ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
EXPECT_FLOAT_EQ(high_res_scale,
pending_layer_->HighResTiling()->contents_scale());
ActivateTree();
SetupPendingTree(empty_pile);
- pending_layer_->CalculateContentsScale(high_res_scale,
- device_scale,
- page_scale,
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ EXPECT_FALSE(pending_layer_->CanHaveTilings());
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ high_res_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ false);
ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
ASSERT_EQ(0u, pending_layer_->tilings()->num_tilings());
ActivateTree();
- active_layer_->CalculateContentsScale(high_res_scale,
- device_scale,
- page_scale,
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ EXPECT_FALSE(active_layer_->CanHaveTilings());
+ SetupDrawPropertiesAndUpdateTiles(active_layer_,
+ high_res_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ false);
ASSERT_EQ(0u, active_layer_->tilings()->num_tilings());
SetupPendingTree(valid_pile);
- pending_layer_->CalculateContentsScale(high_res_scale,
- device_scale,
- page_scale,
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ high_res_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ false);
ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
ASSERT_EQ(0u, active_layer_->tilings()->num_tilings());
EXPECT_FLOAT_EQ(high_res_scale,
SetupTrees(pending_pile, active_pile);
EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
- SetContentsScaleOnBothLayers(32.0f, 1.0f, 32.0f, false);
+ SetContentsScaleOnBothLayers(32.0f, 1.0f, 32.0f, 1.0f, false);
host_impl_.PinchGestureBegin();
- SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, false);
- SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, false);
+ SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, 1.0f, false);
+ SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, 1.0f, false);
EXPECT_EQ(active_layer_->tilings()->NumHighResTilings(), 1);
}
// Set up the high and low res tilings before pinch zoom.
SetupTrees(pending_pile, active_pile);
EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
- SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, false);
+ SetContentsScaleOnBothLayers(2.0f, 1.0f, 1.0f, 1.0f, false);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
EXPECT_EQ(2u, active_layer_->tilings()->num_tilings());
- EXPECT_FLOAT_EQ(
- 1.0f,
- active_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(
- 1.0f * low_res_factor,
- active_layer_->tilings()->tiling_at(1)->contents_scale());
+ EXPECT_FLOAT_EQ(2.0f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(2.0f * low_res_factor,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
// Start a pinch gesture.
host_impl_.PinchGestureBegin();
// Zoom out by a small amount. We should create a tiling at half
- // the scale (1/kMaxScaleRatioDuringPinch).
- SetContentsScaleOnBothLayers(0.90f, 1.0f, 0.9f, false);
+ // the scale (2/kMaxScaleRatioDuringPinch).
+ SetContentsScaleOnBothLayers(1.8f, 1.0f, 0.9f, 1.0f, false);
EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
- EXPECT_FLOAT_EQ(
- 1.0f,
- active_layer_->tilings()->tiling_at(0)->contents_scale());
- EXPECT_FLOAT_EQ(
- 0.5f,
- active_layer_->tilings()->tiling_at(1)->contents_scale());
- EXPECT_FLOAT_EQ(
- 1.0f * low_res_factor,
- active_layer_->tilings()->tiling_at(2)->contents_scale());
+ EXPECT_FLOAT_EQ(2.0f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(1.0f,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
+ EXPECT_FLOAT_EQ(2.0f * low_res_factor,
+ active_layer_->tilings()->tiling_at(2)->contents_scale());
// Zoom out further, close to our low-res scale factor. We should
// use that tiling as high-res, and not create a new tiling.
- SetContentsScaleOnBothLayers(low_res_factor, 1.0f, low_res_factor, false);
+ SetContentsScaleOnBothLayers(
+ low_res_factor, 1.0f, low_res_factor / 2.0f, 1.0f, false);
EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
// Zoom in a lot now. Since we increase by increments of
- // kMaxScaleRatioDuringPinch, this will first use 0.5, then 1.0
- // and then finally create a new tiling at 2.0.
- SetContentsScaleOnBothLayers(2.1f, 1.0f, 2.1f, false);
+ // kMaxScaleRatioDuringPinch, this will first use 1.0, then 2.0
+ // and then finally create a new tiling at 4.0.
+ SetContentsScaleOnBothLayers(4.2f, 1.0f, 2.1f, 1.f, false);
EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
- SetContentsScaleOnBothLayers(2.1f, 1.0f, 2.1f, false);
+ SetContentsScaleOnBothLayers(4.2f, 1.0f, 2.1f, 1.f, false);
EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
- SetContentsScaleOnBothLayers(2.1f, 1.0f, 2.1f, false);
+ SetContentsScaleOnBothLayers(4.2f, 1.0f, 2.1f, 1.f, false);
EXPECT_EQ(4u, active_layer_->tilings()->num_tilings());
- EXPECT_FLOAT_EQ(
- 2.0f,
- active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(4.0f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+}
+
+TEST_F(PictureLayerImplTest, SnappedTilingDuringZoom) {
+ gfx::Size tile_size(300, 300);
+ gfx::Size layer_bounds(2600, 3800);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakePicturePileImpl> active_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+ // Set up the high and low res tilings before pinch zoom.
+ SetupTrees(pending_pile, active_pile);
+ EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+ SetContentsScaleOnBothLayers(0.24f, 1.0f, 0.24f, 1.0f, false);
+ EXPECT_EQ(2u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(0.24f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(0.0625f,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
+
+ // Start a pinch gesture.
+ host_impl_.PinchGestureBegin();
+
+ // Zoom out by a small amount. We should create a tiling at half
+ // the scale (1/kMaxScaleRatioDuringPinch).
+ SetContentsScaleOnBothLayers(0.2f, 1.0f, 0.2f, 1.0f, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(0.24f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(0.12f,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
+ EXPECT_FLOAT_EQ(0.0625,
+ active_layer_->tilings()->tiling_at(2)->contents_scale());
+
+ // Zoom out further, close to our low-res scale factor. We should
+ // use that tiling as high-res, and not create a new tiling.
+ SetContentsScaleOnBothLayers(0.1f, 1.0f, 0.1f, 1.0f, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+
+ // Zoom in. 0.125(desired_scale) should be snapped to 0.12 during zoom-in
+ // because 0.125(desired_scale) is within the ratio(1.2)
+ SetContentsScaleOnBothLayers(0.5f, 1.0f, 0.5f, 1.0f, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
}
TEST_F(PictureLayerImplTest, CleanUpTilings) {
scoped_refptr<FakePicturePileImpl> active_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
std::vector<PictureLayerTiling*> used_tilings;
SetupTrees(pending_pile, active_pile);
float device_scale = 1.7f;
float page_scale = 3.2f;
+ float scale = 1.f;
- SetContentsScaleOnBothLayers(1.f, device_scale, page_scale, false);
+ SetContentsScaleOnBothLayers(scale, device_scale, page_scale, 1.f, false);
ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
// We only have ideal tilings, so they aren't removed.
active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+ host_impl_.PinchGestureBegin();
+
// Changing the ideal but not creating new tilings.
- SetContentsScaleOnBothLayers(1.5f, device_scale, page_scale, false);
+ scale *= 1.5f;
+ page_scale *= 1.5f;
+ SetContentsScaleOnBothLayers(scale, device_scale, page_scale, 1.f, false);
ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
// The tilings are still our target scale, so they aren't removed.
active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+ host_impl_.PinchGestureEnd();
+
// Create a 1.2 scale tiling. Now we have 1.0 and 1.2 tilings. Ideal = 1.2.
- page_scale = 1.2f;
- SetContentsScaleOnBothLayers(1.2f, device_scale, page_scale, false);
+ scale /= 4.f;
+ page_scale /= 4.f;
+ SetContentsScaleOnBothLayers(1.2f, device_scale, page_scale, 1.f, false);
ASSERT_EQ(4u, active_layer_->tilings()->num_tilings());
EXPECT_FLOAT_EQ(
1.f,
ASSERT_EQ(4u, active_layer_->tilings()->num_tilings());
// Now move the ideal scale to 0.5. Our target stays 1.2.
- SetContentsScaleOnBothLayers(0.5f, device_scale, page_scale, false);
+ SetContentsScaleOnBothLayers(0.5f, device_scale, page_scale, 1.f, false);
// The high resolution tiling is between target and ideal, so is not
// removed. The low res tiling for the old ideal=1.0 scale is removed.
ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
// Now move the ideal scale to 1.0. Our target stays 1.2.
- SetContentsScaleOnBothLayers(1.f, device_scale, page_scale, false);
+ SetContentsScaleOnBothLayers(1.f, device_scale, page_scale, 1.f, false);
// All the tilings are between are target and the ideal, so they are not
// removed.
ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
// Now move the ideal scale to 1.1 on the active layer. Our target stays 1.2.
- active_layer_->CalculateContentsScale(1.1f,
- device_scale,
- page_scale,
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(
+ active_layer_, 1.1f, device_scale, page_scale, 1.f, false);
// Because the pending layer's ideal scale is still 1.0, our tilings fall
// in the range [1.0,1.2] and are kept.
// Move the ideal scale on the pending layer to 1.1 as well. Our target stays
// 1.2 still.
- pending_layer_->CalculateContentsScale(1.1f,
- device_scale,
- page_scale,
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(
+ pending_layer_, 1.1f, device_scale, page_scale, 1.f, false);
// Our 1.0 tiling now falls outside the range between our ideal scale and our
// target raster scale. But it is in our used tilings set, so nothing is
#define EXPECT_BOTH_EQ(expression, x) \
do { \
- EXPECT_EQ(pending_layer_->expression, x); \
- EXPECT_EQ(active_layer_->expression, x); \
+ EXPECT_EQ(x, pending_layer_->expression); \
+ EXPECT_EQ(x, active_layer_->expression); \
+ } while (false)
+
+#define EXPECT_BOTH_NE(expression, x) \
+ do { \
+ EXPECT_NE(x, pending_layer_->expression); \
+ EXPECT_NE(x, active_layer_->expression); \
} while (false)
TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) {
float contents_scale = 1.f;
float device_scale = 1.f;
float page_scale = 1.f;
+ float maximum_animation_scale = 1.f;
bool animating_transform = true;
// Animating, so don't create low res even if there isn't one already.
- SetContentsScaleOnBothLayers(
- contents_scale, device_scale, page_scale, animating_transform);
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
EXPECT_BOTH_EQ(num_tilings(), 1u);
// Stop animating, low res gets created.
animating_transform = false;
- SetContentsScaleOnBothLayers(
- contents_scale, device_scale, page_scale, animating_transform);
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
EXPECT_BOTH_EQ(LowResTiling()->contents_scale(), low_res_factor);
EXPECT_BOTH_EQ(num_tilings(), 2u);
contents_scale = 2.f;
page_scale = 2.f;
animating_transform = true;
- SetContentsScaleOnBothLayers(
- contents_scale, device_scale, page_scale, animating_transform);
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
EXPECT_BOTH_EQ(LowResTiling()->contents_scale(), low_res_factor);
EXPECT_BOTH_EQ(num_tilings(), 3u);
// Stop animating, new low res gets created for final page scale.
animating_transform = false;
- SetContentsScaleOnBothLayers(
- contents_scale, device_scale, page_scale, animating_transform);
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
EXPECT_BOTH_EQ(LowResTiling()->contents_scale(), 2.f * low_res_factor);
EXPECT_BOTH_EQ(num_tilings(), 4u);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
float device_scale = 1.f;
float page_scale = 1.f;
+ float maximum_animation_scale = 1.f;
bool animating_transform = false;
// Contents exactly fit on one tile at scale 1, no low res.
float contents_scale = 1.f;
- SetContentsScaleOnBothLayers(
- contents_scale, device_scale, page_scale, animating_transform);
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale);
EXPECT_BOTH_EQ(num_tilings(), 1u);
// Contents that are smaller than one tile, no low res.
contents_scale = 0.123f;
- SetContentsScaleOnBothLayers(
- contents_scale, device_scale, page_scale, animating_transform);
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale);
EXPECT_BOTH_EQ(num_tilings(), 1u);
// Any content bounds that would create more than one tile will
// generate a low res tiling.
contents_scale = 2.5f;
- SetContentsScaleOnBothLayers(
- contents_scale, device_scale, page_scale, animating_transform);
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale);
EXPECT_BOTH_EQ(LowResTiling()->contents_scale(),
contents_scale * low_res_factor);
ResetTilingsAndRasterScales();
// Mask layers dont create low res since they always fit on one tile.
- pending_layer_->SetIsMask(true);
- active_layer_->SetIsMask(true);
- SetContentsScaleOnBothLayers(
- contents_scale, device_scale, page_scale, animating_transform);
+ pending_layer_->pile()->set_is_mask(true);
+ active_layer_->pile()->set_is_mask(true);
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale);
EXPECT_BOTH_EQ(num_tilings(), 1u);
}
+TEST_F(PictureLayerImplTest, HugeMasksDontGetTiles) {
+ gfx::Size tile_size(100, 100);
+
+ scoped_refptr<FakePicturePileImpl> valid_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(1000, 1000));
+ valid_pile->set_is_mask(true);
+ SetupPendingTree(valid_pile);
+
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
+ EXPECT_EQ(1.f, pending_layer_->HighResTiling()->contents_scale());
+ EXPECT_EQ(1u, pending_layer_->num_tilings());
+
+ pending_layer_->HighResTiling()->CreateAllTilesForTesting();
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(
+ pending_layer_->HighResTiling()->AllTilesForTesting());
+
+ ActivateTree();
+
+ // Mask layers have a tiling with a single tile in it.
+ EXPECT_EQ(1u, active_layer_->HighResTiling()->AllTilesForTesting().size());
+ // The mask resource exists.
+ EXPECT_NE(0u, active_layer_->ContentsResourceId());
+
+ // Resize larger than the max texture size.
+ int max_texture_size = host_impl_.GetRendererCapabilities().max_texture_size;
+ scoped_refptr<FakePicturePileImpl> huge_pile =
+ FakePicturePileImpl::CreateFilledPile(
+ tile_size, gfx::Size(max_texture_size + 1, 10));
+ huge_pile->set_is_mask(true);
+ SetupPendingTree(huge_pile);
+
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
+ EXPECT_EQ(1.f, pending_layer_->HighResTiling()->contents_scale());
+ EXPECT_EQ(1u, pending_layer_->num_tilings());
+
+ pending_layer_->HighResTiling()->CreateAllTilesForTesting();
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(
+ pending_layer_->HighResTiling()->AllTilesForTesting());
+
+ ActivateTree();
+
+ // Mask layers have a tiling, but there should be no tiles in it.
+ EXPECT_EQ(0u, active_layer_->HighResTiling()->AllTilesForTesting().size());
+ // The mask resource is empty.
+ EXPECT_EQ(0u, active_layer_->ContentsResourceId());
+}
+
TEST_F(PictureLayerImplTest, ReleaseResources) {
gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
scoped_refptr<FakePicturePileImpl> active_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
-
SetupTrees(pending_pile, active_pile);
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
- pending_layer_->CalculateContentsScale(1.3f, // ideal contents scale
- 2.7f, // device scale
- 3.2f, // page cale
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 1.3f, // ideal contents scale
+ 2.7f, // device scale
+ 3.2f, // page scale
+ 1.f, // maximum animation scale
+ false);
EXPECT_EQ(2u, pending_layer_->tilings()->num_tilings());
// All tilings should be removed when losing output surface.
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
// This should create new tilings.
- pending_layer_->CalculateContentsScale(1.3f, // ideal contents scale
- 2.7f, // device scale
- 3.2f, // page cale
- false,
- &result_scale_x,
- &result_scale_y,
- &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 1.3f, // ideal contents scale
+ 2.7f, // device scale
+ 3.2f, // page scale
+ 1.f, // maximum animation scale
+ false);
EXPECT_EQ(2u, pending_layer_->tilings()->num_tilings());
}
scoped_refptr<FakePicturePileImpl> active_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
-
SetupTrees(pending_pile, active_pile);
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
- pending_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
pending_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting();
host_impl_.InitializeRenderer(FakeOutputSurface::Create3d(
context.Pass()).PassAs<OutputSurface>());
- pending_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
pending_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting();
scoped_refptr<FakePicturePileImpl> active_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
-
SetupTrees(pending_pile, active_pile);
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
- pending_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
ASSERT_LE(1u, pending_layer_->tilings()->num_tilings());
pending_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting();
host_impl_.InitializeRenderer(FakeOutputSurface::Create3d(
context.Pass()).PassAs<OutputSurface>());
- pending_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
ASSERT_LE(1u, pending_layer_->tilings()->num_tilings());
pending_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting();
}
TEST_F(PictureLayerImplTest, DisallowTileDrawQuads) {
- MockQuadCuller quad_culler;
+ MockOcclusionTracker<LayerImpl> occlusion_tracker;
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
SetupTrees(pending_pile, active_pile);
- active_layer_->SetContentBounds(layer_bounds);
active_layer_->draw_properties().visible_content_rect =
gfx::Rect(layer_bounds);
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE, NULL);
- active_layer_->AppendQuads(&quad_culler, &data);
+ active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
active_layer_->DidDraw(NULL);
- ASSERT_EQ(1U, quad_culler.quad_list().size());
- EXPECT_EQ(DrawQuad::PICTURE_CONTENT, quad_culler.quad_list()[0]->material);
+ ASSERT_EQ(1U, render_pass->quad_list.size());
+ EXPECT_EQ(DrawQuad::PICTURE_CONTENT, render_pass->quad_list[0]->material);
}
TEST_F(PictureLayerImplTest, MarkRequiredNullTiles) {
EXPECT_GT(num_offscreen, 0);
}
+TEST_F(PictureLayerImplTest, TileOutsideOfViewportForTilePriorityNotRequired) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(400, 400);
+ gfx::Rect external_viewport_for_tile_priority(400, 200);
+ gfx::Rect visible_content_rect(200, 400);
+
+ scoped_refptr<FakePicturePileImpl> active_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ SetupTrees(pending_pile, active_pile);
+
+ active_layer_->set_fixed_tile_size(tile_size);
+ pending_layer_->set_fixed_tile_size(tile_size);
+ ASSERT_TRUE(pending_layer_->CanHaveTilings());
+ PictureLayerTiling* tiling = pending_layer_->AddTiling(1.f);
+
+ // Set external viewport for tile priority.
+ gfx::Rect viewport = gfx::Rect(layer_bounds);
+ gfx::Transform transform;
+ gfx::Transform transform_for_tile_priority;
+ bool resourceless_software_draw = false;
+ host_impl_.SetExternalDrawConstraints(transform,
+ viewport,
+ viewport,
+ external_viewport_for_tile_priority,
+ transform_for_tile_priority,
+ resourceless_software_draw);
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ // Set visible content rect that is different from
+ // 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);
+
+ pending_layer_->MarkVisibleResourcesAsRequired();
+
+ // Intersect the two rects. Any tile outside should not be required for
+ // activation.
+ gfx::Rect viewport_for_tile_priority =
+ pending_layer_->GetViewportForTilePriorityInContentSpace();
+ viewport_for_tile_priority.Intersect(pending_layer_->visible_content_rect());
+
+ int num_inside = 0;
+ int num_outside = 0;
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling, pending_layer_->contents_scale_x(), gfx::Rect(layer_bounds));
+ iter;
+ ++iter) {
+ if (!*iter)
+ continue;
+ Tile* tile = *iter;
+ if (viewport_for_tile_priority.Intersects(iter.geometry_rect())) {
+ num_inside++;
+ // Mark everything in viewport for tile priority as ready to draw.
+ ManagedTileState::TileVersion& tile_version =
+ tile->GetTileVersionForTesting(
+ tile->DetermineRasterModeForTree(PENDING_TREE));
+ tile_version.SetSolidColorForTesting(SK_ColorRED);
+ } else {
+ num_outside++;
+ EXPECT_FALSE(tile->required_for_activation());
+ }
+ }
+
+ EXPECT_GT(num_inside, 0);
+ EXPECT_GT(num_outside, 0);
+
+ // Activate and draw active layer.
+ host_impl_.ActivateSyncTree();
+ host_impl_.active_tree()->UpdateDrawProperties();
+ active_layer_->draw_properties().visible_content_rect = visible_content_rect;
+
+ 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 tiles in activation rect is ready to draw.
+ 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);
AssertNoTilesRequired(pending_layer_->LowResTiling());
}
+TEST_F(PictureLayerImplTest, HighResRequiredWhenActiveHasDifferentBounds) {
+ gfx::Size layer_bounds(200, 200);
+ gfx::Size tile_size(100, 100);
+ SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
+
+ gfx::Size pending_layer_bounds(400, 400);
+ pending_layer_->SetBounds(pending_layer_bounds);
+
+ CreateHighLowResAndSetAllTilesVisible();
+
+ active_layer_->SetAllTilesReady();
+
+ // Since the active layer has different bounds, the pending layer needs all
+ // high res tiles in order to activate.
+ pending_layer_->MarkVisibleResourcesAsRequired();
+ AssertAllTilesRequired(pending_layer_->HighResTiling());
+ AssertNoTilesRequired(pending_layer_->LowResTiling());
+}
+
TEST_F(PictureLayerImplTest, ActivateUninitializedLayer) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
// by a sync from the active layer. This could happen because if the
// pending layer has not been post-commit initialized it will attempt
// to sync from the active layer.
- bool default_lcd_text_setting = pending_layer_->is_using_lcd_text();
- pending_layer_->force_set_lcd_text(!default_lcd_text_setting);
+ float raster_page_scale = 10.f * pending_layer_->raster_page_scale();
+ pending_layer_->set_raster_page_scale(raster_page_scale);
EXPECT_TRUE(pending_layer_->needs_post_commit_initialization());
- host_impl_.ActivatePendingTree();
+ host_impl_.ActivateSyncTree();
active_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.active_tree()->LayerById(id_));
EXPECT_EQ(0u, active_layer_->num_tilings());
- EXPECT_EQ(!default_lcd_text_setting, active_layer_->is_using_lcd_text());
+ EXPECT_EQ(raster_page_scale, active_layer_->raster_page_scale());
EXPECT_FALSE(active_layer_->needs_post_commit_initialization());
}
+TEST_F(PictureLayerImplTest, ShareTilesOnSync) {
+ SetupDefaultTrees(gfx::Size(1500, 1500));
+ AddDefaultTilingsWithInvalidation(gfx::Rect());
+
+ host_impl_.ActivateSyncTree();
+ host_impl_.CreatePendingTree();
+ active_layer_ = static_cast<FakePictureLayerImpl*>(
+ host_impl_.active_tree()->LayerById(id_));
+
+ // Force the active tree to sync to the pending tree "post-commit".
+ pending_layer_->DoPostCommitInitializationIfNeeded();
+
+ // Both invalidations should drop tiles from the pending tree.
+ EXPECT_EQ(3u, active_layer_->num_tilings());
+ EXPECT_EQ(3u, pending_layer_->num_tilings());
+ for (size_t i = 0; i < active_layer_->num_tilings(); ++i) {
+ PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(i);
+ PictureLayerTiling* pending_tiling =
+ pending_layer_->tilings()->tiling_at(i);
+
+ ASSERT_TRUE(active_tiling);
+ ASSERT_TRUE(pending_tiling);
+
+ EXPECT_TRUE(active_tiling->TileAt(0, 0));
+ EXPECT_TRUE(active_tiling->TileAt(1, 0));
+ EXPECT_TRUE(active_tiling->TileAt(0, 1));
+ EXPECT_TRUE(active_tiling->TileAt(1, 1));
+
+ EXPECT_TRUE(pending_tiling->TileAt(0, 0));
+ EXPECT_TRUE(pending_tiling->TileAt(1, 0));
+ EXPECT_TRUE(pending_tiling->TileAt(0, 1));
+ EXPECT_TRUE(pending_tiling->TileAt(1, 1));
+
+ EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
+ EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
+ EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
+ EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
+ }
+}
+
+TEST_F(PictureLayerImplTest, ShareInvalidActiveTreeTilesOnSync) {
+ SetupDefaultTrees(gfx::Size(1500, 1500));
+ AddDefaultTilingsWithInvalidation(gfx::Rect(0, 0, 1, 1));
+
+ // This activates the 0,0,1,1 invalidation.
+ host_impl_.ActivateSyncTree();
+ host_impl_.CreatePendingTree();
+ active_layer_ = static_cast<FakePictureLayerImpl*>(
+ host_impl_.active_tree()->LayerById(id_));
+
+ // Force the active tree to sync to the pending tree "post-commit".
+ pending_layer_->DoPostCommitInitializationIfNeeded();
+
+ // The active tree invalidation was handled by the active tiles, so they
+ // can be shared with the pending tree.
+ EXPECT_EQ(3u, active_layer_->num_tilings());
+ EXPECT_EQ(3u, pending_layer_->num_tilings());
+ for (size_t i = 0; i < active_layer_->num_tilings(); ++i) {
+ PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(i);
+ PictureLayerTiling* pending_tiling =
+ pending_layer_->tilings()->tiling_at(i);
+
+ ASSERT_TRUE(active_tiling);
+ ASSERT_TRUE(pending_tiling);
+
+ EXPECT_TRUE(active_tiling->TileAt(0, 0));
+ EXPECT_TRUE(active_tiling->TileAt(1, 0));
+ EXPECT_TRUE(active_tiling->TileAt(0, 1));
+ EXPECT_TRUE(active_tiling->TileAt(1, 1));
+
+ EXPECT_TRUE(pending_tiling->TileAt(0, 0));
+ EXPECT_TRUE(pending_tiling->TileAt(1, 0));
+ EXPECT_TRUE(pending_tiling->TileAt(0, 1));
+ EXPECT_TRUE(pending_tiling->TileAt(1, 1));
+
+ EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
+ EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
+ EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
+ EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
+ }
+}
+
+TEST_F(PictureLayerImplTest, RemoveInvalidPendingTreeTilesOnSync) {
+ SetupDefaultTrees(gfx::Size(1500, 1500));
+ AddDefaultTilingsWithInvalidation(gfx::Rect());
+
+ host_impl_.ActivateSyncTree();
+ host_impl_.CreatePendingTree();
+ active_layer_ = static_cast<FakePictureLayerImpl*>(
+ host_impl_.active_tree()->LayerById(id_));
+
+ // Set some invalidation on the pending tree "during commit". We should
+ // replace raster tiles that touch this.
+ pending_layer_->set_invalidation(gfx::Rect(1, 1));
+
+ // Force the active tree to sync to the pending tree "post-commit".
+ pending_layer_->DoPostCommitInitializationIfNeeded();
+
+ // The pending tree invalidation means tiles can not be shared with the
+ // active tree.
+ EXPECT_EQ(3u, active_layer_->num_tilings());
+ EXPECT_EQ(3u, pending_layer_->num_tilings());
+ for (size_t i = 0; i < active_layer_->num_tilings(); ++i) {
+ PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(i);
+ PictureLayerTiling* pending_tiling =
+ pending_layer_->tilings()->tiling_at(i);
+
+ ASSERT_TRUE(active_tiling);
+ ASSERT_TRUE(pending_tiling);
+
+ EXPECT_TRUE(active_tiling->TileAt(0, 0));
+ EXPECT_TRUE(active_tiling->TileAt(1, 0));
+ EXPECT_TRUE(active_tiling->TileAt(0, 1));
+ EXPECT_TRUE(active_tiling->TileAt(1, 1));
+
+ EXPECT_TRUE(pending_tiling->TileAt(0, 0));
+ EXPECT_TRUE(pending_tiling->TileAt(1, 0));
+ EXPECT_TRUE(pending_tiling->TileAt(0, 1));
+ EXPECT_TRUE(pending_tiling->TileAt(1, 1));
+
+ EXPECT_NE(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
+ EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
+ EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
+ EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
+ }
+}
+
TEST_F(PictureLayerImplTest, SyncTilingAfterReleaseResource) {
SetupDefaultTrees(gfx::Size(10, 10));
host_impl_.active_tree()->UpdateDrawProperties();
// Contrived unit test of a real crash. A layer is transparent during a
// context loss, and later becomes opaque, causing active layer SyncTiling to
// be called.
- const float tile_scale = 2.f;
+ float new_scale = 1.f;
active_layer_->ReleaseResources();
- EXPECT_FALSE(active_layer_->tilings()->TilingAtScale(tile_scale));
- pending_layer_->AddTiling(2.f);
- EXPECT_TRUE(active_layer_->tilings()->TilingAtScale(tile_scale));
+ pending_layer_->ReleaseResources();
+ EXPECT_FALSE(active_layer_->tilings()->TilingAtScale(new_scale));
+ pending_layer_->AddTiling(new_scale);
+ EXPECT_TRUE(active_layer_->tilings()->TilingAtScale(new_scale));
+
+ // UpdateDrawProperties early-outs if the tree doesn't need it. It is also
+ // responsible for calling ManageTilings. These checks verify that
+ // ReleaseResources has set needs update draw properties so that the
+ // new tiling gets the appropriate resolution set in ManageTilings.
+ EXPECT_TRUE(host_impl_.active_tree()->needs_update_draw_properties());
+ host_impl_.active_tree()->UpdateDrawProperties();
+ PictureLayerTiling* high_res =
+ active_layer_->tilings()->TilingAtScale(new_scale);
+ ASSERT_TRUE(!!high_res);
+ EXPECT_EQ(HIGH_RESOLUTION, high_res->resolution());
+}
+
+TEST_F(PictureLayerImplTest, SyncTilingAfterGpuRasterizationToggles) {
+ SetupDefaultTrees(gfx::Size(10, 10));
+
+ const float kScale = 1.f;
+ pending_layer_->AddTiling(kScale);
+ EXPECT_TRUE(pending_layer_->tilings()->TilingAtScale(kScale));
+ EXPECT_TRUE(active_layer_->tilings()->TilingAtScale(kScale));
+
+ // Gpu rasterization is disabled by default.
+ EXPECT_FALSE(host_impl_.use_gpu_rasterization());
+ // Toggling the gpu rasterization clears all tilings on both trees.
+ host_impl_.SetUseGpuRasterization(true);
+ EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
+ EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+
+ // Make sure that we can still add tiling to the pending layer,
+ // that gets synced to the active layer.
+ pending_layer_->AddTiling(kScale);
+ EXPECT_TRUE(pending_layer_->tilings()->TilingAtScale(kScale));
+ EXPECT_TRUE(active_layer_->tilings()->TilingAtScale(kScale));
+
+ // Toggling the gpu rasterization clears all tilings on both trees.
+ EXPECT_TRUE(host_impl_.use_gpu_rasterization());
+ host_impl_.SetUseGpuRasterization(false);
+ EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
+ EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+}
+
+TEST_F(PictureLayerImplTest, HighResCreatedWhenBoundsShrink) {
+ SetupDefaultTrees(gfx::Size(10, 10));
+ host_impl_.active_tree()->UpdateDrawProperties();
+ EXPECT_FALSE(host_impl_.active_tree()->needs_update_draw_properties());
+
+ SetupDrawPropertiesAndUpdateTiles(
+ active_layer_, 0.5f, 0.5f, 0.5f, 0.5f, false);
+ active_layer_->tilings()->RemoveAllTilings();
+ PictureLayerTiling* tiling = active_layer_->tilings()->AddTiling(0.5f);
+ active_layer_->tilings()->AddTiling(1.5f);
+ active_layer_->tilings()->AddTiling(0.25f);
+ tiling->set_resolution(HIGH_RESOLUTION);
+
+ // Sanity checks.
+ ASSERT_EQ(3u, active_layer_->tilings()->num_tilings());
+ ASSERT_EQ(tiling, active_layer_->tilings()->TilingAtScale(0.5f));
+
+ // Now, set the bounds to be 1x1 (so that minimum contents scale becomes
+ // 1.0f). Note that we should also ensure that the pending layer needs post
+ // commit initialization, since this is what would happen during commit. In
+ // other words we want the pending layer to sync from the active layer.
+ pending_layer_->SetBounds(gfx::Size(1, 1));
+ pending_layer_->SetNeedsPostCommitInitialization();
+ pending_layer_->set_twin_layer(NULL);
+ active_layer_->set_twin_layer(NULL);
+ EXPECT_TRUE(pending_layer_->needs_post_commit_initialization());
+
+ // Update the draw properties: sync from active tree should happen here.
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ // Another sanity check.
+ ASSERT_EQ(1.f, pending_layer_->MinimumContentsScale());
+
+ // Now we should've synced 1.5f tiling, since that's the only one that doesn't
+ // violate minimum contents scale. At the same time, we should've created a
+ // new high res tiling at scale 1.0f.
+ EXPECT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ ASSERT_TRUE(pending_layer_->tilings()->TilingAtScale(1.0f));
+ EXPECT_EQ(HIGH_RESOLUTION,
+ pending_layer_->tilings()->TilingAtScale(1.0f)->resolution());
+ ASSERT_TRUE(pending_layer_->tilings()->TilingAtScale(1.5f));
+ EXPECT_EQ(NON_IDEAL_RESOLUTION,
+ pending_layer_->tilings()->TilingAtScale(1.5f)->resolution());
}
-TEST_F(PictureLayerImplTest, TilingWithoutGpuRasterization) {
+TEST_F(PictureLayerImplTest, NoLowResTilingWithGpuRasterization) {
gfx::Size default_tile_size(host_impl_.settings().default_tile_size);
gfx::Size layer_bounds(default_tile_size.width() * 4,
default_tile_size.height() * 4);
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
SetupDefaultTrees(layer_bounds);
- EXPECT_FALSE(pending_layer_->ShouldUseGpuRasterization());
+ EXPECT_FALSE(host_impl_.use_gpu_rasterization());
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
- pending_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
// Should have a low-res and a high-res tiling.
ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+
+ ResetTilingsAndRasterScales();
+
+ host_impl_.SetUseGpuRasterization(true);
+ EXPECT_TRUE(host_impl_.use_gpu_rasterization());
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
+
+ // Should only have the high-res tiling.
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
}
TEST_F(PictureLayerImplTest, NoTilingIfDoesNotDrawContent) {
// Set up layers with tilings.
SetupDefaultTrees(gfx::Size(10, 10));
- SetContentsScaleOnBothLayers(1.f, 1.f, 1.f, false);
+ SetContentsScaleOnBothLayers(1.f, 1.f, 1.f, 1.f, false);
pending_layer_->PushPropertiesTo(active_layer_);
EXPECT_TRUE(pending_layer_->DrawsContent());
EXPECT_TRUE(pending_layer_->CanHaveTilings());
SetupDefaultTrees(gfx::Size(10, 10));
host_impl_.PinchGestureBegin();
float high_res_scale = 2.3f;
- SetContentsScaleOnBothLayers(high_res_scale, 1.f, 1.f, false);
+ SetContentsScaleOnBothLayers(high_res_scale, 1.f, 1.f, 1.f, false);
ASSERT_GE(pending_layer_->num_tilings(), 0u);
EXPECT_FLOAT_EQ(high_res_scale,
float high_res_scale = 0.0001f;
EXPECT_GT(pending_layer_->MinimumContentsScale(), high_res_scale);
- SetContentsScaleOnBothLayers(high_res_scale, 1.f, 1.f, false);
+ SetContentsScaleOnBothLayers(high_res_scale, 1.f, 1.f, 1.f, false);
ASSERT_GE(pending_layer_->num_tilings(), 0u);
EXPECT_FLOAT_EQ(pending_layer_->MinimumContentsScale(),
SetupDefaultTrees(gfx::Size(10, 10));
float contents_scale = 0.15f;
- SetContentsScaleOnBothLayers(contents_scale, 1.f, 1.f, false);
+ SetContentsScaleOnBothLayers(contents_scale, 1.f, 1.f, 1.f, false);
ASSERT_GE(pending_layer_->num_tilings(), 0u);
EXPECT_FLOAT_EQ(contents_scale,
EXPECT_LT(page_scale * contents_scale,
pending_layer_->MinimumContentsScale());
-
- SetContentsScaleOnBothLayers(contents_scale, 1.f, page_scale, false);
+ SetContentsScaleOnBothLayers(contents_scale, 1.f, page_scale, 1.f, false);
ASSERT_GE(pending_layer_->num_tilings(), 0u);
EXPECT_FLOAT_EQ(pending_layer_->MinimumContentsScale(),
pending_layer_->HighResTiling()->contents_scale());
class DeferredInitPictureLayerImplTest : public PictureLayerImplTest {
public:
virtual void InitializeRenderer() OVERRIDE {
- host_impl_.InitializeRenderer(FakeOutputSurface::CreateDeferredGL(
- scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice))
- .PassAs<OutputSurface>());
+ bool delegated_rendering = false;
+ host_impl_.InitializeRenderer(
+ FakeOutputSurface::CreateDeferredGL(
+ scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice),
+ delegated_rendering).PassAs<OutputSurface>());
}
virtual void SetUp() OVERRIDE {
// that trees need update draw properties after deferred initialization.
// However, this is also a regression test for PictureLayerImpl in that
// not having this update will cause a crash.
-TEST_F(DeferredInitPictureLayerImplTest,
- PreventUpdateTilePrioritiesDuringLostContext) {
+TEST_F(DeferredInitPictureLayerImplTest, PreventUpdateTilesDuringLostContext) {
host_impl_.pending_tree()->UpdateDrawProperties();
host_impl_.active_tree()->UpdateDrawProperties();
EXPECT_FALSE(host_impl_.pending_tree()->needs_update_draw_properties());
FakeOutputSurface* fake_output_surface =
static_cast<FakeOutputSurface*>(host_impl_.output_surface());
ASSERT_TRUE(fake_output_surface->InitializeAndSetContext3d(
- TestContextProvider::Create(), NULL));
+ TestContextProvider::Create()));
// These will crash PictureLayerImpl if this is not true.
ASSERT_TRUE(host_impl_.pending_tree()->needs_update_draw_properties());
host_impl_.active_tree()->UpdateDrawProperties();
}
-class HybridRasterizationPictureLayerImplTest : public PictureLayerImplTest {
- public:
- HybridRasterizationPictureLayerImplTest()
- : PictureLayerImplTest(HybridRasterizationSettings()) {}
-};
+TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) {
+ gfx::Size layer_bounds(100, 100);
+ gfx::Size viewport_size(1000, 1000);
+ SetupDefaultTrees(layer_bounds);
+ host_impl_.SetViewportSize(viewport_size);
-TEST_F(HybridRasterizationPictureLayerImplTest, Tiling) {
- gfx::Size default_tile_size(host_impl_.settings().default_tile_size);
- gfx::Size layer_bounds(default_tile_size.width() * 4,
- default_tile_size.height() * 4);
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
+ 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;
- SetupDefaultTrees(layer_bounds);
- EXPECT_FALSE(pending_layer_->ShouldUseGpuRasterization());
- EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
- pending_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
- // Should have a low-res and a high-res tiling.
- ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
- pending_layer_->SetHasGpuRasterizationHint(true);
- EXPECT_TRUE(pending_layer_->ShouldUseGpuRasterization());
- EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
- pending_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
- // Should only have the high-res tiling.
- ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
-}
+ // Since we're CPU-rasterizing, starting an animation should cause tiling
+ // resolution to get set to the maximum animation scale factor.
+ animating_transform = true;
+ maximum_animation_scale = 3.f;
+ contents_scale = 2.f;
-class GpuRasterizationPictureLayerImplTest : public PictureLayerImplTest {
- public:
- GpuRasterizationPictureLayerImplTest()
- : PictureLayerImplTest(GpuRasterizationSettings()) {}
-};
+ 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;
-TEST_F(GpuRasterizationPictureLayerImplTest, Tiling) {
- gfx::Size default_tile_size(host_impl_.settings().default_tile_size);
- gfx::Size layer_bounds(default_tile_size.width() * 4,
- default_tile_size.height() * 4);
- float result_scale_x, result_scale_y;
- gfx::Size result_bounds;
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
- SetupDefaultTrees(layer_bounds);
- pending_layer_->SetHasGpuRasterizationHint(true);
- EXPECT_TRUE(pending_layer_->ShouldUseGpuRasterization());
- EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
- pending_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
- // Should only have the high-res tiling.
- ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
+ // When animating with an unknown maximum animation scale factor, a new
+ // high-res tiling should be created at the animation's initial scale.
+ animating_transform = true;
+ contents_scale = 2.f;
+ maximum_animation_scale = 0.f;
- pending_layer_->SetHasGpuRasterizationHint(false);
- EXPECT_TRUE(pending_layer_->ShouldUseGpuRasterization());
- // Should still have the high-res tiling.
- EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings());
- pending_layer_->CalculateContentsScale(
- 1.f, 1.f, 1.f, false, &result_scale_x, &result_scale_y, &result_bounds);
- // Should still only have the high-res tiling.
- ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
+ 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 not 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(), 2.f);
+
+ // Once we stop animating, a new high-res tiling should be created.
+ animating_transform = false;
+ contents_scale = 4.f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
+
+ // When animating with a maxmium animation scale factor that is so large
+ // that the layer grows larger than the viewport at this scale, a new
+ // high-res tiling should get created at the animation's initial scale, not
+ // at its maximum scale.
+ animating_transform = true;
+ contents_scale = 2.f;
+ maximum_animation_scale = 11.f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
+
+ // Once we stop animating, a new high-res tiling should be created.
+ animating_transform = false;
+ contents_scale = 11.f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 11.f);
+
+ // When animating with a maxmium animation scale factor that is so large
+ // that the layer grows larger than the viewport at this scale, and where
+ // the intial source scale is < 1, a new high-res tiling should get created
+ // at source scale 1.
+ animating_transform = true;
+ contents_scale = 0.1f;
+ maximum_animation_scale = 11.f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), device_scale * page_scale);
+
+ // Once we stop animating, a new high-res tiling should be created.
+ animating_transform = false;
+ contents_scale = 11.f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 11.f);
}
TEST_F(PictureLayerImplTest, LayerRasterTileIterator) {
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+ // Empty iterator
+ PictureLayerImpl::LayerRasterTileIterator it;
+ EXPECT_FALSE(it);
+
+ // No tilings.
+ it = PictureLayerImpl::LayerRasterTileIterator(pending_layer_, false);
+ EXPECT_FALSE(it);
+
pending_layer_->AddTiling(low_res_factor);
pending_layer_->AddTiling(0.3f);
pending_layer_->AddTiling(0.7f);
host_impl_.SetViewportSize(gfx::Size(500, 500));
host_impl_.pending_tree()->UpdateDrawProperties();
- PictureLayerImpl::LayerRasterTileIterator it;
- EXPECT_FALSE(it);
-
std::set<Tile*> unique_tiles;
bool reached_prepaint = false;
size_t non_ideal_tile_count = 0u;
EXPECT_EQ(0u, high_res_tile_count);
}
+TEST_F(PictureLayerImplTest, LayerEvictionTileIterator) {
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(1000, 1000);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+ SetupPendingTree(pending_pile);
+
+ ASSERT_TRUE(pending_layer_->CanHaveTilings());
+
+ float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+
+ std::vector<PictureLayerTiling*> tilings;
+ tilings.push_back(pending_layer_->AddTiling(low_res_factor));
+ tilings.push_back(pending_layer_->AddTiling(0.3f));
+ tilings.push_back(pending_layer_->AddTiling(0.7f));
+ tilings.push_back(pending_layer_->AddTiling(1.0f));
+ tilings.push_back(pending_layer_->AddTiling(2.0f));
+
+ host_impl_.SetViewportSize(gfx::Size(500, 500));
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ std::vector<Tile*> all_tiles;
+ for (std::vector<PictureLayerTiling*>::iterator tiling_iterator =
+ tilings.begin();
+ tiling_iterator != tilings.end();
+ ++tiling_iterator) {
+ std::vector<Tile*> tiles = (*tiling_iterator)->AllTilesForTesting();
+ std::copy(tiles.begin(), tiles.end(), std::back_inserter(all_tiles));
+ }
+
+ std::set<Tile*> all_tiles_set(all_tiles.begin(), all_tiles.end());
+
+ bool mark_required = false;
+ size_t number_of_marked_tiles = 0u;
+ size_t number_of_unmarked_tiles = 0u;
+ for (size_t i = 0; i < tilings.size(); ++i) {
+ PictureLayerTiling* tiling = tilings.at(i);
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ pending_layer_->contents_scale_x(),
+ pending_layer_->visible_content_rect());
+ iter;
+ ++iter) {
+ if (mark_required) {
+ number_of_marked_tiles++;
+ iter->MarkRequiredForActivation();
+ } else {
+ number_of_unmarked_tiles++;
+ }
+ mark_required = !mark_required;
+ }
+ }
+
+ // Sanity checks.
+ EXPECT_EQ(91u, all_tiles.size());
+ EXPECT_EQ(91u, all_tiles_set.size());
+ EXPECT_GT(number_of_marked_tiles, 1u);
+ EXPECT_GT(number_of_unmarked_tiles, 1u);
+
+ // Empty iterator.
+ PictureLayerImpl::LayerEvictionTileIterator it;
+ EXPECT_FALSE(it);
+
+ // Tiles don't have resources yet.
+ it = PictureLayerImpl::LayerEvictionTileIterator(
+ pending_layer_, SAME_PRIORITY_FOR_BOTH_TREES);
+ EXPECT_FALSE(it);
+
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
+
+ std::set<Tile*> unique_tiles;
+ float expected_scales[] = {2.0f, 0.3f, 0.7f, low_res_factor, 1.0f};
+ size_t scale_index = 0;
+ bool reached_visible = false;
+ Tile* last_tile = NULL;
+ for (it = PictureLayerImpl::LayerEvictionTileIterator(
+ pending_layer_, SAME_PRIORITY_FOR_BOTH_TREES);
+ it;
+ ++it) {
+ Tile* tile = *it;
+ if (!last_tile)
+ last_tile = tile;
+
+ EXPECT_TRUE(tile);
+
+ TilePriority priority = tile->priority(PENDING_TREE);
+
+ if (priority.priority_bin == TilePriority::NOW) {
+ reached_visible = true;
+ last_tile = tile;
+ break;
+ }
+
+ EXPECT_FALSE(tile->required_for_activation());
+
+ while (std::abs(tile->contents_scale() - expected_scales[scale_index]) >
+ std::numeric_limits<float>::epsilon()) {
+ ++scale_index;
+ ASSERT_LT(scale_index, arraysize(expected_scales));
+ }
+
+ EXPECT_FLOAT_EQ(tile->contents_scale(), expected_scales[scale_index]);
+ unique_tiles.insert(tile);
+
+ // If the tile is the same rough bin as last tile (same activation, bin, and
+ // scale), then distance should be decreasing.
+ if (tile->required_for_activation() ==
+ last_tile->required_for_activation() &&
+ priority.priority_bin ==
+ last_tile->priority(PENDING_TREE).priority_bin &&
+ std::abs(tile->contents_scale() - last_tile->contents_scale()) <
+ std::numeric_limits<float>::epsilon()) {
+ EXPECT_LE(priority.distance_to_visible,
+ last_tile->priority(PENDING_TREE).distance_to_visible);
+ }
+
+ last_tile = tile;
+ }
+
+ EXPECT_TRUE(reached_visible);
+ EXPECT_EQ(65u, unique_tiles.size());
+
+ scale_index = 0;
+ bool reached_required = false;
+ for (; it; ++it) {
+ Tile* tile = *it;
+ EXPECT_TRUE(tile);
+
+ TilePriority priority = tile->priority(PENDING_TREE);
+ EXPECT_EQ(TilePriority::NOW, priority.priority_bin);
+
+ if (reached_required) {
+ EXPECT_TRUE(tile->required_for_activation());
+ } else if (tile->required_for_activation()) {
+ reached_required = true;
+ scale_index = 0;
+ }
+
+ while (std::abs(tile->contents_scale() - expected_scales[scale_index]) >
+ std::numeric_limits<float>::epsilon()) {
+ ++scale_index;
+ ASSERT_LT(scale_index, arraysize(expected_scales));
+ }
+
+ EXPECT_FLOAT_EQ(tile->contents_scale(), expected_scales[scale_index]);
+ unique_tiles.insert(tile);
+ }
+
+ EXPECT_TRUE(reached_required);
+ EXPECT_EQ(all_tiles_set.size(), unique_tiles.size());
+}
+
+TEST_F(PictureLayerImplTest, Occlusion) {
+ gfx::Size tile_size(102, 102);
+ gfx::Size layer_bounds(1000, 1000);
+ gfx::Size viewport_size(1000, 1000);
+
+ LayerTestCommon::LayerImplTest impl;
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(layer_bounds, layer_bounds);
+ SetupPendingTree(pending_pile);
+ pending_layer_->SetBounds(layer_bounds);
+ ActivateTree();
+ active_layer_->set_fixed_tile_size(tile_size);
+
+ host_impl_.SetViewportSize(viewport_size);
+ host_impl_.active_tree()->UpdateDrawProperties();
+
+ std::vector<Tile*> tiles =
+ active_layer_->HighResTiling()->AllTilesForTesting();
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
+
+ {
+ SCOPED_TRACE("No occlusion");
+ gfx::Rect occluded;
+ impl.AppendQuadsWithOcclusion(active_layer_, occluded);
+
+ LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
+ gfx::Rect(layer_bounds));
+ EXPECT_EQ(100u, impl.quad_list().size());
+ }
+
+ {
+ SCOPED_TRACE("Full occlusion");
+ gfx::Rect occluded(active_layer_->visible_content_rect());
+ impl.AppendQuadsWithOcclusion(active_layer_, occluded);
+
+ LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect());
+ EXPECT_EQ(impl.quad_list().size(), 0u);
+ }
+
+ {
+ SCOPED_TRACE("Partial occlusion");
+ gfx::Rect occluded(150, 0, 200, 1000);
+ impl.AppendQuadsWithOcclusion(active_layer_, occluded);
+
+ size_t partially_occluded_count = 0;
+ LayerTestCommon::VerifyQuadsCoverRectWithOcclusion(
+ impl.quad_list(),
+ gfx::Rect(layer_bounds),
+ 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);
+ }
+}
+
+TEST_F(PictureLayerImplTest, RasterScaleChangeWithoutAnimation) {
+ gfx::Size tile_size(host_impl_.settings().default_tile_size);
+ SetupDefaultTrees(tile_size);
+
+ float contents_scale = 2.f;
+ float device_scale = 1.f;
+ float page_scale = 1.f;
+ 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(), 2.f);
+
+ // Changing the source scale without being in an animation will cause
+ // the layer to reset its source scale to 1.f.
+ contents_scale = 3.f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
+
+ // Further changes to the source scale will no longer be reflected in the
+ // contents scale.
+ contents_scale = 0.5f;
+
+ SetContentsScaleOnBothLayers(contents_scale,
+ device_scale,
+ page_scale,
+ maximum_animation_scale,
+ animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
+}
+
+TEST_F(PictureLayerImplTest, LowResReadyToDrawNotEnoughToActivate) {
+ 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();
+ active_layer_->SetAllTilesReady();
+ pending_layer_->MarkVisibleResourcesAsRequired();
+
+ // All pending layer tiles required are not ready.
+ EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+
+ // Initialize all low-res tiles.
+ pending_layer_->SetAllTilesReadyInTiling(pending_layer_->LowResTiling());
+
+ // Low-res tiles should not be enough.
+ EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+
+ // Initialize remaining tiles.
+ pending_layer_->SetAllTilesReady();
+
+ EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+}
+
+TEST_F(PictureLayerImplTest, HighResReadyToDrawNotEnoughToActivate) {
+ 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();
+ active_layer_->SetAllTilesReady();
+ pending_layer_->MarkVisibleResourcesAsRequired();
+
+ // All pending layer tiles required are not ready.
+ EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+
+ // Initialize all high-res tiles.
+ pending_layer_->SetAllTilesReadyInTiling(pending_layer_->HighResTiling());
+
+ // High-res tiles should not be enough.
+ EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+
+ // Initialize remaining tiles.
+ pending_layer_->SetAllTilesReady();
+
+ EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+}
+
+class NoLowResTilingsSettings : public ImplSidePaintingSettings {
+ public:
+ NoLowResTilingsSettings() { create_low_res_tiling = false; }
+};
+
+class NoLowResPictureLayerImplTest : public PictureLayerImplTest {
+ public:
+ NoLowResPictureLayerImplTest()
+ : PictureLayerImplTest(NoLowResTilingsSettings()) {}
+};
+
+TEST_F(NoLowResPictureLayerImplTest, ManageTilingsCreatesTilings) {
+ gfx::Size tile_size(400, 400);
+ gfx::Size layer_bounds(1300, 1900);
+
+ 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);
+ EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
+
+ float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+ EXPECT_LT(low_res_factor, 1.f);
+
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 6.f, // ideal contents scale
+ 3.f, // device scale
+ 2.f, // page scale
+ 1.f, // maximum animation scale
+ false);
+ ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(6.f,
+ pending_layer_->tilings()->tiling_at(0)->contents_scale());
+
+ // If we change the page scale factor, then we should get new tilings.
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 6.6f, // ideal contents scale
+ 3.f, // device scale
+ 2.2f, // page scale
+ 1.f, // maximum animation scale
+ false);
+ ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(6.6f,
+ pending_layer_->tilings()->tiling_at(0)->contents_scale());
+
+ // If we change the device scale factor, then we should get new tilings.
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 7.26f, // ideal contents scale
+ 3.3f, // device scale
+ 2.2f, // page scale
+ 1.f, // maximum animation scale
+ false);
+ ASSERT_EQ(3u, pending_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(7.26f,
+ pending_layer_->tilings()->tiling_at(0)->contents_scale());
+
+ // If we change the device scale factor, but end up at the same total scale
+ // factor somehow, then we don't get new tilings.
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 7.26f, // ideal contents scale
+ 2.2f, // device scale
+ 3.3f, // page scale
+ 1.f, // maximum animation scale
+ false);
+ ASSERT_EQ(3u, pending_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(7.26f,
+ pending_layer_->tilings()->tiling_at(0)->contents_scale());
+}
+
+TEST_F(NoLowResPictureLayerImplTest, MarkRequiredNullTiles) {
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(1000, 1000);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds);
+ // Layers with entirely empty piles can't get tilings.
+ pending_pile->AddRecordingAt(0, 0);
+
+ SetupPendingTree(pending_pile);
+
+ ASSERT_TRUE(pending_layer_->CanHaveTilings());
+ pending_layer_->AddTiling(1.0f);
+ pending_layer_->AddTiling(2.0f);
+
+ // It should be safe to call this (and MarkVisibleResourcesAsRequired)
+ // on a layer with no recordings.
+ host_impl_.pending_tree()->UpdateDrawProperties();
+ pending_layer_->MarkVisibleResourcesAsRequired();
+}
+
+TEST_F(NoLowResPictureLayerImplTest, NothingRequiredIfAllHighResTilesShared) {
+ gfx::Size layer_bounds(400, 400);
+ gfx::Size tile_size(100, 100);
+ SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
+
+ CreateHighLowResAndSetAllTilesVisible();
+
+ Tile* some_active_tile =
+ active_layer_->HighResTiling()->AllTilesForTesting()[0];
+ EXPECT_FALSE(some_active_tile->IsReadyToDraw());
+
+ // All tiles shared (no invalidation), so even though the active tree's
+ // tiles aren't ready, there is nothing required.
+ pending_layer_->MarkVisibleResourcesAsRequired();
+ AssertNoTilesRequired(pending_layer_->HighResTiling());
+ if (host_impl_.settings().create_low_res_tiling) {
+ AssertNoTilesRequired(pending_layer_->LowResTiling());
+ }
+}
+
+TEST_F(NoLowResPictureLayerImplTest, NothingRequiredIfActiveMissingTiles) {
+ gfx::Size layer_bounds(400, 400);
+ gfx::Size tile_size(100, 100);
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ // This pile will create tilings, but has no recordings so will not create any
+ // tiles. This is attempting to simulate scrolling past the end of recorded
+ // content on the active layer, where the recordings are so far away that
+ // no tiles are created.
+ scoped_refptr<FakePicturePileImpl> active_pile =
+ FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
+ tile_size, layer_bounds);
+ SetupTrees(pending_pile, active_pile);
+ pending_layer_->set_fixed_tile_size(tile_size);
+ active_layer_->set_fixed_tile_size(tile_size);
+
+ CreateHighLowResAndSetAllTilesVisible();
+
+ // Active layer has tilings, but no tiles due to missing recordings.
+ EXPECT_TRUE(active_layer_->CanHaveTilings());
+ EXPECT_EQ(active_layer_->tilings()->num_tilings(),
+ host_impl_.settings().create_low_res_tiling ? 2u : 1u);
+ EXPECT_EQ(active_layer_->HighResTiling()->AllTilesForTesting().size(), 0u);
+
+ // Since the active layer has no tiles at all, the pending layer doesn't
+ // need content in order to activate.
+ pending_layer_->MarkVisibleResourcesAsRequired();
+ AssertNoTilesRequired(pending_layer_->HighResTiling());
+ if (host_impl_.settings().create_low_res_tiling)
+ AssertNoTilesRequired(pending_layer_->LowResTiling());
+}
+
+TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+
+ 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);
+ 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;
+ host_impl_.SetExternalDrawConstraints(transform,
+ viewport,
+ viewport,
+ viewport,
+ transform,
+ resourceless_software_draw);
+ active_layer_->draw_properties().visible_content_rect = viewport;
+ active_layer_->draw_properties().screen_space_transform = transform;
+ active_layer_->UpdateTiles(NULL);
+
+ gfx::Rect visible_rect_for_tile_priority =
+ active_layer_->visible_rect_for_tile_priority();
+ EXPECT_FALSE(visible_rect_for_tile_priority.IsEmpty());
+ gfx::Rect viewport_rect_for_tile_priority =
+ active_layer_->viewport_rect_for_tile_priority();
+ EXPECT_FALSE(viewport_rect_for_tile_priority.IsEmpty());
+ 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.
+ time_ticks += base::TimeDelta::FromMilliseconds(200);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ resourceless_software_draw = true;
+ viewport = gfx::ScaleToEnclosingRect(viewport, 2);
+ transform.Translate(1.f, 1.f);
+ active_layer_->draw_properties().visible_content_rect = viewport;
+ active_layer_->draw_properties().screen_space_transform = transform;
+ host_impl_.SetExternalDrawConstraints(transform,
+ viewport,
+ viewport,
+ viewport,
+ transform,
+ resourceless_software_draw);
+ active_layer_->UpdateTiles(NULL);
+
+ EXPECT_RECT_EQ(visible_rect_for_tile_priority,
+ active_layer_->visible_rect_for_tile_priority());
+ EXPECT_RECT_EQ(viewport_rect_for_tile_priority,
+ active_layer_->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(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) {
+ gfx::Size tile_size(400, 400);
+ gfx::Size layer_bounds(1300, 1900);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakePicturePileImpl> active_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+ std::vector<PictureLayerTiling*> used_tilings;
+
+ SetupTrees(pending_pile, active_pile);
+ EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
+
+ float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+ EXPECT_LT(low_res_factor, 1.f);
+
+ float device_scale = 1.7f;
+ float page_scale = 3.2f;
+ float scale = 1.f;
+
+ SetContentsScaleOnBothLayers(scale, device_scale, page_scale, 1.f, false);
+ ASSERT_EQ(1u, active_layer_->tilings()->num_tilings());
+
+ // We only have ideal tilings, so they aren't removed.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(1u, active_layer_->tilings()->num_tilings());
+
+ host_impl_.PinchGestureBegin();
+
+ // Changing the ideal but not creating new tilings.
+ scale *= 1.5f;
+ page_scale *= 1.5f;
+ SetContentsScaleOnBothLayers(scale, device_scale, page_scale, 1.f, false);
+ ASSERT_EQ(1u, active_layer_->tilings()->num_tilings());
+
+ // The tilings are still our target scale, so they aren't removed.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(1u, active_layer_->tilings()->num_tilings());
+
+ host_impl_.PinchGestureEnd();
+
+ // Create a 1.2 scale tiling. Now we have 1.0 and 1.2 tilings. Ideal = 1.2.
+ scale /= 4.f;
+ page_scale /= 4.f;
+ SetContentsScaleOnBothLayers(1.2f, device_scale, page_scale, 1.f, false);
+ ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(1.f,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
+
+ // Mark the non-ideal tilings as used. They won't be removed.
+ used_tilings.clear();
+ used_tilings.push_back(active_layer_->tilings()->tiling_at(1));
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+
+ // Now move the ideal scale to 0.5. Our target stays 1.2.
+ SetContentsScaleOnBothLayers(0.5f, device_scale, page_scale, 1.f, false);
+
+ // The high resolution tiling is between target and ideal, so is not
+ // removed. The low res tiling for the old ideal=1.0 scale is removed.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+
+ // Now move the ideal scale to 1.0. Our target stays 1.2.
+ SetContentsScaleOnBothLayers(1.f, device_scale, page_scale, 1.f, false);
+
+ // All the tilings are between are target and the ideal, so they are not
+ // removed.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+
+ // Now move the ideal scale to 1.1 on the active layer. Our target stays 1.2.
+ SetupDrawPropertiesAndUpdateTiles(
+ active_layer_, 1.1f, device_scale, page_scale, 1.f, false);
+
+ // Because the pending layer's ideal scale is still 1.0, our tilings fall
+ // in the range [1.0,1.2] and are kept.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+
+ // Move the ideal scale on the pending layer to 1.1 as well. Our target stays
+ // 1.2 still.
+ SetupDrawPropertiesAndUpdateTiles(
+ pending_layer_, 1.1f, device_scale, page_scale, 1.f, false);
+
+ // Our 1.0 tiling now falls outside the range between our ideal scale and our
+ // target raster scale. But it is in our used tilings set, so nothing is
+ // deleted.
+ used_tilings.clear();
+ used_tilings.push_back(active_layer_->tilings()->tiling_at(1));
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(2u, active_layer_->tilings()->num_tilings());
+
+ // If we remove it from our used tilings set, it is outside the range to keep
+ // so it is deleted.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(1u, active_layer_->tilings()->num_tilings());
+}
+
+TEST_F(PictureLayerImplTest, ScaleCollision) {
+ gfx::Size tile_size(400, 400);
+ gfx::Size layer_bounds(1300, 1900);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakePicturePileImpl> active_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+ std::vector<PictureLayerTiling*> used_tilings;
+
+ SetupTrees(pending_pile, active_pile);
+
+ float pending_contents_scale = 1.f;
+ float active_contents_scale = 2.f;
+ float device_scale_factor = 1.f;
+ float page_scale_factor = 1.f;
+ float maximum_animation_contents_scale = 1.f;
+ bool animating_transform = false;
+
+ EXPECT_TRUE(host_impl_.settings().create_low_res_tiling);
+ float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+ EXPECT_LT(low_res_factor, 1.f);
+
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ pending_contents_scale,
+ device_scale_factor,
+ page_scale_factor,
+ maximum_animation_contents_scale,
+ animating_transform);
+ SetupDrawPropertiesAndUpdateTiles(active_layer_,
+ active_contents_scale,
+ device_scale_factor,
+ page_scale_factor,
+ maximum_animation_contents_scale,
+ animating_transform);
+
+ ASSERT_EQ(4u, pending_layer_->tilings()->num_tilings());
+ ASSERT_EQ(4u, active_layer_->tilings()->num_tilings());
+
+ EXPECT_EQ(active_contents_scale,
+ pending_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_EQ(pending_contents_scale,
+ pending_layer_->tilings()->tiling_at(1)->contents_scale());
+ EXPECT_EQ(active_contents_scale * low_res_factor,
+ pending_layer_->tilings()->tiling_at(2)->contents_scale());
+ EXPECT_EQ(pending_contents_scale * low_res_factor,
+ pending_layer_->tilings()->tiling_at(3)->contents_scale());
+
+ EXPECT_EQ(active_contents_scale,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_EQ(pending_contents_scale,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
+ EXPECT_EQ(active_contents_scale * low_res_factor,
+ active_layer_->tilings()->tiling_at(2)->contents_scale());
+ EXPECT_EQ(pending_contents_scale * low_res_factor,
+ active_layer_->tilings()->tiling_at(3)->contents_scale());
+
+ // The unused low res tiling from the pending tree must be kept or we may add
+ // it again on the active tree and collide with the pending tree.
+ used_tilings.push_back(active_layer_->tilings()->tiling_at(1));
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(4u, active_layer_->tilings()->num_tilings());
+
+ EXPECT_EQ(active_contents_scale,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_EQ(pending_contents_scale,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
+ EXPECT_EQ(active_contents_scale * low_res_factor,
+ active_layer_->tilings()->tiling_at(2)->contents_scale());
+ EXPECT_EQ(pending_contents_scale * low_res_factor,
+ active_layer_->tilings()->tiling_at(3)->contents_scale());
+}
+
+TEST_F(NoLowResPictureLayerImplTest, ReleaseResources) {
+ gfx::Size tile_size(400, 400);
+ gfx::Size layer_bounds(1300, 1900);
+
+ 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);
+ EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
+
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 1.3f, // ideal contents scale
+ 2.7f, // device scale
+ 3.2f, // page scale
+ 1.f, // maximum animation scale
+ false);
+ EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings());
+
+ // All tilings should be removed when losing output surface.
+ active_layer_->ReleaseResources();
+ EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+ pending_layer_->ReleaseResources();
+ EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
+
+ // This should create new tilings.
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_,
+ 1.3f, // ideal contents scale
+ 2.7f, // device scale
+ 3.2f, // page scale
+ 1.f, // maximum animation scale
+ false);
+ EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings());
+}
+
+TEST_F(PictureLayerImplTest, SharedQuadStateContainsMaxTilingScale) {
+ MockOcclusionTracker<LayerImpl> occlusion_tracker;
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+
+ gfx::Size tile_size(400, 400);
+ gfx::Size layer_bounds(1000, 2000);
+
+ 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);
+
+ SetupDrawPropertiesAndUpdateTiles(pending_layer_, 2.5f, 1.f, 1.f, 1.f, false);
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ active_layer_->draw_properties().visible_content_rect =
+ gfx::Rect(layer_bounds);
+ host_impl_.active_tree()->UpdateDrawProperties();
+
+ float max_contents_scale = active_layer_->MaximumTilingContentsScale();
+ gfx::Transform scaled_draw_transform = active_layer_->draw_transform();
+ scaled_draw_transform.Scale(SK_MScalar1 / max_contents_scale,
+ SK_MScalar1 / max_contents_scale);
+
+ AppendQuadsData data;
+ active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
+
+ // SharedQuadState should have be of size 1, as we are doing AppenQuad once.
+ EXPECT_EQ(1u, render_pass->shared_quad_state_list.size());
+ // The content_to_target_transform should be scaled by the
+ // MaximumTilingContentsScale on the layer.
+ EXPECT_EQ(scaled_draw_transform.ToString(),
+ render_pass->shared_quad_state_list[0]
+ ->content_to_target_transform.ToString());
+ // The content_bounds should be scaled by the
+ // MaximumTilingContentsScale on the layer.
+ EXPECT_EQ(gfx::Size(2500u, 5000u).ToString(),
+ render_pass->shared_quad_state_list[0]->content_bounds.ToString());
+ // The visible_content_rect should be scaled by the
+ // MaximumTilingContentsScale on the layer.
+ EXPECT_EQ(
+ gfx::Rect(0u, 0u, 2500u, 5000u).ToString(),
+ render_pass->shared_quad_state_list[0]->visible_content_rect.ToString());
+}
+
+TEST_F(PictureLayerImplTest, UpdateTilesForMasksWithNoVisibleContent) {
+ gfx::Size tile_size(400, 400);
+ gfx::Size bounds(100000, 100);
+
+ host_impl_.CreatePendingTree();
+
+ scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_.pending_tree(), 1);
+
+ scoped_ptr<FakePictureLayerImpl> layer_with_mask =
+ FakePictureLayerImpl::Create(host_impl_.pending_tree(), 2);
+
+ layer_with_mask->SetBounds(bounds);
+ layer_with_mask->SetContentBounds(bounds);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, bounds);
+ pending_pile->set_is_mask(true);
+ scoped_ptr<FakePictureLayerImpl> mask = FakePictureLayerImpl::CreateWithPile(
+ host_impl_.pending_tree(), 3, pending_pile);
+
+ mask->SetBounds(bounds);
+ mask->SetContentBounds(bounds);
+ mask->SetDrawsContent(true);
+
+ FakePictureLayerImpl* pending_mask_content = mask.get();
+ layer_with_mask->SetMaskLayer(mask.PassAs<LayerImpl>());
+
+ scoped_ptr<FakePictureLayerImpl> child_of_layer_with_mask =
+ FakePictureLayerImpl::Create(host_impl_.pending_tree(), 4);
+
+ child_of_layer_with_mask->SetBounds(bounds);
+ child_of_layer_with_mask->SetContentBounds(bounds);
+ child_of_layer_with_mask->SetDrawsContent(true);
+
+ layer_with_mask->AddChild(child_of_layer_with_mask.PassAs<LayerImpl>());
+
+ root->AddChild(layer_with_mask.PassAs<LayerImpl>());
+
+ host_impl_.pending_tree()->SetRootLayer(root.Pass());
+
+ EXPECT_FALSE(pending_mask_content->tilings());
+ host_impl_.pending_tree()->UpdateDrawProperties();
+ EXPECT_NE(0u, pending_mask_content->num_tilings());
+}
+
+class PictureLayerImplTestWithDelegatingRenderer : public PictureLayerImplTest {
+ public:
+ PictureLayerImplTestWithDelegatingRenderer() : PictureLayerImplTest() {}
+
+ virtual void InitializeRenderer() OVERRIDE {
+ host_impl_.InitializeRenderer(
+ FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>());
+ }
+};
+
+TEST_F(PictureLayerImplTestWithDelegatingRenderer,
+ DelegatingRendererWithTileOOM) {
+ // This test is added for crbug.com/402321, where quad should be produced when
+ // raster on demand is not allowed and tile is OOM.
+ gfx::Size tile_size = host_impl_.settings().default_tile_size;
+ gfx::Size layer_bounds(1000, 1000);
+
+ // Create tiles.
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ SetupPendingTree(pending_pile);
+ pending_layer_->SetBounds(layer_bounds);
+ host_impl_.SetViewportSize(layer_bounds);
+ ActivateTree();
+ host_impl_.active_tree()->UpdateDrawProperties();
+ std::vector<Tile*> tiles =
+ active_layer_->HighResTiling()->AllTilesForTesting();
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
+
+ // Force tiles after max_tiles to be OOM. TileManager uses
+ // GlobalStateThatImpactsTilesPriority from LayerTreeHostImpl, and we cannot
+ // directly set state to host_impl_, so we set policy that would change the
+ // state. We also need to update tree priority separately.
+ GlobalStateThatImpactsTilePriority state;
+ size_t max_tiles = 1;
+ size_t memory_limit = max_tiles * 4 * tile_size.width() * tile_size.height();
+ size_t resource_limit = max_tiles;
+ ManagedMemoryPolicy policy(memory_limit,
+ gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING,
+ resource_limit);
+ host_impl_.SetMemoryPolicy(policy);
+ host_impl_.SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
+ host_impl_.ManageTiles();
+
+ MockOcclusionTracker<LayerImpl> occlusion_tracker;
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ AppendQuadsData data;
+ active_layer_->WillDraw(DRAW_MODE_HARDWARE, NULL);
+ active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
+ active_layer_->DidDraw(NULL);
+
+ // Even when OOM, quads should be produced, and should be different material
+ // from quads with resource.
+ EXPECT_LT(max_tiles, render_pass->quad_list.size());
+ EXPECT_EQ(DrawQuad::Material::TILED_CONTENT,
+ render_pass->quad_list.front()->material);
+ EXPECT_EQ(DrawQuad::Material::SOLID_COLOR,
+ render_pass->quad_list.back()->material);
+}
+
+class OcclusionTrackingSettings : public ImplSidePaintingSettings {
+ public:
+ OcclusionTrackingSettings() { use_occlusion_for_tile_prioritization = true; }
+};
+
+class OcclusionTrackingPictureLayerImplTest : public PictureLayerImplTest {
+ public:
+ OcclusionTrackingPictureLayerImplTest()
+ : PictureLayerImplTest(OcclusionTrackingSettings()) {}
+
+ void VerifyEvictionConsidersOcclusion(
+ PictureLayerImpl* layer,
+ size_t expected_occluded_tile_count[NUM_TREE_PRIORITIES]) {
+ for (int priority_count = 0; priority_count < NUM_TREE_PRIORITIES;
+ ++priority_count) {
+ TreePriority tree_priority = static_cast<TreePriority>(priority_count);
+ size_t occluded_tile_count = 0u;
+ Tile* last_tile = NULL;
+
+ for (PictureLayerImpl::LayerEvictionTileIterator it =
+ PictureLayerImpl::LayerEvictionTileIterator(layer,
+ tree_priority);
+ it;
+ ++it) {
+ Tile* tile = *it;
+ if (!last_tile)
+ last_tile = tile;
+
+ // 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.
+ bool tile_is_occluded =
+ tile->is_occluded_for_tree_priority(tree_priority);
+ if (tile_is_occluded) {
+ occluded_tile_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;
+ }
+ EXPECT_EQ(expected_occluded_tile_count[priority_count],
+ occluded_tile_count);
+ }
+ }
+};
+
+TEST_F(OcclusionTrackingPictureLayerImplTest,
+ OccludedTilesSkippedDuringRasterization) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+
+ gfx::Size tile_size(102, 102);
+ gfx::Size layer_bounds(1000, 1000);
+ gfx::Size viewport_size(500, 500);
+ gfx::Point occluding_layer_position(310, 0);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ SetupPendingTree(pending_pile);
+ pending_layer_->set_fixed_tile_size(tile_size);
+
+ host_impl_.SetViewportSize(viewport_size);
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ // No occlusion.
+ int unoccluded_tile_count = 0;
+ for (PictureLayerImpl::LayerRasterTileIterator it =
+ PictureLayerImpl::LayerRasterTileIterator(pending_layer_, false);
+ it;
+ ++it) {
+ Tile* tile = *it;
+
+ // Occluded tiles should not be iterated over.
+ EXPECT_FALSE(tile->is_occluded(PENDING_TREE));
+
+ // Some tiles may not be visible (i.e. outside the viewport). The rest are
+ // visible and at least partially unoccluded, verified by the above expect.
+ bool tile_is_visible =
+ tile->content_rect().Intersects(pending_layer_->visible_content_rect());
+ if (tile_is_visible)
+ unoccluded_tile_count++;
+ }
+ EXPECT_EQ(unoccluded_tile_count, 25 + 4);
+
+ // Partial occlusion.
+ pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1));
+ LayerImpl* layer1 = pending_layer_->children()[0];
+ layer1->SetBounds(layer_bounds);
+ layer1->SetContentBounds(layer_bounds);
+ layer1->SetDrawsContent(true);
+ layer1->SetContentsOpaque(true);
+ layer1->SetPosition(occluding_layer_position);
+
+ time_ticks += base::TimeDelta::FromMilliseconds(200);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ unoccluded_tile_count = 0;
+ for (PictureLayerImpl::LayerRasterTileIterator it =
+ PictureLayerImpl::LayerRasterTileIterator(pending_layer_, false);
+ it;
+ ++it) {
+ Tile* tile = *it;
+
+ EXPECT_FALSE(tile->is_occluded(PENDING_TREE));
+
+ bool tile_is_visible =
+ tile->content_rect().Intersects(pending_layer_->visible_content_rect());
+ if (tile_is_visible)
+ unoccluded_tile_count++;
+ }
+ EXPECT_EQ(unoccluded_tile_count, 20 + 2);
+
+ // Full occlusion.
+ layer1->SetPosition(gfx::Point(0, 0));
+
+ time_ticks += base::TimeDelta::FromMilliseconds(200);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ unoccluded_tile_count = 0;
+ for (PictureLayerImpl::LayerRasterTileIterator it =
+ PictureLayerImpl::LayerRasterTileIterator(pending_layer_, false);
+ it;
+ ++it) {
+ Tile* tile = *it;
+
+ EXPECT_FALSE(tile->is_occluded(PENDING_TREE));
+
+ bool tile_is_visible =
+ tile->content_rect().Intersects(pending_layer_->visible_content_rect());
+ if (tile_is_visible)
+ unoccluded_tile_count++;
+ }
+ EXPECT_EQ(unoccluded_tile_count, 0);
+}
+
+TEST_F(OcclusionTrackingPictureLayerImplTest,
+ OccludedTilesNotMarkedAsRequired) {
+ base::TimeTicks time_ticks;
+ time_ticks += base::TimeDelta::FromMilliseconds(1);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+
+ gfx::Size tile_size(102, 102);
+ gfx::Size layer_bounds(1000, 1000);
+ gfx::Size viewport_size(500, 500);
+ gfx::Point occluding_layer_position(310, 0);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ SetupPendingTree(pending_pile);
+ pending_layer_->set_fixed_tile_size(tile_size);
+
+ host_impl_.SetViewportSize(viewport_size);
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ // No occlusion.
+ int occluded_tile_count = 0;
+ for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
+ PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i);
+
+ occluded_tile_count = 0;
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ pending_layer_->contents_scale_x(),
+ gfx::Rect(layer_bounds));
+ iter;
+ ++iter) {
+ if (!*iter)
+ continue;
+ const Tile* tile = *iter;
+
+ // Fully occluded tiles are not required for activation.
+ if (tile->is_occluded(PENDING_TREE)) {
+ EXPECT_FALSE(tile->required_for_activation());
+ occluded_tile_count++;
+ }
+ }
+ EXPECT_EQ(occluded_tile_count, 0);
+ }
+
+ // Partial occlusion.
+ pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1));
+ LayerImpl* layer1 = pending_layer_->children()[0];
+ layer1->SetBounds(layer_bounds);
+ layer1->SetContentBounds(layer_bounds);
+ layer1->SetDrawsContent(true);
+ layer1->SetContentsOpaque(true);
+ layer1->SetPosition(occluding_layer_position);
+
+ time_ticks += base::TimeDelta::FromMilliseconds(200);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
+ PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i);
+
+ occluded_tile_count = 0;
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ pending_layer_->contents_scale_x(),
+ gfx::Rect(layer_bounds));
+ iter;
+ ++iter) {
+ if (!*iter)
+ continue;
+ const Tile* tile = *iter;
+
+ if (tile->is_occluded(PENDING_TREE)) {
+ EXPECT_FALSE(tile->required_for_activation());
+ occluded_tile_count++;
+ }
+ }
+ switch (i) {
+ case 0:
+ EXPECT_EQ(occluded_tile_count, 5);
+ break;
+ case 1:
+ EXPECT_EQ(occluded_tile_count, 2);
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+
+ // Full occlusion.
+ layer1->SetPosition(gfx::PointF(0, 0));
+
+ time_ticks += base::TimeDelta::FromMilliseconds(200);
+ host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
+ PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i);
+
+ occluded_tile_count = 0;
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ pending_layer_->contents_scale_x(),
+ gfx::Rect(layer_bounds));
+ iter;
+ ++iter) {
+ if (!*iter)
+ continue;
+ const Tile* tile = *iter;
+
+ if (tile->is_occluded(PENDING_TREE)) {
+ EXPECT_FALSE(tile->required_for_activation());
+ occluded_tile_count++;
+ }
+ }
+ switch (i) {
+ case 0:
+ EXPECT_EQ(occluded_tile_count, 25);
+ break;
+ case 1:
+ EXPECT_EQ(occluded_tile_count, 4);
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+}
+
+TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales) {
+ gfx::Size tile_size(102, 102);
+ gfx::Size layer_bounds(1000, 1000);
+ gfx::Size viewport_size(500, 500);
+ gfx::Point occluding_layer_position(310, 0);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ SetupPendingTree(pending_pile);
+ pending_layer_->set_fixed_tile_size(tile_size);
+
+ ASSERT_TRUE(pending_layer_->CanHaveTilings());
+
+ float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+
+ std::vector<PictureLayerTiling*> tilings;
+ tilings.push_back(pending_layer_->AddTiling(low_res_factor));
+ tilings.push_back(pending_layer_->AddTiling(0.3f));
+ tilings.push_back(pending_layer_->AddTiling(0.7f));
+ tilings.push_back(pending_layer_->AddTiling(1.0f));
+ tilings.push_back(pending_layer_->AddTiling(2.0f));
+
+ pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1));
+ LayerImpl* layer1 = pending_layer_->children()[0];
+ layer1->SetBounds(layer_bounds);
+ layer1->SetContentBounds(layer_bounds);
+ layer1->SetDrawsContent(true);
+ layer1->SetContentsOpaque(true);
+ layer1->SetPosition(occluding_layer_position);
+
+ host_impl_.SetViewportSize(viewport_size);
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ int tiling_count = 0;
+ int occluded_tile_count = 0;
+ for (std::vector<PictureLayerTiling*>::iterator tiling_iterator =
+ tilings.begin();
+ tiling_iterator != tilings.end();
+ ++tiling_iterator) {
+ std::vector<Tile*> tiles = (*tiling_iterator)->AllTilesForTesting();
+
+ occluded_tile_count = 0;
+ for (size_t i = 0; i < tiles.size(); ++i) {
+ if (tiles[i]->is_occluded(PENDING_TREE)) {
+ gfx::Rect scaled_content_rect = ScaleToEnclosingRect(
+ tiles[i]->content_rect(), 1.0f / tiles[i]->contents_scale());
+ EXPECT_GE(scaled_content_rect.x(), occluding_layer_position.x());
+ occluded_tile_count++;
+ }
+ }
+ switch (tiling_count) {
+ case 0:
+ case 1:
+ EXPECT_EQ(occluded_tile_count, 2);
+ break;
+ case 2:
+ EXPECT_EQ(occluded_tile_count, 4);
+ break;
+ case 3:
+ EXPECT_EQ(occluded_tile_count, 5);
+ break;
+ case 4:
+ EXPECT_EQ(occluded_tile_count, 30);
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ tiling_count++;
+ }
+
+ EXPECT_EQ(tiling_count, 5);
+}
+
+TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) {
+ gfx::Size tile_size(102, 102);
+ gfx::Size layer_bounds(1000, 1000);
+ gfx::Size viewport_size(1000, 1000);
+ gfx::Point occluding_layer_position(310, 0);
+ gfx::Rect invalidation_rect(230, 230, 102, 102);
+
+ 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);
+
+ // Partially occlude the active layer.
+ active_layer_->AddChild(LayerImpl::Create(host_impl_.active_tree(), 2));
+ LayerImpl* layer1 = active_layer_->children()[0];
+ layer1->SetBounds(layer_bounds);
+ layer1->SetContentBounds(layer_bounds);
+ layer1->SetDrawsContent(true);
+ layer1->SetContentsOpaque(true);
+ layer1->SetPosition(occluding_layer_position);
+
+ // Partially invalidate the pending layer.
+ pending_layer_->set_invalidation(invalidation_rect);
+
+ host_impl_.SetViewportSize(viewport_size);
+
+ active_layer_->CreateDefaultTilingsAndTiles();
+ pending_layer_->CreateDefaultTilingsAndTiles();
+
+ for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
+ PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i);
+
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ pending_layer_->contents_scale_x(),
+ gfx::Rect(layer_bounds));
+ iter;
+ ++iter) {
+ if (!*iter)
+ continue;
+ const Tile* tile = *iter;
+
+ // All tiles are unoccluded on the pending tree.
+ EXPECT_FALSE(tile->is_occluded(PENDING_TREE));
+
+ Tile* twin_tile =
+ pending_layer_->GetTwinTiling(tiling)->TileAt(iter.i(), iter.j());
+ gfx::Rect scaled_content_rect = ScaleToEnclosingRect(
+ tile->content_rect(), 1.0f / tile->contents_scale());
+
+ if (scaled_content_rect.Intersects(invalidation_rect)) {
+ // Tiles inside the invalidation rect are only on the pending tree.
+ EXPECT_NE(tile, twin_tile);
+
+ // Unshared tiles should be unoccluded on the active tree by default.
+ EXPECT_FALSE(tile->is_occluded(ACTIVE_TREE));
+ } else {
+ // Tiles outside the invalidation rect are shared between both trees.
+ EXPECT_EQ(tile, twin_tile);
+ // Shared tiles are occluded on the active tree iff they lie beneath the
+ // occluding layer.
+ EXPECT_EQ(tile->is_occluded(ACTIVE_TREE),
+ scaled_content_rect.x() >= occluding_layer_position.x());
+ }
+ }
+ }
+
+ for (size_t i = 0; i < active_layer_->num_tilings(); ++i) {
+ PictureLayerTiling* tiling = active_layer_->tilings()->tiling_at(i);
+
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ active_layer_->contents_scale_x(),
+ gfx::Rect(layer_bounds));
+ iter;
+ ++iter) {
+ if (!*iter)
+ continue;
+ const Tile* tile = *iter;
+
+ Tile* twin_tile =
+ active_layer_->GetTwinTiling(tiling)->TileAt(iter.i(), iter.j());
+ gfx::Rect scaled_content_rect = ScaleToEnclosingRect(
+ tile->content_rect(), 1.0f / tile->contents_scale());
+
+ // Since we've already checked the shared tiles, only consider tiles in
+ // the invalidation rect.
+ if (scaled_content_rect.Intersects(invalidation_rect)) {
+ // Tiles inside the invalidation rect are only on the active tree.
+ EXPECT_NE(tile, twin_tile);
+
+ // Unshared tiles should be unoccluded on the pending tree by default.
+ EXPECT_FALSE(tile->is_occluded(PENDING_TREE));
+
+ // Unshared tiles are occluded on the active tree iff they lie beneath
+ // the occluding layer.
+ EXPECT_EQ(tile->is_occluded(ACTIVE_TREE),
+ scaled_content_rect.x() >= occluding_layer_position.x());
+ }
+ }
+ }
+}
+
+TEST_F(OcclusionTrackingPictureLayerImplTest,
+ OccludedTilesConsideredDuringEviction) {
+ gfx::Size tile_size(102, 102);
+ gfx::Size layer_bounds(1000, 1000);
+ gfx::Size viewport_size(500, 500);
+ gfx::Point pending_occluding_layer_position(310, 0);
+ gfx::Point active_occluding_layer_position(0, 310);
+ gfx::Rect invalidation_rect(230, 230, 102, 102);
+
+ 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);
+
+ pending_layer_->set_fixed_tile_size(tile_size);
+ active_layer_->set_fixed_tile_size(tile_size);
+
+ float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+
+ std::vector<PictureLayerTiling*> tilings;
+ tilings.push_back(pending_layer_->AddTiling(low_res_factor));
+ tilings.push_back(pending_layer_->AddTiling(0.3f));
+ tilings.push_back(pending_layer_->AddTiling(0.7f));
+ tilings.push_back(pending_layer_->AddTiling(1.0f));
+ tilings.push_back(pending_layer_->AddTiling(2.0f));
+
+ EXPECT_EQ(5u, pending_layer_->num_tilings());
+ EXPECT_EQ(5u, active_layer_->num_tilings());
+
+ // Partially occlude the pending layer.
+ pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1));
+ LayerImpl* pending_occluding_layer = pending_layer_->children()[0];
+ pending_occluding_layer->SetBounds(layer_bounds);
+ pending_occluding_layer->SetContentBounds(layer_bounds);
+ pending_occluding_layer->SetDrawsContent(true);
+ pending_occluding_layer->SetContentsOpaque(true);
+ pending_occluding_layer->SetPosition(pending_occluding_layer_position);
+
+ // Partially occlude the active layer.
+ active_layer_->AddChild(LayerImpl::Create(host_impl_.active_tree(), 2));
+ LayerImpl* active_occluding_layer = active_layer_->children()[0];
+ active_occluding_layer->SetBounds(layer_bounds);
+ active_occluding_layer->SetContentBounds(layer_bounds);
+ active_occluding_layer->SetDrawsContent(true);
+ active_occluding_layer->SetContentsOpaque(true);
+ active_occluding_layer->SetPosition(active_occluding_layer_position);
+
+ // Partially invalidate the pending layer. Tiles inside the invalidation rect
+ // are not shared between trees.
+ pending_layer_->set_invalidation(invalidation_rect);
+
+ host_impl_.SetViewportSize(viewport_size);
+ host_impl_.active_tree()->UpdateDrawProperties();
+ host_impl_.pending_tree()->UpdateDrawProperties();
+
+ // The expected number of occluded tiles on each of the 5 tilings for each of
+ // the 3 tree priorities.
+ size_t expected_occluded_tile_count_on_both[] = {9u, 1u, 1u, 1u, 1u};
+ size_t expected_occluded_tile_count_on_active[] = {30u, 5u, 4u, 2u, 2u};
+ size_t expected_occluded_tile_count_on_pending[] = {30u, 5u, 4u, 2u, 2u};
+
+ // The total expected number of occluded tiles on all tilings for each of the
+ // 3 tree priorities.
+ size_t total_expected_occluded_tile_count[] = {13u, 43u, 43u};
+
+ ASSERT_EQ(arraysize(total_expected_occluded_tile_count), NUM_TREE_PRIORITIES);
+
+ // Verify number of occluded tiles on the pending layer for each tiling.
+ for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
+ PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i);
+ tiling->CreateAllTilesForTesting();
+
+ size_t occluded_tile_count_on_pending = 0u;
+ size_t occluded_tile_count_on_active = 0u;
+ size_t occluded_tile_count_on_both = 0u;
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ pending_layer_->contents_scale_x(),
+ gfx::Rect(layer_bounds));
+ iter;
+ ++iter) {
+ Tile* tile = *iter;
+
+ if (tile->is_occluded(PENDING_TREE))
+ occluded_tile_count_on_pending++;
+ if (tile->is_occluded(ACTIVE_TREE))
+ occluded_tile_count_on_active++;
+ if (tile->is_occluded(PENDING_TREE) && tile->is_occluded(ACTIVE_TREE))
+ occluded_tile_count_on_both++;
+ }
+ EXPECT_EQ(expected_occluded_tile_count_on_pending[i],
+ occluded_tile_count_on_pending)
+ << i;
+ EXPECT_EQ(expected_occluded_tile_count_on_active[i],
+ occluded_tile_count_on_active)
+ << i;
+ EXPECT_EQ(expected_occluded_tile_count_on_both[i],
+ occluded_tile_count_on_both)
+ << i;
+ }
+
+ // Verify number of occluded tiles on the active layer for each tiling.
+ for (size_t i = 0; i < active_layer_->num_tilings(); ++i) {
+ PictureLayerTiling* tiling = active_layer_->tilings()->tiling_at(i);
+ tiling->CreateAllTilesForTesting();
+
+ size_t occluded_tile_count_on_pending = 0u;
+ size_t occluded_tile_count_on_active = 0u;
+ size_t occluded_tile_count_on_both = 0u;
+ for (PictureLayerTiling::CoverageIterator iter(
+ tiling,
+ pending_layer_->contents_scale_x(),
+ gfx::Rect(layer_bounds));
+ iter;
+ ++iter) {
+ Tile* tile = *iter;
+
+ if (tile->is_occluded(PENDING_TREE))
+ occluded_tile_count_on_pending++;
+ if (tile->is_occluded(ACTIVE_TREE))
+ occluded_tile_count_on_active++;
+ if (tile->is_occluded(PENDING_TREE) && tile->is_occluded(ACTIVE_TREE))
+ occluded_tile_count_on_both++;
+ }
+ EXPECT_EQ(expected_occluded_tile_count_on_pending[i],
+ occluded_tile_count_on_pending)
+ << i;
+ EXPECT_EQ(expected_occluded_tile_count_on_active[i],
+ occluded_tile_count_on_active)
+ << i;
+ EXPECT_EQ(expected_occluded_tile_count_on_both[i],
+ occluded_tile_count_on_both)
+ << i;
+ }
+
+ std::vector<Tile*> all_tiles;
+ for (std::vector<PictureLayerTiling*>::iterator tiling_iterator =
+ tilings.begin();
+ tiling_iterator != tilings.end();
+ ++tiling_iterator) {
+ std::vector<Tile*> tiles = (*tiling_iterator)->AllTilesForTesting();
+ std::copy(tiles.begin(), tiles.end(), std::back_inserter(all_tiles));
+ }
+
+ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
+
+ VerifyEvictionConsidersOcclusion(pending_layer_,
+ total_expected_occluded_tile_count);
+ VerifyEvictionConsidersOcclusion(active_layer_,
+ total_expected_occluded_tile_count);
+}
+
+TEST_F(PictureLayerImplTest, RecycledTwinLayer) {
+ gfx::Size tile_size(102, 102);
+ gfx::Size layer_bounds(1000, 1000);
+
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ SetupPendingTree(pile);
+ EXPECT_FALSE(pending_layer_->GetRecycledTwinLayer());
+
+ ActivateTree();
+ EXPECT_TRUE(active_layer_->GetRecycledTwinLayer());
+ EXPECT_EQ(old_pending_layer_, active_layer_->GetRecycledTwinLayer());
+
+ SetupPendingTree(pile);
+ EXPECT_FALSE(pending_layer_->GetRecycledTwinLayer());
+ EXPECT_FALSE(active_layer_->GetRecycledTwinLayer());
+
+ ActivateTree();
+ EXPECT_TRUE(active_layer_->GetRecycledTwinLayer());
+ EXPECT_EQ(old_pending_layer_, active_layer_->GetRecycledTwinLayer());
+
+ host_impl_.ResetRecycleTreeForTesting();
+ EXPECT_FALSE(active_layer_->GetRecycledTwinLayer());
+}
+
} // namespace
} // namespace cc