Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / cc / layers / picture_layer_impl_unittest.cc
index 38e968e..c72d19c 100644 (file)
@@ -13,6 +13,8 @@
 #include "cc/layers/append_quads_data.h"
 #include "cc/layers/picture_layer.h"
 #include "cc/quads/draw_quad.h"
+#include "cc/quads/tile_draw_quad.h"
+#include "cc/test/begin_frame_args_test.h"
 #include "cc/test/fake_content_layer_client.h"
 #include "cc/test/fake_impl_proxy.h"
 #include "cc/test/fake_layer_tree_host_impl.h"
@@ -44,13 +46,18 @@ class MockCanvas : public SkCanvas {
   std::vector<SkRect> rects_;
 };
 
+class NoLowResTilingsSettings : public ImplSidePaintingSettings {};
+
+class LowResTilingsSettings : public ImplSidePaintingSettings {
+ public:
+  LowResTilingsSettings() { create_low_res_tiling = true; }
+};
+
 class PictureLayerImplTest : public testing::Test {
  public:
   PictureLayerImplTest()
       : proxy_(base::MessageLoopProxy::current()),
-        host_impl_(ImplSidePaintingSettings(),
-                   &proxy_,
-                   &shared_bitmap_manager_),
+        host_impl_(LowResTilingsSettings(), &proxy_, &shared_bitmap_manager_),
         id_(7),
         pending_layer_(NULL),
         old_pending_layer_(NULL),
@@ -158,7 +165,7 @@ class PictureLayerImplTest : public testing::Test {
         maximum_animation_contents_scale;
     layer->draw_properties().screen_space_transform_is_animating =
         animating_transform_to_screen;
-    layer->UpdateTiles(NULL);
+    layer->UpdateTiles(Occlusion());
   }
   static void VerifyAllTilesExistAndHavePile(
       const PictureLayerTiling* tiling,
@@ -263,6 +270,8 @@ class PictureLayerImplTest : public testing::Test {
     }
   }
 
+  void TestQuadsForSolidColor(bool test_for_solid);
+
   FakeImplProxy proxy_;
   TestSharedBitmapManager shared_bitmap_manager_;
   FakeLayerTreeHostImpl host_impl_;
@@ -311,7 +320,8 @@ TEST_F(PictureLayerImplTest, CloneNoInvalidation) {
 TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
   base::TimeTicks time_ticks;
   time_ticks += base::TimeDelta::FromMilliseconds(1);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(400, 400);
 
@@ -327,7 +337,8 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
   SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
 
   time_ticks += base::TimeDelta::FromMilliseconds(200);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
 
   // Update tiles with viewport for tile priority as (0, 0, 100, 100) and the
   // identify transform for tile priority.
@@ -344,7 +355,7 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
                                         resourceless_software_draw);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
   gfx::Rect viewport_rect_for_tile_priority_in_view_space =
       viewport_rect_for_tile_priority;
@@ -368,7 +379,8 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
   // rotated. The actual viewport for tile priority used by PictureLayerImpl
   // should be (200, 200, 100, 100) applied with the said transform.
   time_ticks += base::TimeDelta::FromMilliseconds(200);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
 
   viewport_rect_for_tile_priority = gfx::Rect(200, 200, 100, 100);
   transform_for_tile_priority.Translate(100, 100);
@@ -381,12 +393,16 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
                                         resourceless_software_draw);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
   gfx::Transform screen_to_view(gfx::Transform::kSkipInitialization);
   bool success = transform_for_tile_priority.GetInverse(&screen_to_view);
   EXPECT_TRUE(success);
 
+  // Note that we don't clip this to the layer bounds, since it is expected that
+  // the rect will sometimes be outside of the layer bounds. If we clip to
+  // bounds, then tile priorities will end up being incorrect in cases of fully
+  // offscreen layer.
   viewport_rect_for_tile_priority_in_view_space =
       gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
           screen_to_view, viewport_rect_for_tile_priority));
@@ -395,10 +411,6 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
   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);
@@ -409,10 +421,12 @@ TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
   }
 }
 
-TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
+TEST_F(PictureLayerImplTest,
+       ResourcelessSoftwareDrawHasValidViewportForTilePriority) {
   base::TimeTicks time_ticks;
   time_ticks += base::TimeDelta::FromMilliseconds(1);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
 
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(400, 400);
@@ -429,8 +443,6 @@ TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
   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;
@@ -442,7 +454,7 @@ TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
                                         resourceless_software_draw);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
   gfx::Rect visible_rect_for_tile_priority =
       active_layer_->visible_rect_for_tile_priority();
@@ -453,10 +465,12 @@ TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
   gfx::Transform screen_space_transform_for_tile_priority =
       active_layer_->screen_space_transform_for_tile_priority();
 
-  // Expand viewport and set it as invalid for prioritizing tiles.
-  // Should not update tile viewport.
+  // PictureLayerImpl does not make a special case for
+  // resource_less_software_draw, so the tile viewport and matrix should be
+  // respected.
   time_ticks += base::TimeDelta::FromMilliseconds(200);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
   resourceless_software_draw = true;
   viewport = gfx::ScaleToEnclosingRect(viewport, 2);
   transform.Translate(1.f, 1.f);
@@ -468,8 +482,13 @@ TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
                                         viewport,
                                         transform,
                                         resourceless_software_draw);
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
+  visible_rect_for_tile_priority =
+      gfx::ScaleToEnclosingRect(visible_rect_for_tile_priority, 2);
+  viewport_rect_for_tile_priority =
+      gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority, 2);
+  screen_space_transform_for_tile_priority = transform;
   EXPECT_RECT_EQ(visible_rect_for_tile_priority,
                  active_layer_->visible_rect_for_tile_priority());
   EXPECT_RECT_EQ(viewport_rect_for_tile_priority,
@@ -477,59 +496,6 @@ TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
   EXPECT_TRANSFORMATION_MATRIX_EQ(
       screen_space_transform_for_tile_priority,
       active_layer_->screen_space_transform_for_tile_priority());
-
-  // Keep expanded viewport but mark it valid. Should update tile viewport.
-  time_ticks += base::TimeDelta::FromMilliseconds(200);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
-  resourceless_software_draw = false;
-  host_impl_.SetExternalDrawConstraints(transform,
-                                        viewport,
-                                        viewport,
-                                        viewport,
-                                        transform,
-                                        resourceless_software_draw);
-  active_layer_->UpdateTiles(NULL);
-
-  EXPECT_FALSE(visible_rect_for_tile_priority ==
-               active_layer_->visible_rect_for_tile_priority());
-  EXPECT_FALSE(viewport_rect_for_tile_priority ==
-               active_layer_->viewport_rect_for_tile_priority());
-  EXPECT_FALSE(screen_space_transform_for_tile_priority ==
-               active_layer_->screen_space_transform_for_tile_priority());
-}
-
-TEST_F(PictureLayerImplTest, InvalidViewportAfterReleaseResources) {
-  gfx::Size tile_size(100, 100);
-  gfx::Size layer_bounds(400, 400);
-
-  scoped_refptr<FakePicturePileImpl> pending_pile =
-      FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-  scoped_refptr<FakePicturePileImpl> active_pile =
-      FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
-  SetupTrees(pending_pile, active_pile);
-
-  Region invalidation;
-  AddDefaultTilingsWithInvalidation(invalidation);
-
-  bool resourceless_software_draw = true;
-  gfx::Rect viewport = gfx::Rect(layer_bounds);
-  gfx::Transform identity = gfx::Transform();
-  host_impl_.SetExternalDrawConstraints(identity,
-                                        viewport,
-                                        viewport,
-                                        viewport,
-                                        identity,
-                                        resourceless_software_draw);
-  ResetTilingsAndRasterScales();
-  host_impl_.pending_tree()->UpdateDrawProperties();
-  host_impl_.active_tree()->UpdateDrawProperties();
-  EXPECT_TRUE(active_layer_->HighResTiling());
-
-  size_t num_tilings = active_layer_->num_tilings();
-  active_layer_->UpdateTiles(NULL);
-  pending_layer_->AddTiling(0.5f);
-  EXPECT_EQ(num_tilings + 1, active_layer_->num_tilings());
 }
 
 TEST_F(PictureLayerImplTest, ClonePartialInvalidation) {
@@ -563,9 +529,9 @@ TEST_F(PictureLayerImplTest, ClonePartialInvalidation) {
       EXPECT_TRUE(*iter);
       EXPECT_FALSE(iter.geometry_rect().IsEmpty());
       if (iter.geometry_rect().Intersects(content_invalidation))
-        EXPECT_EQ(pending_pile, iter->picture_pile());
+        EXPECT_EQ(pending_pile.get(), iter->picture_pile());
       else
-        EXPECT_EQ(active_pile, iter->picture_pile());
+        EXPECT_EQ(active_pile.get(), iter->picture_pile());
     }
   }
 }
@@ -632,9 +598,9 @@ TEST_F(PictureLayerImplTest, NoInvalidationBoundsChange) {
           iter.geometry_rect().bottom() >= active_content_bounds.height() ||
           active_tiles[0]->content_rect().size() !=
               pending_tiles[0]->content_rect().size()) {
-        EXPECT_EQ(pending_pile, iter->picture_pile());
+        EXPECT_EQ(pending_pile.get(), iter->picture_pile());
       } else {
-        EXPECT_EQ(active_pile, iter->picture_pile());
+        EXPECT_EQ(active_pile.get(), iter->picture_pile());
       }
     }
   }
@@ -687,9 +653,9 @@ TEST_F(PictureLayerImplTest, AddTilesFromNewRecording) {
                                               iter.full_tile_geometry_rect());
 
       if (in_pending && !in_active)
-        EXPECT_EQ(pending_pile, iter->picture_pile());
+        EXPECT_EQ(pending_pile.get(), iter->picture_pile());
       else if (in_active)
-        EXPECT_EQ(active_pile, iter->picture_pile());
+        EXPECT_EQ(active_pile.get(), iter->picture_pile());
       else
         EXPECT_FALSE(*iter);
     }
@@ -1421,7 +1387,8 @@ TEST_F(PictureLayerImplTest, DisallowTileDrawQuads) {
   active_layer_->DidDraw(NULL);
 
   ASSERT_EQ(1U, render_pass->quad_list.size());
-  EXPECT_EQ(DrawQuad::PICTURE_CONTENT, render_pass->quad_list[0]->material);
+  EXPECT_EQ(DrawQuad::PICTURE_CONTENT,
+            render_pass->quad_list.front()->material);
 }
 
 TEST_F(PictureLayerImplTest, MarkRequiredNullTiles) {
@@ -1511,7 +1478,8 @@ TEST_F(PictureLayerImplTest, MarkRequiredOffscreenTiles) {
 TEST_F(PictureLayerImplTest, TileOutsideOfViewportForTilePriorityNotRequired) {
   base::TimeTicks time_ticks;
   time_ticks += base::TimeDelta::FromMilliseconds(1);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
 
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(400, 400);
@@ -1546,8 +1514,9 @@ TEST_F(PictureLayerImplTest, TileOutsideOfViewportForTilePriorityNotRequired) {
   // external_viewport_for_tile_priority.
   pending_layer_->draw_properties().visible_content_rect = visible_content_rect;
   time_ticks += base::TimeDelta::FromMilliseconds(200);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
-  pending_layer_->UpdateTiles(NULL);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
+  pending_layer_->UpdateTiles(Occlusion());
 
   pending_layer_->MarkVisibleResourcesAsRequired();
 
@@ -1599,6 +1568,154 @@ TEST_F(PictureLayerImplTest, TileOutsideOfViewportForTilePriorityNotRequired) {
   EXPECT_EQ(0u, data.num_incomplete_tiles);
 }
 
+TEST_F(PictureLayerImplTest, HighResTileIsComplete) {
+  base::TimeTicks time_ticks;
+  time_ticks += base::TimeDelta::FromMilliseconds(1);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
+
+  gfx::Size tile_size(100, 100);
+  gfx::Size layer_bounds(200, 200);
+
+  host_impl_.SetViewportSize(layer_bounds);
+
+  scoped_refptr<FakePicturePileImpl> pending_pile =
+      FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+  SetupPendingTree(pending_pile);
+  ActivateTree();
+
+  // All high res tiles have resources.
+  active_layer_->set_fixed_tile_size(tile_size);
+  host_impl_.active_tree()->UpdateDrawProperties();
+  std::vector<Tile*> tiles =
+      active_layer_->tilings()->tiling_at(0)->AllTilesForTesting();
+  host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
+
+  MockOcclusionTracker<LayerImpl> occlusion_tracker;
+  scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+  AppendQuadsData data;
+  active_layer_->WillDraw(DRAW_MODE_SOFTWARE, NULL);
+  active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
+  active_layer_->DidDraw(NULL);
+
+  // All high res tiles drew, nothing was incomplete.
+  EXPECT_EQ(9u, render_pass->quad_list.size());
+  EXPECT_EQ(0u, data.num_missing_tiles);
+  EXPECT_EQ(0u, data.num_incomplete_tiles);
+}
+
+TEST_F(PictureLayerImplTest, LowResTileIsIncomplete) {
+  base::TimeTicks time_ticks;
+  time_ticks += base::TimeDelta::FromMilliseconds(1);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
+
+  gfx::Size tile_size(100, 100);
+  gfx::Size layer_bounds(200, 200);
+
+  host_impl_.SetViewportSize(layer_bounds);
+
+  scoped_refptr<FakePicturePileImpl> pending_pile =
+      FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+  SetupPendingTree(pending_pile);
+  ActivateTree();
+
+  // All high res tiles have resources except one.
+  active_layer_->set_fixed_tile_size(tile_size);
+  host_impl_.active_tree()->UpdateDrawProperties();
+  std::vector<Tile*> high_tiles =
+      active_layer_->tilings()->tiling_at(0)->AllTilesForTesting();
+  high_tiles.erase(high_tiles.begin());
+  host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(high_tiles);
+
+  // All low res tiles have resources.
+  std::vector<Tile*> low_tiles =
+      active_layer_->tilings()->tiling_at(1)->AllTilesForTesting();
+  host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(low_tiles);
+
+  MockOcclusionTracker<LayerImpl> occlusion_tracker;
+  scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+  AppendQuadsData data;
+  active_layer_->WillDraw(DRAW_MODE_SOFTWARE, NULL);
+  active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
+  active_layer_->DidDraw(NULL);
+
+  // The missing high res tile was replaced by a low res tile.
+  EXPECT_EQ(9u, render_pass->quad_list.size());
+  EXPECT_EQ(0u, data.num_missing_tiles);
+  EXPECT_EQ(1u, data.num_incomplete_tiles);
+}
+
+TEST_F(PictureLayerImplTest,
+       HighResAndIdealResTileIsCompleteWhenRasterScaleIsNotIdeal) {
+  base::TimeTicks time_ticks;
+  time_ticks += base::TimeDelta::FromMilliseconds(1);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
+
+  gfx::Size tile_size(100, 100);
+  gfx::Size layer_bounds(200, 200);
+
+  host_impl_.SetViewportSize(layer_bounds);
+
+  scoped_refptr<FakePicturePileImpl> pending_pile =
+      FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+  scoped_refptr<FakePicturePileImpl> active_pile =
+      FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+  SetupTrees(pending_pile, active_pile);
+
+  active_layer_->set_fixed_tile_size(tile_size);
+
+  active_layer_->draw_properties().visible_content_rect =
+      gfx::Rect(layer_bounds);
+  SetupDrawPropertiesAndUpdateTiles(active_layer_, 2.f, 1.f, 1.f, 1.f, false);
+
+  // One ideal tile exists, this will get used when drawing.
+  std::vector<Tile*> ideal_tiles;
+  EXPECT_EQ(2.f, active_layer_->HighResTiling()->contents_scale());
+  ideal_tiles.push_back(active_layer_->HighResTiling()->TileAt(0, 0));
+  host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(
+      ideal_tiles);
+
+  // Due to layer scale throttling, the raster contents scale is changed to 1,
+  // while the ideal is still 2.
+  SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
+  SetupDrawPropertiesAndUpdateTiles(active_layer_, 2.f, 1.f, 1.f, 1.f, false);
+
+  EXPECT_EQ(1.f, active_layer_->HighResTiling()->contents_scale());
+  EXPECT_EQ(1.f, active_layer_->raster_contents_scale());
+  EXPECT_EQ(2.f, active_layer_->ideal_contents_scale());
+
+  // Both tilings still exist.
+  EXPECT_EQ(2.f, active_layer_->tilings()->tiling_at(0)->contents_scale());
+  EXPECT_EQ(1.f, active_layer_->tilings()->tiling_at(1)->contents_scale());
+
+  // All high res tiles have resources.
+  std::vector<Tile*> high_tiles =
+      active_layer_->HighResTiling()->AllTilesForTesting();
+  host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(high_tiles);
+
+  MockOcclusionTracker<LayerImpl> occlusion_tracker;
+  scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+  AppendQuadsData data;
+  active_layer_->WillDraw(DRAW_MODE_SOFTWARE, NULL);
+  active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
+  active_layer_->DidDraw(NULL);
+
+  // All high res tiles drew, and the one ideal res tile drew.
+  ASSERT_GT(render_pass->quad_list.size(), 9u);
+  EXPECT_EQ(gfx::SizeF(99.f, 99.f),
+            TileDrawQuad::MaterialCast(render_pass->quad_list.front())
+                ->tex_coord_rect.size());
+  EXPECT_EQ(gfx::SizeF(49.5f, 49.5f),
+            TileDrawQuad::MaterialCast(render_pass->quad_list.ElementAt(1))
+                ->tex_coord_rect.size());
+
+  // Neither the high res nor the ideal tiles were considered as incomplete.
+  EXPECT_EQ(0u, data.num_missing_tiles);
+  EXPECT_EQ(0u, data.num_incomplete_tiles);
+}
+
 TEST_F(PictureLayerImplTest, HighResRequiredWhenUnsharedActiveAllReady) {
   gfx::Size layer_bounds(400, 400);
   gfx::Size tile_size(100, 100);
@@ -1800,9 +1917,13 @@ TEST_F(PictureLayerImplTest, ShareTilesOnSync) {
     EXPECT_TRUE(pending_tiling->TileAt(1, 1));
 
     EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
+    EXPECT_TRUE(active_tiling->TileAt(0, 0)->is_shared());
     EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
+    EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared());
     EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
+    EXPECT_TRUE(active_tiling->TileAt(0, 1)->is_shared());
     EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
+    EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared());
   }
 }
 
@@ -1842,9 +1963,13 @@ TEST_F(PictureLayerImplTest, ShareInvalidActiveTreeTilesOnSync) {
     EXPECT_TRUE(pending_tiling->TileAt(1, 1));
 
     EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
+    EXPECT_TRUE(active_tiling->TileAt(0, 0)->is_shared());
     EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
+    EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared());
     EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
+    EXPECT_TRUE(active_tiling->TileAt(0, 1)->is_shared());
     EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
+    EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared());
   }
 }
 
@@ -1887,9 +2012,14 @@ TEST_F(PictureLayerImplTest, RemoveInvalidPendingTreeTilesOnSync) {
     EXPECT_TRUE(pending_tiling->TileAt(1, 1));
 
     EXPECT_NE(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
+    EXPECT_FALSE(active_tiling->TileAt(0, 0)->is_shared());
+    EXPECT_FALSE(pending_tiling->TileAt(0, 0)->is_shared());
     EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0));
+    EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared());
     EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1));
+    EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared());
     EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
+    EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared());
   }
 }
 
@@ -2270,7 +2400,117 @@ TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) {
   EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 11.f);
 }
 
+TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForGpuRasterization) {
+  gfx::Size layer_bounds(100, 100);
+  gfx::Size viewport_size(1000, 1000);
+  SetupDefaultTrees(layer_bounds);
+  host_impl_.SetViewportSize(viewport_size);
+  host_impl_.SetUseGpuRasterization(true);
+
+  float contents_scale = 1.f;
+  float device_scale = 1.3f;
+  float page_scale = 1.4f;
+  float maximum_animation_scale = 1.f;
+  bool animating_transform = false;
+
+  SetContentsScaleOnBothLayers(contents_scale,
+                               device_scale,
+                               page_scale,
+                               maximum_animation_scale,
+                               animating_transform);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
+
+  // Since we're GPU-rasterizing, starting an animation should cause tiling
+  // resolution to get set to the current contents scale.
+  animating_transform = true;
+  contents_scale = 2.f;
+  maximum_animation_scale = 4.f;
+
+  SetContentsScaleOnBothLayers(contents_scale,
+                               device_scale,
+                               page_scale,
+                               maximum_animation_scale,
+                               animating_transform);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
+
+  // Further changes to scale during the animation should cause a new high-res
+  // tiling to get created.
+  contents_scale = 3.f;
+
+  SetContentsScaleOnBothLayers(contents_scale,
+                               device_scale,
+                               page_scale,
+                               maximum_animation_scale,
+                               animating_transform);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
+
+  // Since we're re-rasterizing during the animation, scales smaller than 1
+  // should be respected.
+  contents_scale = 0.25f;
+
+  SetContentsScaleOnBothLayers(contents_scale,
+                               device_scale,
+                               page_scale,
+                               maximum_animation_scale,
+                               animating_transform);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 0.25f);
+
+  // Once we stop animating, a new high-res tiling should be created.
+  contents_scale = 4.f;
+  animating_transform = false;
+
+  SetContentsScaleOnBothLayers(contents_scale,
+                               device_scale,
+                               page_scale,
+                               maximum_animation_scale,
+                               animating_transform);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
+
+  static_cast<FakePicturePileImpl*>(pending_layer_->pile())->set_has_text(true);
+  static_cast<FakePicturePileImpl*>(active_layer_->pile())->set_has_text(true);
+
+  // Since we're GPU-rasterizing but have text, starting an animation should
+  // cause tiling resolution to get set to the maximum animation scale.
+  animating_transform = true;
+  contents_scale = 2.f;
+  maximum_animation_scale = 3.f;
+
+  SetContentsScaleOnBothLayers(contents_scale,
+                               device_scale,
+                               page_scale,
+                               maximum_animation_scale,
+                               animating_transform);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
+
+  // Further changes to scale during the animation should not cause a new
+  // high-res tiling to get created.
+  contents_scale = 4.f;
+  maximum_animation_scale = 5.f;
+
+  SetContentsScaleOnBothLayers(contents_scale,
+                               device_scale,
+                               page_scale,
+                               maximum_animation_scale,
+                               animating_transform);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
+
+  // Once we stop animating, a new high-res tiling should be created.
+  animating_transform = false;
+
+  SetContentsScaleOnBothLayers(contents_scale,
+                               device_scale,
+                               page_scale,
+                               maximum_animation_scale,
+                               animating_transform);
+  EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);
+}
+
 TEST_F(PictureLayerImplTest, LayerRasterTileIterator) {
+  base::TimeTicks time_ticks;
+  time_ticks += base::TimeDelta::FromMilliseconds(1);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
+
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(1000, 1000);
 
@@ -2336,6 +2576,45 @@ TEST_F(PictureLayerImplTest, LayerRasterTileIterator) {
   EXPECT_EQ(low_res_tile_count + high_res_tile_count + non_ideal_tile_count,
             unique_tiles.size());
 
+  // No NOW tiles.
+  time_ticks += base::TimeDelta::FromMilliseconds(200);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
+
+  pending_layer_->draw_properties().visible_content_rect =
+      gfx::Rect(1100, 1100, 500, 500);
+  pending_layer_->UpdateTiles(Occlusion());
+
+  unique_tiles.clear();
+  high_res_tile_count = 0u;
+  for (it = PictureLayerImpl::LayerRasterTileIterator(pending_layer_, false);
+       it;
+       ++it) {
+    Tile* tile = *it;
+    TilePriority priority = tile->priority(PENDING_TREE);
+
+    EXPECT_TRUE(tile);
+
+    // Non-high res tiles only get visible tiles.
+    EXPECT_EQ(HIGH_RESOLUTION, priority.resolution);
+    EXPECT_NE(TilePriority::NOW, priority.priority_bin);
+
+    high_res_tile_count += priority.resolution == HIGH_RESOLUTION;
+
+    unique_tiles.insert(tile);
+  }
+
+  EXPECT_EQ(16u, high_res_tile_count);
+  EXPECT_EQ(high_res_tile_count, unique_tiles.size());
+
+  time_ticks += base::TimeDelta::FromMilliseconds(200);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
+
+  pending_layer_->draw_properties().visible_content_rect =
+      gfx::Rect(0, 0, 500, 500);
+  pending_layer_->UpdateTiles(Occlusion());
+
   std::vector<Tile*> high_res_tiles = high_res_tiling->AllTilesForTesting();
   for (std::vector<Tile*>::iterator tile_it = high_res_tiles.begin();
        tile_it != high_res_tiles.end();
@@ -2568,11 +2847,8 @@ TEST_F(PictureLayerImplTest, Occlusion) {
     impl.AppendQuadsWithOcclusion(active_layer_, occluded);
 
     size_t partially_occluded_count = 0;
-    LayerTestCommon::VerifyQuadsCoverRectWithOcclusion(
-        impl.quad_list(),
-        gfx::Rect(layer_bounds),
-        occluded,
-        &partially_occluded_count);
+    LayerTestCommon::VerifyQuadsAreOccluded(
+        impl.quad_list(), occluded, &partially_occluded_count);
     // The layer outputs one quad, which is partially occluded.
     EXPECT_EQ(100u - 10u, impl.quad_list().size());
     EXPECT_EQ(10u + 10u, partially_occluded_count);
@@ -2647,7 +2923,7 @@ TEST_F(PictureLayerImplTest, LowResReadyToDrawNotEnoughToActivate) {
   EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
 }
 
-TEST_F(PictureLayerImplTest, HighResReadyToDrawNotEnoughToActivate) {
+TEST_F(PictureLayerImplTest, HighResReadyToDrawEnoughToActivate) {
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(1000, 1000);
 
@@ -2666,19 +2942,60 @@ TEST_F(PictureLayerImplTest, HighResReadyToDrawNotEnoughToActivate) {
   // Initialize all high-res tiles.
   pending_layer_->SetAllTilesReadyInTiling(pending_layer_->HighResTiling());
 
-  // High-res tiles should not be enough.
-  EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+  // High-res tiles should be enough, since they cover everything visible.
+  EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+}
 
-  // Initialize remaining tiles.
-  pending_layer_->SetAllTilesReady();
+TEST_F(PictureLayerImplTest,
+       SharedActiveHighResReadyAndPendingLowResReadyNotEnoughToActivate) {
+  gfx::Size tile_size(100, 100);
+  gfx::Size layer_bounds(1000, 1000);
+
+  SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
+
+  // Make sure some tiles are not shared.
+  pending_layer_->set_invalidation(gfx::Rect(gfx::Point(50, 50), tile_size));
+
+  CreateHighLowResAndSetAllTilesVisible();
 
+  // Initialize all high-res tiles in the active layer.
+  active_layer_->SetAllTilesReadyInTiling(active_layer_->HighResTiling());
+  // And all the low-res tiles in the pending layer.
+  pending_layer_->SetAllTilesReadyInTiling(pending_layer_->LowResTiling());
+
+  pending_layer_->MarkVisibleResourcesAsRequired();
+
+  // The unshared high-res tiles are not ready, so we cannot activate.
+  EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+
+  // When the unshared pending high-res tiles are ready, we can activate.
+  pending_layer_->SetAllTilesReadyInTiling(pending_layer_->HighResTiling());
   EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
 }
 
-class NoLowResTilingsSettings : public ImplSidePaintingSettings {
- public:
-  NoLowResTilingsSettings() { create_low_res_tiling = false; }
-};
+TEST_F(PictureLayerImplTest, SharedActiveHighResReadyNotEnoughToActivate) {
+  gfx::Size tile_size(100, 100);
+  gfx::Size layer_bounds(1000, 1000);
+
+  SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
+
+  // Make sure some tiles are not shared.
+  pending_layer_->set_invalidation(gfx::Rect(gfx::Point(50, 50), tile_size));
+
+  CreateHighLowResAndSetAllTilesVisible();
+
+  // Initialize all high-res tiles in the active layer.
+  active_layer_->SetAllTilesReadyInTiling(active_layer_->HighResTiling());
+
+  pending_layer_->MarkVisibleResourcesAsRequired();
+
+  // The unshared high-res tiles are not ready, so we cannot activate.
+  EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+
+  // When the unshared pending high-res tiles are ready, we can activate.
+  pending_layer_->SetAllTilesReadyInTiling(pending_layer_->HighResTiling());
+  EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw());
+}
 
 class NoLowResPictureLayerImplTest : public PictureLayerImplTest {
  public:
@@ -2819,10 +3136,12 @@ TEST_F(NoLowResPictureLayerImplTest, NothingRequiredIfActiveMissingTiles) {
     AssertNoTilesRequired(pending_layer_->LowResTiling());
 }
 
-TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
+TEST_F(NoLowResPictureLayerImplTest,
+       ResourcelessSoftwareDrawHasValidViewportForTilePriority) {
   base::TimeTicks time_ticks;
   time_ticks += base::TimeDelta::FromMilliseconds(1);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
 
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(400, 400);
@@ -2839,8 +3158,6 @@ TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
   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;
@@ -2852,7 +3169,7 @@ TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
                                         resourceless_software_draw);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
   gfx::Rect visible_rect_for_tile_priority =
       active_layer_->visible_rect_for_tile_priority();
@@ -2863,10 +3180,12 @@ TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
   gfx::Transform screen_space_transform_for_tile_priority =
       active_layer_->screen_space_transform_for_tile_priority();
 
-  // Expand viewport and set it as invalid for prioritizing tiles.
-  // Should not update tile viewport.
+  // PictureLayerImpl does not make a special case for
+  // resource_less_software_draw, so the tile viewport and matrix should be
+  // respected.
   time_ticks += base::TimeDelta::FromMilliseconds(200);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
   resourceless_software_draw = true;
   viewport = gfx::ScaleToEnclosingRect(viewport, 2);
   transform.Translate(1.f, 1.f);
@@ -2878,7 +3197,13 @@ TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
                                         viewport,
                                         transform,
                                         resourceless_software_draw);
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
+
+  visible_rect_for_tile_priority =
+      gfx::ScaleToEnclosingRect(visible_rect_for_tile_priority, 2);
+  viewport_rect_for_tile_priority =
+      gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority, 2);
+  screen_space_transform_for_tile_priority = transform;
 
   EXPECT_RECT_EQ(visible_rect_for_tile_priority,
                  active_layer_->visible_rect_for_tile_priority());
@@ -2887,59 +3212,6 @@ TEST_F(NoLowResPictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
   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) {
@@ -3310,7 +3582,7 @@ TEST_F(PictureLayerImplTestWithDelegatingRenderer,
             render_pass->quad_list.back()->material);
 }
 
-class OcclusionTrackingSettings : public ImplSidePaintingSettings {
+class OcclusionTrackingSettings : public LowResTilingsSettings {
  public:
   OcclusionTrackingSettings() { use_occlusion_for_tile_prioritization = true; }
 };
@@ -3373,7 +3645,8 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
        OccludedTilesSkippedDuringRasterization) {
   base::TimeTicks time_ticks;
   time_ticks += base::TimeDelta::FromMilliseconds(1);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
 
   gfx::Size tile_size(102, 102);
   gfx::Size layer_bounds(1000, 1000);
@@ -3418,7 +3691,8 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
   layer1->SetPosition(occluding_layer_position);
 
   time_ticks += base::TimeDelta::FromMilliseconds(200);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
   host_impl_.pending_tree()->UpdateDrawProperties();
 
   unoccluded_tile_count = 0;
@@ -3441,7 +3715,8 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
   layer1->SetPosition(gfx::Point(0, 0));
 
   time_ticks += base::TimeDelta::FromMilliseconds(200);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
   host_impl_.pending_tree()->UpdateDrawProperties();
 
   unoccluded_tile_count = 0;
@@ -3465,7 +3740,8 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
        OccludedTilesNotMarkedAsRequired) {
   base::TimeTicks time_ticks;
   time_ticks += base::TimeDelta::FromMilliseconds(1);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
 
   gfx::Size tile_size(102, 102);
   gfx::Size layer_bounds(1000, 1000);
@@ -3515,7 +3791,8 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
   layer1->SetPosition(occluding_layer_position);
 
   time_ticks += base::TimeDelta::FromMilliseconds(200);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
   host_impl_.pending_tree()->UpdateDrawProperties();
 
   for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
@@ -3553,7 +3830,8 @@ TEST_F(OcclusionTrackingPictureLayerImplTest,
   layer1->SetPosition(gfx::PointF(0, 0));
 
   time_ticks += base::TimeDelta::FromMilliseconds(200);
-  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
   host_impl_.pending_tree()->UpdateDrawProperties();
 
   for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) {
@@ -3944,5 +4222,153 @@ TEST_F(PictureLayerImplTest, RecycledTwinLayer) {
   EXPECT_FALSE(active_layer_->GetRecycledTwinLayer());
 }
 
+void PictureLayerImplTest::TestQuadsForSolidColor(bool test_for_solid) {
+  base::TimeTicks time_ticks;
+  time_ticks += base::TimeDelta::FromMilliseconds(1);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
+
+  gfx::Size tile_size(100, 100);
+  gfx::Size layer_bounds(200, 200);
+  gfx::Rect layer_rect(layer_bounds);
+
+  FakeContentLayerClient client;
+  scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
+  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&host_client);
+  host->SetRootLayer(layer);
+  PicturePile* pile = layer->GetPicturePileForTesting();
+
+  host_impl_.SetViewportSize(layer_bounds);
+
+  int frame_number = 0;
+  FakeRenderingStatsInstrumentation stats_instrumentation;
+
+  client.set_fill_with_nonsolid_color(!test_for_solid);
+
+  Region invalidation(layer_rect);
+  pile->UpdateAndExpandInvalidation(&client,
+                                    &invalidation,
+                                    SK_ColorWHITE,
+                                    false,
+                                    false,
+                                    layer_bounds,
+                                    layer_rect,
+                                    frame_number++,
+                                    Picture::RECORD_NORMALLY,
+                                    &stats_instrumentation);
+
+  scoped_refptr<PicturePileImpl> pending_pile =
+      PicturePileImpl::CreateFromOther(pile);
+
+  SetupPendingTree(pending_pile);
+  ActivateTree();
+
+  if (test_for_solid) {
+    EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+  } else {
+    ASSERT_TRUE(active_layer_->tilings());
+    active_layer_->set_fixed_tile_size(tile_size);
+    host_impl_.active_tree()->UpdateDrawProperties();
+    ASSERT_GT(active_layer_->tilings()->num_tilings(), 0u);
+    std::vector<Tile*> tiles =
+        active_layer_->tilings()->tiling_at(0)->AllTilesForTesting();
+    EXPECT_FALSE(tiles.empty());
+    host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
+  }
+
+  MockOcclusionTracker<LayerImpl> occlusion_tracker;
+  scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+  AppendQuadsData data;
+  active_layer_->WillDraw(DRAW_MODE_SOFTWARE, NULL);
+  active_layer_->AppendQuads(render_pass.get(), occlusion_tracker, &data);
+  active_layer_->DidDraw(NULL);
+
+  DrawQuad::Material expected = test_for_solid
+                                    ? DrawQuad::Material::SOLID_COLOR
+                                    : DrawQuad::Material::TILED_CONTENT;
+  EXPECT_EQ(expected, render_pass->quad_list.front()->material);
+}
+
+TEST_F(PictureLayerImplTest, DrawSolidQuads) {
+  TestQuadsForSolidColor(true);
+}
+
+TEST_F(PictureLayerImplTest, DrawNonSolidQuads) {
+  TestQuadsForSolidColor(false);
+}
+
+TEST_F(PictureLayerImplTest, NonSolidToSolidNoTilings) {
+  base::TimeTicks time_ticks;
+  time_ticks += base::TimeDelta::FromMilliseconds(1);
+  host_impl_.SetCurrentBeginFrameArgs(
+      CreateBeginFrameArgsForTesting(time_ticks));
+
+  gfx::Size tile_size(100, 100);
+  gfx::Size layer_bounds(200, 200);
+  gfx::Rect layer_rect(layer_bounds);
+
+  FakeContentLayerClient client;
+  scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
+  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&host_client);
+  host->SetRootLayer(layer);
+  PicturePile* pile = layer->GetPicturePileForTesting();
+
+  host_impl_.SetViewportSize(layer_bounds);
+
+  int frame_number = 0;
+  FakeRenderingStatsInstrumentation stats_instrumentation;
+
+  client.set_fill_with_nonsolid_color(true);
+
+  Region invalidation1(layer_rect);
+  pile->UpdateAndExpandInvalidation(&client,
+                                    &invalidation1,
+                                    SK_ColorWHITE,
+                                    false,
+                                    false,
+                                    layer_bounds,
+                                    layer_rect,
+                                    frame_number++,
+                                    Picture::RECORD_NORMALLY,
+                                    &stats_instrumentation);
+
+  scoped_refptr<PicturePileImpl> pending_pile1 =
+      PicturePileImpl::CreateFromOther(pile);
+
+  SetupPendingTree(pending_pile1);
+  ActivateTree();
+  host_impl_.active_tree()->UpdateDrawProperties();
+
+  // We've started with a solid layer that contains some tilings.
+  ASSERT_TRUE(active_layer_->tilings());
+  EXPECT_NE(0u, active_layer_->tilings()->num_tilings());
+
+  client.set_fill_with_nonsolid_color(false);
+
+  Region invalidation2(layer_rect);
+  pile->UpdateAndExpandInvalidation(&client,
+                                    &invalidation2,
+                                    SK_ColorWHITE,
+                                    false,
+                                    false,
+                                    layer_bounds,
+                                    layer_rect,
+                                    frame_number++,
+                                    Picture::RECORD_NORMALLY,
+                                    &stats_instrumentation);
+
+  scoped_refptr<PicturePileImpl> pending_pile2 =
+      PicturePileImpl::CreateFromOther(pile);
+
+  SetupPendingTree(pending_pile2);
+  ActivateTree();
+
+  // We've switched to a solid color, so we should end up with no tilings.
+  ASSERT_TRUE(active_layer_->tilings());
+  EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+}
+
 }  // namespace
 }  // namespace cc