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