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