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/geometry_test_utils.h"
22 #include "cc/test/test_shared_bitmap_manager.h"
23 #include "cc/test/tiled_layer_test_common.h"
24 #include "cc/trees/occlusion_tracker.h"
25 #include "cc/trees/single_thread_proxy.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "ui/gfx/geometry/rect_conversions.h"
28 #include "ui/gfx/transform.h"
33 class TestOcclusionTracker
: public OcclusionTracker
<Layer
> {
35 TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000)) {
36 stack_
.push_back(StackObject());
39 void SetRenderTarget(Layer
* render_target
) {
40 stack_
.back().target
= render_target
;
43 void SetOcclusion(const SimpleEnclosedRegion
& occlusion
) {
44 stack_
.back().occlusion_from_inside_target
= occlusion
;
48 class SynchronousOutputSurfaceLayerTreeHost
: public LayerTreeHost
{
50 static scoped_ptr
<SynchronousOutputSurfaceLayerTreeHost
> Create(
51 LayerTreeHostClient
* client
,
52 SharedBitmapManager
* manager
,
53 const LayerTreeSettings
& settings
,
54 scoped_refptr
<base::SingleThreadTaskRunner
> impl_task_runner
) {
55 return make_scoped_ptr(new SynchronousOutputSurfaceLayerTreeHost(
56 client
, manager
, settings
, impl_task_runner
));
59 ~SynchronousOutputSurfaceLayerTreeHost() override
{}
61 bool EnsureOutputSurfaceCreated() {
62 base::MessageLoop::current()->PostDelayedTask(
64 run_loop_
.QuitClosure(),
65 base::TimeDelta::FromSeconds(5));
67 return output_surface_created_
;
70 void OnCreateAndInitializeOutputSurfaceAttempted(bool success
) override
{
71 LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(success
);
72 output_surface_created_
= success
;
77 SynchronousOutputSurfaceLayerTreeHost(
78 LayerTreeHostClient
* client
,
79 SharedBitmapManager
* manager
,
80 const LayerTreeSettings
& settings
,
81 scoped_refptr
<base::SingleThreadTaskRunner
> impl_task_runner
)
82 : LayerTreeHost(client
, manager
, NULL
, settings
),
83 output_surface_created_(false) {
84 LayerTreeHost::InitializeThreaded(base::MessageLoopProxy::current(),
89 bool output_surface_created_
;
90 base::RunLoop run_loop_
;
93 class TiledLayerTest
: public testing::Test
{
97 output_surface_(FakeOutputSurface::Create3d()),
98 queue_(make_scoped_ptr(new ResourceUpdateQueue
)),
99 impl_thread_("ImplThread"),
100 fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D
),
101 occlusion_(nullptr) {
102 settings_
.max_partial_texture_updates
= std::numeric_limits
<size_t>::max();
103 settings_
.layer_transforms_should_scale_layer_contents
= true;
106 void SetUp() override
{
107 impl_thread_
.Start();
108 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
109 layer_tree_host_
= SynchronousOutputSurfaceLayerTreeHost::Create(
110 &fake_layer_tree_host_client_
,
111 shared_bitmap_manager_
.get(),
113 impl_thread_
.message_loop_proxy());
114 fake_layer_tree_host_client_
.SetLayerTreeHost(layer_tree_host_
.get());
115 proxy_
= layer_tree_host_
->proxy();
116 resource_manager_
= PrioritizedResourceManager::Create(proxy_
);
117 layer_tree_host_
->SetLayerTreeHostClientReady();
118 CHECK(layer_tree_host_
->EnsureOutputSurfaceCreated());
119 layer_tree_host_
->SetRootLayer(Layer::Create());
121 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
123 DebugScopedSetImplThreadAndMainThreadBlocked
124 impl_thread_and_main_thread_blocked(proxy_
);
125 resource_provider_
= ResourceProvider::Create(output_surface_
.get(),
126 shared_bitmap_manager_
.get(),
132 host_impl_
= make_scoped_ptr(
133 new FakeLayerTreeHostImpl(proxy_
, shared_bitmap_manager_
.get()));
136 virtual ~TiledLayerTest() {
137 ResourceManagerClearAllMemory(resource_manager_
.get(),
138 resource_provider_
.get());
140 DebugScopedSetImplThreadAndMainThreadBlocked
141 impl_thread_and_main_thread_blocked(proxy_
);
142 resource_provider_
= nullptr;
143 host_impl_
= nullptr;
146 void ResourceManagerClearAllMemory(
147 PrioritizedResourceManager
* resource_manager
,
148 ResourceProvider
* resource_provider
) {
150 DebugScopedSetImplThreadAndMainThreadBlocked
151 impl_thread_and_main_thread_blocked(proxy_
);
152 resource_manager
->ClearAllMemory(resource_provider
);
153 resource_manager
->ReduceMemory(resource_provider
);
155 resource_manager
->UnlinkAndClearEvictedBackings();
158 void UpdateTextures() {
159 DebugScopedSetImplThreadAndMainThreadBlocked
160 impl_thread_and_main_thread_blocked(proxy_
);
162 scoped_ptr
<ResourceUpdateController
> update_controller
=
163 ResourceUpdateController::Create(nullptr,
164 proxy_
->ImplThreadTaskRunner(),
166 resource_provider_
.get());
167 update_controller
->Finalize();
168 queue_
= make_scoped_ptr(new ResourceUpdateQueue
);
171 void LayerPushPropertiesTo(FakeTiledLayer
* layer
,
172 FakeTiledLayerImpl
* layer_impl
) {
173 DebugScopedSetImplThreadAndMainThreadBlocked
174 impl_thread_and_main_thread_blocked(proxy_
);
175 layer
->PushPropertiesTo(layer_impl
);
176 layer
->ResetNumDependentsNeedPushProperties();
179 void LayerUpdate(FakeTiledLayer
* layer
, TestOcclusionTracker
* occluded
) {
180 DebugScopedSetMainThread
main_thread(proxy_
);
181 layer
->Update(queue_
.get(), occluded
);
184 void CalcDrawProps(RenderSurfaceLayerList
* render_surface_layer_list
) {
186 occlusion_
->SetRenderTarget(layer_tree_host_
->root_layer());
188 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting
inputs(
189 layer_tree_host_
->root_layer(),
190 layer_tree_host_
->device_viewport_size(),
191 render_surface_layer_list
);
192 inputs
.device_scale_factor
= layer_tree_host_
->device_scale_factor();
193 inputs
.max_texture_size
=
194 layer_tree_host_
->GetRendererCapabilities().max_texture_size
;
195 inputs
.can_adjust_raster_scales
= true;
196 LayerTreeHostCommon::CalculateDrawProperties(&inputs
);
199 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
200 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
) {
201 scoped_refptr
<FakeTiledLayer
> layer2
;
202 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
;
203 return UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
206 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
207 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
,
208 const scoped_refptr
<FakeTiledLayer
>& layer2
,
209 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl2
) {
211 resource_manager_
->ClearPriorities();
213 layer1
->SetTexturePriorities(priority_calculator_
);
215 layer2
->SetTexturePriorities(priority_calculator_
);
216 resource_manager_
->PrioritizeTextures();
218 // Save paint properties
220 layer1
->SavePaintProperties();
222 layer2
->SavePaintProperties();
226 layer1
->Update(queue_
.get(), occlusion_
);
228 layer2
->Update(queue_
.get(), occlusion_
);
230 bool needs_update
= false;
232 needs_update
|= layer1
->NeedsIdlePaint();
234 needs_update
|= layer2
->NeedsIdlePaint();
236 // Update textures and push.
239 LayerPushPropertiesTo(layer1
.get(), layer_impl1
.get());
241 LayerPushPropertiesTo(layer2
.get(), layer_impl2
.get());
248 LayerTreeSettings settings_
;
249 FakeOutputSurfaceClient output_surface_client_
;
250 scoped_ptr
<OutputSurface
> output_surface_
;
251 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
252 scoped_ptr
<ResourceProvider
> resource_provider_
;
253 scoped_ptr
<ResourceUpdateQueue
> queue_
;
254 PriorityCalculator priority_calculator_
;
255 base::Thread impl_thread_
;
256 FakeLayerTreeHostClient fake_layer_tree_host_client_
;
257 scoped_ptr
<SynchronousOutputSurfaceLayerTreeHost
> layer_tree_host_
;
258 scoped_ptr
<FakeLayerTreeHostImpl
> host_impl_
;
259 scoped_ptr
<PrioritizedResourceManager
> resource_manager_
;
260 TestOcclusionTracker
* occlusion_
;
263 TEST_F(TiledLayerTest
, PushDirtyTiles
) {
264 scoped_refptr
<FakeTiledLayer
> layer
=
265 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
266 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
267 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
268 RenderSurfaceLayerList render_surface_layer_list
;
270 layer_tree_host_
->root_layer()->AddChild(layer
);
272 // The tile size is 100x100, so this invalidates and then paints two tiles.
273 layer
->SetBounds(gfx::Size(100, 200));
274 CalcDrawProps(&render_surface_layer_list
);
275 UpdateAndPush(layer
, layer_impl
);
277 // We should have both tiles on the impl side.
278 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
279 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
281 // Invalidates both tiles, but then only update one of them.
282 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 200));
283 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
284 UpdateAndPush(layer
, layer_impl
);
286 // We should only have the first tile since the other tile was invalidated but
288 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
289 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
292 TEST_F(TiledLayerTest
, Scale
) {
293 layer_tree_host_
->SetDeviceScaleFactor(1.5);
295 scoped_refptr
<FakeTiledLayer
> layer
=
296 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
297 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
298 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
299 RenderSurfaceLayerList render_surface_layer_list
;
301 layer_tree_host_
->root_layer()->AddChild(layer
);
303 layer
->SetBounds(gfx::Size(100, 200));
304 CalcDrawProps(&render_surface_layer_list
);
306 // Change the width so that it doesn't divide cleanly by the scale.
307 layer
->SetBounds(gfx::Size(101, 200));
308 UpdateAndPush(layer
, layer_impl
);
310 EXPECT_EQ(1.5, layer
->fake_layer_updater()->last_contents_width_scale());
313 TEST_F(TiledLayerTest
, PushOccludedDirtyTiles
) {
314 scoped_refptr
<FakeTiledLayer
> layer
=
315 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
316 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
317 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
318 TestOcclusionTracker occluded
;
319 occlusion_
= &occluded
;
320 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
322 layer_tree_host_
->root_layer()->AddChild(layer
);
325 RenderSurfaceLayerList render_surface_layer_list
;
327 // The tile size is 100x100, so this invalidates and then paints two tiles.
328 layer
->SetBounds(gfx::Size(100, 200));
329 CalcDrawProps(&render_surface_layer_list
);
330 UpdateAndPush(layer
, layer_impl
);
332 // We should have both tiles on the impl side.
333 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
334 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
338 RenderSurfaceLayerList render_surface_layer_list
;
340 // Invalidates part of the top tile...
341 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
342 // ....but the area is occluded.
343 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 50, 50)));
344 CalcDrawProps(&render_surface_layer_list
);
345 UpdateAndPush(layer
, layer_impl
);
347 // We should still have both tiles, as part of the top tile is still
349 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
350 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
354 TEST_F(TiledLayerTest
, PushDeletedTiles
) {
355 scoped_refptr
<FakeTiledLayer
> layer
=
356 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
357 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
358 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
359 RenderSurfaceLayerList render_surface_layer_list
;
361 layer_tree_host_
->root_layer()->AddChild(layer
);
363 // The tile size is 100x100, so this invalidates and then paints two tiles.
364 layer
->SetBounds(gfx::Size(100, 200));
365 CalcDrawProps(&render_surface_layer_list
);
366 UpdateAndPush(layer
, layer_impl
);
368 // We should have both tiles on the impl side.
369 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
370 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
372 resource_manager_
->ClearPriorities();
373 ResourceManagerClearAllMemory(resource_manager_
.get(),
374 resource_provider_
.get());
375 resource_manager_
->SetMaxMemoryLimitBytes(4 * 1024 * 1024);
377 // This should drop the tiles on the impl thread.
378 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
380 // We should now have no textures on the impl thread.
381 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
382 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
384 // This should recreate and update one of the deleted textures.
385 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
386 UpdateAndPush(layer
, layer_impl
);
388 // We should have one tiles on the impl side.
389 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
390 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
393 TEST_F(TiledLayerTest
, PushIdlePaintTiles
) {
394 scoped_refptr
<FakeTiledLayer
> layer
=
395 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
396 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
397 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
398 RenderSurfaceLayerList render_surface_layer_list
;
400 layer_tree_host_
->root_layer()->AddChild(layer
);
402 // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the
403 // center. This paints 1 visible of the 25 invalid tiles.
404 layer
->SetBounds(gfx::Size(500, 500));
405 CalcDrawProps(&render_surface_layer_list
);
406 layer
->draw_properties().visible_content_rect
= gfx::Rect(200, 200, 100, 100);
407 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
408 // We should need idle-painting for surrounding tiles.
409 EXPECT_TRUE(needs_update
);
411 // We should have one tile on the impl side.
412 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(2, 2));
414 // For the next four updates, we should detect we still need idle painting.
415 for (int i
= 0; i
< 4; i
++) {
416 needs_update
= UpdateAndPush(layer
, layer_impl
);
417 EXPECT_TRUE(needs_update
);
420 // We should always finish painting eventually.
421 for (int i
= 0; i
< 20; i
++)
422 needs_update
= UpdateAndPush(layer
, layer_impl
);
424 // We should have pre-painted all of the surrounding tiles.
425 for (int i
= 0; i
< 5; i
++) {
426 for (int j
= 0; j
< 5; j
++)
427 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(i
, j
));
430 EXPECT_FALSE(needs_update
);
433 TEST_F(TiledLayerTest
, PredictivePainting
) {
434 scoped_refptr
<FakeTiledLayer
> layer
=
435 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
436 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
437 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
439 layer_tree_host_
->root_layer()->AddChild(layer
);
441 // Prepainting should occur in the scroll direction first, and the
442 // visible rect should be extruded only along the dominant axis.
443 gfx::Vector2d directions
[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0),
444 gfx::Vector2d(0, -10), gfx::Vector2d(0, 10),
445 gfx::Vector2d(10, 20),
446 gfx::Vector2d(-20, 10) };
447 // We should push all tiles that touch the extruded visible rect.
448 gfx::Rect pushed_visible_tiles
[6] = {
449 gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2),
450 gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1)
452 // The first pre-paint should also paint first in the scroll
453 // direction so we should find one additional tile in the scroll direction.
454 gfx::Rect pushed_prepaint_tiles
[6] = {
455 gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3),
456 gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1)
458 for (int k
= 0; k
< 6; k
++) {
459 // The tile size is 100x100. Setup 5x5 tiles with one visible tile
461 gfx::Size bounds
= gfx::Size(500, 500);
462 gfx::Rect visible_rect
= gfx::Rect(200, 200, 100, 100);
463 gfx::Rect previous_visible_rect
=
464 gfx::Rect(visible_rect
.origin() + directions
[k
], visible_rect
.size());
465 gfx::Rect next_visible_rect
=
466 gfx::Rect(visible_rect
.origin() - directions
[k
], visible_rect
.size());
468 // Setup. Use the previous_visible_rect to setup the prediction for next
470 layer
->SetBounds(bounds
);
472 RenderSurfaceLayerList render_surface_layer_list
;
473 CalcDrawProps(&render_surface_layer_list
);
474 layer
->draw_properties().visible_content_rect
= previous_visible_rect
;
475 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
477 // Invalidate and move the visible_rect in the scroll direction.
478 // Check that the correct tiles have been painted in the visible pass.
479 layer
->SetNeedsDisplay();
480 layer
->draw_properties().visible_content_rect
= visible_rect
;
481 needs_update
= UpdateAndPush(layer
, layer_impl
);
482 for (int i
= 0; i
< 5; i
++) {
483 for (int j
= 0; j
< 5; j
++)
484 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
),
485 pushed_visible_tiles
[k
].Contains(i
, j
));
488 // Move the transform in the same direction without invalidating.
489 // Check that non-visible pre-painting occured in the correct direction.
490 // Ignore diagonal scrolls here (k > 3) as these have new visible content
493 layer
->draw_properties().visible_content_rect
= next_visible_rect
;
494 needs_update
= UpdateAndPush(layer
, layer_impl
);
495 for (int i
= 0; i
< 5; i
++) {
496 for (int j
= 0; j
< 5; j
++)
497 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
),
498 pushed_prepaint_tiles
[k
].Contains(i
, j
));
502 // We should always finish painting eventually.
503 for (int i
= 0; i
< 20; i
++)
504 needs_update
= UpdateAndPush(layer
, layer_impl
);
505 EXPECT_FALSE(needs_update
);
509 TEST_F(TiledLayerTest
, PushTilesAfterIdlePaintFailed
) {
510 // Start with 2mb of memory, but the test is going to try to use just more
511 // than 1mb, so we reduce to 1mb later.
512 resource_manager_
->SetMaxMemoryLimitBytes(2 * 1024 * 1024);
513 scoped_refptr
<FakeTiledLayer
> layer1
=
514 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
515 scoped_ptr
<FakeTiledLayerImpl
> layer_impl1
=
516 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
517 scoped_refptr
<FakeTiledLayer
> layer2
=
518 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
519 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
=
520 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
521 RenderSurfaceLayerList render_surface_layer_list
;
523 layer_tree_host_
->root_layer()->AddChild(layer1
);
524 layer_tree_host_
->root_layer()->AddChild(layer2
);
526 // For this test we have two layers. layer1 exhausts most texture memory,
527 // leaving room for 2 more tiles from layer2, but not all three tiles. First
528 // we paint layer1, and one tile from layer2. Then when we idle paint layer2,
529 // we will fail on the third tile of layer2, and this should not leave the
530 // second tile in a bad state.
532 // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough
533 // for 2 tiles only in the other layer.
534 gfx::Rect
layer1_rect(0, 0, 100, 2400);
536 // This requires 4*30000 bytes of memory.
537 gfx::Rect
layer2_rect(0, 0, 100, 300);
539 // Paint a single tile in layer2 so that it will idle paint.
540 layer1
->SetBounds(layer1_rect
.size());
541 layer2
->SetBounds(layer2_rect
.size());
542 CalcDrawProps(&render_surface_layer_list
);
543 layer1
->draw_properties().visible_content_rect
= layer1_rect
;
544 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
545 bool needs_update
= UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
546 // We should need idle-painting for both remaining tiles in layer2.
547 EXPECT_TRUE(needs_update
);
549 // Reduce our memory limits to 1mb.
550 resource_manager_
->SetMaxMemoryLimitBytes(1024 * 1024);
552 // Now idle paint layer2. We are going to run out of memory though!
553 // Oh well, commit the frame and push.
554 for (int i
= 0; i
< 4; i
++) {
555 needs_update
= UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
558 // Sanity check, we should have textures for the big layer.
559 EXPECT_TRUE(layer_impl1
->HasResourceIdForTileAt(0, 0));
560 EXPECT_TRUE(layer_impl1
->HasResourceIdForTileAt(0, 23));
562 // We should only have the first two tiles from layer2 since
563 // it failed to idle update the last tile.
564 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 0));
565 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 0));
566 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 1));
567 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 1));
569 EXPECT_FALSE(needs_update
);
570 EXPECT_FALSE(layer_impl2
->HasResourceIdForTileAt(0, 2));
573 TEST_F(TiledLayerTest
, PushIdlePaintedOccludedTiles
) {
574 scoped_refptr
<FakeTiledLayer
> layer
=
575 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
576 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
577 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
578 RenderSurfaceLayerList render_surface_layer_list
;
579 TestOcclusionTracker occluded
;
580 occlusion_
= &occluded
;
582 layer_tree_host_
->root_layer()->AddChild(layer
);
584 // The tile size is 100x100, so this invalidates one occluded tile, culls it
585 // during paint, but prepaints it.
586 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 100, 100)));
588 layer
->SetBounds(gfx::Size(100, 100));
589 CalcDrawProps(&render_surface_layer_list
);
590 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
591 UpdateAndPush(layer
, layer_impl
);
593 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
596 TEST_F(TiledLayerTest
, PushTilesMarkedDirtyDuringPaint
) {
597 scoped_refptr
<FakeTiledLayer
> layer
=
598 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
599 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
600 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
601 RenderSurfaceLayerList render_surface_layer_list
;
603 layer_tree_host_
->root_layer()->AddChild(layer
);
605 // The tile size is 100x100, so this invalidates and then paints two tiles.
606 // However, during the paint, we invalidate one of the tiles. This should
607 // not prevent the tile from being pushed.
608 layer
->fake_layer_updater()->SetRectToInvalidate(
609 gfx::Rect(0, 50, 100, 50), layer
.get());
610 layer
->SetBounds(gfx::Size(100, 200));
611 CalcDrawProps(&render_surface_layer_list
);
612 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
613 UpdateAndPush(layer
, layer_impl
);
615 // We should have both tiles on the impl side.
616 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
617 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
620 TEST_F(TiledLayerTest
, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer
) {
621 scoped_refptr
<FakeTiledLayer
> layer1
=
622 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
623 scoped_refptr
<FakeTiledLayer
> layer2
=
624 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
625 scoped_ptr
<FakeTiledLayerImpl
> layer1_impl
=
626 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
627 scoped_ptr
<FakeTiledLayerImpl
> layer2_impl
=
628 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
629 RenderSurfaceLayerList render_surface_layer_list
;
631 layer_tree_host_
->root_layer()->AddChild(layer1
);
632 layer_tree_host_
->root_layer()->AddChild(layer2
);
634 // Invalidate a tile on layer1, during update of layer 2.
635 layer2
->fake_layer_updater()->SetRectToInvalidate(
636 gfx::Rect(0, 50, 100, 50), layer1
.get());
637 layer1
->SetBounds(gfx::Size(100, 200));
638 layer2
->SetBounds(gfx::Size(100, 200));
639 CalcDrawProps(&render_surface_layer_list
);
640 layer1
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
641 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
642 UpdateAndPush(layer1
, layer1_impl
, layer2
, layer2_impl
);
644 // We should have both tiles on the impl side for all layers.
645 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 0));
646 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 1));
647 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 0));
648 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 1));
651 TEST_F(TiledLayerTest
, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer
) {
652 scoped_refptr
<FakeTiledLayer
> layer1
=
653 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
654 scoped_refptr
<FakeTiledLayer
> layer2
=
655 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
656 scoped_ptr
<FakeTiledLayerImpl
> layer1_impl
=
657 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
658 scoped_ptr
<FakeTiledLayerImpl
> layer2_impl
=
659 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
660 RenderSurfaceLayerList render_surface_layer_list
;
662 layer_tree_host_
->root_layer()->AddChild(layer1
);
663 layer_tree_host_
->root_layer()->AddChild(layer2
);
665 layer1
->fake_layer_updater()->SetRectToInvalidate(
666 gfx::Rect(0, 50, 100, 50), layer2
.get());
667 layer1
->SetBounds(gfx::Size(100, 200));
668 layer2
->SetBounds(gfx::Size(100, 200));
669 CalcDrawProps(&render_surface_layer_list
);
670 layer1
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
671 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
672 UpdateAndPush(layer1
, layer1_impl
, layer2
, layer2_impl
);
674 // We should have both tiles on the impl side for all layers.
675 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 0));
676 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 1));
677 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 0));
678 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 1));
681 TEST_F(TiledLayerTest
, PaintSmallAnimatedLayersImmediately
) {
682 // Create a LayerTreeHost that has the right viewportsize,
683 // so the layer is considered small enough.
684 bool run_out_of_memory
[2] = { false, true };
685 for (int i
= 0; i
< 2; i
++) {
686 // Create a layer with 5x5 tiles, with 4x4 size viewport.
687 int viewport_width
= 4 * FakeTiledLayer::tile_size().width();
688 int viewport_height
= 4 * FakeTiledLayer::tile_size().width();
689 int layer_width
= 5 * FakeTiledLayer::tile_size().width();
690 int layer_height
= 5 * FakeTiledLayer::tile_size().height();
691 int memory_for_layer
= layer_width
* layer_height
* 4;
692 layer_tree_host_
->SetViewportSize(
693 gfx::Size(viewport_width
, viewport_height
));
695 // Use 10x5 tiles to run out of memory.
696 if (run_out_of_memory
[i
])
699 resource_manager_
->SetMaxMemoryLimitBytes(memory_for_layer
);
701 scoped_refptr
<FakeTiledLayer
> layer
=
702 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
703 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
704 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
705 RenderSurfaceLayerList render_surface_layer_list
;
707 layer_tree_host_
->root_layer()->AddChild(layer
);
709 // Full size layer with half being visible.
710 layer
->SetBounds(gfx::Size(layer_width
, layer_height
));
711 gfx::Rect
visible_rect(0, 0, layer_width
/ 2, layer_height
);
712 CalcDrawProps(&render_surface_layer_list
);
714 // Pretend the layer is animating.
715 layer
->draw_properties().target_space_transform_is_animating
= true;
716 layer
->draw_properties().visible_content_rect
= visible_rect
;
717 layer
->SetLayerTreeHost(layer_tree_host_
.get());
719 // The layer should paint its entire contents on the first paint
720 // if it is close to the viewport size and has the available memory.
721 layer
->SetTexturePriorities(priority_calculator_
);
722 resource_manager_
->PrioritizeTextures();
723 layer
->SavePaintProperties();
724 layer
->Update(queue_
.get(), nullptr);
726 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
728 // We should have all the tiles for the small animated layer.
729 // We should still have the visible tiles when we didn't
730 // have enough memory for all the tiles.
731 if (!run_out_of_memory
[i
]) {
732 for (int i
= 0; i
< 5; ++i
) {
733 for (int j
= 0; j
< 5; ++j
)
734 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(i
, j
));
737 for (int i
= 0; i
< 10; ++i
) {
738 for (int j
= 0; j
< 5; ++j
)
739 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
), i
< 5);
743 layer
->RemoveFromParent();
747 TEST_F(TiledLayerTest
, IdlePaintOutOfMemory
) {
748 scoped_refptr
<FakeTiledLayer
> layer
=
749 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
750 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
751 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
752 RenderSurfaceLayerList render_surface_layer_list
;
754 layer_tree_host_
->root_layer()->AddChild(layer
);
756 // We have enough memory for only the visible rect, so we will run out of
757 // memory in first idle paint.
758 int memory_limit
= 4 * 100 * 100; // 1 tiles, 4 bytes per pixel.
759 resource_manager_
->SetMaxMemoryLimitBytes(memory_limit
);
761 // The tile size is 100x100, so this invalidates and then paints two tiles.
762 bool needs_update
= false;
763 layer
->SetBounds(gfx::Size(300, 300));
764 CalcDrawProps(&render_surface_layer_list
);
765 layer
->draw_properties().visible_content_rect
= gfx::Rect(100, 100, 100, 100);
766 for (int i
= 0; i
< 2; i
++)
767 needs_update
= UpdateAndPush(layer
, layer_impl
);
769 // Idle-painting should see no more priority tiles for painting.
770 EXPECT_FALSE(needs_update
);
772 // We should have one tile on the impl side.
773 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 1));
776 TEST_F(TiledLayerTest
, IdlePaintZeroSizedLayer
) {
777 scoped_refptr
<FakeTiledLayer
> layer
=
778 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
779 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
780 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
782 layer_tree_host_
->root_layer()->AddChild(layer
);
784 bool animating
[2] = { false, true };
785 for (int i
= 0; i
< 2; i
++) {
786 // Pretend the layer is animating.
787 layer
->draw_properties().target_space_transform_is_animating
= animating
[i
];
789 // The layer's bounds are empty.
790 // Empty layers don't paint or idle-paint.
791 layer
->SetBounds(gfx::Size());
793 RenderSurfaceLayerList render_surface_layer_list
;
794 CalcDrawProps(&render_surface_layer_list
);
795 layer
->draw_properties().visible_content_rect
= gfx::Rect();
796 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
798 // Empty layers don't have tiles.
799 EXPECT_EQ(0u, layer
->NumPaintedTiles());
801 // Empty layers don't need prepaint.
802 EXPECT_FALSE(needs_update
);
804 // Empty layers don't have tiles.
805 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
809 TEST_F(TiledLayerTest
, IdlePaintNonVisibleLayers
) {
810 scoped_refptr
<FakeTiledLayer
> layer
=
811 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
812 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
813 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
815 // Alternate between not visible and visible.
816 gfx::Rect
v(0, 0, 100, 100);
817 gfx::Rect
nv(0, 0, 0, 0);
818 gfx::Rect visible_rect
[10] = { nv
, nv
, v
, v
, nv
, nv
, v
, v
, nv
, nv
};
819 bool invalidate
[10] = { true, true, true, true, true, true, true, true, false,
822 // We should not have any tiles except for when the layer was visible
823 // or after the layer was visible and we didn't invalidate.
824 bool have_tile
[10] = { false, false, true, true, false, false, true, true,
827 layer_tree_host_
->root_layer()->AddChild(layer
);
829 for (int i
= 0; i
< 10; i
++) {
830 layer
->SetBounds(gfx::Size(100, 100));
832 RenderSurfaceLayerList render_surface_layer_list
;
833 CalcDrawProps(&render_surface_layer_list
);
834 layer
->draw_properties().visible_content_rect
= visible_rect
[i
];
837 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 100));
838 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
840 // We should never signal idle paint, as we painted the entire layer
841 // or the layer was not visible.
842 EXPECT_FALSE(needs_update
);
843 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(0, 0), have_tile
[i
]);
847 TEST_F(TiledLayerTest
, InvalidateFromPrepare
) {
848 scoped_refptr
<FakeTiledLayer
> layer
=
849 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
850 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
851 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
852 RenderSurfaceLayerList render_surface_layer_list
;
854 layer_tree_host_
->root_layer()->AddChild(layer
);
856 // The tile size is 100x100, so this invalidates and then paints two tiles.
857 layer
->SetBounds(gfx::Size(100, 200));
858 CalcDrawProps(&render_surface_layer_list
);
859 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
860 UpdateAndPush(layer
, layer_impl
);
862 // We should have both tiles on the impl side.
863 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
864 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
866 layer
->fake_layer_updater()->ClearPrepareCount();
867 // Invoke update again. As the layer is valid update shouldn't be invoked on
869 UpdateAndPush(layer
, layer_impl
);
870 EXPECT_EQ(0, layer
->fake_layer_updater()->prepare_count());
872 // SetRectToInvalidate triggers InvalidateContentRect() being invoked from
874 layer
->fake_layer_updater()->SetRectToInvalidate(
875 gfx::Rect(25, 25, 50, 50), layer
.get());
876 layer
->fake_layer_updater()->ClearPrepareCount();
877 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
878 UpdateAndPush(layer
, layer_impl
);
879 EXPECT_EQ(1, layer
->fake_layer_updater()->prepare_count());
880 layer
->fake_layer_updater()->ClearPrepareCount();
882 // The layer should still be invalid as update invoked invalidate.
883 UpdateAndPush(layer
, layer_impl
); // visible
884 EXPECT_EQ(1, layer
->fake_layer_updater()->prepare_count());
887 TEST_F(TiledLayerTest
, VerifyUpdateRectWhenContentBoundsAreScaled
) {
888 // The update rect (that indicates what was actually painted) should be in
889 // layer space, not the content space.
890 scoped_refptr
<FakeTiledLayerWithScaledBounds
> layer
= make_scoped_refptr(
891 new FakeTiledLayerWithScaledBounds(resource_manager_
.get()));
893 layer_tree_host_
->root_layer()->AddChild(layer
);
895 gfx::Rect
layer_bounds(0, 0, 300, 200);
896 gfx::Rect
content_bounds(0, 0, 150, 250);
898 layer
->SetBounds(layer_bounds
.size());
899 layer
->SetContentBounds(content_bounds
.size());
900 layer
->draw_properties().visible_content_rect
= content_bounds
;
901 layer
->draw_properties().contents_scale_x
= .5f
;
902 layer
->draw_properties().contents_scale_y
= 1.25f
;
904 // On first update, the update_rect includes all tiles, even beyond the
905 // boundaries of the layer.
906 // However, it should still be in layer space, not content space.
907 layer
->InvalidateContentRect(content_bounds
);
909 layer
->SetTexturePriorities(priority_calculator_
);
910 resource_manager_
->PrioritizeTextures();
911 layer
->SavePaintProperties();
912 layer
->Update(queue_
.get(), nullptr);
914 // Update rect is 200x300 (tile size of 100x100). Scaled this gives 400x240.
915 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 400, 240), layer
->update_rect());
918 // After the tiles are updated once, another invalidate only needs to update
919 // the bounds of the layer.
920 layer
->SetTexturePriorities(priority_calculator_
);
921 resource_manager_
->PrioritizeTextures();
922 layer
->InvalidateContentRect(content_bounds
);
923 layer
->SavePaintProperties();
924 layer
->Update(queue_
.get(), nullptr);
925 EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds
), layer
->update_rect());
928 // Partial re-paint should also be represented by the update rect in layer
929 // space, not content space.
930 gfx::Rect
partial_damage(30, 100, 10, 10);
931 layer
->InvalidateContentRect(partial_damage
);
932 layer
->SetTexturePriorities(priority_calculator_
);
933 resource_manager_
->PrioritizeTextures();
934 layer
->SavePaintProperties();
935 layer
->Update(queue_
.get(), nullptr);
936 EXPECT_FLOAT_RECT_EQ(gfx::RectF(60, 80, 20, 8), layer
->update_rect());
939 TEST_F(TiledLayerTest
, VerifyInvalidationWhenContentsScaleChanges
) {
940 scoped_refptr
<FakeTiledLayer
> layer
=
941 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
942 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
943 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
944 RenderSurfaceLayerList render_surface_layer_list
;
946 layer_tree_host_
->root_layer()->AddChild(layer
);
948 // Create a layer with one tile.
949 layer
->SetBounds(gfx::Size(100, 100));
950 CalcDrawProps(&render_surface_layer_list
);
951 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
952 layer
->Update(queue_
.get(), nullptr);
954 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
955 layer
->last_needs_display_rect());
957 // Push the tiles to the impl side and check that there is exactly one.
958 layer
->SetTexturePriorities(priority_calculator_
);
959 resource_manager_
->PrioritizeTextures();
960 layer
->SavePaintProperties();
961 layer
->Update(queue_
.get(), nullptr);
963 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
964 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
965 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
966 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 0));
967 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 1));
969 layer
->SetNeedsDisplayRect(gfx::Rect());
970 EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer
->last_needs_display_rect());
972 // Change the contents scale.
973 layer
->UpdateContentsScale(2.f
);
974 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 200, 200);
976 // The impl side should get 2x2 tiles now.
977 layer
->SetTexturePriorities(priority_calculator_
);
978 resource_manager_
->PrioritizeTextures();
979 layer
->SavePaintProperties();
980 layer
->Update(queue_
.get(), nullptr);
982 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
983 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
984 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
985 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 0));
986 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 1));
988 // Verify that changing the contents scale caused invalidation, and
989 // that the layer-space rectangle requiring painting is not scaled.
990 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
991 layer
->last_needs_display_rect());
993 // Invalidate the entire layer again, but do not paint. All tiles should be
994 // gone now from the impl side.
995 layer
->SetNeedsDisplay();
996 layer
->SetTexturePriorities(priority_calculator_
);
997 resource_manager_
->PrioritizeTextures();
999 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1000 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
1001 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
1002 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 0));
1003 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 1));
1006 TEST_F(TiledLayerTest
, SkipsDrawGetsReset
) {
1007 // Create two 300 x 300 tiled layers.
1008 gfx::Size
content_bounds(300, 300);
1009 gfx::Rect
content_rect(content_bounds
);
1011 // We have enough memory for only one of the two layers.
1012 int memory_limit
= 4 * 300 * 300; // 4 bytes per pixel.
1014 scoped_refptr
<FakeTiledLayer
> root_layer
= make_scoped_refptr(
1015 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1016 scoped_refptr
<FakeTiledLayer
> child_layer
= make_scoped_refptr(
1017 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1018 root_layer
->AddChild(child_layer
);
1020 root_layer
->SetBounds(content_bounds
);
1021 root_layer
->draw_properties().visible_content_rect
= content_rect
;
1022 root_layer
->SetPosition(gfx::PointF(0, 0));
1023 child_layer
->SetBounds(content_bounds
);
1024 child_layer
->draw_properties().visible_content_rect
= content_rect
;
1025 child_layer
->SetPosition(gfx::PointF(0, 0));
1026 root_layer
->InvalidateContentRect(content_rect
);
1027 child_layer
->InvalidateContentRect(content_rect
);
1029 layer_tree_host_
->SetRootLayer(root_layer
);
1030 layer_tree_host_
->SetViewportSize(gfx::Size(300, 300));
1031 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1034 layer_tree_host_
->UpdateLayers(queue_
.get());
1036 // We'll skip the root layer.
1037 EXPECT_TRUE(root_layer
->SkipsDraw());
1038 EXPECT_FALSE(child_layer
->SkipsDraw());
1040 layer_tree_host_
->CommitComplete();
1042 // Remove the child layer.
1043 root_layer
->RemoveAllChildren();
1045 layer_tree_host_
->UpdateLayers(queue_
.get());
1046 EXPECT_FALSE(root_layer
->SkipsDraw());
1048 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1049 resource_provider_
.get());
1050 layer_tree_host_
->SetRootLayer(nullptr);
1053 TEST_F(TiledLayerTest
, ResizeToSmaller
) {
1054 scoped_refptr
<FakeTiledLayer
> layer
=
1055 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1057 layer_tree_host_
->root_layer()->AddChild(layer
);
1059 layer
->SetBounds(gfx::Size(700, 700));
1060 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 700, 700);
1061 layer
->InvalidateContentRect(gfx::Rect(0, 0, 700, 700));
1063 layer
->SetTexturePriorities(priority_calculator_
);
1064 resource_manager_
->PrioritizeTextures();
1065 layer
->SavePaintProperties();
1066 layer
->Update(queue_
.get(), nullptr);
1068 layer
->SetBounds(gfx::Size(200, 200));
1069 layer
->InvalidateContentRect(gfx::Rect(0, 0, 200, 200));
1072 TEST_F(TiledLayerTest
, HugeLayerUpdateCrash
) {
1073 scoped_refptr
<FakeTiledLayer
> layer
=
1074 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1076 layer_tree_host_
->root_layer()->AddChild(layer
);
1079 layer
->SetBounds(gfx::Size(size
, size
));
1080 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 700, 700);
1081 layer
->InvalidateContentRect(gfx::Rect(0, 0, size
, size
));
1083 // Ensure no crash for bounds where size * size would overflow an int.
1084 layer
->SetTexturePriorities(priority_calculator_
);
1085 resource_manager_
->PrioritizeTextures();
1086 layer
->SavePaintProperties();
1087 layer
->Update(queue_
.get(), nullptr);
1090 class TiledLayerPartialUpdateTest
: public TiledLayerTest
{
1092 TiledLayerPartialUpdateTest() { settings_
.max_partial_texture_updates
= 4; }
1095 TEST_F(TiledLayerPartialUpdateTest
, PartialUpdates
) {
1096 // Create one 300 x 200 tiled layer with 3 x 2 tiles.
1097 gfx::Size
content_bounds(300, 200);
1098 gfx::Rect
content_rect(content_bounds
);
1100 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
1101 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1102 layer
->SetBounds(content_bounds
);
1103 layer
->SetPosition(gfx::PointF(0, 0));
1104 layer
->draw_properties().visible_content_rect
= content_rect
;
1105 layer
->InvalidateContentRect(content_rect
);
1107 layer_tree_host_
->SetRootLayer(layer
);
1108 layer_tree_host_
->SetViewportSize(gfx::Size(300, 200));
1110 // Full update of all 6 tiles.
1111 layer_tree_host_
->UpdateLayers(queue_
.get());
1113 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1114 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1115 EXPECT_EQ(6u, queue_
->FullUploadSize());
1116 EXPECT_EQ(0u, queue_
->PartialUploadSize());
1118 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1119 EXPECT_FALSE(queue_
->HasMoreUpdates());
1120 layer
->fake_layer_updater()->ClearUpdateCount();
1121 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1123 layer_tree_host_
->CommitComplete();
1125 // Full update of 3 tiles and partial update of 3 tiles.
1126 layer
->InvalidateContentRect(gfx::Rect(0, 0, 300, 150));
1127 layer_tree_host_
->UpdateLayers(queue_
.get());
1129 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1130 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1131 EXPECT_EQ(3u, queue_
->FullUploadSize());
1132 EXPECT_EQ(3u, queue_
->PartialUploadSize());
1134 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1135 EXPECT_FALSE(queue_
->HasMoreUpdates());
1136 layer
->fake_layer_updater()->ClearUpdateCount();
1137 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1139 layer_tree_host_
->CommitComplete();
1141 // Partial update of 6 tiles.
1142 layer
->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1144 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1145 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1146 layer_tree_host_
->UpdateLayers(queue_
.get());
1147 EXPECT_EQ(2u, queue_
->FullUploadSize());
1148 EXPECT_EQ(4u, queue_
->PartialUploadSize());
1150 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1151 EXPECT_FALSE(queue_
->HasMoreUpdates());
1152 layer
->fake_layer_updater()->ClearUpdateCount();
1153 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1155 layer_tree_host_
->CommitComplete();
1157 // Checkerboard all tiles.
1158 layer
->InvalidateContentRect(gfx::Rect(0, 0, 300, 200));
1160 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1161 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1162 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1164 layer_tree_host_
->CommitComplete();
1166 // Partial update of 6 checkerboard tiles.
1167 layer
->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1169 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1170 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1171 layer_tree_host_
->UpdateLayers(queue_
.get());
1172 EXPECT_EQ(6u, queue_
->FullUploadSize());
1173 EXPECT_EQ(0u, queue_
->PartialUploadSize());
1175 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1176 EXPECT_FALSE(queue_
->HasMoreUpdates());
1177 layer
->fake_layer_updater()->ClearUpdateCount();
1178 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1180 layer_tree_host_
->CommitComplete();
1182 // Partial update of 4 tiles.
1183 layer
->InvalidateContentRect(gfx::Rect(50, 50, 100, 100));
1185 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1186 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1187 layer_tree_host_
->UpdateLayers(queue_
.get());
1188 EXPECT_EQ(0u, queue_
->FullUploadSize());
1189 EXPECT_EQ(4u, queue_
->PartialUploadSize());
1191 EXPECT_EQ(4, layer
->fake_layer_updater()->update_count());
1192 EXPECT_FALSE(queue_
->HasMoreUpdates());
1193 layer
->fake_layer_updater()->ClearUpdateCount();
1194 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1196 layer_tree_host_
->CommitComplete();
1198 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1199 resource_provider_
.get());
1200 layer_tree_host_
->SetRootLayer(nullptr);
1203 TEST_F(TiledLayerTest
, TilesPaintedWithoutOcclusion
) {
1204 scoped_refptr
<FakeTiledLayer
> layer
=
1205 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1206 RenderSurfaceLayerList render_surface_layer_list
;
1208 layer_tree_host_
->root_layer()->AddChild(layer
);
1210 // The tile size is 100x100, so this invalidates and then paints two tiles.
1211 layer
->SetBounds(gfx::Size(100, 200));
1212 CalcDrawProps(&render_surface_layer_list
);
1214 layer
->SetTexturePriorities(priority_calculator_
);
1215 resource_manager_
->PrioritizeTextures();
1216 layer
->SavePaintProperties();
1217 layer
->Update(queue_
.get(), nullptr);
1218 EXPECT_EQ(2, layer
->fake_layer_updater()->update_count());
1221 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusion
) {
1222 scoped_refptr
<FakeTiledLayer
> layer
=
1223 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1224 RenderSurfaceLayerList render_surface_layer_list
;
1225 TestOcclusionTracker occluded
;
1226 occlusion_
= &occluded
;
1228 layer_tree_host_
->root_layer()->AddChild(layer
);
1230 // The tile size is 100x100.
1232 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1233 layer
->SetBounds(gfx::Size(600, 600));
1234 CalcDrawProps(&render_surface_layer_list
);
1236 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1237 layer
->draw_properties().drawable_content_rect
=
1238 gfx::Rect(layer
->content_bounds());
1239 layer
->draw_properties().visible_content_rect
=
1240 gfx::Rect(layer
->content_bounds());
1241 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1243 layer
->SetTexturePriorities(priority_calculator_
);
1244 resource_manager_
->PrioritizeTextures();
1245 layer
->SavePaintProperties();
1246 layer
->Update(queue_
.get(), &occluded
);
1247 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1249 layer
->fake_layer_updater()->ClearUpdateCount();
1250 layer
->SetTexturePriorities(priority_calculator_
);
1251 resource_manager_
->PrioritizeTextures();
1253 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 200, 300, 100)));
1254 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1255 layer
->SavePaintProperties();
1256 layer
->Update(queue_
.get(), &occluded
);
1257 EXPECT_EQ(36 - 2, layer
->fake_layer_updater()->update_count());
1259 layer
->fake_layer_updater()->ClearUpdateCount();
1260 layer
->SetTexturePriorities(priority_calculator_
);
1261 resource_manager_
->PrioritizeTextures();
1263 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 250, 300, 100)));
1264 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1265 layer
->SavePaintProperties();
1266 layer
->Update(queue_
.get(), &occluded
);
1267 EXPECT_EQ(36, layer
->fake_layer_updater()->update_count());
1270 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndVisiblityConstraints
) {
1271 scoped_refptr
<FakeTiledLayer
> layer
=
1272 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1273 RenderSurfaceLayerList render_surface_layer_list
;
1274 TestOcclusionTracker occluded
;
1275 occlusion_
= &occluded
;
1277 layer_tree_host_
->root_layer()->AddChild(layer
);
1279 // The tile size is 100x100.
1281 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1282 layer
->SetBounds(gfx::Size(600, 600));
1283 CalcDrawProps(&render_surface_layer_list
);
1285 // The partially occluded tiles (by the 150 occlusion height) are visible
1286 // beyond the occlusion, so not culled.
1287 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1288 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 360);
1289 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 360);
1290 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1292 layer
->SetTexturePriorities(priority_calculator_
);
1293 resource_manager_
->PrioritizeTextures();
1294 layer
->SavePaintProperties();
1295 layer
->Update(queue_
.get(), &occluded
);
1296 EXPECT_EQ(24 - 3, layer
->fake_layer_updater()->update_count());
1298 layer
->fake_layer_updater()->ClearUpdateCount();
1300 // Now the visible region stops at the edge of the occlusion so the partly
1301 // visible tiles become fully occluded.
1302 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1303 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 350);
1304 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 350);
1305 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1306 layer
->SetTexturePriorities(priority_calculator_
);
1307 resource_manager_
->PrioritizeTextures();
1308 layer
->SavePaintProperties();
1309 layer
->Update(queue_
.get(), &occluded
);
1310 EXPECT_EQ(24 - 6, layer
->fake_layer_updater()->update_count());
1312 layer
->fake_layer_updater()->ClearUpdateCount();
1314 // Now the visible region is even smaller than the occlusion, it should have
1316 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1317 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 340);
1318 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 340);
1319 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1320 layer
->SetTexturePriorities(priority_calculator_
);
1321 resource_manager_
->PrioritizeTextures();
1322 layer
->SavePaintProperties();
1323 layer
->Update(queue_
.get(), &occluded
);
1324 EXPECT_EQ(24 - 6, layer
->fake_layer_updater()->update_count());
1327 TEST_F(TiledLayerTest
, TilesNotPaintedWithoutInvalidation
) {
1328 scoped_refptr
<FakeTiledLayer
> layer
=
1329 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1330 RenderSurfaceLayerList render_surface_layer_list
;
1331 TestOcclusionTracker occluded
;
1332 occlusion_
= &occluded
;
1334 layer_tree_host_
->root_layer()->AddChild(layer
);
1336 // The tile size is 100x100.
1338 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1339 layer
->SetBounds(gfx::Size(600, 600));
1340 CalcDrawProps(&render_surface_layer_list
);
1342 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1343 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 600);
1344 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 600);
1345 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1346 layer
->SetTexturePriorities(priority_calculator_
);
1347 resource_manager_
->PrioritizeTextures();
1348 layer
->SavePaintProperties();
1349 layer
->Update(queue_
.get(), &occluded
);
1350 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1353 layer
->fake_layer_updater()->ClearUpdateCount();
1354 layer
->SetTexturePriorities(priority_calculator_
);
1355 resource_manager_
->PrioritizeTextures();
1356 layer
->SavePaintProperties();
1358 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted
1360 layer
->Update(queue_
.get(), &occluded
);
1361 EXPECT_EQ(3, layer
->fake_layer_updater()->update_count());
1364 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndTransforms
) {
1365 scoped_refptr
<FakeTiledLayer
> layer
=
1366 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1367 RenderSurfaceLayerList render_surface_layer_list
;
1368 TestOcclusionTracker occluded
;
1369 occlusion_
= &occluded
;
1371 layer_tree_host_
->root_layer()->AddChild(layer
);
1373 // The tile size is 100x100.
1375 // This makes sure the painting works when the occluded region (in screen
1376 // space) is transformed differently than the layer.
1377 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1378 layer
->SetBounds(gfx::Size(600, 600));
1379 CalcDrawProps(&render_surface_layer_list
);
1380 gfx::Transform screen_transform
;
1381 screen_transform
.Scale(0.5, 0.5);
1382 layer
->draw_properties().screen_space_transform
= screen_transform
;
1383 layer
->draw_properties().target_space_transform
= screen_transform
;
1385 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 50)));
1386 layer
->draw_properties().drawable_content_rect
=
1387 gfx::Rect(layer
->content_bounds());
1388 layer
->draw_properties().visible_content_rect
=
1389 gfx::Rect(layer
->content_bounds());
1390 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1391 layer
->SetTexturePriorities(priority_calculator_
);
1392 resource_manager_
->PrioritizeTextures();
1393 layer
->SavePaintProperties();
1394 layer
->Update(queue_
.get(), &occluded
);
1395 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1398 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndScaling
) {
1399 scoped_refptr
<FakeTiledLayer
> layer
=
1400 new FakeTiledLayer(resource_manager_
.get());
1401 RenderSurfaceLayerList render_surface_layer_list
;
1402 TestOcclusionTracker occluded
;
1403 occlusion_
= &occluded
;
1405 scoped_refptr
<FakeTiledLayer
> scale_layer
=
1406 new FakeTiledLayer(resource_manager_
.get());
1407 gfx::Transform scale_transform
;
1408 scale_transform
.Scale(2.0, 2.0);
1409 scale_layer
->SetTransform(scale_transform
);
1411 layer_tree_host_
->root_layer()->AddChild(scale_layer
);
1413 // The tile size is 100x100.
1415 // This makes sure the painting works when the content space is scaled to
1416 // a different layer space.
1417 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1418 layer
->SetBounds(gfx::Size(300, 300));
1419 scale_layer
->AddChild(layer
);
1420 CalcDrawProps(&render_surface_layer_list
);
1421 EXPECT_FLOAT_EQ(2.f
, layer
->contents_scale_x());
1422 EXPECT_FLOAT_EQ(2.f
, layer
->contents_scale_y());
1423 EXPECT_EQ(gfx::Size(600, 600).ToString(),
1424 layer
->content_bounds().ToString());
1426 // No tiles are covered by the 300x50 occlusion.
1427 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 50)));
1428 layer
->draw_properties().drawable_content_rect
=
1429 gfx::Rect(layer
->bounds());
1430 layer
->draw_properties().visible_content_rect
=
1431 gfx::Rect(layer
->content_bounds());
1432 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1433 layer
->SetTexturePriorities(priority_calculator_
);
1434 resource_manager_
->PrioritizeTextures();
1435 layer
->SavePaintProperties();
1436 layer
->Update(queue_
.get(), &occluded
);
1437 int visible_tiles1
= 6 * 6;
1438 EXPECT_EQ(visible_tiles1
, layer
->fake_layer_updater()->update_count());
1440 layer
->fake_layer_updater()->ClearUpdateCount();
1442 // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still.
1443 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1444 layer
->draw_properties().drawable_content_rect
=
1445 gfx::Rect(layer
->bounds());
1446 layer
->draw_properties().visible_content_rect
=
1447 gfx::Rect(layer
->content_bounds());
1448 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1449 layer
->SetTexturePriorities(priority_calculator_
);
1450 resource_manager_
->PrioritizeTextures();
1451 layer
->SavePaintProperties();
1452 layer
->Update(queue_
.get(), &occluded
);
1453 int visible_tiles2
= 6 * 6 - 3;
1454 EXPECT_EQ(visible_tiles2
, layer
->fake_layer_updater()->update_count());
1456 layer
->fake_layer_updater()->ClearUpdateCount();
1458 // This makes sure content scaling and transforms work together.
1459 // When the tiles are scaled down by half, they are 50x50 each in the
1461 gfx::Transform screen_transform
;
1462 screen_transform
.Scale(0.5, 0.5);
1463 layer
->draw_properties().screen_space_transform
= screen_transform
;
1464 layer
->draw_properties().target_space_transform
= screen_transform
;
1466 // An occlusion of 150x100 will cover 3*2 = 6 tiles.
1467 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 100)));
1469 gfx::Rect
layer_bounds_rect(layer
->bounds());
1470 layer
->draw_properties().drawable_content_rect
=
1471 gfx::ScaleToEnclosingRect(layer_bounds_rect
, 0.5f
);
1472 layer
->draw_properties().visible_content_rect
=
1473 gfx::Rect(layer
->content_bounds());
1474 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1475 layer
->SetTexturePriorities(priority_calculator_
);
1476 resource_manager_
->PrioritizeTextures();
1477 layer
->SavePaintProperties();
1478 layer
->Update(queue_
.get(), &occluded
);
1479 int visible_tiles3
= 6 * 6 - 6;
1480 EXPECT_EQ(visible_tiles3
, layer
->fake_layer_updater()->update_count());
1483 TEST_F(TiledLayerTest
, DontAllocateContentsWhenTargetSurfaceCantBeAllocated
) {
1484 // Tile size is 100x100.
1485 gfx::Rect
root_rect(0, 0, 300, 200);
1486 gfx::Rect
child_rect(0, 0, 300, 100);
1487 gfx::Rect
child2_rect(0, 100, 300, 100);
1489 scoped_refptr
<FakeTiledLayer
> root
= make_scoped_refptr(
1490 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1491 scoped_refptr
<Layer
> surface
= Layer::Create();
1492 scoped_refptr
<FakeTiledLayer
> child
= make_scoped_refptr(
1493 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1494 scoped_refptr
<FakeTiledLayer
> child2
= make_scoped_refptr(
1495 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1497 root
->SetBounds(root_rect
.size());
1498 root
->draw_properties().drawable_content_rect
= root_rect
;
1499 root
->draw_properties().visible_content_rect
= root_rect
;
1500 root
->AddChild(surface
);
1502 surface
->SetForceRenderSurface(true);
1503 surface
->SetOpacity(0.5);
1504 surface
->AddChild(child
);
1505 surface
->AddChild(child2
);
1507 child
->SetBounds(child_rect
.size());
1508 child
->SetPosition(child_rect
.origin());
1509 child
->draw_properties().visible_content_rect
= child_rect
;
1510 child
->draw_properties().drawable_content_rect
= root_rect
;
1512 child2
->SetBounds(child2_rect
.size());
1513 child2
->SetPosition(child2_rect
.origin());
1514 child2
->draw_properties().visible_content_rect
= child2_rect
;
1515 child2
->draw_properties().drawable_content_rect
= root_rect
;
1517 layer_tree_host_
->SetRootLayer(root
);
1518 layer_tree_host_
->SetViewportSize(root_rect
.size());
1520 // With a huge memory limit, all layers should update and push their textures.
1521 root
->InvalidateContentRect(root_rect
);
1522 child
->InvalidateContentRect(child_rect
);
1523 child2
->InvalidateContentRect(child2_rect
);
1524 layer_tree_host_
->UpdateLayers(queue_
.get());
1527 EXPECT_EQ(6, root
->fake_layer_updater()->update_count());
1528 EXPECT_EQ(3, child
->fake_layer_updater()->update_count());
1529 EXPECT_EQ(3, child2
->fake_layer_updater()->update_count());
1530 EXPECT_FALSE(queue_
->HasMoreUpdates());
1532 root
->fake_layer_updater()->ClearUpdateCount();
1533 child
->fake_layer_updater()->ClearUpdateCount();
1534 child2
->fake_layer_updater()->ClearUpdateCount();
1536 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1537 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1538 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1539 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1540 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1541 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1542 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1543 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1544 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1546 for (unsigned i
= 0; i
< 3; ++i
) {
1547 for (unsigned j
= 0; j
< 2; ++j
)
1548 EXPECT_TRUE(root_impl
->HasResourceIdForTileAt(i
, j
));
1549 EXPECT_TRUE(child_impl
->HasResourceIdForTileAt(i
, 0));
1550 EXPECT_TRUE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1553 layer_tree_host_
->CommitComplete();
1555 // With a memory limit that includes only the root layer (3x2 tiles) and half
1556 // the surface that the child layers draw into, the child layers will not be
1557 // allocated. If the surface isn't accounted for, then one of the children
1558 // would fit within the memory limit.
1559 root
->InvalidateContentRect(root_rect
);
1560 child
->InvalidateContentRect(child_rect
);
1561 child2
->InvalidateContentRect(child2_rect
);
1563 size_t memory_limit
= (3 * 2 + 3 * 1) * (100 * 100) * 4;
1564 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1566 layer_tree_host_
->UpdateLayers(queue_
.get());
1569 EXPECT_EQ(6, root
->fake_layer_updater()->update_count());
1570 EXPECT_EQ(0, child
->fake_layer_updater()->update_count());
1571 EXPECT_EQ(0, child2
->fake_layer_updater()->update_count());
1572 EXPECT_FALSE(queue_
->HasMoreUpdates());
1574 root
->fake_layer_updater()->ClearUpdateCount();
1575 child
->fake_layer_updater()->ClearUpdateCount();
1576 child2
->fake_layer_updater()->ClearUpdateCount();
1578 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1579 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1580 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1581 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1582 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1583 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1584 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1585 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1586 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1588 for (unsigned i
= 0; i
< 3; ++i
) {
1589 for (unsigned j
= 0; j
< 2; ++j
)
1590 EXPECT_TRUE(root_impl
->HasResourceIdForTileAt(i
, j
));
1591 EXPECT_FALSE(child_impl
->HasResourceIdForTileAt(i
, 0));
1592 EXPECT_FALSE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1595 layer_tree_host_
->CommitComplete();
1597 // With a memory limit that includes only half the root layer, no contents
1598 // will be allocated. If render surface memory wasn't accounted for, there is
1599 // enough space for one of the children layers, but they draw into a surface
1600 // that can't be allocated.
1601 root
->InvalidateContentRect(root_rect
);
1602 child
->InvalidateContentRect(child_rect
);
1603 child2
->InvalidateContentRect(child2_rect
);
1605 memory_limit
= (3 * 1) * (100 * 100) * 4;
1606 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1608 layer_tree_host_
->UpdateLayers(queue_
.get());
1611 EXPECT_EQ(0, root
->fake_layer_updater()->update_count());
1612 EXPECT_EQ(0, child
->fake_layer_updater()->update_count());
1613 EXPECT_EQ(0, child2
->fake_layer_updater()->update_count());
1614 EXPECT_FALSE(queue_
->HasMoreUpdates());
1616 root
->fake_layer_updater()->ClearUpdateCount();
1617 child
->fake_layer_updater()->ClearUpdateCount();
1618 child2
->fake_layer_updater()->ClearUpdateCount();
1620 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1621 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1622 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1623 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1624 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1625 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1626 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1627 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1628 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1630 for (unsigned i
= 0; i
< 3; ++i
) {
1631 for (unsigned j
= 0; j
< 2; ++j
)
1632 EXPECT_FALSE(root_impl
->HasResourceIdForTileAt(i
, j
));
1633 EXPECT_FALSE(child_impl
->HasResourceIdForTileAt(i
, 0));
1634 EXPECT_FALSE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1637 layer_tree_host_
->CommitComplete();
1639 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1640 resource_provider_
.get());
1641 layer_tree_host_
->SetRootLayer(nullptr);
1644 class TrackingLayerPainter
: public LayerPainter
{
1646 static scoped_ptr
<TrackingLayerPainter
> Create() {
1647 return make_scoped_ptr(new TrackingLayerPainter());
1650 void Paint(SkCanvas
* canvas
, const gfx::Rect
& content_rect
) override
{
1651 painted_rect_
= content_rect
;
1654 gfx::Rect
PaintedRect() const { return painted_rect_
; }
1655 void ResetPaintedRect() { painted_rect_
= gfx::Rect(); }
1658 gfx::Rect painted_rect_
;
1661 class UpdateTrackingTiledLayer
: public FakeTiledLayer
{
1663 explicit UpdateTrackingTiledLayer(PrioritizedResourceManager
* manager
)
1664 : FakeTiledLayer(manager
) {
1665 scoped_ptr
<TrackingLayerPainter
> painter(TrackingLayerPainter::Create());
1666 tracking_layer_painter_
= painter
.get();
1667 layer_updater_
= BitmapContentLayerUpdater::Create(painter
.Pass(), 0);
1670 TrackingLayerPainter
* tracking_layer_painter() const {
1671 return tracking_layer_painter_
;
1675 LayerUpdater
* Updater() const override
{ return layer_updater_
.get(); }
1676 ~UpdateTrackingTiledLayer() override
{}
1678 TrackingLayerPainter
* tracking_layer_painter_
;
1679 scoped_refptr
<BitmapContentLayerUpdater
> layer_updater_
;
1682 TEST_F(TiledLayerTest
, NonIntegerContentsScaleIsNotDistortedDuringPaint
) {
1683 scoped_refptr
<UpdateTrackingTiledLayer
> layer
=
1684 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_
.get()));
1686 layer_tree_host_
->root_layer()->AddChild(layer
);
1688 gfx::Rect
layer_rect(0, 0, 30, 31);
1689 layer
->SetPosition(layer_rect
.origin());
1690 layer
->SetBounds(layer_rect
.size());
1691 layer
->UpdateContentsScale(1.5f
);
1693 gfx::Rect
content_rect(0, 0, 45, 47);
1694 EXPECT_EQ(content_rect
.size(), layer
->content_bounds());
1695 layer
->draw_properties().visible_content_rect
= content_rect
;
1696 layer
->draw_properties().drawable_content_rect
= content_rect
;
1698 layer
->SetTexturePriorities(priority_calculator_
);
1699 resource_manager_
->PrioritizeTextures();
1700 layer
->SavePaintProperties();
1702 // Update the whole tile.
1703 layer
->Update(queue_
.get(), nullptr);
1704 layer
->tracking_layer_painter()->ResetPaintedRect();
1706 EXPECT_RECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
1709 // Invalidate the entire layer in content space. When painting, the rect given
1710 // to webkit should match the layer's bounds.
1711 layer
->InvalidateContentRect(content_rect
);
1712 layer
->Update(queue_
.get(), nullptr);
1714 // Rounding leads to an extra pixel.
1715 gfx::Rect
expanded_layer_rect(layer_rect
);
1716 expanded_layer_rect
.set_height(32);
1717 EXPECT_RECT_EQ(expanded_layer_rect
,
1718 layer
->tracking_layer_painter()->PaintedRect());
1721 TEST_F(TiledLayerTest
,
1722 NonIntegerContentsScaleIsNotDistortedDuringInvalidation
) {
1723 scoped_refptr
<UpdateTrackingTiledLayer
> layer
=
1724 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_
.get()));
1726 layer_tree_host_
->root_layer()->AddChild(layer
);
1728 gfx::Rect
layer_rect(0, 0, 30, 31);
1729 layer
->SetPosition(layer_rect
.origin());
1730 layer
->SetBounds(layer_rect
.size());
1731 layer
->UpdateContentsScale(1.3f
);
1733 gfx::Rect
content_rect(layer
->content_bounds());
1734 layer
->draw_properties().visible_content_rect
= content_rect
;
1735 layer
->draw_properties().drawable_content_rect
= content_rect
;
1737 layer
->SetTexturePriorities(priority_calculator_
);
1738 resource_manager_
->PrioritizeTextures();
1739 layer
->SavePaintProperties();
1741 // Update the whole tile.
1742 layer
->Update(queue_
.get(), nullptr);
1743 layer
->tracking_layer_painter()->ResetPaintedRect();
1745 EXPECT_RECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
1748 // Invalidate the entire layer in layer space. When painting, the rect given
1749 // to webkit should match the layer's bounds.
1750 layer
->SetNeedsDisplayRect(layer_rect
);
1751 layer
->Update(queue_
.get(), nullptr);
1753 // Rounding leads to an extra pixel.
1754 gfx::Rect
expanded_layer_rect(layer_rect
);
1755 expanded_layer_rect
.set_height(32);
1756 EXPECT_RECT_EQ(expanded_layer_rect
,
1757 layer
->tracking_layer_painter()->PaintedRect());