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