Home | History | Annotate | Download | only in layers
      1 // Copyright 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "cc/layers/tiled_layer.h"
      6 
      7 #include <limits>
      8 #include <vector>
      9 
     10 #include "base/run_loop.h"
     11 #include "cc/resources/bitmap_content_layer_updater.h"
     12 #include "cc/resources/layer_painter.h"
     13 #include "cc/resources/prioritized_resource_manager.h"
     14 #include "cc/resources/resource_update_controller.h"
     15 #include "cc/test/animation_test_common.h"
     16 #include "cc/test/fake_layer_tree_host_client.h"
     17 #include "cc/test/fake_layer_tree_host_impl.h"
     18 #include "cc/test/fake_output_surface.h"
     19 #include "cc/test/fake_output_surface_client.h"
     20 #include "cc/test/fake_proxy.h"
     21 #include "cc/test/fake_rendering_stats_instrumentation.h"
     22 #include "cc/test/geometry_test_utils.h"
     23 #include "cc/test/test_shared_bitmap_manager.h"
     24 #include "cc/test/tiled_layer_test_common.h"
     25 #include "cc/trees/occlusion_tracker.h"
     26 #include "cc/trees/single_thread_proxy.h"
     27 #include "testing/gtest/include/gtest/gtest.h"
     28 #include "ui/gfx/rect_conversions.h"
     29 #include "ui/gfx/transform.h"
     30 
     31 namespace cc {
     32 namespace {
     33 
     34 class TestOcclusionTracker : public OcclusionTracker<Layer> {
     35  public:
     36   TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000)) {
     37     stack_.push_back(StackObject());
     38   }
     39 
     40   void SetRenderTarget(Layer* render_target) {
     41     stack_.back().target = render_target;
     42   }
     43 
     44   void SetOcclusion(const SimpleEnclosedRegion& occlusion) {
     45     stack_.back().occlusion_from_inside_target = occlusion;
     46   }
     47 };
     48 
     49 class SynchronousOutputSurfaceLayerTreeHost : public LayerTreeHost {
     50  public:
     51   static scoped_ptr<SynchronousOutputSurfaceLayerTreeHost> Create(
     52       LayerTreeHostClient* client,
     53       SharedBitmapManager* manager,
     54       const LayerTreeSettings& settings,
     55       scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
     56     return make_scoped_ptr(new SynchronousOutputSurfaceLayerTreeHost(
     57         client, manager, settings, impl_task_runner));
     58   }
     59 
     60   virtual ~SynchronousOutputSurfaceLayerTreeHost() {}
     61 
     62   bool EnsureOutputSurfaceCreated() {
     63     base::MessageLoop::current()->PostDelayedTask(
     64         FROM_HERE,
     65         run_loop_.QuitClosure(),
     66         base::TimeDelta::FromSeconds(5));
     67     run_loop_.Run();
     68     return output_surface_created_;
     69   }
     70 
     71   virtual void OnCreateAndInitializeOutputSurfaceAttempted(
     72       bool success) OVERRIDE {
     73     LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(success);
     74     output_surface_created_ = success;
     75     run_loop_.Quit();
     76   }
     77 
     78  private:
     79   SynchronousOutputSurfaceLayerTreeHost(
     80       LayerTreeHostClient* client,
     81       SharedBitmapManager* manager,
     82       const LayerTreeSettings& settings,
     83       scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
     84       : LayerTreeHost(client, manager, settings),
     85         output_surface_created_(false) {
     86     LayerTreeHost::InitializeThreaded(base::MessageLoopProxy::current(),
     87                                       impl_task_runner);
     88   }
     89 
     90   bool output_surface_created_;
     91   base::RunLoop run_loop_;
     92 };
     93 
     94 class TiledLayerTest : public testing::Test {
     95  public:
     96   TiledLayerTest()
     97       : proxy_(NULL),
     98         output_surface_(FakeOutputSurface::Create3d()),
     99         queue_(make_scoped_ptr(new ResourceUpdateQueue)),
    100         impl_thread_("ImplThread"),
    101         fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D),
    102         occlusion_(NULL) {
    103     settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max();
    104     settings_.layer_transforms_should_scale_layer_contents = true;
    105   }
    106 
    107   virtual void SetUp() {
    108     impl_thread_.Start();
    109     shared_bitmap_manager_.reset(new TestSharedBitmapManager());
    110     layer_tree_host_ = SynchronousOutputSurfaceLayerTreeHost::Create(
    111         &fake_layer_tree_host_client_,
    112         shared_bitmap_manager_.get(),
    113         settings_,
    114         impl_thread_.message_loop_proxy());
    115     fake_layer_tree_host_client_.SetLayerTreeHost(layer_tree_host_.get());
    116     proxy_ = layer_tree_host_->proxy();
    117     resource_manager_ = PrioritizedResourceManager::Create(proxy_);
    118     layer_tree_host_->SetLayerTreeHostClientReady();
    119     CHECK(layer_tree_host_->EnsureOutputSurfaceCreated());
    120     layer_tree_host_->SetRootLayer(Layer::Create());
    121 
    122     CHECK(output_surface_->BindToClient(&output_surface_client_));
    123 
    124     DebugScopedSetImplThreadAndMainThreadBlocked
    125         impl_thread_and_main_thread_blocked(proxy_);
    126     resource_provider_ = ResourceProvider::Create(output_surface_.get(),
    127                                                   shared_bitmap_manager_.get(),
    128                                                   NULL,
    129                                                   0,
    130                                                   false,
    131                                                   1,
    132                                                   false);
    133     host_impl_ = make_scoped_ptr(
    134         new FakeLayerTreeHostImpl(proxy_, shared_bitmap_manager_.get()));
    135   }
    136 
    137   virtual ~TiledLayerTest() {
    138     ResourceManagerClearAllMemory(resource_manager_.get(),
    139                                   resource_provider_.get());
    140 
    141     DebugScopedSetImplThreadAndMainThreadBlocked
    142     impl_thread_and_main_thread_blocked(proxy_);
    143     resource_provider_.reset();
    144     host_impl_.reset();
    145   }
    146 
    147   void ResourceManagerClearAllMemory(
    148       PrioritizedResourceManager* resource_manager,
    149       ResourceProvider* resource_provider) {
    150     {
    151       DebugScopedSetImplThreadAndMainThreadBlocked
    152       impl_thread_and_main_thread_blocked(proxy_);
    153       resource_manager->ClearAllMemory(resource_provider);
    154       resource_manager->ReduceMemory(resource_provider);
    155     }
    156     resource_manager->UnlinkAndClearEvictedBackings();
    157   }
    158 
    159   void UpdateTextures() {
    160     DebugScopedSetImplThreadAndMainThreadBlocked
    161     impl_thread_and_main_thread_blocked(proxy_);
    162     DCHECK(queue_);
    163     scoped_ptr<ResourceUpdateController> update_controller =
    164         ResourceUpdateController::Create(NULL,
    165                                          proxy_->ImplThreadTaskRunner(),
    166                                          queue_.Pass(),
    167                                          resource_provider_.get());
    168     update_controller->Finalize();
    169     queue_ = make_scoped_ptr(new ResourceUpdateQueue);
    170   }
    171 
    172   void LayerPushPropertiesTo(FakeTiledLayer* layer,
    173                              FakeTiledLayerImpl* layer_impl) {
    174     DebugScopedSetImplThreadAndMainThreadBlocked
    175     impl_thread_and_main_thread_blocked(proxy_);
    176     layer->PushPropertiesTo(layer_impl);
    177     layer->ResetNumDependentsNeedPushProperties();
    178   }
    179 
    180   void LayerUpdate(FakeTiledLayer* layer, TestOcclusionTracker* occluded) {
    181     DebugScopedSetMainThread main_thread(proxy_);
    182     layer->Update(queue_.get(), occluded);
    183   }
    184 
    185   void CalcDrawProps(RenderSurfaceLayerList* render_surface_layer_list) {
    186     if (occlusion_)
    187       occlusion_->SetRenderTarget(layer_tree_host_->root_layer());
    188 
    189     LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
    190         layer_tree_host_->root_layer(),
    191         layer_tree_host_->device_viewport_size(),
    192         render_surface_layer_list);
    193     inputs.device_scale_factor = layer_tree_host_->device_scale_factor();
    194     inputs.max_texture_size =
    195         layer_tree_host_->GetRendererCapabilities().max_texture_size;
    196     inputs.can_adjust_raster_scales = true;
    197     LayerTreeHostCommon::CalculateDrawProperties(&inputs);
    198   }
    199 
    200   bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1,
    201                      const scoped_ptr<FakeTiledLayerImpl>& layer_impl1) {
    202     scoped_refptr<FakeTiledLayer> layer2;
    203     scoped_ptr<FakeTiledLayerImpl> layer_impl2;
    204     return UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2);
    205   }
    206 
    207   bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1,
    208                      const scoped_ptr<FakeTiledLayerImpl>& layer_impl1,
    209                      const scoped_refptr<FakeTiledLayer>& layer2,
    210                      const scoped_ptr<FakeTiledLayerImpl>& layer_impl2) {
    211     // Get textures
    212     resource_manager_->ClearPriorities();
    213     if (layer1.get())
    214       layer1->SetTexturePriorities(priority_calculator_);
    215     if (layer2.get())
    216       layer2->SetTexturePriorities(priority_calculator_);
    217     resource_manager_->PrioritizeTextures();
    218 
    219     // Save paint properties
    220     if (layer1.get())
    221       layer1->SavePaintProperties();
    222     if (layer2.get())
    223       layer2->SavePaintProperties();
    224 
    225     // Update content
    226     if (layer1.get())
    227       layer1->Update(queue_.get(), occlusion_);
    228     if (layer2.get())
    229       layer2->Update(queue_.get(), occlusion_);
    230 
    231     bool needs_update = false;
    232     if (layer1.get())
    233       needs_update |= layer1->NeedsIdlePaint();
    234     if (layer2.get())
    235       needs_update |= layer2->NeedsIdlePaint();
    236 
    237     // Update textures and push.
    238     UpdateTextures();
    239     if (layer1.get())
    240       LayerPushPropertiesTo(layer1.get(), layer_impl1.get());
    241     if (layer2.get())
    242       LayerPushPropertiesTo(layer2.get(), layer_impl2.get());
    243 
    244     return needs_update;
    245   }
    246 
    247  public:
    248   Proxy* proxy_;
    249   LayerTreeSettings settings_;
    250   FakeOutputSurfaceClient output_surface_client_;
    251   scoped_ptr<OutputSurface> output_surface_;
    252   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
    253   scoped_ptr<ResourceProvider> resource_provider_;
    254   scoped_ptr<ResourceUpdateQueue> queue_;
    255   PriorityCalculator priority_calculator_;
    256   base::Thread impl_thread_;
    257   FakeLayerTreeHostClient fake_layer_tree_host_client_;
    258   scoped_ptr<SynchronousOutputSurfaceLayerTreeHost> layer_tree_host_;
    259   scoped_ptr<FakeLayerTreeHostImpl> host_impl_;
    260   scoped_ptr<PrioritizedResourceManager> resource_manager_;
    261   TestOcclusionTracker* occlusion_;
    262 };
    263 
    264 TEST_F(TiledLayerTest, PushDirtyTiles) {
    265   scoped_refptr<FakeTiledLayer> layer =
    266       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    267   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    268       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    269   RenderSurfaceLayerList render_surface_layer_list;
    270 
    271   layer_tree_host_->root_layer()->AddChild(layer);
    272 
    273   // The tile size is 100x100, so this invalidates and then paints two tiles.
    274   layer->SetBounds(gfx::Size(100, 200));
    275   CalcDrawProps(&render_surface_layer_list);
    276   UpdateAndPush(layer, layer_impl);
    277 
    278   // We should have both tiles on the impl side.
    279   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    280   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
    281 
    282   // Invalidates both tiles, but then only update one of them.
    283   layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 200));
    284   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
    285   UpdateAndPush(layer, layer_impl);
    286 
    287   // We should only have the first tile since the other tile was invalidated but
    288   // not painted.
    289   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    290   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
    291 }
    292 
    293 TEST_F(TiledLayerTest, Scale) {
    294   layer_tree_host_->SetDeviceScaleFactor(1.5);
    295 
    296   scoped_refptr<FakeTiledLayer> layer =
    297       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    298   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    299       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    300   RenderSurfaceLayerList render_surface_layer_list;
    301 
    302   layer_tree_host_->root_layer()->AddChild(layer);
    303 
    304   layer->SetBounds(gfx::Size(100, 200));
    305   CalcDrawProps(&render_surface_layer_list);
    306 
    307   // Change the width so that it doesn't divide cleanly by the scale.
    308   layer->SetBounds(gfx::Size(101, 200));
    309   UpdateAndPush(layer, layer_impl);
    310 
    311   EXPECT_EQ(1.5, layer->fake_layer_updater()->last_contents_width_scale());
    312 }
    313 
    314 TEST_F(TiledLayerTest, PushOccludedDirtyTiles) {
    315   scoped_refptr<FakeTiledLayer> layer =
    316       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    317   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    318       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    319   TestOcclusionTracker occluded;
    320   occlusion_ = &occluded;
    321   layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
    322 
    323   layer_tree_host_->root_layer()->AddChild(layer);
    324 
    325   {
    326     RenderSurfaceLayerList render_surface_layer_list;
    327 
    328     // The tile size is 100x100, so this invalidates and then paints two tiles.
    329     layer->SetBounds(gfx::Size(100, 200));
    330     CalcDrawProps(&render_surface_layer_list);
    331     UpdateAndPush(layer, layer_impl);
    332 
    333     // We should have both tiles on the impl side.
    334     EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    335     EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
    336   }
    337 
    338   {
    339     RenderSurfaceLayerList render_surface_layer_list;
    340 
    341     // Invalidates part of the top tile...
    342     layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
    343     // ....but the area is occluded.
    344     occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 50, 50)));
    345     CalcDrawProps(&render_surface_layer_list);
    346     UpdateAndPush(layer, layer_impl);
    347 
    348     // We should still have both tiles, as part of the top tile is still
    349     // unoccluded.
    350     EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    351     EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
    352   }
    353 }
    354 
    355 TEST_F(TiledLayerTest, PushDeletedTiles) {
    356   scoped_refptr<FakeTiledLayer> layer =
    357       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    358   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    359       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    360   RenderSurfaceLayerList render_surface_layer_list;
    361 
    362   layer_tree_host_->root_layer()->AddChild(layer);
    363 
    364   // The tile size is 100x100, so this invalidates and then paints two tiles.
    365   layer->SetBounds(gfx::Size(100, 200));
    366   CalcDrawProps(&render_surface_layer_list);
    367   UpdateAndPush(layer, layer_impl);
    368 
    369   // We should have both tiles on the impl side.
    370   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    371   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
    372 
    373   resource_manager_->ClearPriorities();
    374   ResourceManagerClearAllMemory(resource_manager_.get(),
    375                                 resource_provider_.get());
    376   resource_manager_->SetMaxMemoryLimitBytes(4 * 1024 * 1024);
    377 
    378   // This should drop the tiles on the impl thread.
    379   LayerPushPropertiesTo(layer.get(), layer_impl.get());
    380 
    381   // We should now have no textures on the impl thread.
    382   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0));
    383   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
    384 
    385   // This should recreate and update one of the deleted textures.
    386   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
    387   UpdateAndPush(layer, layer_impl);
    388 
    389   // We should have one tiles on the impl side.
    390   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    391   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
    392 }
    393 
    394 TEST_F(TiledLayerTest, PushIdlePaintTiles) {
    395   scoped_refptr<FakeTiledLayer> layer =
    396       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    397   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    398       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    399   RenderSurfaceLayerList render_surface_layer_list;
    400 
    401   layer_tree_host_->root_layer()->AddChild(layer);
    402 
    403   // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the
    404   // center.  This paints 1 visible of the 25 invalid tiles.
    405   layer->SetBounds(gfx::Size(500, 500));
    406   CalcDrawProps(&render_surface_layer_list);
    407   layer->draw_properties().visible_content_rect = gfx::Rect(200, 200, 100, 100);
    408   bool needs_update = UpdateAndPush(layer, layer_impl);
    409   // We should need idle-painting for surrounding tiles.
    410   EXPECT_TRUE(needs_update);
    411 
    412   // We should have one tile on the impl side.
    413   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(2, 2));
    414 
    415   // For the next four updates, we should detect we still need idle painting.
    416   for (int i = 0; i < 4; i++) {
    417     needs_update = UpdateAndPush(layer, layer_impl);
    418     EXPECT_TRUE(needs_update);
    419   }
    420 
    421   // We should always finish painting eventually.
    422   for (int i = 0; i < 20; i++)
    423     needs_update = UpdateAndPush(layer, layer_impl);
    424 
    425   // We should have pre-painted all of the surrounding tiles.
    426   for (int i = 0; i < 5; i++) {
    427     for (int j = 0; j < 5; j++)
    428       EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j));
    429   }
    430 
    431   EXPECT_FALSE(needs_update);
    432 }
    433 
    434 TEST_F(TiledLayerTest, PredictivePainting) {
    435   scoped_refptr<FakeTiledLayer> layer =
    436       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    437   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    438       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    439 
    440   layer_tree_host_->root_layer()->AddChild(layer);
    441 
    442   // Prepainting should occur in the scroll direction first, and the
    443   // visible rect should be extruded only along the dominant axis.
    444   gfx::Vector2d directions[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0),
    445                                   gfx::Vector2d(0, -10), gfx::Vector2d(0, 10),
    446                                   gfx::Vector2d(10, 20),
    447                                   gfx::Vector2d(-20, 10) };
    448   // We should push all tiles that touch the extruded visible rect.
    449   gfx::Rect pushed_visible_tiles[6] = {
    450     gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2),
    451     gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1)
    452   };
    453   // The first pre-paint should also paint first in the scroll
    454   // direction so we should find one additional tile in the scroll direction.
    455   gfx::Rect pushed_prepaint_tiles[6] = {
    456     gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3),
    457     gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1)
    458   };
    459   for (int k = 0; k < 6; k++) {
    460     // The tile size is 100x100. Setup 5x5 tiles with one visible tile
    461     // in the center.
    462     gfx::Size bounds = gfx::Size(500, 500);
    463     gfx::Rect visible_rect = gfx::Rect(200, 200, 100, 100);
    464     gfx::Rect previous_visible_rect =
    465         gfx::Rect(visible_rect.origin() + directions[k], visible_rect.size());
    466     gfx::Rect next_visible_rect =
    467         gfx::Rect(visible_rect.origin() - directions[k], visible_rect.size());
    468 
    469     // Setup. Use the previous_visible_rect to setup the prediction for next
    470     // frame.
    471     layer->SetBounds(bounds);
    472 
    473     RenderSurfaceLayerList render_surface_layer_list;
    474     CalcDrawProps(&render_surface_layer_list);
    475     layer->draw_properties().visible_content_rect = previous_visible_rect;
    476     bool needs_update = UpdateAndPush(layer, layer_impl);
    477 
    478     // Invalidate and move the visible_rect in the scroll direction.
    479     // Check that the correct tiles have been painted in the visible pass.
    480     layer->SetNeedsDisplay();
    481     layer->draw_properties().visible_content_rect = visible_rect;
    482     needs_update = UpdateAndPush(layer, layer_impl);
    483     for (int i = 0; i < 5; i++) {
    484       for (int j = 0; j < 5; j++)
    485         EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j),
    486                   pushed_visible_tiles[k].Contains(i, j));
    487     }
    488 
    489     // Move the transform in the same direction without invalidating.
    490     // Check that non-visible pre-painting occured in the correct direction.
    491     // Ignore diagonal scrolls here (k > 3) as these have new visible content
    492     // now.
    493     if (k <= 3) {
    494       layer->draw_properties().visible_content_rect = next_visible_rect;
    495       needs_update = UpdateAndPush(layer, layer_impl);
    496       for (int i = 0; i < 5; i++) {
    497         for (int j = 0; j < 5; j++)
    498           EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j),
    499                     pushed_prepaint_tiles[k].Contains(i, j));
    500       }
    501     }
    502 
    503     // We should always finish painting eventually.
    504     for (int i = 0; i < 20; i++)
    505       needs_update = UpdateAndPush(layer, layer_impl);
    506     EXPECT_FALSE(needs_update);
    507   }
    508 }
    509 
    510 TEST_F(TiledLayerTest, PushTilesAfterIdlePaintFailed) {
    511   // Start with 2mb of memory, but the test is going to try to use just more
    512   // than 1mb, so we reduce to 1mb later.
    513   resource_manager_->SetMaxMemoryLimitBytes(2 * 1024 * 1024);
    514   scoped_refptr<FakeTiledLayer> layer1 =
    515       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    516   scoped_ptr<FakeTiledLayerImpl> layer_impl1 =
    517       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    518   scoped_refptr<FakeTiledLayer> layer2 =
    519       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    520   scoped_ptr<FakeTiledLayerImpl> layer_impl2 =
    521       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2));
    522   RenderSurfaceLayerList render_surface_layer_list;
    523 
    524   layer_tree_host_->root_layer()->AddChild(layer1);
    525   layer_tree_host_->root_layer()->AddChild(layer2);
    526 
    527   // For this test we have two layers. layer1 exhausts most texture memory,
    528   // leaving room for 2 more tiles from layer2, but not all three tiles. First
    529   // we paint layer1, and one tile from layer2. Then when we idle paint layer2,
    530   // we will fail on the third tile of layer2, and this should not leave the
    531   // second tile in a bad state.
    532 
    533   // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough
    534   // for 2 tiles only in the other layer.
    535   gfx::Rect layer1_rect(0, 0, 100, 2400);
    536 
    537   // This requires 4*30000 bytes of memory.
    538   gfx::Rect layer2_rect(0, 0, 100, 300);
    539 
    540   // Paint a single tile in layer2 so that it will idle paint.
    541   layer1->SetBounds(layer1_rect.size());
    542   layer2->SetBounds(layer2_rect.size());
    543   CalcDrawProps(&render_surface_layer_list);
    544   layer1->draw_properties().visible_content_rect = layer1_rect;
    545   layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
    546   bool needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2);
    547   // We should need idle-painting for both remaining tiles in layer2.
    548   EXPECT_TRUE(needs_update);
    549 
    550   // Reduce our memory limits to 1mb.
    551   resource_manager_->SetMaxMemoryLimitBytes(1024 * 1024);
    552 
    553   // Now idle paint layer2. We are going to run out of memory though!
    554   // Oh well, commit the frame and push.
    555   for (int i = 0; i < 4; i++) {
    556     needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2);
    557   }
    558 
    559   // Sanity check, we should have textures for the big layer.
    560   EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 0));
    561   EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 23));
    562 
    563   // We should only have the first two tiles from layer2 since
    564   // it failed to idle update the last tile.
    565   EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0));
    566   EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0));
    567   EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1));
    568   EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1));
    569 
    570   EXPECT_FALSE(needs_update);
    571   EXPECT_FALSE(layer_impl2->HasResourceIdForTileAt(0, 2));
    572 }
    573 
    574 TEST_F(TiledLayerTest, PushIdlePaintedOccludedTiles) {
    575   scoped_refptr<FakeTiledLayer> layer =
    576       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    577   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    578       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    579   RenderSurfaceLayerList render_surface_layer_list;
    580   TestOcclusionTracker occluded;
    581   occlusion_ = &occluded;
    582 
    583   layer_tree_host_->root_layer()->AddChild(layer);
    584 
    585   // The tile size is 100x100, so this invalidates one occluded tile, culls it
    586   // during paint, but prepaints it.
    587   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 100, 100)));
    588 
    589   layer->SetBounds(gfx::Size(100, 100));
    590   CalcDrawProps(&render_surface_layer_list);
    591   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
    592   UpdateAndPush(layer, layer_impl);
    593 
    594   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    595 }
    596 
    597 TEST_F(TiledLayerTest, PushTilesMarkedDirtyDuringPaint) {
    598   scoped_refptr<FakeTiledLayer> layer =
    599       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    600   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    601       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    602   RenderSurfaceLayerList render_surface_layer_list;
    603 
    604   layer_tree_host_->root_layer()->AddChild(layer);
    605 
    606   // The tile size is 100x100, so this invalidates and then paints two tiles.
    607   // However, during the paint, we invalidate one of the tiles. This should
    608   // not prevent the tile from being pushed.
    609   layer->fake_layer_updater()->SetRectToInvalidate(
    610       gfx::Rect(0, 50, 100, 50), layer.get());
    611   layer->SetBounds(gfx::Size(100, 200));
    612   CalcDrawProps(&render_surface_layer_list);
    613   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
    614   UpdateAndPush(layer, layer_impl);
    615 
    616   // We should have both tiles on the impl side.
    617   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    618   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
    619 }
    620 
    621 TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer) {
    622   scoped_refptr<FakeTiledLayer> layer1 =
    623       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    624   scoped_refptr<FakeTiledLayer> layer2 =
    625       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    626   scoped_ptr<FakeTiledLayerImpl> layer1_impl =
    627       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    628   scoped_ptr<FakeTiledLayerImpl> layer2_impl =
    629       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2));
    630   RenderSurfaceLayerList render_surface_layer_list;
    631 
    632   layer_tree_host_->root_layer()->AddChild(layer1);
    633   layer_tree_host_->root_layer()->AddChild(layer2);
    634 
    635   // Invalidate a tile on layer1, during update of layer 2.
    636   layer2->fake_layer_updater()->SetRectToInvalidate(
    637       gfx::Rect(0, 50, 100, 50), layer1.get());
    638   layer1->SetBounds(gfx::Size(100, 200));
    639   layer2->SetBounds(gfx::Size(100, 200));
    640   CalcDrawProps(&render_surface_layer_list);
    641   layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
    642   layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
    643   UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl);
    644 
    645   // We should have both tiles on the impl side for all layers.
    646   EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0));
    647   EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1));
    648   EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0));
    649   EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1));
    650 }
    651 
    652 TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer) {
    653   scoped_refptr<FakeTiledLayer> layer1 =
    654       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    655   scoped_refptr<FakeTiledLayer> layer2 =
    656       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    657   scoped_ptr<FakeTiledLayerImpl> layer1_impl =
    658       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    659   scoped_ptr<FakeTiledLayerImpl> layer2_impl =
    660       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2));
    661   RenderSurfaceLayerList render_surface_layer_list;
    662 
    663   layer_tree_host_->root_layer()->AddChild(layer1);
    664   layer_tree_host_->root_layer()->AddChild(layer2);
    665 
    666   layer1->fake_layer_updater()->SetRectToInvalidate(
    667       gfx::Rect(0, 50, 100, 50), layer2.get());
    668   layer1->SetBounds(gfx::Size(100, 200));
    669   layer2->SetBounds(gfx::Size(100, 200));
    670   CalcDrawProps(&render_surface_layer_list);
    671   layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
    672   layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
    673   UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl);
    674 
    675   // We should have both tiles on the impl side for all layers.
    676   EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0));
    677   EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1));
    678   EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0));
    679   EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1));
    680 }
    681 
    682 TEST_F(TiledLayerTest, PaintSmallAnimatedLayersImmediately) {
    683   // Create a LayerTreeHost that has the right viewportsize,
    684   // so the layer is considered small enough.
    685   bool run_out_of_memory[2] = { false, true };
    686   for (int i = 0; i < 2; i++) {
    687     // Create a layer with 5x5 tiles, with 4x4 size viewport.
    688     int viewport_width = 4 * FakeTiledLayer::tile_size().width();
    689     int viewport_height = 4 * FakeTiledLayer::tile_size().width();
    690     int layer_width = 5 * FakeTiledLayer::tile_size().width();
    691     int layer_height = 5 * FakeTiledLayer::tile_size().height();
    692     int memory_for_layer = layer_width * layer_height * 4;
    693     layer_tree_host_->SetViewportSize(
    694         gfx::Size(viewport_width, viewport_height));
    695 
    696     // Use 10x5 tiles to run out of memory.
    697     if (run_out_of_memory[i])
    698       layer_width *= 2;
    699 
    700     resource_manager_->SetMaxMemoryLimitBytes(memory_for_layer);
    701 
    702     scoped_refptr<FakeTiledLayer> layer =
    703         make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    704     scoped_ptr<FakeTiledLayerImpl> layer_impl =
    705         make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    706     RenderSurfaceLayerList render_surface_layer_list;
    707 
    708     layer_tree_host_->root_layer()->AddChild(layer);
    709 
    710     // Full size layer with half being visible.
    711     layer->SetBounds(gfx::Size(layer_width, layer_height));
    712     gfx::Rect visible_rect(0, 0, layer_width / 2, layer_height);
    713     CalcDrawProps(&render_surface_layer_list);
    714 
    715     // Pretend the layer is animating.
    716     layer->draw_properties().target_space_transform_is_animating = true;
    717     layer->draw_properties().visible_content_rect = visible_rect;
    718     layer->SetLayerTreeHost(layer_tree_host_.get());
    719 
    720     // The layer should paint its entire contents on the first paint
    721     // if it is close to the viewport size and has the available memory.
    722     layer->SetTexturePriorities(priority_calculator_);
    723     resource_manager_->PrioritizeTextures();
    724     layer->SavePaintProperties();
    725     layer->Update(queue_.get(), NULL);
    726     UpdateTextures();
    727     LayerPushPropertiesTo(layer.get(), layer_impl.get());
    728 
    729     // We should have all the tiles for the small animated layer.
    730     // We should still have the visible tiles when we didn't
    731     // have enough memory for all the tiles.
    732     if (!run_out_of_memory[i]) {
    733       for (int i = 0; i < 5; ++i) {
    734         for (int j = 0; j < 5; ++j)
    735           EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j));
    736       }
    737     } else {
    738       for (int i = 0; i < 10; ++i) {
    739         for (int j = 0; j < 5; ++j)
    740           EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), i < 5);
    741       }
    742     }
    743 
    744     layer->RemoveFromParent();
    745   }
    746 }
    747 
    748 TEST_F(TiledLayerTest, IdlePaintOutOfMemory) {
    749   scoped_refptr<FakeTiledLayer> layer =
    750       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    751   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    752       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    753   RenderSurfaceLayerList render_surface_layer_list;
    754 
    755   layer_tree_host_->root_layer()->AddChild(layer);
    756 
    757   // We have enough memory for only the visible rect, so we will run out of
    758   // memory in first idle paint.
    759   int memory_limit = 4 * 100 * 100;  // 1 tiles, 4 bytes per pixel.
    760   resource_manager_->SetMaxMemoryLimitBytes(memory_limit);
    761 
    762   // The tile size is 100x100, so this invalidates and then paints two tiles.
    763   bool needs_update = false;
    764   layer->SetBounds(gfx::Size(300, 300));
    765   CalcDrawProps(&render_surface_layer_list);
    766   layer->draw_properties().visible_content_rect = gfx::Rect(100, 100, 100, 100);
    767   for (int i = 0; i < 2; i++)
    768     needs_update = UpdateAndPush(layer, layer_impl);
    769 
    770   // Idle-painting should see no more priority tiles for painting.
    771   EXPECT_FALSE(needs_update);
    772 
    773   // We should have one tile on the impl side.
    774   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1));
    775 }
    776 
    777 TEST_F(TiledLayerTest, IdlePaintZeroSizedLayer) {
    778   scoped_refptr<FakeTiledLayer> layer =
    779       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    780   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    781       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    782 
    783   layer_tree_host_->root_layer()->AddChild(layer);
    784 
    785   bool animating[2] = { false, true };
    786   for (int i = 0; i < 2; i++) {
    787     // Pretend the layer is animating.
    788     layer->draw_properties().target_space_transform_is_animating = animating[i];
    789 
    790     // The layer's bounds are empty.
    791     // Empty layers don't paint or idle-paint.
    792     layer->SetBounds(gfx::Size());
    793 
    794     RenderSurfaceLayerList render_surface_layer_list;
    795     CalcDrawProps(&render_surface_layer_list);
    796     layer->draw_properties().visible_content_rect = gfx::Rect();
    797     bool needs_update = UpdateAndPush(layer, layer_impl);
    798 
    799     // Empty layers don't have tiles.
    800     EXPECT_EQ(0u, layer->NumPaintedTiles());
    801 
    802     // Empty layers don't need prepaint.
    803     EXPECT_FALSE(needs_update);
    804 
    805     // Empty layers don't have tiles.
    806     EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0));
    807   }
    808 }
    809 
    810 TEST_F(TiledLayerTest, IdlePaintNonVisibleLayers) {
    811   scoped_refptr<FakeTiledLayer> layer =
    812       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    813   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    814       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    815 
    816   // Alternate between not visible and visible.
    817   gfx::Rect v(0, 0, 100, 100);
    818   gfx::Rect nv(0, 0, 0, 0);
    819   gfx::Rect visible_rect[10] = { nv, nv, v, v, nv, nv, v, v, nv, nv };
    820   bool invalidate[10] = { true, true, true, true, true, true, true, true, false,
    821                           false };
    822 
    823   // We should not have any tiles except for when the layer was visible
    824   // or after the layer was visible and we didn't invalidate.
    825   bool have_tile[10] = { false, false, true, true, false, false, true, true,
    826                          true, true };
    827 
    828   layer_tree_host_->root_layer()->AddChild(layer);
    829 
    830   for (int i = 0; i < 10; i++) {
    831     layer->SetBounds(gfx::Size(100, 100));
    832 
    833     RenderSurfaceLayerList render_surface_layer_list;
    834     CalcDrawProps(&render_surface_layer_list);
    835     layer->draw_properties().visible_content_rect = visible_rect[i];
    836 
    837     if (invalidate[i])
    838       layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 100));
    839     bool needs_update = UpdateAndPush(layer, layer_impl);
    840 
    841     // We should never signal idle paint, as we painted the entire layer
    842     // or the layer was not visible.
    843     EXPECT_FALSE(needs_update);
    844     EXPECT_EQ(layer_impl->HasResourceIdForTileAt(0, 0), have_tile[i]);
    845   }
    846 }
    847 
    848 TEST_F(TiledLayerTest, InvalidateFromPrepare) {
    849   scoped_refptr<FakeTiledLayer> layer =
    850       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    851   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    852       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    853   RenderSurfaceLayerList render_surface_layer_list;
    854 
    855   layer_tree_host_->root_layer()->AddChild(layer);
    856 
    857   // The tile size is 100x100, so this invalidates and then paints two tiles.
    858   layer->SetBounds(gfx::Size(100, 200));
    859   CalcDrawProps(&render_surface_layer_list);
    860   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
    861   UpdateAndPush(layer, layer_impl);
    862 
    863   // We should have both tiles on the impl side.
    864   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    865   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
    866 
    867   layer->fake_layer_updater()->ClearPrepareCount();
    868   // Invoke update again. As the layer is valid update shouldn't be invoked on
    869   // the LayerUpdater.
    870   UpdateAndPush(layer, layer_impl);
    871   EXPECT_EQ(0, layer->fake_layer_updater()->prepare_count());
    872 
    873   // SetRectToInvalidate triggers InvalidateContentRect() being invoked from
    874   // update.
    875   layer->fake_layer_updater()->SetRectToInvalidate(
    876       gfx::Rect(25, 25, 50, 50), layer.get());
    877   layer->fake_layer_updater()->ClearPrepareCount();
    878   layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
    879   UpdateAndPush(layer, layer_impl);
    880   EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count());
    881   layer->fake_layer_updater()->ClearPrepareCount();
    882 
    883   // The layer should still be invalid as update invoked invalidate.
    884   UpdateAndPush(layer, layer_impl);  // visible
    885   EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count());
    886 }
    887 
    888 TEST_F(TiledLayerTest, VerifyUpdateRectWhenContentBoundsAreScaled) {
    889   // The update rect (that indicates what was actually painted) should be in
    890   // layer space, not the content space.
    891   scoped_refptr<FakeTiledLayerWithScaledBounds> layer = make_scoped_refptr(
    892       new FakeTiledLayerWithScaledBounds(resource_manager_.get()));
    893 
    894   layer_tree_host_->root_layer()->AddChild(layer);
    895 
    896   gfx::Rect layer_bounds(0, 0, 300, 200);
    897   gfx::Rect content_bounds(0, 0, 150, 250);
    898 
    899   layer->SetBounds(layer_bounds.size());
    900   layer->SetContentBounds(content_bounds.size());
    901   layer->draw_properties().visible_content_rect = content_bounds;
    902   layer->draw_properties().contents_scale_x = .5f;
    903   layer->draw_properties().contents_scale_y = 1.25f;
    904 
    905   // On first update, the update_rect includes all tiles, even beyond the
    906   // boundaries of the layer.
    907   // However, it should still be in layer space, not content space.
    908   layer->InvalidateContentRect(content_bounds);
    909 
    910   layer->SetTexturePriorities(priority_calculator_);
    911   resource_manager_->PrioritizeTextures();
    912   layer->SavePaintProperties();
    913   layer->Update(queue_.get(), NULL);
    914 
    915   // Update rect is 200x300 (tile size of 100x100). Scaled this gives 400x240.
    916   EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 400, 240), layer->update_rect());
    917   UpdateTextures();
    918 
    919   // After the tiles are updated once, another invalidate only needs to update
    920   // the bounds of the layer.
    921   layer->SetTexturePriorities(priority_calculator_);
    922   resource_manager_->PrioritizeTextures();
    923   layer->InvalidateContentRect(content_bounds);
    924   layer->SavePaintProperties();
    925   layer->Update(queue_.get(), NULL);
    926   EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds), layer->update_rect());
    927   UpdateTextures();
    928 
    929   // Partial re-paint should also be represented by the update rect in layer
    930   // space, not content space.
    931   gfx::Rect partial_damage(30, 100, 10, 10);
    932   layer->InvalidateContentRect(partial_damage);
    933   layer->SetTexturePriorities(priority_calculator_);
    934   resource_manager_->PrioritizeTextures();
    935   layer->SavePaintProperties();
    936   layer->Update(queue_.get(), NULL);
    937   EXPECT_FLOAT_RECT_EQ(gfx::RectF(60, 80, 20, 8), layer->update_rect());
    938 }
    939 
    940 TEST_F(TiledLayerTest, VerifyInvalidationWhenContentsScaleChanges) {
    941   scoped_refptr<FakeTiledLayer> layer =
    942       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
    943   scoped_ptr<FakeTiledLayerImpl> layer_impl =
    944       make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
    945   RenderSurfaceLayerList render_surface_layer_list;
    946 
    947   layer_tree_host_->root_layer()->AddChild(layer);
    948 
    949   // Create a layer with one tile.
    950   layer->SetBounds(gfx::Size(100, 100));
    951   CalcDrawProps(&render_surface_layer_list);
    952   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
    953   layer->Update(queue_.get(), NULL);
    954   UpdateTextures();
    955   EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
    956                        layer->last_needs_display_rect());
    957 
    958   // Push the tiles to the impl side and check that there is exactly one.
    959   layer->SetTexturePriorities(priority_calculator_);
    960   resource_manager_->PrioritizeTextures();
    961   layer->SavePaintProperties();
    962   layer->Update(queue_.get(), NULL);
    963   UpdateTextures();
    964   LayerPushPropertiesTo(layer.get(), layer_impl.get());
    965   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    966   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
    967   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0));
    968   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1));
    969 
    970   layer->SetNeedsDisplayRect(gfx::Rect());
    971   EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer->last_needs_display_rect());
    972 
    973   // Change the contents scale.
    974   layer->UpdateContentsScale(2.f);
    975   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 200, 200);
    976 
    977   // The impl side should get 2x2 tiles now.
    978   layer->SetTexturePriorities(priority_calculator_);
    979   resource_manager_->PrioritizeTextures();
    980   layer->SavePaintProperties();
    981   layer->Update(queue_.get(), NULL);
    982   UpdateTextures();
    983   LayerPushPropertiesTo(layer.get(), layer_impl.get());
    984   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
    985   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
    986   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 0));
    987   EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1));
    988 
    989   // Verify that changing the contents scale caused invalidation, and
    990   // that the layer-space rectangle requiring painting is not scaled.
    991   EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
    992                        layer->last_needs_display_rect());
    993 
    994   // Invalidate the entire layer again, but do not paint. All tiles should be
    995   // gone now from the impl side.
    996   layer->SetNeedsDisplay();
    997   layer->SetTexturePriorities(priority_calculator_);
    998   resource_manager_->PrioritizeTextures();
    999 
   1000   LayerPushPropertiesTo(layer.get(), layer_impl.get());
   1001   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0));
   1002   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
   1003   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0));
   1004   EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1));
   1005 }
   1006 
   1007 TEST_F(TiledLayerTest, SkipsDrawGetsReset) {
   1008   // Create two 300 x 300 tiled layers.
   1009   gfx::Size content_bounds(300, 300);
   1010   gfx::Rect content_rect(content_bounds);
   1011 
   1012   // We have enough memory for only one of the two layers.
   1013   int memory_limit = 4 * 300 * 300;  // 4 bytes per pixel.
   1014 
   1015   scoped_refptr<FakeTiledLayer> root_layer = make_scoped_refptr(
   1016       new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
   1017   scoped_refptr<FakeTiledLayer> child_layer = make_scoped_refptr(
   1018       new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
   1019   root_layer->AddChild(child_layer);
   1020 
   1021   root_layer->SetBounds(content_bounds);
   1022   root_layer->draw_properties().visible_content_rect = content_rect;
   1023   root_layer->SetPosition(gfx::PointF(0, 0));
   1024   child_layer->SetBounds(content_bounds);
   1025   child_layer->draw_properties().visible_content_rect = content_rect;
   1026   child_layer->SetPosition(gfx::PointF(0, 0));
   1027   root_layer->InvalidateContentRect(content_rect);
   1028   child_layer->InvalidateContentRect(content_rect);
   1029 
   1030   layer_tree_host_->SetRootLayer(root_layer);
   1031   layer_tree_host_->SetViewportSize(gfx::Size(300, 300));
   1032   layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
   1033       memory_limit);
   1034 
   1035   layer_tree_host_->UpdateLayers(queue_.get());
   1036 
   1037   // We'll skip the root layer.
   1038   EXPECT_TRUE(root_layer->SkipsDraw());
   1039   EXPECT_FALSE(child_layer->SkipsDraw());
   1040 
   1041   layer_tree_host_->CommitComplete();
   1042 
   1043   // Remove the child layer.
   1044   root_layer->RemoveAllChildren();
   1045 
   1046   layer_tree_host_->UpdateLayers(queue_.get());
   1047   EXPECT_FALSE(root_layer->SkipsDraw());
   1048 
   1049   ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
   1050                                 resource_provider_.get());
   1051   layer_tree_host_->SetRootLayer(NULL);
   1052 }
   1053 
   1054 TEST_F(TiledLayerTest, ResizeToSmaller) {
   1055   scoped_refptr<FakeTiledLayer> layer =
   1056       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
   1057 
   1058   layer_tree_host_->root_layer()->AddChild(layer);
   1059 
   1060   layer->SetBounds(gfx::Size(700, 700));
   1061   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700);
   1062   layer->InvalidateContentRect(gfx::Rect(0, 0, 700, 700));
   1063 
   1064   layer->SetTexturePriorities(priority_calculator_);
   1065   resource_manager_->PrioritizeTextures();
   1066   layer->SavePaintProperties();
   1067   layer->Update(queue_.get(), NULL);
   1068 
   1069   layer->SetBounds(gfx::Size(200, 200));
   1070   layer->InvalidateContentRect(gfx::Rect(0, 0, 200, 200));
   1071 }
   1072 
   1073 TEST_F(TiledLayerTest, HugeLayerUpdateCrash) {
   1074   scoped_refptr<FakeTiledLayer> layer =
   1075       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
   1076 
   1077   layer_tree_host_->root_layer()->AddChild(layer);
   1078 
   1079   int size = 1 << 30;
   1080   layer->SetBounds(gfx::Size(size, size));
   1081   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700);
   1082   layer->InvalidateContentRect(gfx::Rect(0, 0, size, size));
   1083 
   1084   // Ensure no crash for bounds where size * size would overflow an int.
   1085   layer->SetTexturePriorities(priority_calculator_);
   1086   resource_manager_->PrioritizeTextures();
   1087   layer->SavePaintProperties();
   1088   layer->Update(queue_.get(), NULL);
   1089 }
   1090 
   1091 class TiledLayerPartialUpdateTest : public TiledLayerTest {
   1092  public:
   1093   TiledLayerPartialUpdateTest() { settings_.max_partial_texture_updates = 4; }
   1094 };
   1095 
   1096 TEST_F(TiledLayerPartialUpdateTest, PartialUpdates) {
   1097   // Create one 300 x 200 tiled layer with 3 x 2 tiles.
   1098   gfx::Size content_bounds(300, 200);
   1099   gfx::Rect content_rect(content_bounds);
   1100 
   1101   scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(
   1102       new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
   1103   layer->SetBounds(content_bounds);
   1104   layer->SetPosition(gfx::PointF(0, 0));
   1105   layer->draw_properties().visible_content_rect = content_rect;
   1106   layer->InvalidateContentRect(content_rect);
   1107 
   1108   layer_tree_host_->SetRootLayer(layer);
   1109   layer_tree_host_->SetViewportSize(gfx::Size(300, 200));
   1110 
   1111   // Full update of all 6 tiles.
   1112   layer_tree_host_->UpdateLayers(queue_.get());
   1113   {
   1114     scoped_ptr<FakeTiledLayerImpl> layer_impl =
   1115         make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
   1116     EXPECT_EQ(6u, queue_->FullUploadSize());
   1117     EXPECT_EQ(0u, queue_->PartialUploadSize());
   1118     UpdateTextures();
   1119     EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
   1120     EXPECT_FALSE(queue_->HasMoreUpdates());
   1121     layer->fake_layer_updater()->ClearUpdateCount();
   1122     LayerPushPropertiesTo(layer.get(), layer_impl.get());
   1123   }
   1124   layer_tree_host_->CommitComplete();
   1125 
   1126   // Full update of 3 tiles and partial update of 3 tiles.
   1127   layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 150));
   1128   layer_tree_host_->UpdateLayers(queue_.get());
   1129   {
   1130     scoped_ptr<FakeTiledLayerImpl> layer_impl =
   1131         make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
   1132     EXPECT_EQ(3u, queue_->FullUploadSize());
   1133     EXPECT_EQ(3u, queue_->PartialUploadSize());
   1134     UpdateTextures();
   1135     EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
   1136     EXPECT_FALSE(queue_->HasMoreUpdates());
   1137     layer->fake_layer_updater()->ClearUpdateCount();
   1138     LayerPushPropertiesTo(layer.get(), layer_impl.get());
   1139   }
   1140   layer_tree_host_->CommitComplete();
   1141 
   1142   // Partial update of 6 tiles.
   1143   layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
   1144   {
   1145     scoped_ptr<FakeTiledLayerImpl> layer_impl =
   1146         make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
   1147     layer_tree_host_->UpdateLayers(queue_.get());
   1148     EXPECT_EQ(2u, queue_->FullUploadSize());
   1149     EXPECT_EQ(4u, queue_->PartialUploadSize());
   1150     UpdateTextures();
   1151     EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
   1152     EXPECT_FALSE(queue_->HasMoreUpdates());
   1153     layer->fake_layer_updater()->ClearUpdateCount();
   1154     LayerPushPropertiesTo(layer.get(), layer_impl.get());
   1155   }
   1156   layer_tree_host_->CommitComplete();
   1157 
   1158   // Checkerboard all tiles.
   1159   layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 200));
   1160   {
   1161     scoped_ptr<FakeTiledLayerImpl> layer_impl =
   1162         make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
   1163     LayerPushPropertiesTo(layer.get(), layer_impl.get());
   1164   }
   1165   layer_tree_host_->CommitComplete();
   1166 
   1167   // Partial update of 6 checkerboard tiles.
   1168   layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
   1169   {
   1170     scoped_ptr<FakeTiledLayerImpl> layer_impl =
   1171         make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
   1172     layer_tree_host_->UpdateLayers(queue_.get());
   1173     EXPECT_EQ(6u, queue_->FullUploadSize());
   1174     EXPECT_EQ(0u, queue_->PartialUploadSize());
   1175     UpdateTextures();
   1176     EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
   1177     EXPECT_FALSE(queue_->HasMoreUpdates());
   1178     layer->fake_layer_updater()->ClearUpdateCount();
   1179     LayerPushPropertiesTo(layer.get(), layer_impl.get());
   1180   }
   1181   layer_tree_host_->CommitComplete();
   1182 
   1183   // Partial update of 4 tiles.
   1184   layer->InvalidateContentRect(gfx::Rect(50, 50, 100, 100));
   1185   {
   1186     scoped_ptr<FakeTiledLayerImpl> layer_impl =
   1187         make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
   1188     layer_tree_host_->UpdateLayers(queue_.get());
   1189     EXPECT_EQ(0u, queue_->FullUploadSize());
   1190     EXPECT_EQ(4u, queue_->PartialUploadSize());
   1191     UpdateTextures();
   1192     EXPECT_EQ(4, layer->fake_layer_updater()->update_count());
   1193     EXPECT_FALSE(queue_->HasMoreUpdates());
   1194     layer->fake_layer_updater()->ClearUpdateCount();
   1195     LayerPushPropertiesTo(layer.get(), layer_impl.get());
   1196   }
   1197   layer_tree_host_->CommitComplete();
   1198 
   1199   ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
   1200                                 resource_provider_.get());
   1201   layer_tree_host_->SetRootLayer(NULL);
   1202 }
   1203 
   1204 TEST_F(TiledLayerTest, TilesPaintedWithoutOcclusion) {
   1205   scoped_refptr<FakeTiledLayer> layer =
   1206       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
   1207   RenderSurfaceLayerList render_surface_layer_list;
   1208 
   1209   layer_tree_host_->root_layer()->AddChild(layer);
   1210 
   1211   // The tile size is 100x100, so this invalidates and then paints two tiles.
   1212   layer->SetBounds(gfx::Size(100, 200));
   1213   CalcDrawProps(&render_surface_layer_list);
   1214 
   1215   layer->SetTexturePriorities(priority_calculator_);
   1216   resource_manager_->PrioritizeTextures();
   1217   layer->SavePaintProperties();
   1218   layer->Update(queue_.get(), NULL);
   1219   EXPECT_EQ(2, layer->fake_layer_updater()->update_count());
   1220 }
   1221 
   1222 TEST_F(TiledLayerTest, TilesPaintedWithOcclusion) {
   1223   scoped_refptr<FakeTiledLayer> layer =
   1224       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
   1225   RenderSurfaceLayerList render_surface_layer_list;
   1226   TestOcclusionTracker occluded;
   1227   occlusion_ = &occluded;
   1228 
   1229   layer_tree_host_->root_layer()->AddChild(layer);
   1230 
   1231   // The tile size is 100x100.
   1232 
   1233   layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
   1234   layer->SetBounds(gfx::Size(600, 600));
   1235   CalcDrawProps(&render_surface_layer_list);
   1236 
   1237   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
   1238   layer->draw_properties().drawable_content_rect =
   1239       gfx::Rect(layer->content_bounds());
   1240   layer->draw_properties().visible_content_rect =
   1241       gfx::Rect(layer->content_bounds());
   1242   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1243 
   1244   layer->SetTexturePriorities(priority_calculator_);
   1245   resource_manager_->PrioritizeTextures();
   1246   layer->SavePaintProperties();
   1247   layer->Update(queue_.get(), &occluded);
   1248   EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count());
   1249 
   1250   layer->fake_layer_updater()->ClearUpdateCount();
   1251   layer->SetTexturePriorities(priority_calculator_);
   1252   resource_manager_->PrioritizeTextures();
   1253 
   1254   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 200, 300, 100)));
   1255   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1256   layer->SavePaintProperties();
   1257   layer->Update(queue_.get(), &occluded);
   1258   EXPECT_EQ(36 - 2, layer->fake_layer_updater()->update_count());
   1259 
   1260   layer->fake_layer_updater()->ClearUpdateCount();
   1261   layer->SetTexturePriorities(priority_calculator_);
   1262   resource_manager_->PrioritizeTextures();
   1263 
   1264   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 250, 300, 100)));
   1265   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1266   layer->SavePaintProperties();
   1267   layer->Update(queue_.get(), &occluded);
   1268   EXPECT_EQ(36, layer->fake_layer_updater()->update_count());
   1269 }
   1270 
   1271 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndVisiblityConstraints) {
   1272   scoped_refptr<FakeTiledLayer> layer =
   1273       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
   1274   RenderSurfaceLayerList render_surface_layer_list;
   1275   TestOcclusionTracker occluded;
   1276   occlusion_ = &occluded;
   1277 
   1278   layer_tree_host_->root_layer()->AddChild(layer);
   1279 
   1280   // The tile size is 100x100.
   1281 
   1282   layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
   1283   layer->SetBounds(gfx::Size(600, 600));
   1284   CalcDrawProps(&render_surface_layer_list);
   1285 
   1286   // The partially occluded tiles (by the 150 occlusion height) are visible
   1287   // beyond the occlusion, so not culled.
   1288   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
   1289   layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 360);
   1290   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 360);
   1291   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1292 
   1293   layer->SetTexturePriorities(priority_calculator_);
   1294   resource_manager_->PrioritizeTextures();
   1295   layer->SavePaintProperties();
   1296   layer->Update(queue_.get(), &occluded);
   1297   EXPECT_EQ(24 - 3, layer->fake_layer_updater()->update_count());
   1298 
   1299   layer->fake_layer_updater()->ClearUpdateCount();
   1300 
   1301   // Now the visible region stops at the edge of the occlusion so the partly
   1302   // visible tiles become fully occluded.
   1303   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
   1304   layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 350);
   1305   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 350);
   1306   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1307   layer->SetTexturePriorities(priority_calculator_);
   1308   resource_manager_->PrioritizeTextures();
   1309   layer->SavePaintProperties();
   1310   layer->Update(queue_.get(), &occluded);
   1311   EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count());
   1312 
   1313   layer->fake_layer_updater()->ClearUpdateCount();
   1314 
   1315   // Now the visible region is even smaller than the occlusion, it should have
   1316   // the same result.
   1317   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
   1318   layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 340);
   1319   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 340);
   1320   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1321   layer->SetTexturePriorities(priority_calculator_);
   1322   resource_manager_->PrioritizeTextures();
   1323   layer->SavePaintProperties();
   1324   layer->Update(queue_.get(), &occluded);
   1325   EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count());
   1326 }
   1327 
   1328 TEST_F(TiledLayerTest, TilesNotPaintedWithoutInvalidation) {
   1329   scoped_refptr<FakeTiledLayer> layer =
   1330       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
   1331   RenderSurfaceLayerList render_surface_layer_list;
   1332   TestOcclusionTracker occluded;
   1333   occlusion_ = &occluded;
   1334 
   1335   layer_tree_host_->root_layer()->AddChild(layer);
   1336 
   1337   // The tile size is 100x100.
   1338 
   1339   layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
   1340   layer->SetBounds(gfx::Size(600, 600));
   1341   CalcDrawProps(&render_surface_layer_list);
   1342 
   1343   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
   1344   layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 600);
   1345   layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 600);
   1346   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1347   layer->SetTexturePriorities(priority_calculator_);
   1348   resource_manager_->PrioritizeTextures();
   1349   layer->SavePaintProperties();
   1350   layer->Update(queue_.get(), &occluded);
   1351   EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count());
   1352   UpdateTextures();
   1353 
   1354   layer->fake_layer_updater()->ClearUpdateCount();
   1355   layer->SetTexturePriorities(priority_calculator_);
   1356   resource_manager_->PrioritizeTextures();
   1357   layer->SavePaintProperties();
   1358 
   1359   // Repaint without marking it dirty. The 3 culled tiles will be pre-painted
   1360   // now.
   1361   layer->Update(queue_.get(), &occluded);
   1362   EXPECT_EQ(3, layer->fake_layer_updater()->update_count());
   1363 }
   1364 
   1365 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndTransforms) {
   1366   scoped_refptr<FakeTiledLayer> layer =
   1367       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
   1368   RenderSurfaceLayerList render_surface_layer_list;
   1369   TestOcclusionTracker occluded;
   1370   occlusion_ = &occluded;
   1371 
   1372   layer_tree_host_->root_layer()->AddChild(layer);
   1373 
   1374   // The tile size is 100x100.
   1375 
   1376   // This makes sure the painting works when the occluded region (in screen
   1377   // space) is transformed differently than the layer.
   1378   layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
   1379   layer->SetBounds(gfx::Size(600, 600));
   1380   CalcDrawProps(&render_surface_layer_list);
   1381   gfx::Transform screen_transform;
   1382   screen_transform.Scale(0.5, 0.5);
   1383   layer->draw_properties().screen_space_transform = screen_transform;
   1384   layer->draw_properties().target_space_transform = screen_transform;
   1385 
   1386   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 50)));
   1387   layer->draw_properties().drawable_content_rect =
   1388       gfx::Rect(layer->content_bounds());
   1389   layer->draw_properties().visible_content_rect =
   1390       gfx::Rect(layer->content_bounds());
   1391   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1392   layer->SetTexturePriorities(priority_calculator_);
   1393   resource_manager_->PrioritizeTextures();
   1394   layer->SavePaintProperties();
   1395   layer->Update(queue_.get(), &occluded);
   1396   EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count());
   1397 }
   1398 
   1399 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndScaling) {
   1400   scoped_refptr<FakeTiledLayer> layer =
   1401       new FakeTiledLayer(resource_manager_.get());
   1402   RenderSurfaceLayerList render_surface_layer_list;
   1403   TestOcclusionTracker occluded;
   1404   occlusion_ = &occluded;
   1405 
   1406   scoped_refptr<FakeTiledLayer> scale_layer =
   1407       new FakeTiledLayer(resource_manager_.get());
   1408   gfx::Transform scale_transform;
   1409   scale_transform.Scale(2.0, 2.0);
   1410   scale_layer->SetTransform(scale_transform);
   1411 
   1412   layer_tree_host_->root_layer()->AddChild(scale_layer);
   1413 
   1414   // The tile size is 100x100.
   1415 
   1416   // This makes sure the painting works when the content space is scaled to
   1417   // a different layer space.
   1418   layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
   1419   layer->SetBounds(gfx::Size(300, 300));
   1420   scale_layer->AddChild(layer);
   1421   CalcDrawProps(&render_surface_layer_list);
   1422   EXPECT_FLOAT_EQ(2.f, layer->contents_scale_x());
   1423   EXPECT_FLOAT_EQ(2.f, layer->contents_scale_y());
   1424   EXPECT_EQ(gfx::Size(600, 600).ToString(),
   1425             layer->content_bounds().ToString());
   1426 
   1427   // No tiles are covered by the 300x50 occlusion.
   1428   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 50)));
   1429   layer->draw_properties().drawable_content_rect =
   1430       gfx::Rect(layer->bounds());
   1431   layer->draw_properties().visible_content_rect =
   1432       gfx::Rect(layer->content_bounds());
   1433   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1434   layer->SetTexturePriorities(priority_calculator_);
   1435   resource_manager_->PrioritizeTextures();
   1436   layer->SavePaintProperties();
   1437   layer->Update(queue_.get(), &occluded);
   1438   int visible_tiles1 = 6 * 6;
   1439   EXPECT_EQ(visible_tiles1, layer->fake_layer_updater()->update_count());
   1440 
   1441   layer->fake_layer_updater()->ClearUpdateCount();
   1442 
   1443   // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still.
   1444   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
   1445   layer->draw_properties().drawable_content_rect =
   1446       gfx::Rect(layer->bounds());
   1447   layer->draw_properties().visible_content_rect =
   1448       gfx::Rect(layer->content_bounds());
   1449   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1450   layer->SetTexturePriorities(priority_calculator_);
   1451   resource_manager_->PrioritizeTextures();
   1452   layer->SavePaintProperties();
   1453   layer->Update(queue_.get(), &occluded);
   1454   int visible_tiles2 = 6 * 6 - 3;
   1455   EXPECT_EQ(visible_tiles2, layer->fake_layer_updater()->update_count());
   1456 
   1457   layer->fake_layer_updater()->ClearUpdateCount();
   1458 
   1459   // This makes sure content scaling and transforms work together.
   1460   // When the tiles are scaled down by half, they are 50x50 each in the
   1461   // screen.
   1462   gfx::Transform screen_transform;
   1463   screen_transform.Scale(0.5, 0.5);
   1464   layer->draw_properties().screen_space_transform = screen_transform;
   1465   layer->draw_properties().target_space_transform = screen_transform;
   1466 
   1467   // An occlusion of 150x100 will cover 3*2 = 6 tiles.
   1468   occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 100)));
   1469 
   1470   gfx::Rect layer_bounds_rect(layer->bounds());
   1471   layer->draw_properties().drawable_content_rect =
   1472       gfx::ScaleToEnclosingRect(layer_bounds_rect, 0.5f);
   1473   layer->draw_properties().visible_content_rect =
   1474       gfx::Rect(layer->content_bounds());
   1475   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
   1476   layer->SetTexturePriorities(priority_calculator_);
   1477   resource_manager_->PrioritizeTextures();
   1478   layer->SavePaintProperties();
   1479   layer->Update(queue_.get(), &occluded);
   1480   int visible_tiles3 = 6 * 6 - 6;
   1481   EXPECT_EQ(visible_tiles3, layer->fake_layer_updater()->update_count());
   1482 }
   1483 
   1484 TEST_F(TiledLayerTest, DontAllocateContentsWhenTargetSurfaceCantBeAllocated) {
   1485   // Tile size is 100x100.
   1486   gfx::Rect root_rect(0, 0, 300, 200);
   1487   gfx::Rect child_rect(0, 0, 300, 100);
   1488   gfx::Rect child2_rect(0, 100, 300, 100);
   1489 
   1490   scoped_refptr<FakeTiledLayer> root = make_scoped_refptr(
   1491       new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
   1492   scoped_refptr<Layer> surface = Layer::Create();
   1493   scoped_refptr<FakeTiledLayer> child = make_scoped_refptr(
   1494       new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
   1495   scoped_refptr<FakeTiledLayer> child2 = make_scoped_refptr(
   1496       new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
   1497 
   1498   root->SetBounds(root_rect.size());
   1499   root->draw_properties().drawable_content_rect = root_rect;
   1500   root->draw_properties().visible_content_rect = root_rect;
   1501   root->AddChild(surface);
   1502 
   1503   surface->SetForceRenderSurface(true);
   1504   surface->SetOpacity(0.5);
   1505   surface->AddChild(child);
   1506   surface->AddChild(child2);
   1507 
   1508   child->SetBounds(child_rect.size());
   1509   child->SetPosition(child_rect.origin());
   1510   child->draw_properties().visible_content_rect = child_rect;
   1511   child->draw_properties().drawable_content_rect = root_rect;
   1512 
   1513   child2->SetBounds(child2_rect.size());
   1514   child2->SetPosition(child2_rect.origin());
   1515   child2->draw_properties().visible_content_rect = child2_rect;
   1516   child2->draw_properties().drawable_content_rect = root_rect;
   1517 
   1518   layer_tree_host_->SetRootLayer(root);
   1519   layer_tree_host_->SetViewportSize(root_rect.size());
   1520 
   1521   // With a huge memory limit, all layers should update and push their textures.
   1522   root->InvalidateContentRect(root_rect);
   1523   child->InvalidateContentRect(child_rect);
   1524   child2->InvalidateContentRect(child2_rect);
   1525   layer_tree_host_->UpdateLayers(queue_.get());
   1526   {
   1527     UpdateTextures();
   1528     EXPECT_EQ(6, root->fake_layer_updater()->update_count());
   1529     EXPECT_EQ(3, child->fake_layer_updater()->update_count());
   1530     EXPECT_EQ(3, child2->fake_layer_updater()->update_count());
   1531     EXPECT_FALSE(queue_->HasMoreUpdates());
   1532 
   1533     root->fake_layer_updater()->ClearUpdateCount();
   1534     child->fake_layer_updater()->ClearUpdateCount();
   1535     child2->fake_layer_updater()->ClearUpdateCount();
   1536 
   1537     scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
   1538         new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
   1539     scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
   1540         new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
   1541     scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
   1542         new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
   1543     LayerPushPropertiesTo(child2.get(), child2_impl.get());
   1544     LayerPushPropertiesTo(child.get(), child_impl.get());
   1545     LayerPushPropertiesTo(root.get(), root_impl.get());
   1546 
   1547     for (unsigned i = 0; i < 3; ++i) {
   1548       for (unsigned j = 0; j < 2; ++j)
   1549         EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j));
   1550       EXPECT_TRUE(child_impl->HasResourceIdForTileAt(i, 0));
   1551       EXPECT_TRUE(child2_impl->HasResourceIdForTileAt(i, 0));
   1552     }
   1553   }
   1554   layer_tree_host_->CommitComplete();
   1555 
   1556   // With a memory limit that includes only the root layer (3x2 tiles) and half
   1557   // the surface that the child layers draw into, the child layers will not be
   1558   // allocated. If the surface isn't accounted for, then one of the children
   1559   // would fit within the memory limit.
   1560   root->InvalidateContentRect(root_rect);
   1561   child->InvalidateContentRect(child_rect);
   1562   child2->InvalidateContentRect(child2_rect);
   1563 
   1564   size_t memory_limit = (3 * 2 + 3 * 1) * (100 * 100) * 4;
   1565   layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
   1566       memory_limit);
   1567   layer_tree_host_->UpdateLayers(queue_.get());
   1568   {
   1569     UpdateTextures();
   1570     EXPECT_EQ(6, root->fake_layer_updater()->update_count());
   1571     EXPECT_EQ(0, child->fake_layer_updater()->update_count());
   1572     EXPECT_EQ(0, child2->fake_layer_updater()->update_count());
   1573     EXPECT_FALSE(queue_->HasMoreUpdates());
   1574 
   1575     root->fake_layer_updater()->ClearUpdateCount();
   1576     child->fake_layer_updater()->ClearUpdateCount();
   1577     child2->fake_layer_updater()->ClearUpdateCount();
   1578 
   1579     scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
   1580         new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
   1581     scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
   1582         new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
   1583     scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
   1584         new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
   1585     LayerPushPropertiesTo(child2.get(), child2_impl.get());
   1586     LayerPushPropertiesTo(child.get(), child_impl.get());
   1587     LayerPushPropertiesTo(root.get(), root_impl.get());
   1588 
   1589     for (unsigned i = 0; i < 3; ++i) {
   1590       for (unsigned j = 0; j < 2; ++j)
   1591         EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j));
   1592       EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0));
   1593       EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0));
   1594     }
   1595   }
   1596   layer_tree_host_->CommitComplete();
   1597 
   1598   // With a memory limit that includes only half the root layer, no contents
   1599   // will be allocated. If render surface memory wasn't accounted for, there is
   1600   // enough space for one of the children layers, but they draw into a surface
   1601   // that can't be allocated.
   1602   root->InvalidateContentRect(root_rect);
   1603   child->InvalidateContentRect(child_rect);
   1604   child2->InvalidateContentRect(child2_rect);
   1605 
   1606   memory_limit = (3 * 1) * (100 * 100) * 4;
   1607   layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
   1608       memory_limit);
   1609   layer_tree_host_->UpdateLayers(queue_.get());
   1610   {
   1611     UpdateTextures();
   1612     EXPECT_EQ(0, root->fake_layer_updater()->update_count());
   1613     EXPECT_EQ(0, child->fake_layer_updater()->update_count());
   1614     EXPECT_EQ(0, child2->fake_layer_updater()->update_count());
   1615     EXPECT_FALSE(queue_->HasMoreUpdates());
   1616 
   1617     root->fake_layer_updater()->ClearUpdateCount();
   1618     child->fake_layer_updater()->ClearUpdateCount();
   1619     child2->fake_layer_updater()->ClearUpdateCount();
   1620 
   1621     scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
   1622         new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
   1623     scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
   1624         new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
   1625     scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
   1626         new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
   1627     LayerPushPropertiesTo(child2.get(), child2_impl.get());
   1628     LayerPushPropertiesTo(child.get(), child_impl.get());
   1629     LayerPushPropertiesTo(root.get(), root_impl.get());
   1630 
   1631     for (unsigned i = 0; i < 3; ++i) {
   1632       for (unsigned j = 0; j < 2; ++j)
   1633         EXPECT_FALSE(root_impl->HasResourceIdForTileAt(i, j));
   1634       EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0));
   1635       EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0));
   1636     }
   1637   }
   1638   layer_tree_host_->CommitComplete();
   1639 
   1640   ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
   1641                                 resource_provider_.get());
   1642   layer_tree_host_->SetRootLayer(NULL);
   1643 }
   1644 
   1645 class TrackingLayerPainter : public LayerPainter {
   1646  public:
   1647   static scoped_ptr<TrackingLayerPainter> Create() {
   1648     return make_scoped_ptr(new TrackingLayerPainter());
   1649   }
   1650 
   1651   virtual void Paint(SkCanvas* canvas, const gfx::Rect& content_rect) OVERRIDE {
   1652     painted_rect_ = content_rect;
   1653   }
   1654 
   1655   gfx::Rect PaintedRect() const { return painted_rect_; }
   1656   void ResetPaintedRect() { painted_rect_ = gfx::Rect(); }
   1657 
   1658  private:
   1659   gfx::Rect painted_rect_;
   1660 };
   1661 
   1662 class UpdateTrackingTiledLayer : public FakeTiledLayer {
   1663  public:
   1664   explicit UpdateTrackingTiledLayer(PrioritizedResourceManager* manager)
   1665       : FakeTiledLayer(manager) {
   1666     scoped_ptr<TrackingLayerPainter> painter(TrackingLayerPainter::Create());
   1667     tracking_layer_painter_ = painter.get();
   1668     layer_updater_ =
   1669         BitmapContentLayerUpdater::Create(painter.PassAs<LayerPainter>(),
   1670                                           &stats_instrumentation_,
   1671                                           0);
   1672   }
   1673 
   1674   TrackingLayerPainter* tracking_layer_painter() const {
   1675     return tracking_layer_painter_;
   1676   }
   1677 
   1678  private:
   1679   virtual LayerUpdater* Updater() const OVERRIDE {
   1680     return layer_updater_.get();
   1681   }
   1682   virtual ~UpdateTrackingTiledLayer() {}
   1683 
   1684   TrackingLayerPainter* tracking_layer_painter_;
   1685   scoped_refptr<BitmapContentLayerUpdater> layer_updater_;
   1686   FakeRenderingStatsInstrumentation stats_instrumentation_;
   1687 };
   1688 
   1689 TEST_F(TiledLayerTest, NonIntegerContentsScaleIsNotDistortedDuringPaint) {
   1690   scoped_refptr<UpdateTrackingTiledLayer> layer =
   1691       make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get()));
   1692 
   1693   layer_tree_host_->root_layer()->AddChild(layer);
   1694 
   1695   gfx::Rect layer_rect(0, 0, 30, 31);
   1696   layer->SetPosition(layer_rect.origin());
   1697   layer->SetBounds(layer_rect.size());
   1698   layer->UpdateContentsScale(1.5f);
   1699 
   1700   gfx::Rect content_rect(0, 0, 45, 47);
   1701   EXPECT_EQ(content_rect.size(), layer->content_bounds());
   1702   layer->draw_properties().visible_content_rect = content_rect;
   1703   layer->draw_properties().drawable_content_rect = content_rect;
   1704 
   1705   layer->SetTexturePriorities(priority_calculator_);
   1706   resource_manager_->PrioritizeTextures();
   1707   layer->SavePaintProperties();
   1708 
   1709   // Update the whole tile.
   1710   layer->Update(queue_.get(), NULL);
   1711   layer->tracking_layer_painter()->ResetPaintedRect();
   1712 
   1713   EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect());
   1714   UpdateTextures();
   1715 
   1716   // Invalidate the entire layer in content space. When painting, the rect given
   1717   // to webkit should match the layer's bounds.
   1718   layer->InvalidateContentRect(content_rect);
   1719   layer->Update(queue_.get(), NULL);
   1720 
   1721   // Rounding leads to an extra pixel.
   1722   gfx::Rect expanded_layer_rect(layer_rect);
   1723   expanded_layer_rect.set_height(32);
   1724   EXPECT_RECT_EQ(expanded_layer_rect,
   1725                  layer->tracking_layer_painter()->PaintedRect());
   1726 }
   1727 
   1728 TEST_F(TiledLayerTest,
   1729        NonIntegerContentsScaleIsNotDistortedDuringInvalidation) {
   1730   scoped_refptr<UpdateTrackingTiledLayer> layer =
   1731       make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get()));
   1732 
   1733   layer_tree_host_->root_layer()->AddChild(layer);
   1734 
   1735   gfx::Rect layer_rect(0, 0, 30, 31);
   1736   layer->SetPosition(layer_rect.origin());
   1737   layer->SetBounds(layer_rect.size());
   1738   layer->UpdateContentsScale(1.3f);
   1739 
   1740   gfx::Rect content_rect(layer->content_bounds());
   1741   layer->draw_properties().visible_content_rect = content_rect;
   1742   layer->draw_properties().drawable_content_rect = content_rect;
   1743 
   1744   layer->SetTexturePriorities(priority_calculator_);
   1745   resource_manager_->PrioritizeTextures();
   1746   layer->SavePaintProperties();
   1747 
   1748   // Update the whole tile.
   1749   layer->Update(queue_.get(), NULL);
   1750   layer->tracking_layer_painter()->ResetPaintedRect();
   1751 
   1752   EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect());
   1753   UpdateTextures();
   1754 
   1755   // Invalidate the entire layer in layer space. When painting, the rect given
   1756   // to webkit should match the layer's bounds.
   1757   layer->SetNeedsDisplayRect(layer_rect);
   1758   layer->Update(queue_.get(), NULL);
   1759 
   1760   // Rounding leads to an extra pixel.
   1761   gfx::Rect expanded_layer_rect(layer_rect);
   1762   expanded_layer_rect.set_height(32);
   1763   EXPECT_RECT_EQ(expanded_layer_rect,
   1764                  layer->tracking_layer_painter()->PaintedRect());
   1765 }
   1766 
   1767 }  // namespace
   1768 }  // namespace cc
   1769