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