Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / cc / layers / tiled_layer_unittest.cc
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