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"
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"
34 class TestOcclusionTracker : public OcclusionTracker<Layer> {
36 TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000)) {
37 stack_.push_back(StackObject());
40 void SetRenderTarget(Layer* render_target) {
41 stack_.back().target = render_target;
44 void SetOcclusion(const SimpleEnclosedRegion& occlusion) {
45 stack_.back().occlusion_from_inside_target = occlusion;
49 class SynchronousOutputSurfaceLayerTreeHost : public LayerTreeHost {
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));
60 virtual ~SynchronousOutputSurfaceLayerTreeHost() {}
62 bool EnsureOutputSurfaceCreated() {
63 base::MessageLoop::current()->PostDelayedTask(
65 run_loop_.QuitClosure(),
66 base::TimeDelta::FromSeconds(5));
68 return output_surface_created_;
71 virtual void OnCreateAndInitializeOutputSurfaceAttempted(
72 bool success) OVERRIDE {
73 LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(success);
74 output_surface_created_ = success;
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(),
90 bool output_surface_created_;
91 base::RunLoop run_loop_;
94 class TiledLayerTest : public testing::Test {
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),
103 settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max();
104 settings_.layer_transforms_should_scale_layer_contents = true;
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(),
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());
122 CHECK(output_surface_->BindToClient(&output_surface_client_));
124 DebugScopedSetImplThreadAndMainThreadBlocked
125 impl_thread_and_main_thread_blocked(proxy_);
126 resource_provider_ = ResourceProvider::Create(output_surface_.get(),
127 shared_bitmap_manager_.get(),
133 host_impl_ = make_scoped_ptr(
134 new FakeLayerTreeHostImpl(proxy_, shared_bitmap_manager_.get()));
137 virtual ~TiledLayerTest() {
138 ResourceManagerClearAllMemory(resource_manager_.get(),
139 resource_provider_.get());
141 DebugScopedSetImplThreadAndMainThreadBlocked
142 impl_thread_and_main_thread_blocked(proxy_);
143 resource_provider_.reset();
147 void ResourceManagerClearAllMemory(
148 PrioritizedResourceManager* resource_manager,
149 ResourceProvider* resource_provider) {
151 DebugScopedSetImplThreadAndMainThreadBlocked
152 impl_thread_and_main_thread_blocked(proxy_);
153 resource_manager->ClearAllMemory(resource_provider);
154 resource_manager->ReduceMemory(resource_provider);
156 resource_manager->UnlinkAndClearEvictedBackings();
159 void UpdateTextures() {
160 DebugScopedSetImplThreadAndMainThreadBlocked
161 impl_thread_and_main_thread_blocked(proxy_);
163 scoped_ptr<ResourceUpdateController> update_controller =
164 ResourceUpdateController::Create(NULL,
165 proxy_->ImplThreadTaskRunner(),
167 resource_provider_.get());
168 update_controller->Finalize();
169 queue_ = make_scoped_ptr(new ResourceUpdateQueue);
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();
180 void LayerUpdate(FakeTiledLayer* layer, TestOcclusionTracker* occluded) {
181 DebugScopedSetMainThread main_thread(proxy_);
182 layer->Update(queue_.get(), occluded);
185 void CalcDrawProps(RenderSurfaceLayerList* render_surface_layer_list) {
187 occlusion_->SetRenderTarget(layer_tree_host_->root_layer());
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);
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);
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) {
212 resource_manager_->ClearPriorities();
214 layer1->SetTexturePriorities(priority_calculator_);
216 layer2->SetTexturePriorities(priority_calculator_);
217 resource_manager_->PrioritizeTextures();
219 // Save paint properties
221 layer1->SavePaintProperties();
223 layer2->SavePaintProperties();
227 layer1->Update(queue_.get(), occlusion_);
229 layer2->Update(queue_.get(), occlusion_);
231 bool needs_update = false;
233 needs_update |= layer1->NeedsIdlePaint();
235 needs_update |= layer2->NeedsIdlePaint();
237 // Update textures and push.
240 LayerPushPropertiesTo(layer1.get(), layer_impl1.get());
242 LayerPushPropertiesTo(layer2.get(), layer_impl2.get());
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_;
264 TEST_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;
271 layer_tree_host_->root_layer()->AddChild(layer);
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);
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));
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);
287 // We should only have the first tile since the other tile was invalidated but
289 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
290 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
293 TEST_F(TiledLayerTest, Scale) {
294 layer_tree_host_->SetDeviceScaleFactor(1.5);
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;
302 layer_tree_host_->root_layer()->AddChild(layer);
304 layer->SetBounds(gfx::Size(100, 200));
305 CalcDrawProps(&render_surface_layer_list);
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);
311 EXPECT_EQ(1.5, layer->fake_layer_updater()->last_contents_width_scale());
314 TEST_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));
323 layer_tree_host_->root_layer()->AddChild(layer);
326 RenderSurfaceLayerList render_surface_layer_list;
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);
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));
339 RenderSurfaceLayerList render_surface_layer_list;
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);
348 // We should still have both tiles, as part of the top tile is still
350 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
351 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
355 TEST_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;
362 layer_tree_host_->root_layer()->AddChild(layer);
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);
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));
373 resource_manager_->ClearPriorities();
374 ResourceManagerClearAllMemory(resource_manager_.get(),
375 resource_provider_.get());
376 resource_manager_->SetMaxMemoryLimitBytes(4 * 1024 * 1024);
378 // This should drop the tiles on the impl thread.
379 LayerPushPropertiesTo(layer.get(), layer_impl.get());
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));
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);
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));
394 TEST_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;
401 layer_tree_host_->root_layer()->AddChild(layer);
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);
412 // We should have one tile on the impl side.
413 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(2, 2));
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);
421 // We should always finish painting eventually.
422 for (int i = 0; i < 20; i++)
423 needs_update = UpdateAndPush(layer, layer_impl);
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));
431 EXPECT_FALSE(needs_update);
434 TEST_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));
440 layer_tree_host_->root_layer()->AddChild(layer);
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)
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)
459 for (int k = 0; k < 6; k++) {
460 // The tile size is 100x100. Setup 5x5 tiles with one visible tile
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());
469 // Setup. Use the previous_visible_rect to setup the prediction for next
471 layer->SetBounds(bounds);
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);
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));
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
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));
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);
510 TEST_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;
524 layer_tree_host_->root_layer()->AddChild(layer1);
525 layer_tree_host_->root_layer()->AddChild(layer2);
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.
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);
537 // This requires 4*30000 bytes of memory.
538 gfx::Rect layer2_rect(0, 0, 100, 300);
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);
550 // Reduce our memory limits to 1mb.
551 resource_manager_->SetMaxMemoryLimitBytes(1024 * 1024);
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);
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));
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));
570 EXPECT_FALSE(needs_update);
571 EXPECT_FALSE(layer_impl2->HasResourceIdForTileAt(0, 2));
574 TEST_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;
583 layer_tree_host_->root_layer()->AddChild(layer);
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)));
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);
594 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
597 TEST_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;
604 layer_tree_host_->root_layer()->AddChild(layer);
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);
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));
621 TEST_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;
632 layer_tree_host_->root_layer()->AddChild(layer1);
633 layer_tree_host_->root_layer()->AddChild(layer2);
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);
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));
652 TEST_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;
663 layer_tree_host_->root_layer()->AddChild(layer1);
664 layer_tree_host_->root_layer()->AddChild(layer2);
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);
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));
682 TEST_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));
696 // Use 10x5 tiles to run out of memory.
697 if (run_out_of_memory[i])
700 resource_manager_->SetMaxMemoryLimitBytes(memory_for_layer);
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;
708 layer_tree_host_->root_layer()->AddChild(layer);
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);
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());
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);
727 LayerPushPropertiesTo(layer.get(), layer_impl.get());
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));
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);
744 layer->RemoveFromParent();
748 TEST_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;
755 layer_tree_host_->root_layer()->AddChild(layer);
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);
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);
770 // Idle-painting should see no more priority tiles for painting.
771 EXPECT_FALSE(needs_update);
773 // We should have one tile on the impl side.
774 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1));
777 TEST_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));
783 layer_tree_host_->root_layer()->AddChild(layer);
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];
790 // The layer's bounds are empty.
791 // Empty layers don't paint or idle-paint.
792 layer->SetBounds(gfx::Size());
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);
799 // Empty layers don't have tiles.
800 EXPECT_EQ(0u, layer->NumPaintedTiles());
802 // Empty layers don't need prepaint.
803 EXPECT_FALSE(needs_update);
805 // Empty layers don't have tiles.
806 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0));
810 TEST_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));
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,
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,
828 layer_tree_host_->root_layer()->AddChild(layer);
830 for (int i = 0; i < 10; i++) {
831 layer->SetBounds(gfx::Size(100, 100));
833 RenderSurfaceLayerList render_surface_layer_list;
834 CalcDrawProps(&render_surface_layer_list);
835 layer->draw_properties().visible_content_rect = visible_rect[i];
838 layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 100));
839 bool needs_update = UpdateAndPush(layer, layer_impl);
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]);
848 TEST_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;
855 layer_tree_host_->root_layer()->AddChild(layer);
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);
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));
867 layer->fake_layer_updater()->ClearPrepareCount();
868 // Invoke update again. As the layer is valid update shouldn't be invoked on
870 UpdateAndPush(layer, layer_impl);
871 EXPECT_EQ(0, layer->fake_layer_updater()->prepare_count());
873 // SetRectToInvalidate triggers InvalidateContentRect() being invoked from
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();
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());
888 TEST_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()));
894 layer_tree_host_->root_layer()->AddChild(layer);
896 gfx::Rect layer_bounds(0, 0, 300, 200);
897 gfx::Rect content_bounds(0, 0, 150, 250);
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;
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);
910 layer->SetTexturePriorities(priority_calculator_);
911 resource_manager_->PrioritizeTextures();
912 layer->SavePaintProperties();
913 layer->Update(queue_.get(), NULL);
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());
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());
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());
940 TEST_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;
947 layer_tree_host_->root_layer()->AddChild(layer);
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);
955 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
956 layer->last_needs_display_rect());
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);
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));
970 layer->SetNeedsDisplayRect(gfx::Rect());
971 EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer->last_needs_display_rect());
973 // Change the contents scale.
974 layer->UpdateContentsScale(2.f);
975 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 200, 200);
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);
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));
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());
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();
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));
1007 TEST_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);
1012 // We have enough memory for only one of the two layers.
1013 int memory_limit = 4 * 300 * 300; // 4 bytes per pixel.
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);
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);
1030 layer_tree_host_->SetRootLayer(root_layer);
1031 layer_tree_host_->SetViewportSize(gfx::Size(300, 300));
1032 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
1035 layer_tree_host_->UpdateLayers(queue_.get());
1037 // We'll skip the root layer.
1038 EXPECT_TRUE(root_layer->SkipsDraw());
1039 EXPECT_FALSE(child_layer->SkipsDraw());
1041 layer_tree_host_->CommitComplete();
1043 // Remove the child layer.
1044 root_layer->RemoveAllChildren();
1046 layer_tree_host_->UpdateLayers(queue_.get());
1047 EXPECT_FALSE(root_layer->SkipsDraw());
1049 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
1050 resource_provider_.get());
1051 layer_tree_host_->SetRootLayer(NULL);
1054 TEST_F(TiledLayerTest, ResizeToSmaller) {
1055 scoped_refptr<FakeTiledLayer> layer =
1056 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1058 layer_tree_host_->root_layer()->AddChild(layer);
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));
1064 layer->SetTexturePriorities(priority_calculator_);
1065 resource_manager_->PrioritizeTextures();
1066 layer->SavePaintProperties();
1067 layer->Update(queue_.get(), NULL);
1069 layer->SetBounds(gfx::Size(200, 200));
1070 layer->InvalidateContentRect(gfx::Rect(0, 0, 200, 200));
1073 TEST_F(TiledLayerTest, HugeLayerUpdateCrash) {
1074 scoped_refptr<FakeTiledLayer> layer =
1075 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1077 layer_tree_host_->root_layer()->AddChild(layer);
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));
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);
1091 class TiledLayerPartialUpdateTest : public TiledLayerTest {
1093 TiledLayerPartialUpdateTest() { settings_.max_partial_texture_updates = 4; }
1096 TEST_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);
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);
1108 layer_tree_host_->SetRootLayer(layer);
1109 layer_tree_host_->SetViewportSize(gfx::Size(300, 200));
1111 // Full update of all 6 tiles.
1112 layer_tree_host_->UpdateLayers(queue_.get());
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());
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());
1124 layer_tree_host_->CommitComplete();
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());
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());
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());
1140 layer_tree_host_->CommitComplete();
1142 // Partial update of 6 tiles.
1143 layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
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());
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());
1156 layer_tree_host_->CommitComplete();
1158 // Checkerboard all tiles.
1159 layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 200));
1161 scoped_ptr<FakeTiledLayerImpl> layer_impl =
1162 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
1163 LayerPushPropertiesTo(layer.get(), layer_impl.get());
1165 layer_tree_host_->CommitComplete();
1167 // Partial update of 6 checkerboard tiles.
1168 layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
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());
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());
1181 layer_tree_host_->CommitComplete();
1183 // Partial update of 4 tiles.
1184 layer->InvalidateContentRect(gfx::Rect(50, 50, 100, 100));
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());
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());
1197 layer_tree_host_->CommitComplete();
1199 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
1200 resource_provider_.get());
1201 layer_tree_host_->SetRootLayer(NULL);
1204 TEST_F(TiledLayerTest, TilesPaintedWithoutOcclusion) {
1205 scoped_refptr<FakeTiledLayer> layer =
1206 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1207 RenderSurfaceLayerList render_surface_layer_list;
1209 layer_tree_host_->root_layer()->AddChild(layer);
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);
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());
1222 TEST_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;
1229 layer_tree_host_->root_layer()->AddChild(layer);
1231 // The tile size is 100x100.
1233 layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
1234 layer->SetBounds(gfx::Size(600, 600));
1235 CalcDrawProps(&render_surface_layer_list);
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));
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());
1250 layer->fake_layer_updater()->ClearUpdateCount();
1251 layer->SetTexturePriorities(priority_calculator_);
1252 resource_manager_->PrioritizeTextures();
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());
1260 layer->fake_layer_updater()->ClearUpdateCount();
1261 layer->SetTexturePriorities(priority_calculator_);
1262 resource_manager_->PrioritizeTextures();
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());
1271 TEST_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;
1278 layer_tree_host_->root_layer()->AddChild(layer);
1280 // The tile size is 100x100.
1282 layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
1283 layer->SetBounds(gfx::Size(600, 600));
1284 CalcDrawProps(&render_surface_layer_list);
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));
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());
1299 layer->fake_layer_updater()->ClearUpdateCount();
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());
1313 layer->fake_layer_updater()->ClearUpdateCount();
1315 // Now the visible region is even smaller than the occlusion, it should have
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());
1328 TEST_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;
1335 layer_tree_host_->root_layer()->AddChild(layer);
1337 // The tile size is 100x100.
1339 layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
1340 layer->SetBounds(gfx::Size(600, 600));
1341 CalcDrawProps(&render_surface_layer_list);
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());
1354 layer->fake_layer_updater()->ClearUpdateCount();
1355 layer->SetTexturePriorities(priority_calculator_);
1356 resource_manager_->PrioritizeTextures();
1357 layer->SavePaintProperties();
1359 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted
1361 layer->Update(queue_.get(), &occluded);
1362 EXPECT_EQ(3, layer->fake_layer_updater()->update_count());
1365 TEST_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;
1372 layer_tree_host_->root_layer()->AddChild(layer);
1374 // The tile size is 100x100.
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;
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());
1399 TEST_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;
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);
1412 layer_tree_host_->root_layer()->AddChild(scale_layer);
1414 // The tile size is 100x100.
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());
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());
1441 layer->fake_layer_updater()->ClearUpdateCount();
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());
1457 layer->fake_layer_updater()->ClearUpdateCount();
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
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;
1467 // An occlusion of 150x100 will cover 3*2 = 6 tiles.
1468 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 100)));
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());
1484 TEST_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);
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()));
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);
1503 surface->SetForceRenderSurface(true);
1504 surface->SetOpacity(0.5);
1505 surface->AddChild(child);
1506 surface->AddChild(child2);
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;
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;
1518 layer_tree_host_->SetRootLayer(root);
1519 layer_tree_host_->SetViewportSize(root_rect.size());
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());
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());
1533 root->fake_layer_updater()->ClearUpdateCount();
1534 child->fake_layer_updater()->ClearUpdateCount();
1535 child2->fake_layer_updater()->ClearUpdateCount();
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());
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));
1554 layer_tree_host_->CommitComplete();
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);
1564 size_t memory_limit = (3 * 2 + 3 * 1) * (100 * 100) * 4;
1565 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
1567 layer_tree_host_->UpdateLayers(queue_.get());
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());
1575 root->fake_layer_updater()->ClearUpdateCount();
1576 child->fake_layer_updater()->ClearUpdateCount();
1577 child2->fake_layer_updater()->ClearUpdateCount();
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());
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));
1596 layer_tree_host_->CommitComplete();
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);
1606 memory_limit = (3 * 1) * (100 * 100) * 4;
1607 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
1609 layer_tree_host_->UpdateLayers(queue_.get());
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());
1617 root->fake_layer_updater()->ClearUpdateCount();
1618 child->fake_layer_updater()->ClearUpdateCount();
1619 child2->fake_layer_updater()->ClearUpdateCount();
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());
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));
1638 layer_tree_host_->CommitComplete();
1640 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
1641 resource_provider_.get());
1642 layer_tree_host_->SetRootLayer(NULL);
1645 class TrackingLayerPainter : public LayerPainter {
1647 static scoped_ptr<TrackingLayerPainter> Create() {
1648 return make_scoped_ptr(new TrackingLayerPainter());
1651 virtual void Paint(SkCanvas* canvas, const gfx::Rect& content_rect) OVERRIDE {
1652 painted_rect_ = content_rect;
1655 gfx::Rect PaintedRect() const { return painted_rect_; }
1656 void ResetPaintedRect() { painted_rect_ = gfx::Rect(); }
1659 gfx::Rect painted_rect_;
1662 class UpdateTrackingTiledLayer : public FakeTiledLayer {
1664 explicit UpdateTrackingTiledLayer(PrioritizedResourceManager* manager)
1665 : FakeTiledLayer(manager) {
1666 scoped_ptr<TrackingLayerPainter> painter(TrackingLayerPainter::Create());
1667 tracking_layer_painter_ = painter.get();
1669 BitmapContentLayerUpdater::Create(painter.PassAs<LayerPainter>(),
1670 &stats_instrumentation_,
1674 TrackingLayerPainter* tracking_layer_painter() const {
1675 return tracking_layer_painter_;
1679 virtual LayerUpdater* Updater() const OVERRIDE {
1680 return layer_updater_.get();
1682 virtual ~UpdateTrackingTiledLayer() {}
1684 TrackingLayerPainter* tracking_layer_painter_;
1685 scoped_refptr<BitmapContentLayerUpdater> layer_updater_;
1686 FakeRenderingStatsInstrumentation stats_instrumentation_;
1689 TEST_F(TiledLayerTest, NonIntegerContentsScaleIsNotDistortedDuringPaint) {
1690 scoped_refptr<UpdateTrackingTiledLayer> layer =
1691 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get()));
1693 layer_tree_host_->root_layer()->AddChild(layer);
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);
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;
1705 layer->SetTexturePriorities(priority_calculator_);
1706 resource_manager_->PrioritizeTextures();
1707 layer->SavePaintProperties();
1709 // Update the whole tile.
1710 layer->Update(queue_.get(), NULL);
1711 layer->tracking_layer_painter()->ResetPaintedRect();
1713 EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect());
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);
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());
1728 TEST_F(TiledLayerTest,
1729 NonIntegerContentsScaleIsNotDistortedDuringInvalidation) {
1730 scoped_refptr<UpdateTrackingTiledLayer> layer =
1731 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get()));
1733 layer_tree_host_->root_layer()->AddChild(layer);
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);
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;
1744 layer->SetTexturePriorities(priority_calculator_);
1745 resource_manager_->PrioritizeTextures();
1746 layer->SavePaintProperties();
1748 // Update the whole tile.
1749 layer->Update(queue_.get(), NULL);
1750 layer->tracking_layer_painter()->ResetPaintedRect();
1752 EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect());
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);
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());