Upstream version 9.38.198.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 Region& occlusion) {
45     stack_.back().occlusion_from_inside_target = occlusion;
46   }
47 };
48
49 class SynchronousOutputSurfaceLayerTreeHost : public LayerTreeHost {
50  public:
51   static scoped_ptr<SynchronousOutputSurfaceLayerTreeHost> Create(
52       LayerTreeHostClient* client,
53       SharedBitmapManager* manager,
54       const LayerTreeSettings& settings,
55       scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
56     return make_scoped_ptr(new SynchronousOutputSurfaceLayerTreeHost(
57         client, manager, settings, impl_task_runner));
58   }
59
60   virtual ~SynchronousOutputSurfaceLayerTreeHost() {}
61
62   bool EnsureOutputSurfaceCreated() {
63     base::MessageLoop::current()->PostDelayedTask(
64         FROM_HERE,
65         run_loop_.QuitClosure(),
66         base::TimeDelta::FromSeconds(5));
67     run_loop_.Run();
68     return output_surface_created_;
69   }
70
71   virtual void OnCreateAndInitializeOutputSurfaceAttempted(
72       bool success) OVERRIDE {
73     LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(success);
74     output_surface_created_ = success;
75     run_loop_.Quit();
76   }
77
78  private:
79   SynchronousOutputSurfaceLayerTreeHost(
80       LayerTreeHostClient* client,
81       SharedBitmapManager* manager,
82       const LayerTreeSettings& settings,
83       scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
84       : LayerTreeHost(client, manager, settings),
85         output_surface_created_(false) {
86     LayerTreeHost::InitializeThreaded(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     proxy_ = layer_tree_host_->proxy();
116     resource_manager_ = PrioritizedResourceManager::Create(proxy_);
117     layer_tree_host_->SetLayerTreeHostClientReady();
118     CHECK(layer_tree_host_->EnsureOutputSurfaceCreated());
119     layer_tree_host_->SetRootLayer(Layer::Create());
120
121     CHECK(output_surface_->BindToClient(&output_surface_client_));
122
123     DebugScopedSetImplThreadAndMainThreadBlocked
124         impl_thread_and_main_thread_blocked(proxy_);
125     resource_provider_ = ResourceProvider::Create(
126         output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
127         false);
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->SetBounds(gfx::Size(300, 300));
1390   scale_layer->AddChild(layer);
1391   CalcDrawProps(&render_surface_layer_list);
1392   EXPECT_FLOAT_EQ(2.f, layer->contents_scale_x());
1393   EXPECT_FLOAT_EQ(2.f, layer->contents_scale_y());
1394   EXPECT_EQ(gfx::Size(600, 600).ToString(),
1395             layer->content_bounds().ToString());
1396
1397   // No tiles are covered by the 300x50 occlusion.
1398   occluded.SetOcclusion(gfx::Rect(200, 200, 300, 50));
1399   layer->draw_properties().drawable_content_rect =
1400       gfx::Rect(layer->bounds());
1401   layer->draw_properties().visible_content_rect =
1402       gfx::Rect(layer->content_bounds());
1403   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1404   layer->SetTexturePriorities(priority_calculator_);
1405   resource_manager_->PrioritizeTextures();
1406   layer->SavePaintProperties();
1407   layer->Update(queue_.get(), &occluded);
1408   int visible_tiles1 = 6 * 6;
1409   EXPECT_EQ(visible_tiles1, layer->fake_layer_updater()->update_count());
1410
1411   layer->fake_layer_updater()->ClearUpdateCount();
1412
1413   // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still.
1414   occluded.SetOcclusion(gfx::Rect(200, 200, 300, 100));
1415   layer->draw_properties().drawable_content_rect =
1416       gfx::Rect(layer->bounds());
1417   layer->draw_properties().visible_content_rect =
1418       gfx::Rect(layer->content_bounds());
1419   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1420   layer->SetTexturePriorities(priority_calculator_);
1421   resource_manager_->PrioritizeTextures();
1422   layer->SavePaintProperties();
1423   layer->Update(queue_.get(), &occluded);
1424   int visible_tiles2 = 6 * 6 - 3;
1425   EXPECT_EQ(visible_tiles2, layer->fake_layer_updater()->update_count());
1426
1427   layer->fake_layer_updater()->ClearUpdateCount();
1428
1429   // This makes sure content scaling and transforms work together.
1430   // When the tiles are scaled down by half, they are 50x50 each in the
1431   // screen.
1432   gfx::Transform screen_transform;
1433   screen_transform.Scale(0.5, 0.5);
1434   layer->draw_properties().screen_space_transform = screen_transform;
1435   layer->draw_properties().target_space_transform = screen_transform;
1436
1437   // An occlusion of 150x100 will cover 3*2 = 6 tiles.
1438   occluded.SetOcclusion(gfx::Rect(100, 100, 150, 100));
1439
1440   gfx::Rect layer_bounds_rect(layer->bounds());
1441   layer->draw_properties().drawable_content_rect =
1442       gfx::ScaleToEnclosingRect(layer_bounds_rect, 0.5f);
1443   layer->draw_properties().visible_content_rect =
1444       gfx::Rect(layer->content_bounds());
1445   layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1446   layer->SetTexturePriorities(priority_calculator_);
1447   resource_manager_->PrioritizeTextures();
1448   layer->SavePaintProperties();
1449   layer->Update(queue_.get(), &occluded);
1450   int visible_tiles3 = 6 * 6 - 6;
1451   EXPECT_EQ(visible_tiles3, layer->fake_layer_updater()->update_count());
1452 }
1453
1454 TEST_F(TiledLayerTest, VisibleContentOpaqueRegion) {
1455   scoped_refptr<FakeTiledLayer> layer =
1456       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1457   RenderSurfaceLayerList render_surface_layer_list;
1458   TestOcclusionTracker occluded;
1459   occlusion_ = &occluded;
1460   layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
1461
1462   layer_tree_host_->root_layer()->AddChild(layer);
1463
1464   // The tile size is 100x100, so this invalidates and then paints two tiles in
1465   // various ways.
1466
1467   gfx::Rect opaque_paint_rect;
1468   Region opaque_contents;
1469
1470   gfx::Rect content_bounds = gfx::Rect(0, 0, 100, 200);
1471   gfx::Rect visible_bounds = gfx::Rect(0, 0, 100, 150);
1472
1473   layer->SetBounds(content_bounds.size());
1474   CalcDrawProps(&render_surface_layer_list);
1475   layer->draw_properties().drawable_content_rect = visible_bounds;
1476   layer->draw_properties().visible_content_rect = visible_bounds;
1477
1478   // If the layer doesn't paint opaque content, then the
1479   // VisibleContentOpaqueRegion should be empty.
1480   layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1481   layer->InvalidateContentRect(content_bounds);
1482   layer->SetTexturePriorities(priority_calculator_);
1483   resource_manager_->PrioritizeTextures();
1484   layer->SavePaintProperties();
1485   layer->Update(queue_.get(), &occluded);
1486   opaque_contents = layer->VisibleContentOpaqueRegion();
1487   EXPECT_TRUE(opaque_contents.IsEmpty());
1488
1489   // VisibleContentOpaqueRegion should match the visible part of what is painted
1490   // opaque.
1491   opaque_paint_rect = gfx::Rect(10, 10, 90, 190);
1492   layer->fake_layer_updater()->SetOpaquePaintRect(opaque_paint_rect);
1493   layer->InvalidateContentRect(content_bounds);
1494   layer->SetTexturePriorities(priority_calculator_);
1495   resource_manager_->PrioritizeTextures();
1496   layer->SavePaintProperties();
1497   layer->Update(queue_.get(), &occluded);
1498   UpdateTextures();
1499   opaque_contents = layer->VisibleContentOpaqueRegion();
1500   EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect, visible_bounds).ToString(),
1501             opaque_contents.ToString());
1502
1503   // If we paint again without invalidating, the same stuff should be opaque.
1504   layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1505   layer->SetTexturePriorities(priority_calculator_);
1506   resource_manager_->PrioritizeTextures();
1507   layer->SavePaintProperties();
1508   layer->Update(queue_.get(), &occluded);
1509   UpdateTextures();
1510   opaque_contents = layer->VisibleContentOpaqueRegion();
1511   EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect, visible_bounds).ToString(),
1512             opaque_contents.ToString());
1513
1514   // If we repaint a non-opaque part of the tile, then it shouldn't lose its
1515   // opaque-ness. And other tiles should not be affected.
1516   layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1517   layer->InvalidateContentRect(gfx::Rect(0, 0, 1, 1));
1518   layer->SetTexturePriorities(priority_calculator_);
1519   resource_manager_->PrioritizeTextures();
1520   layer->SavePaintProperties();
1521   layer->Update(queue_.get(), &occluded);
1522   UpdateTextures();
1523   opaque_contents = layer->VisibleContentOpaqueRegion();
1524   EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect, visible_bounds).ToString(),
1525             opaque_contents.ToString());
1526
1527   // If we repaint an opaque part of the tile, then it should lose its
1528   // opaque-ness. But other tiles should still not be affected.
1529   layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1530   layer->InvalidateContentRect(gfx::Rect(10, 10, 1, 1));
1531   layer->SetTexturePriorities(priority_calculator_);
1532   resource_manager_->PrioritizeTextures();
1533   layer->SavePaintProperties();
1534   layer->Update(queue_.get(), &occluded);
1535   UpdateTextures();
1536   opaque_contents = layer->VisibleContentOpaqueRegion();
1537   EXPECT_EQ(gfx::IntersectRects(gfx::Rect(10, 100, 90, 100),
1538                                 visible_bounds).ToString(),
1539             opaque_contents.ToString());
1540 }
1541
1542 TEST_F(TiledLayerTest, DontAllocateContentsWhenTargetSurfaceCantBeAllocated) {
1543   // Tile size is 100x100.
1544   gfx::Rect root_rect(0, 0, 300, 200);
1545   gfx::Rect child_rect(0, 0, 300, 100);
1546   gfx::Rect child2_rect(0, 100, 300, 100);
1547
1548   scoped_refptr<FakeTiledLayer> root = make_scoped_refptr(
1549       new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
1550   scoped_refptr<Layer> surface = Layer::Create();
1551   scoped_refptr<FakeTiledLayer> child = make_scoped_refptr(
1552       new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
1553   scoped_refptr<FakeTiledLayer> child2 = make_scoped_refptr(
1554       new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
1555
1556   root->SetBounds(root_rect.size());
1557   root->draw_properties().drawable_content_rect = root_rect;
1558   root->draw_properties().visible_content_rect = root_rect;
1559   root->AddChild(surface);
1560
1561   surface->SetForceRenderSurface(true);
1562   surface->SetOpacity(0.5);
1563   surface->AddChild(child);
1564   surface->AddChild(child2);
1565
1566   child->SetBounds(child_rect.size());
1567   child->SetPosition(child_rect.origin());
1568   child->draw_properties().visible_content_rect = child_rect;
1569   child->draw_properties().drawable_content_rect = root_rect;
1570
1571   child2->SetBounds(child2_rect.size());
1572   child2->SetPosition(child2_rect.origin());
1573   child2->draw_properties().visible_content_rect = child2_rect;
1574   child2->draw_properties().drawable_content_rect = root_rect;
1575
1576   layer_tree_host_->SetRootLayer(root);
1577   layer_tree_host_->SetViewportSize(root_rect.size());
1578
1579   // With a huge memory limit, all layers should update and push their textures.
1580   root->InvalidateContentRect(root_rect);
1581   child->InvalidateContentRect(child_rect);
1582   child2->InvalidateContentRect(child2_rect);
1583   layer_tree_host_->UpdateLayers(queue_.get());
1584   {
1585     UpdateTextures();
1586     EXPECT_EQ(6, root->fake_layer_updater()->update_count());
1587     EXPECT_EQ(3, child->fake_layer_updater()->update_count());
1588     EXPECT_EQ(3, child2->fake_layer_updater()->update_count());
1589     EXPECT_FALSE(queue_->HasMoreUpdates());
1590
1591     root->fake_layer_updater()->ClearUpdateCount();
1592     child->fake_layer_updater()->ClearUpdateCount();
1593     child2->fake_layer_updater()->ClearUpdateCount();
1594
1595     scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
1596         new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
1597     scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
1598         new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
1599     scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
1600         new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
1601     LayerPushPropertiesTo(child2.get(), child2_impl.get());
1602     LayerPushPropertiesTo(child.get(), child_impl.get());
1603     LayerPushPropertiesTo(root.get(), root_impl.get());
1604
1605     for (unsigned i = 0; i < 3; ++i) {
1606       for (unsigned j = 0; j < 2; ++j)
1607         EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j));
1608       EXPECT_TRUE(child_impl->HasResourceIdForTileAt(i, 0));
1609       EXPECT_TRUE(child2_impl->HasResourceIdForTileAt(i, 0));
1610     }
1611   }
1612   layer_tree_host_->CommitComplete();
1613
1614   // With a memory limit that includes only the root layer (3x2 tiles) and half
1615   // the surface that the child layers draw into, the child layers will not be
1616   // allocated. If the surface isn't accounted for, then one of the children
1617   // would fit within the memory limit.
1618   root->InvalidateContentRect(root_rect);
1619   child->InvalidateContentRect(child_rect);
1620   child2->InvalidateContentRect(child2_rect);
1621
1622   size_t memory_limit = (3 * 2 + 3 * 1) * (100 * 100) * 4;
1623   layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
1624       memory_limit);
1625   layer_tree_host_->UpdateLayers(queue_.get());
1626   {
1627     UpdateTextures();
1628     EXPECT_EQ(6, root->fake_layer_updater()->update_count());
1629     EXPECT_EQ(0, child->fake_layer_updater()->update_count());
1630     EXPECT_EQ(0, child2->fake_layer_updater()->update_count());
1631     EXPECT_FALSE(queue_->HasMoreUpdates());
1632
1633     root->fake_layer_updater()->ClearUpdateCount();
1634     child->fake_layer_updater()->ClearUpdateCount();
1635     child2->fake_layer_updater()->ClearUpdateCount();
1636
1637     scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
1638         new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
1639     scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
1640         new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
1641     scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
1642         new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
1643     LayerPushPropertiesTo(child2.get(), child2_impl.get());
1644     LayerPushPropertiesTo(child.get(), child_impl.get());
1645     LayerPushPropertiesTo(root.get(), root_impl.get());
1646
1647     for (unsigned i = 0; i < 3; ++i) {
1648       for (unsigned j = 0; j < 2; ++j)
1649         EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j));
1650       EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0));
1651       EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0));
1652     }
1653   }
1654   layer_tree_host_->CommitComplete();
1655
1656   // With a memory limit that includes only half the root layer, no contents
1657   // will be allocated. If render surface memory wasn't accounted for, there is
1658   // enough space for one of the children layers, but they draw into a surface
1659   // that can't be allocated.
1660   root->InvalidateContentRect(root_rect);
1661   child->InvalidateContentRect(child_rect);
1662   child2->InvalidateContentRect(child2_rect);
1663
1664   memory_limit = (3 * 1) * (100 * 100) * 4;
1665   layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
1666       memory_limit);
1667   layer_tree_host_->UpdateLayers(queue_.get());
1668   {
1669     UpdateTextures();
1670     EXPECT_EQ(0, root->fake_layer_updater()->update_count());
1671     EXPECT_EQ(0, child->fake_layer_updater()->update_count());
1672     EXPECT_EQ(0, child2->fake_layer_updater()->update_count());
1673     EXPECT_FALSE(queue_->HasMoreUpdates());
1674
1675     root->fake_layer_updater()->ClearUpdateCount();
1676     child->fake_layer_updater()->ClearUpdateCount();
1677     child2->fake_layer_updater()->ClearUpdateCount();
1678
1679     scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
1680         new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
1681     scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
1682         new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
1683     scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
1684         new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
1685     LayerPushPropertiesTo(child2.get(), child2_impl.get());
1686     LayerPushPropertiesTo(child.get(), child_impl.get());
1687     LayerPushPropertiesTo(root.get(), root_impl.get());
1688
1689     for (unsigned i = 0; i < 3; ++i) {
1690       for (unsigned j = 0; j < 2; ++j)
1691         EXPECT_FALSE(root_impl->HasResourceIdForTileAt(i, j));
1692       EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0));
1693       EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0));
1694     }
1695   }
1696   layer_tree_host_->CommitComplete();
1697
1698   ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
1699                                 resource_provider_.get());
1700   layer_tree_host_->SetRootLayer(NULL);
1701 }
1702
1703 class TrackingLayerPainter : public LayerPainter {
1704  public:
1705   static scoped_ptr<TrackingLayerPainter> Create() {
1706     return make_scoped_ptr(new TrackingLayerPainter());
1707   }
1708
1709   virtual void Paint(SkCanvas* canvas,
1710                      const gfx::Rect& content_rect,
1711                      gfx::RectF* opaque) OVERRIDE {
1712     painted_rect_ = content_rect;
1713   }
1714
1715   gfx::Rect PaintedRect() const { return painted_rect_; }
1716   void ResetPaintedRect() { painted_rect_ = gfx::Rect(); }
1717
1718  private:
1719   gfx::Rect painted_rect_;
1720 };
1721
1722 class UpdateTrackingTiledLayer : public FakeTiledLayer {
1723  public:
1724   explicit UpdateTrackingTiledLayer(PrioritizedResourceManager* manager)
1725       : FakeTiledLayer(manager) {
1726     scoped_ptr<TrackingLayerPainter> painter(TrackingLayerPainter::Create());
1727     tracking_layer_painter_ = painter.get();
1728     layer_updater_ =
1729         BitmapContentLayerUpdater::Create(painter.PassAs<LayerPainter>(),
1730                                           &stats_instrumentation_,
1731                                           0);
1732   }
1733
1734   TrackingLayerPainter* tracking_layer_painter() const {
1735     return tracking_layer_painter_;
1736   }
1737
1738  private:
1739   virtual LayerUpdater* Updater() const OVERRIDE {
1740     return layer_updater_.get();
1741   }
1742   virtual ~UpdateTrackingTiledLayer() {}
1743
1744   TrackingLayerPainter* tracking_layer_painter_;
1745   scoped_refptr<BitmapContentLayerUpdater> layer_updater_;
1746   FakeRenderingStatsInstrumentation stats_instrumentation_;
1747 };
1748
1749 TEST_F(TiledLayerTest, NonIntegerContentsScaleIsNotDistortedDuringPaint) {
1750   scoped_refptr<UpdateTrackingTiledLayer> layer =
1751       make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get()));
1752
1753   layer_tree_host_->root_layer()->AddChild(layer);
1754
1755   gfx::Rect layer_rect(0, 0, 30, 31);
1756   layer->SetPosition(layer_rect.origin());
1757   layer->SetBounds(layer_rect.size());
1758   layer->UpdateContentsScale(1.5f);
1759
1760   gfx::Rect content_rect(0, 0, 45, 47);
1761   EXPECT_EQ(content_rect.size(), layer->content_bounds());
1762   layer->draw_properties().visible_content_rect = content_rect;
1763   layer->draw_properties().drawable_content_rect = content_rect;
1764
1765   layer->SetTexturePriorities(priority_calculator_);
1766   resource_manager_->PrioritizeTextures();
1767   layer->SavePaintProperties();
1768
1769   // Update the whole tile.
1770   layer->Update(queue_.get(), NULL);
1771   layer->tracking_layer_painter()->ResetPaintedRect();
1772
1773   EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect());
1774   UpdateTextures();
1775
1776   // Invalidate the entire layer in content space. When painting, the rect given
1777   // to webkit should match the layer's bounds.
1778   layer->InvalidateContentRect(content_rect);
1779   layer->Update(queue_.get(), NULL);
1780
1781   EXPECT_RECT_EQ(layer_rect, layer->tracking_layer_painter()->PaintedRect());
1782 }
1783
1784 TEST_F(TiledLayerTest,
1785        NonIntegerContentsScaleIsNotDistortedDuringInvalidation) {
1786   scoped_refptr<UpdateTrackingTiledLayer> layer =
1787       make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get()));
1788
1789   layer_tree_host_->root_layer()->AddChild(layer);
1790
1791   gfx::Rect layer_rect(0, 0, 30, 31);
1792   layer->SetPosition(layer_rect.origin());
1793   layer->SetBounds(layer_rect.size());
1794   layer->UpdateContentsScale(1.3f);
1795
1796   gfx::Rect content_rect(layer->content_bounds());
1797   layer->draw_properties().visible_content_rect = content_rect;
1798   layer->draw_properties().drawable_content_rect = content_rect;
1799
1800   layer->SetTexturePriorities(priority_calculator_);
1801   resource_manager_->PrioritizeTextures();
1802   layer->SavePaintProperties();
1803
1804   // Update the whole tile.
1805   layer->Update(queue_.get(), NULL);
1806   layer->tracking_layer_painter()->ResetPaintedRect();
1807
1808   EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect());
1809   UpdateTextures();
1810
1811   // Invalidate the entire layer in layer space. When painting, the rect given
1812   // to webkit should match the layer's bounds.
1813   layer->SetNeedsDisplayRect(layer_rect);
1814   layer->Update(queue_.get(), NULL);
1815
1816   EXPECT_RECT_EQ(layer_rect, layer->tracking_layer_painter()->PaintedRect());
1817 }
1818
1819 }  // namespace
1820 }  // namespace cc