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