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/location.h"
11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "cc/resources/bitmap_content_layer_updater.h"
15 #include "cc/resources/layer_painter.h"
16 #include "cc/resources/prioritized_resource_manager.h"
17 #include "cc/resources/resource_update_controller.h"
18 #include "cc/test/animation_test_common.h"
19 #include "cc/test/fake_layer_tree_host_client.h"
20 #include "cc/test/fake_layer_tree_host_impl.h"
21 #include "cc/test/fake_output_surface.h"
22 #include "cc/test/fake_output_surface_client.h"
23 #include "cc/test/fake_proxy.h"
24 #include "cc/test/fake_resource_provider.h"
25 #include "cc/test/geometry_test_utils.h"
26 #include "cc/test/test_shared_bitmap_manager.h"
27 #include "cc/test/tiled_layer_test_common.h"
28 #include "cc/trees/occlusion_tracker.h"
29 #include "cc/trees/single_thread_proxy.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "ui/gfx/geometry/rect_conversions.h"
32 #include "ui/gfx/transform.h"
37 class TestOcclusionTracker
: public OcclusionTracker
<Layer
> {
39 TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000)) {
40 stack_
.push_back(StackObject());
43 void SetRenderTarget(Layer
* render_target
) {
44 stack_
.back().target
= render_target
;
47 void SetOcclusion(const SimpleEnclosedRegion
& occlusion
) {
48 stack_
.back().occlusion_from_inside_target
= occlusion
;
52 class SynchronousOutputSurfaceClient
: public FakeLayerTreeHostClient
{
54 SynchronousOutputSurfaceClient()
55 : FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
) {}
57 bool EnsureOutputSurfaceCreated() {
58 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
59 FROM_HERE
, run_loop_
.QuitClosure(), base::TimeDelta::FromSeconds(5));
61 return output_surface_created_
;
64 void DidInitializeOutputSurface() override
{
65 FakeLayerTreeHostClient::DidInitializeOutputSurface();
66 output_surface_created_
= true;
70 void DidFailToInitializeOutputSurface() override
{
71 FakeLayerTreeHostClient::DidFailToInitializeOutputSurface();
72 output_surface_created_
= false;
77 bool output_surface_created_
;
78 base::RunLoop run_loop_
;
81 class TiledLayerTest
: public testing::Test
{
85 output_surface_(FakeOutputSurface::Create3d()),
86 queue_(make_scoped_ptr(new ResourceUpdateQueue
)),
87 impl_thread_("ImplThread"),
89 settings_
.max_partial_texture_updates
= std::numeric_limits
<size_t>::max();
90 settings_
.layer_transforms_should_scale_layer_contents
= true;
91 settings_
.impl_side_painting
= false;
92 settings_
.verify_property_trees
= false;
95 void SetUp() override
{
97 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
98 LayerTreeHost::InitParams params
;
99 params
.client
= &synchronous_output_surface_client_
;
100 params
.shared_bitmap_manager
= shared_bitmap_manager_
.get();
101 params
.settings
= &settings_
;
102 params
.main_task_runner
= base::ThreadTaskRunnerHandle::Get();
105 LayerTreeHost::CreateThreaded(impl_thread_
.task_runner(), ¶ms
);
106 synchronous_output_surface_client_
.SetLayerTreeHost(layer_tree_host_
.get());
107 proxy_
= layer_tree_host_
->proxy();
108 resource_manager_
= PrioritizedResourceManager::Create(proxy_
);
109 layer_tree_host_
->SetLayerTreeHostClientReady();
110 CHECK(synchronous_output_surface_client_
.EnsureOutputSurfaceCreated());
112 layer_tree_host_
->SetRootLayer(Layer::Create(layer_settings_
));
114 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
116 DebugScopedSetImplThreadAndMainThreadBlocked
117 impl_thread_and_main_thread_blocked(proxy_
);
118 resource_provider_
= FakeResourceProvider::Create(
119 output_surface_
.get(), shared_bitmap_manager_
.get());
120 host_impl_
= make_scoped_ptr(new FakeLayerTreeHostImpl(
121 proxy_
, shared_bitmap_manager_
.get(), nullptr));
124 ~TiledLayerTest() override
{
125 ResourceManagerClearAllMemory(resource_manager_
.get(),
126 resource_provider_
.get());
128 DebugScopedSetImplThreadAndMainThreadBlocked
129 impl_thread_and_main_thread_blocked(proxy_
);
130 resource_provider_
= nullptr;
131 host_impl_
= nullptr;
134 void ResourceManagerClearAllMemory(
135 PrioritizedResourceManager
* resource_manager
,
136 ResourceProvider
* resource_provider
) {
138 DebugScopedSetImplThreadAndMainThreadBlocked
139 impl_thread_and_main_thread_blocked(proxy_
);
140 resource_manager
->ClearAllMemory(resource_provider
);
141 resource_manager
->ReduceMemory(resource_provider
);
143 resource_manager
->UnlinkAndClearEvictedBackings();
146 void UpdateTextures() {
147 DebugScopedSetImplThreadAndMainThreadBlocked
148 impl_thread_and_main_thread_blocked(proxy_
);
150 scoped_ptr
<ResourceUpdateController
> update_controller
=
151 ResourceUpdateController::Create(nullptr,
152 proxy_
->ImplThreadTaskRunner(),
154 resource_provider_
.get());
155 update_controller
->Finalize();
156 queue_
= make_scoped_ptr(new ResourceUpdateQueue
);
159 void LayerPushPropertiesTo(FakeTiledLayer
* layer
,
160 FakeTiledLayerImpl
* layer_impl
) {
161 DebugScopedSetImplThreadAndMainThreadBlocked
162 impl_thread_and_main_thread_blocked(proxy_
);
163 layer
->PushPropertiesTo(layer_impl
);
164 layer
->ResetNumDependentsNeedPushProperties();
167 void LayerUpdate(FakeTiledLayer
* layer
, TestOcclusionTracker
* occluded
) {
168 DebugScopedSetMainThread
main_thread(proxy_
);
169 layer
->Update(queue_
.get(), occluded
);
172 void CalcDrawProps(RenderSurfaceLayerList
* render_surface_layer_list
) {
174 occlusion_
->SetRenderTarget(layer_tree_host_
->root_layer());
176 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting
inputs(
177 layer_tree_host_
->root_layer(),
178 layer_tree_host_
->device_viewport_size(),
179 render_surface_layer_list
);
180 inputs
.device_scale_factor
= layer_tree_host_
->device_scale_factor();
181 inputs
.max_texture_size
=
182 layer_tree_host_
->GetRendererCapabilities().max_texture_size
;
183 inputs
.can_adjust_raster_scales
= true;
184 inputs
.verify_property_trees
= false;
185 LayerTreeHostCommon::CalculateDrawProperties(&inputs
);
188 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
189 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
) {
190 scoped_refptr
<FakeTiledLayer
> layer2
;
191 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
;
192 return UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
195 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
196 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
,
197 const scoped_refptr
<FakeTiledLayer
>& layer2
,
198 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl2
) {
200 resource_manager_
->ClearPriorities();
202 layer1
->SetTexturePriorities(priority_calculator_
);
204 layer2
->SetTexturePriorities(priority_calculator_
);
205 resource_manager_
->PrioritizeTextures();
207 // Save paint properties
209 layer1
->SavePaintProperties();
211 layer2
->SavePaintProperties();
215 layer1
->Update(queue_
.get(), occlusion_
);
217 layer2
->Update(queue_
.get(), occlusion_
);
219 bool needs_update
= false;
221 needs_update
|= layer1
->NeedsIdlePaint();
223 needs_update
|= layer2
->NeedsIdlePaint();
225 // Update textures and push.
228 LayerPushPropertiesTo(layer1
.get(), layer_impl1
.get());
230 LayerPushPropertiesTo(layer2
.get(), layer_impl2
.get());
237 LayerTreeSettings settings_
;
238 LayerSettings layer_settings_
;
239 FakeOutputSurfaceClient output_surface_client_
;
240 scoped_ptr
<OutputSurface
> output_surface_
;
241 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
242 scoped_ptr
<ResourceProvider
> resource_provider_
;
243 scoped_ptr
<ResourceUpdateQueue
> queue_
;
244 PriorityCalculator priority_calculator_
;
245 base::Thread impl_thread_
;
246 SynchronousOutputSurfaceClient synchronous_output_surface_client_
;
247 scoped_ptr
<LayerTreeHost
> layer_tree_host_
;
248 scoped_ptr
<FakeLayerTreeHostImpl
> host_impl_
;
249 scoped_ptr
<PrioritizedResourceManager
> resource_manager_
;
250 TestOcclusionTracker
* occlusion_
;
253 TEST_F(TiledLayerTest
, PushDirtyTiles
) {
254 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
256 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
257 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
258 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
259 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
260 RenderSurfaceLayerList render_surface_layer_list
;
262 layer_tree_host_
->root_layer()->AddChild(layer
);
264 // The tile size is 100x100, so this invalidates and then paints two tiles.
265 layer
->SetBounds(gfx::Size(100, 200));
266 CalcDrawProps(&render_surface_layer_list
);
267 UpdateAndPush(layer
, layer_impl
);
269 // We should have both tiles on the impl side.
270 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
271 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
273 // Invalidates both tiles, but then only update one of them.
274 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 200));
275 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
276 UpdateAndPush(layer
, layer_impl
);
278 // We should only have the first tile since the other tile was invalidated but
280 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
281 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
284 TEST_F(TiledLayerTest
, Scale
) {
285 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
287 layer_tree_host_
->SetDeviceScaleFactor(1.5);
289 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
290 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
291 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
292 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
293 RenderSurfaceLayerList render_surface_layer_list
;
295 layer_tree_host_
->root_layer()->AddChild(layer
);
297 layer
->SetBounds(gfx::Size(100, 200));
298 CalcDrawProps(&render_surface_layer_list
);
300 // Change the width so that it doesn't divide cleanly by the scale.
301 layer
->SetBounds(gfx::Size(101, 200));
302 UpdateAndPush(layer
, layer_impl
);
304 EXPECT_EQ(1.5, layer
->fake_layer_updater()->last_contents_width_scale());
307 TEST_F(TiledLayerTest
, PushOccludedDirtyTiles
) {
308 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
309 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
310 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
311 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
312 TestOcclusionTracker occluded
;
313 occlusion_
= &occluded
;
314 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
316 layer_tree_host_
->root_layer()->AddChild(layer
);
319 RenderSurfaceLayerList render_surface_layer_list
;
321 // The tile size is 100x100, so this invalidates and then paints two tiles.
322 layer
->SetBounds(gfx::Size(100, 200));
323 CalcDrawProps(&render_surface_layer_list
);
324 UpdateAndPush(layer
, layer_impl
);
326 // We should have both tiles on the impl side.
327 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
328 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
332 RenderSurfaceLayerList render_surface_layer_list
;
334 // Invalidates part of the top tile...
335 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
336 // ....but the area is occluded.
337 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 50, 50)));
338 CalcDrawProps(&render_surface_layer_list
);
339 UpdateAndPush(layer
, layer_impl
);
341 // We should still have both tiles, as part of the top tile is still
343 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
344 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
348 TEST_F(TiledLayerTest
, PushDeletedTiles
) {
349 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
351 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
352 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
353 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
354 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
355 RenderSurfaceLayerList render_surface_layer_list
;
357 layer_tree_host_
->root_layer()->AddChild(layer
);
359 // The tile size is 100x100, so this invalidates and then paints two tiles.
360 layer
->SetBounds(gfx::Size(100, 200));
361 CalcDrawProps(&render_surface_layer_list
);
362 UpdateAndPush(layer
, layer_impl
);
364 // We should have both tiles on the impl side.
365 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
366 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
368 resource_manager_
->ClearPriorities();
369 ResourceManagerClearAllMemory(resource_manager_
.get(),
370 resource_provider_
.get());
371 resource_manager_
->SetMaxMemoryLimitBytes(4 * 1024 * 1024);
373 // This should drop the tiles on the impl thread.
374 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
376 // We should now have no textures on the impl thread.
377 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
378 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
380 // This should recreate and update one of the deleted textures.
381 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
382 UpdateAndPush(layer
, layer_impl
);
384 // We should have one tiles on the impl side.
385 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
386 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
389 TEST_F(TiledLayerTest
, PushIdlePaintTiles
) {
390 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
391 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
392 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
393 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
394 RenderSurfaceLayerList render_surface_layer_list
;
396 layer_tree_host_
->root_layer()->AddChild(layer
);
398 // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the
399 // center. This paints 1 visible of the 25 invalid tiles.
400 layer
->SetBounds(gfx::Size(500, 500));
401 CalcDrawProps(&render_surface_layer_list
);
402 layer
->draw_properties().visible_content_rect
= gfx::Rect(200, 200, 100, 100);
403 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
404 // We should need idle-painting for surrounding tiles.
405 EXPECT_TRUE(needs_update
);
407 // We should have one tile on the impl side.
408 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(2, 2));
410 // For the next four updates, we should detect we still need idle painting.
411 for (int i
= 0; i
< 4; i
++) {
412 needs_update
= UpdateAndPush(layer
, layer_impl
);
413 EXPECT_TRUE(needs_update
);
416 // We should always finish painting eventually.
417 for (int i
= 0; i
< 20; i
++)
418 needs_update
= UpdateAndPush(layer
, layer_impl
);
420 // We should have pre-painted all of the surrounding tiles.
421 for (int i
= 0; i
< 5; i
++) {
422 for (int j
= 0; j
< 5; j
++)
423 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(i
, j
));
426 EXPECT_FALSE(needs_update
);
429 TEST_F(TiledLayerTest
, PredictivePainting
) {
430 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
431 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
432 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
433 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
435 layer_tree_host_
->root_layer()->AddChild(layer
);
437 // Prepainting should occur in the scroll direction first, and the
438 // visible rect should be extruded only along the dominant axis.
439 gfx::Vector2d directions
[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0),
440 gfx::Vector2d(0, -10), gfx::Vector2d(0, 10),
441 gfx::Vector2d(10, 20),
442 gfx::Vector2d(-20, 10) };
443 // We should push all tiles that touch the extruded visible rect.
444 gfx::Rect pushed_visible_tiles
[6] = {
445 gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2),
446 gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1)
448 // The first pre-paint should also paint first in the scroll
449 // direction so we should find one additional tile in the scroll direction.
450 gfx::Rect pushed_prepaint_tiles
[6] = {
451 gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3),
452 gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1)
454 for (int k
= 0; k
< 6; k
++) {
455 // The tile size is 100x100. Setup 5x5 tiles with one visible tile
457 gfx::Size bounds
= gfx::Size(500, 500);
458 gfx::Rect visible_rect
= gfx::Rect(200, 200, 100, 100);
459 gfx::Rect previous_visible_rect
=
460 gfx::Rect(visible_rect
.origin() + directions
[k
], visible_rect
.size());
461 gfx::Rect next_visible_rect
=
462 gfx::Rect(visible_rect
.origin() - directions
[k
], visible_rect
.size());
464 // Setup. Use the previous_visible_rect to setup the prediction for next
466 layer
->SetBounds(bounds
);
468 RenderSurfaceLayerList render_surface_layer_list
;
469 CalcDrawProps(&render_surface_layer_list
);
470 layer
->draw_properties().visible_content_rect
= previous_visible_rect
;
471 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
473 // Invalidate and move the visible_rect in the scroll direction.
474 // Check that the correct tiles have been painted in the visible pass.
475 layer
->SetNeedsDisplay();
476 layer
->draw_properties().visible_content_rect
= visible_rect
;
477 needs_update
= UpdateAndPush(layer
, layer_impl
);
478 for (int i
= 0; i
< 5; i
++) {
479 for (int j
= 0; j
< 5; j
++)
480 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
),
481 pushed_visible_tiles
[k
].Contains(i
, j
));
484 // Move the transform in the same direction without invalidating.
485 // Check that non-visible pre-painting occured in the correct direction.
486 // Ignore diagonal scrolls here (k > 3) as these have new visible content
489 layer
->draw_properties().visible_content_rect
= next_visible_rect
;
490 needs_update
= UpdateAndPush(layer
, layer_impl
);
491 for (int i
= 0; i
< 5; i
++) {
492 for (int j
= 0; j
< 5; j
++)
493 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
),
494 pushed_prepaint_tiles
[k
].Contains(i
, j
));
498 // We should always finish painting eventually.
499 for (int i
= 0; i
< 20; i
++)
500 needs_update
= UpdateAndPush(layer
, layer_impl
);
501 EXPECT_FALSE(needs_update
);
505 TEST_F(TiledLayerTest
, PushTilesAfterIdlePaintFailed
) {
506 // Start with 2mb of memory, but the test is going to try to use just more
507 // than 1mb, so we reduce to 1mb later.
508 resource_manager_
->SetMaxMemoryLimitBytes(2 * 1024 * 1024);
509 scoped_refptr
<FakeTiledLayer
> layer1
= make_scoped_refptr(
510 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
511 scoped_ptr
<FakeTiledLayerImpl
> layer_impl1
=
512 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
513 scoped_refptr
<FakeTiledLayer
> layer2
= make_scoped_refptr(
514 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
515 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
=
516 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
517 RenderSurfaceLayerList render_surface_layer_list
;
519 layer_tree_host_
->root_layer()->AddChild(layer1
);
520 layer_tree_host_
->root_layer()->AddChild(layer2
);
522 // For this test we have two layers. layer1 exhausts most texture memory,
523 // leaving room for 2 more tiles from layer2, but not all three tiles. First
524 // we paint layer1, and one tile from layer2. Then when we idle paint layer2,
525 // we will fail on the third tile of layer2, and this should not leave the
526 // second tile in a bad state.
528 // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough
529 // for 2 tiles only in the other layer.
530 gfx::Rect
layer1_rect(0, 0, 100, 2400);
532 // This requires 4*30000 bytes of memory.
533 gfx::Rect
layer2_rect(0, 0, 100, 300);
535 // Paint a single tile in layer2 so that it will idle paint.
536 layer1
->SetBounds(layer1_rect
.size());
537 layer2
->SetBounds(layer2_rect
.size());
538 CalcDrawProps(&render_surface_layer_list
);
539 layer1
->draw_properties().visible_content_rect
= layer1_rect
;
540 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
541 bool needs_update
= UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
542 // We should need idle-painting for both remaining tiles in layer2.
543 EXPECT_TRUE(needs_update
);
545 // Reduce our memory limits to 1mb.
546 resource_manager_
->SetMaxMemoryLimitBytes(1024 * 1024);
548 // Now idle paint layer2. We are going to run out of memory though!
549 // Oh well, commit the frame and push.
550 for (int i
= 0; i
< 4; i
++) {
551 needs_update
= UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
554 // Sanity check, we should have textures for the big layer.
555 EXPECT_TRUE(layer_impl1
->HasResourceIdForTileAt(0, 0));
556 EXPECT_TRUE(layer_impl1
->HasResourceIdForTileAt(0, 23));
558 // We should only have the first two tiles from layer2 since
559 // it failed to idle update the last tile.
560 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 0));
561 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 0));
562 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 1));
563 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 1));
565 EXPECT_FALSE(needs_update
);
566 EXPECT_FALSE(layer_impl2
->HasResourceIdForTileAt(0, 2));
569 TEST_F(TiledLayerTest
, PushIdlePaintedOccludedTiles
) {
570 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
571 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
572 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
573 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
574 RenderSurfaceLayerList render_surface_layer_list
;
575 TestOcclusionTracker occluded
;
576 occlusion_
= &occluded
;
578 layer_tree_host_
->root_layer()->AddChild(layer
);
580 // The tile size is 100x100, so this invalidates one occluded tile, culls it
581 // during paint, but prepaints it.
582 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 100, 100)));
584 layer
->SetBounds(gfx::Size(100, 100));
585 CalcDrawProps(&render_surface_layer_list
);
586 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
587 UpdateAndPush(layer
, layer_impl
);
589 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
592 TEST_F(TiledLayerTest
, PushTilesMarkedDirtyDuringPaint
) {
593 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
594 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
595 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
596 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
597 RenderSurfaceLayerList render_surface_layer_list
;
599 layer_tree_host_
->root_layer()->AddChild(layer
);
601 // The tile size is 100x100, so this invalidates and then paints two tiles.
602 // However, during the paint, we invalidate one of the tiles. This should
603 // not prevent the tile from being pushed.
604 layer
->fake_layer_updater()->SetRectToInvalidate(
605 gfx::Rect(0, 50, 100, 50), layer
.get());
606 layer
->SetBounds(gfx::Size(100, 200));
607 CalcDrawProps(&render_surface_layer_list
);
608 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
609 UpdateAndPush(layer
, layer_impl
);
611 // We should have both tiles on the impl side.
612 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
613 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
616 TEST_F(TiledLayerTest
, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer
) {
617 scoped_refptr
<FakeTiledLayer
> layer1
= make_scoped_refptr(
618 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
619 scoped_refptr
<FakeTiledLayer
> layer2
= make_scoped_refptr(
620 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
621 scoped_ptr
<FakeTiledLayerImpl
> layer1_impl
=
622 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
623 scoped_ptr
<FakeTiledLayerImpl
> layer2_impl
=
624 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
625 RenderSurfaceLayerList render_surface_layer_list
;
627 layer_tree_host_
->root_layer()->AddChild(layer1
);
628 layer_tree_host_
->root_layer()->AddChild(layer2
);
630 // Invalidate a tile on layer1, during update of layer 2.
631 layer2
->fake_layer_updater()->SetRectToInvalidate(
632 gfx::Rect(0, 50, 100, 50), layer1
.get());
633 layer1
->SetBounds(gfx::Size(100, 200));
634 layer2
->SetBounds(gfx::Size(100, 200));
635 CalcDrawProps(&render_surface_layer_list
);
636 layer1
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
637 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
638 UpdateAndPush(layer1
, layer1_impl
, layer2
, layer2_impl
);
640 // We should have both tiles on the impl side for all layers.
641 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 0));
642 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 1));
643 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 0));
644 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 1));
647 TEST_F(TiledLayerTest
, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer
) {
648 scoped_refptr
<FakeTiledLayer
> layer1
= make_scoped_refptr(
649 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
650 scoped_refptr
<FakeTiledLayer
> layer2
= make_scoped_refptr(
651 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
652 scoped_ptr
<FakeTiledLayerImpl
> layer1_impl
=
653 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
654 scoped_ptr
<FakeTiledLayerImpl
> layer2_impl
=
655 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
656 RenderSurfaceLayerList render_surface_layer_list
;
658 layer_tree_host_
->root_layer()->AddChild(layer1
);
659 layer_tree_host_
->root_layer()->AddChild(layer2
);
661 layer1
->fake_layer_updater()->SetRectToInvalidate(
662 gfx::Rect(0, 50, 100, 50), layer2
.get());
663 layer1
->SetBounds(gfx::Size(100, 200));
664 layer2
->SetBounds(gfx::Size(100, 200));
665 CalcDrawProps(&render_surface_layer_list
);
666 layer1
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
667 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
668 UpdateAndPush(layer1
, layer1_impl
, layer2
, layer2_impl
);
670 // We should have both tiles on the impl side for all layers.
671 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 0));
672 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 1));
673 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 0));
674 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 1));
677 TEST_F(TiledLayerTest
, PaintSmallAnimatedLayersImmediately
) {
678 // Create a LayerTreeHost that has the right viewportsize,
679 // so the layer is considered small enough.
680 bool run_out_of_memory
[2] = { false, true };
681 for (int i
= 0; i
< 2; i
++) {
682 // Create a layer with 5x5 tiles, with 4x4 size viewport.
683 int viewport_width
= 4 * FakeTiledLayer::tile_size().width();
684 int viewport_height
= 4 * FakeTiledLayer::tile_size().width();
685 int layer_width
= 5 * FakeTiledLayer::tile_size().width();
686 int layer_height
= 5 * FakeTiledLayer::tile_size().height();
687 int memory_for_layer
= layer_width
* layer_height
* 4;
688 layer_tree_host_
->SetViewportSize(
689 gfx::Size(viewport_width
, viewport_height
));
691 // Use 10x5 tiles to run out of memory.
692 if (run_out_of_memory
[i
])
695 resource_manager_
->SetMaxMemoryLimitBytes(memory_for_layer
);
697 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
698 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
699 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
700 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
701 RenderSurfaceLayerList render_surface_layer_list
;
703 layer_tree_host_
->root_layer()->AddChild(layer
);
705 // Full size layer with half being visible.
706 layer
->SetBounds(gfx::Size(layer_width
, layer_height
));
707 gfx::Rect
visible_rect(0, 0, layer_width
/ 2, layer_height
);
708 CalcDrawProps(&render_surface_layer_list
);
710 // Pretend the layer is animating.
711 layer
->draw_properties().target_space_transform_is_animating
= true;
712 layer
->draw_properties().visible_content_rect
= visible_rect
;
713 layer
->SetLayerTreeHost(layer_tree_host_
.get());
715 // The layer should paint its entire contents on the first paint
716 // if it is close to the viewport size and has the available memory.
717 layer
->SetTexturePriorities(priority_calculator_
);
718 resource_manager_
->PrioritizeTextures();
719 layer
->SavePaintProperties();
720 layer
->Update(queue_
.get(), nullptr);
722 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
724 // We should have all the tiles for the small animated layer.
725 // We should still have the visible tiles when we didn't
726 // have enough memory for all the tiles.
727 if (!run_out_of_memory
[i
]) {
728 for (int i
= 0; i
< 5; ++i
) {
729 for (int j
= 0; j
< 5; ++j
)
730 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(i
, j
));
733 for (int i
= 0; i
< 10; ++i
) {
734 for (int j
= 0; j
< 5; ++j
)
735 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
), i
< 5);
739 layer
->RemoveFromParent();
743 TEST_F(TiledLayerTest
, IdlePaintOutOfMemory
) {
744 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
745 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
746 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
747 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
748 RenderSurfaceLayerList render_surface_layer_list
;
750 layer_tree_host_
->root_layer()->AddChild(layer
);
752 // We have enough memory for only the visible rect, so we will run out of
753 // memory in first idle paint.
754 int memory_limit
= 4 * 100 * 100; // 1 tiles, 4 bytes per pixel.
755 resource_manager_
->SetMaxMemoryLimitBytes(memory_limit
);
757 // The tile size is 100x100, so this invalidates and then paints two tiles.
758 bool needs_update
= false;
759 layer
->SetBounds(gfx::Size(300, 300));
760 CalcDrawProps(&render_surface_layer_list
);
761 layer
->draw_properties().visible_content_rect
= gfx::Rect(100, 100, 100, 100);
762 for (int i
= 0; i
< 2; i
++)
763 needs_update
= UpdateAndPush(layer
, layer_impl
);
765 // Idle-painting should see no more priority tiles for painting.
766 EXPECT_FALSE(needs_update
);
768 // We should have one tile on the impl side.
769 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 1));
772 TEST_F(TiledLayerTest
, IdlePaintZeroSizedLayer
) {
773 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
774 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
775 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
776 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
778 layer_tree_host_
->root_layer()->AddChild(layer
);
780 bool animating
[2] = { false, true };
781 for (int i
= 0; i
< 2; i
++) {
782 // Pretend the layer is animating.
783 layer
->draw_properties().target_space_transform_is_animating
= animating
[i
];
785 // The layer's bounds are empty.
786 // Empty layers don't paint or idle-paint.
787 layer
->SetBounds(gfx::Size());
789 RenderSurfaceLayerList render_surface_layer_list
;
790 CalcDrawProps(&render_surface_layer_list
);
791 layer
->draw_properties().visible_content_rect
= gfx::Rect();
792 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
794 // Empty layers don't have tiles.
795 EXPECT_EQ(0u, layer
->NumPaintedTiles());
797 // Empty layers don't need prepaint.
798 EXPECT_FALSE(needs_update
);
800 // Empty layers don't have tiles.
801 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
805 TEST_F(TiledLayerTest
, IdlePaintNonVisibleLayers
) {
806 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
807 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
808 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
809 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
811 // Alternate between not visible and visible.
812 gfx::Rect
v(0, 0, 100, 100);
813 gfx::Rect
nv(0, 0, 0, 0);
814 gfx::Rect visible_rect
[10] = { nv
, nv
, v
, v
, nv
, nv
, v
, v
, nv
, nv
};
815 bool invalidate
[10] = { true, true, true, true, true, true, true, true, false,
818 // We should not have any tiles except for when the layer was visible
819 // or after the layer was visible and we didn't invalidate.
820 bool have_tile
[10] = { false, false, true, true, false, false, true, true,
823 layer_tree_host_
->root_layer()->AddChild(layer
);
825 for (int i
= 0; i
< 10; i
++) {
826 layer
->SetBounds(gfx::Size(100, 100));
828 RenderSurfaceLayerList render_surface_layer_list
;
829 CalcDrawProps(&render_surface_layer_list
);
830 layer
->draw_properties().visible_content_rect
= visible_rect
[i
];
833 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 100));
834 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
836 // We should never signal idle paint, as we painted the entire layer
837 // or the layer was not visible.
838 EXPECT_FALSE(needs_update
);
839 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(0, 0), have_tile
[i
]);
843 TEST_F(TiledLayerTest
, InvalidateFromPrepare
) {
844 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
845 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
846 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
847 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
848 RenderSurfaceLayerList render_surface_layer_list
;
850 layer_tree_host_
->root_layer()->AddChild(layer
);
852 // The tile size is 100x100, so this invalidates and then paints two tiles.
853 layer
->SetBounds(gfx::Size(100, 200));
854 CalcDrawProps(&render_surface_layer_list
);
855 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
856 UpdateAndPush(layer
, layer_impl
);
858 // We should have both tiles on the impl side.
859 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
860 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
862 layer
->fake_layer_updater()->ClearPrepareCount();
863 // Invoke update again. As the layer is valid update shouldn't be invoked on
865 UpdateAndPush(layer
, layer_impl
);
866 EXPECT_EQ(0, layer
->fake_layer_updater()->prepare_count());
868 // SetRectToInvalidate triggers InvalidateContentRect() being invoked from
870 layer
->fake_layer_updater()->SetRectToInvalidate(
871 gfx::Rect(25, 25, 50, 50), layer
.get());
872 layer
->fake_layer_updater()->ClearPrepareCount();
873 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
874 UpdateAndPush(layer
, layer_impl
);
875 EXPECT_EQ(1, layer
->fake_layer_updater()->prepare_count());
876 layer
->fake_layer_updater()->ClearPrepareCount();
878 // The layer should still be invalid as update invoked invalidate.
879 UpdateAndPush(layer
, layer_impl
); // visible
880 EXPECT_EQ(1, layer
->fake_layer_updater()->prepare_count());
883 TEST_F(TiledLayerTest
, VerifyUpdateRectWhenContentBoundsAreScaled
) {
884 // The update rect (that indicates what was actually painted) should be in
885 // layer space, not the content space.
886 scoped_refptr
<FakeTiledLayerWithScaledBounds
> layer
=
887 make_scoped_refptr(new FakeTiledLayerWithScaledBounds(
888 layer_settings_
, resource_manager_
.get()));
890 layer_tree_host_
->root_layer()->AddChild(layer
);
892 gfx::Rect
layer_bounds(0, 0, 300, 200);
893 gfx::Rect
content_bounds(0, 0, 150, 250);
895 layer
->SetBounds(layer_bounds
.size());
896 layer
->SetContentBounds(content_bounds
.size());
897 layer
->draw_properties().visible_content_rect
= content_bounds
;
898 layer
->draw_properties().contents_scale_x
= .5f
;
899 layer
->draw_properties().contents_scale_y
= 1.25f
;
901 // On first update, the update_rect includes all tiles, even beyond the
902 // boundaries of the layer.
903 // However, it should still be in layer space, not content space.
904 layer
->InvalidateContentRect(content_bounds
);
906 layer
->SetTexturePriorities(priority_calculator_
);
907 resource_manager_
->PrioritizeTextures();
908 layer
->SavePaintProperties();
909 layer
->Update(queue_
.get(), nullptr);
911 // Update rect is 200x300 (tile size of 100x100). Scaled this gives 400x240.
912 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 400, 240), layer
->update_rect());
915 // After the tiles are updated once, another invalidate only needs to update
916 // the bounds of the layer.
917 layer
->SetTexturePriorities(priority_calculator_
);
918 resource_manager_
->PrioritizeTextures();
919 layer
->InvalidateContentRect(content_bounds
);
920 layer
->SavePaintProperties();
921 layer
->Update(queue_
.get(), nullptr);
922 EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds
), layer
->update_rect());
925 // Partial re-paint should also be represented by the update rect in layer
926 // space, not content space.
927 gfx::Rect
partial_damage(30, 100, 10, 10);
928 layer
->InvalidateContentRect(partial_damage
);
929 layer
->SetTexturePriorities(priority_calculator_
);
930 resource_manager_
->PrioritizeTextures();
931 layer
->SavePaintProperties();
932 layer
->Update(queue_
.get(), nullptr);
933 EXPECT_FLOAT_RECT_EQ(gfx::RectF(60, 80, 20, 8), layer
->update_rect());
936 TEST_F(TiledLayerTest
, VerifyInvalidationWhenContentsScaleChanges
) {
937 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
938 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
939 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
940 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
941 RenderSurfaceLayerList render_surface_layer_list
;
943 layer_tree_host_
->root_layer()->AddChild(layer
);
945 // Create a layer with one tile.
946 layer
->SetBounds(gfx::Size(100, 100));
947 CalcDrawProps(&render_surface_layer_list
);
948 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
949 layer
->Update(queue_
.get(), nullptr);
951 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
952 layer
->last_needs_display_rect());
954 // Push the tiles to the impl side and check that there is exactly one.
955 layer
->SetTexturePriorities(priority_calculator_
);
956 resource_manager_
->PrioritizeTextures();
957 layer
->SavePaintProperties();
958 layer
->Update(queue_
.get(), nullptr);
960 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
961 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
962 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
963 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 0));
964 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 1));
966 layer
->SetNeedsDisplayRect(gfx::Rect());
967 EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer
->last_needs_display_rect());
969 // Change the contents scale.
970 layer
->UpdateContentsScale(2.f
);
971 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 200, 200);
973 // The impl side should get 2x2 tiles now.
974 layer
->SetTexturePriorities(priority_calculator_
);
975 resource_manager_
->PrioritizeTextures();
976 layer
->SavePaintProperties();
977 layer
->Update(queue_
.get(), nullptr);
979 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
980 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
981 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
982 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 0));
983 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 1));
985 // Verify that changing the contents scale caused invalidation, and
986 // that the layer-space rectangle requiring painting is not scaled.
987 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
988 layer
->last_needs_display_rect());
990 // Invalidate the entire layer again, but do not paint. All tiles should be
991 // gone now from the impl side.
992 layer
->SetNeedsDisplay();
993 layer
->SetTexturePriorities(priority_calculator_
);
994 resource_manager_
->PrioritizeTextures();
996 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
997 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
998 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
999 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 0));
1000 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 1));
1003 TEST_F(TiledLayerTest
, SkipsDrawGetsReset
) {
1004 // Create two 300 x 300 tiled layers.
1005 gfx::Size
content_bounds(300, 300);
1006 gfx::Rect
content_rect(content_bounds
);
1008 // We have enough memory for only one of the two layers.
1009 int memory_limit
= 4 * 300 * 300; // 4 bytes per pixel.
1011 scoped_refptr
<FakeTiledLayer
> root_layer
=
1012 make_scoped_refptr(new FakeTiledLayer(
1013 layer_settings_
, layer_tree_host_
->contents_texture_manager()));
1014 scoped_refptr
<FakeTiledLayer
> child_layer
=
1015 make_scoped_refptr(new FakeTiledLayer(
1016 layer_settings_
, layer_tree_host_
->contents_texture_manager()));
1017 root_layer
->AddChild(child_layer
);
1019 root_layer
->SetBounds(content_bounds
);
1020 root_layer
->draw_properties().visible_content_rect
= content_rect
;
1021 root_layer
->SetPosition(gfx::PointF(0, 0));
1022 child_layer
->SetBounds(content_bounds
);
1023 child_layer
->draw_properties().visible_content_rect
= content_rect
;
1024 child_layer
->SetPosition(gfx::PointF(0, 0));
1025 root_layer
->InvalidateContentRect(content_rect
);
1026 child_layer
->InvalidateContentRect(content_rect
);
1028 layer_tree_host_
->SetRootLayer(root_layer
);
1029 layer_tree_host_
->SetViewportSize(gfx::Size(300, 300));
1030 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1033 layer_tree_host_
->UpdateLayers(queue_
.get());
1035 // We'll skip the root layer.
1036 EXPECT_TRUE(root_layer
->SkipsDraw());
1037 EXPECT_FALSE(child_layer
->SkipsDraw());
1039 layer_tree_host_
->CommitComplete();
1041 // Remove the child layer.
1042 root_layer
->RemoveAllChildren();
1044 layer_tree_host_
->UpdateLayers(queue_
.get());
1045 EXPECT_FALSE(root_layer
->SkipsDraw());
1047 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1048 resource_provider_
.get());
1049 layer_tree_host_
->SetRootLayer(nullptr);
1052 TEST_F(TiledLayerTest
, ResizeToSmaller
) {
1053 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
1054 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
1056 layer_tree_host_
->root_layer()->AddChild(layer
);
1058 layer
->SetBounds(gfx::Size(700, 700));
1059 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 700, 700);
1060 layer
->InvalidateContentRect(gfx::Rect(0, 0, 700, 700));
1062 layer
->SetTexturePriorities(priority_calculator_
);
1063 resource_manager_
->PrioritizeTextures();
1064 layer
->SavePaintProperties();
1065 layer
->Update(queue_
.get(), nullptr);
1067 layer
->SetBounds(gfx::Size(200, 200));
1068 layer
->InvalidateContentRect(gfx::Rect(0, 0, 200, 200));
1071 TEST_F(TiledLayerTest
, HugeLayerUpdateCrash
) {
1072 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
1073 new FakeTiledLayer(layer_settings_
, resource_manager_
.get()));
1075 layer_tree_host_
->root_layer()->AddChild(layer
);
1078 layer
->SetBounds(gfx::Size(size
, size
));
1079 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 700, 700);
1080 layer
->InvalidateContentRect(gfx::Rect(0, 0, size
, size
));
1082 // Ensure no crash for bounds where size * size would overflow an int.
1083 layer
->SetTexturePriorities(priority_calculator_
);
1084 resource_manager_
->PrioritizeTextures();
1085 layer
->SavePaintProperties();
1086 layer
->Update(queue_
.get(), nullptr);
1089 class TiledLayerPartialUpdateTest
: public TiledLayerTest
{
1091 TiledLayerPartialUpdateTest() { settings_
.max_partial_texture_updates
= 4; }
1094 TEST_F(TiledLayerPartialUpdateTest
, PartialUpdates
) {
1095 // Create one 300 x 200 tiled layer with 3 x 2 tiles.
1096 gfx::Size
content_bounds(300, 200);
1097 gfx::Rect
content_rect(content_bounds
);
1099 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(new FakeTiledLayer(
1100 layer_settings_
, layer_tree_host_
->contents_texture_manager()));
1101 layer
->SetBounds(content_bounds
);
1102 layer
->SetPosition(gfx::PointF(0, 0));
1103 layer
->draw_properties().visible_content_rect
= content_rect
;
1104 layer
->InvalidateContentRect(content_rect
);
1106 layer_tree_host_
->SetRootLayer(layer
);
1107 layer_tree_host_
->SetViewportSize(gfx::Size(300, 200));
1109 // Full update of all 6 tiles.
1110 layer_tree_host_
->UpdateLayers(queue_
.get());
1112 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1113 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1114 EXPECT_EQ(6u, queue_
->FullUploadSize());
1115 EXPECT_EQ(0u, queue_
->PartialUploadSize());
1117 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1118 EXPECT_FALSE(queue_
->HasMoreUpdates());
1119 layer
->fake_layer_updater()->ClearUpdateCount();
1120 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1122 layer_tree_host_
->CommitComplete();
1124 // Full update of 3 tiles and partial update of 3 tiles.
1125 layer
->InvalidateContentRect(gfx::Rect(0, 0, 300, 150));
1126 layer_tree_host_
->UpdateLayers(queue_
.get());
1128 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1129 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1130 EXPECT_EQ(3u, queue_
->FullUploadSize());
1131 EXPECT_EQ(3u, queue_
->PartialUploadSize());
1133 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1134 EXPECT_FALSE(queue_
->HasMoreUpdates());
1135 layer
->fake_layer_updater()->ClearUpdateCount();
1136 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1138 layer_tree_host_
->CommitComplete();
1140 // Partial update of 6 tiles.
1141 layer
->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1143 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1144 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1145 layer_tree_host_
->UpdateLayers(queue_
.get());
1146 EXPECT_EQ(2u, queue_
->FullUploadSize());
1147 EXPECT_EQ(4u, queue_
->PartialUploadSize());
1149 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1150 EXPECT_FALSE(queue_
->HasMoreUpdates());
1151 layer
->fake_layer_updater()->ClearUpdateCount();
1152 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1154 layer_tree_host_
->CommitComplete();
1156 // Checkerboard all tiles.
1157 layer
->InvalidateContentRect(gfx::Rect(0, 0, 300, 200));
1159 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1160 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1161 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1163 layer_tree_host_
->CommitComplete();
1165 // Partial update of 6 checkerboard tiles.
1166 layer
->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1168 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1169 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1170 layer_tree_host_
->UpdateLayers(queue_
.get());
1171 EXPECT_EQ(6u, queue_
->FullUploadSize());
1172 EXPECT_EQ(0u, queue_
->PartialUploadSize());
1174 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1175 EXPECT_FALSE(queue_
->HasMoreUpdates());
1176 layer
->fake_layer_updater()->ClearUpdateCount();
1177 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1179 layer_tree_host_
->CommitComplete();
1181 // Partial update of 4 tiles.
1182 layer
->InvalidateContentRect(gfx::Rect(50, 50, 100, 100));
1184 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1185 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1186 layer_tree_host_
->UpdateLayers(queue_
.get());
1187 EXPECT_EQ(0u, queue_
->FullUploadSize());
1188 EXPECT_EQ(4u, queue_
->PartialUploadSize());
1190 EXPECT_EQ(4, layer
->fake_layer_updater()->update_count());
1191 EXPECT_FALSE(queue_
->HasMoreUpdates());
1192 layer
->fake_layer_updater()->ClearUpdateCount();
1193 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1195 layer_tree_host_
->CommitComplete();
1197 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1198 resource_provider_
.get());
1199 layer_tree_host_
->SetRootLayer(nullptr);
1202 TEST_F(TiledLayerTest
, TilesPaintedWithoutOcclusion
) {
1203 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
1205 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
1206 new FakeTiledLayer(layer_settings_
, 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(), nullptr);
1219 EXPECT_EQ(2, layer
->fake_layer_updater()->update_count());
1222 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusion
) {
1223 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
1224 new FakeTiledLayer(layer_settings_
, 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
= make_scoped_refptr(
1273 new FakeTiledLayer(layer_settings_
, 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
= make_scoped_refptr(
1330 new FakeTiledLayer(layer_settings_
, 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
= make_scoped_refptr(
1367 new FakeTiledLayer(layer_settings_
, 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(layer_settings_
, resource_manager_
.get());
1402 RenderSurfaceLayerList render_surface_layer_list
;
1403 TestOcclusionTracker occluded
;
1404 occlusion_
= &occluded
;
1406 scoped_refptr
<FakeTiledLayer
> scale_layer
=
1407 new FakeTiledLayer(layer_settings_
, 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(new FakeTiledLayer(
1491 layer_settings_
, layer_tree_host_
->contents_texture_manager()));
1492 scoped_refptr
<Layer
> surface
= Layer::Create(layer_settings_
);
1493 scoped_refptr
<FakeTiledLayer
> child
= make_scoped_refptr(new FakeTiledLayer(
1494 layer_settings_
, layer_tree_host_
->contents_texture_manager()));
1495 scoped_refptr
<FakeTiledLayer
> child2
= make_scoped_refptr(new FakeTiledLayer(
1496 layer_settings_
, 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(nullptr);
1645 class TrackingLayerPainter
: public LayerPainter
{
1647 static scoped_ptr
<TrackingLayerPainter
> Create() {
1648 return make_scoped_ptr(new TrackingLayerPainter());
1651 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(const LayerSettings
& settings
,
1665 PrioritizedResourceManager
* manager
)
1666 : FakeTiledLayer(settings
, manager
) {
1667 scoped_ptr
<TrackingLayerPainter
> painter(TrackingLayerPainter::Create());
1668 tracking_layer_painter_
= painter
.get();
1669 layer_updater_
= BitmapContentLayerUpdater::Create(painter
.Pass(), 0);
1672 TrackingLayerPainter
* tracking_layer_painter() const {
1673 return tracking_layer_painter_
;
1677 LayerUpdater
* Updater() const override
{ return layer_updater_
.get(); }
1678 ~UpdateTrackingTiledLayer() override
{}
1680 TrackingLayerPainter
* tracking_layer_painter_
;
1681 scoped_refptr
<BitmapContentLayerUpdater
> layer_updater_
;
1684 TEST_F(TiledLayerTest
, NonIntegerContentsScaleIsNotDistortedDuringPaint
) {
1685 scoped_refptr
<UpdateTrackingTiledLayer
> layer
= make_scoped_refptr(
1686 new UpdateTrackingTiledLayer(layer_settings_
, resource_manager_
.get()));
1688 layer_tree_host_
->root_layer()->AddChild(layer
);
1690 gfx::Rect
layer_rect(0, 0, 30, 31);
1691 layer
->SetPosition(layer_rect
.origin());
1692 layer
->SetBounds(layer_rect
.size());
1693 layer
->UpdateContentsScale(1.5f
);
1695 gfx::Rect
content_rect(0, 0, 45, 47);
1696 EXPECT_EQ(content_rect
.size(), layer
->content_bounds());
1697 layer
->draw_properties().visible_content_rect
= content_rect
;
1698 layer
->draw_properties().drawable_content_rect
= content_rect
;
1700 layer
->SetTexturePriorities(priority_calculator_
);
1701 resource_manager_
->PrioritizeTextures();
1702 layer
->SavePaintProperties();
1704 // Update the whole tile.
1705 layer
->Update(queue_
.get(), nullptr);
1706 layer
->tracking_layer_painter()->ResetPaintedRect();
1708 EXPECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
1711 // Invalidate the entire layer in content space. When painting, the rect given
1712 // to webkit should match the layer's bounds.
1713 layer
->InvalidateContentRect(content_rect
);
1714 layer
->Update(queue_
.get(), nullptr);
1716 // Rounding leads to an extra pixel.
1717 gfx::Rect
expanded_layer_rect(layer_rect
);
1718 expanded_layer_rect
.set_height(32);
1719 EXPECT_EQ(expanded_layer_rect
,
1720 layer
->tracking_layer_painter()->PaintedRect());
1723 TEST_F(TiledLayerTest
,
1724 NonIntegerContentsScaleIsNotDistortedDuringInvalidation
) {
1725 scoped_refptr
<UpdateTrackingTiledLayer
> layer
= make_scoped_refptr(
1726 new UpdateTrackingTiledLayer(layer_settings_
, resource_manager_
.get()));
1728 layer_tree_host_
->root_layer()->AddChild(layer
);
1730 gfx::Rect
layer_rect(0, 0, 30, 31);
1731 layer
->SetPosition(layer_rect
.origin());
1732 layer
->SetBounds(layer_rect
.size());
1733 layer
->UpdateContentsScale(1.3f
);
1735 gfx::Rect
content_rect(layer
->content_bounds());
1736 layer
->draw_properties().visible_content_rect
= content_rect
;
1737 layer
->draw_properties().drawable_content_rect
= content_rect
;
1739 layer
->SetTexturePriorities(priority_calculator_
);
1740 resource_manager_
->PrioritizeTextures();
1741 layer
->SavePaintProperties();
1743 // Update the whole tile.
1744 layer
->Update(queue_
.get(), nullptr);
1745 layer
->tracking_layer_painter()->ResetPaintedRect();
1747 EXPECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
1750 // Invalidate the entire layer in layer space. When painting, the rect given
1751 // to webkit should match the layer's bounds.
1752 layer
->SetNeedsDisplayRect(layer_rect
);
1753 layer
->Update(queue_
.get(), nullptr);
1755 // Rounding leads to an extra pixel.
1756 gfx::Rect
expanded_layer_rect(layer_rect
);
1757 expanded_layer_rect
.set_height(32);
1758 EXPECT_EQ(expanded_layer_rect
,
1759 layer
->tracking_layer_painter()->PaintedRect());