1 // Copyright 2013 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/trees/layer_tree_host.h"
7 #include "cc/test/fake_content_layer_client.h"
8 #include "cc/test/fake_picture_layer.h"
9 #include "cc/test/fake_picture_layer_impl.h"
10 #include "cc/test/layer_tree_test.h"
11 #include "cc/trees/layer_tree_impl.h"
16 // These tests deal with picture layers.
17 class LayerTreeHostPictureTest
: public LayerTreeTest
{
19 void SetupTreeWithSinglePictureLayer(const gfx::Size
& size
) {
20 scoped_refptr
<Layer
> root
= Layer::Create();
21 root
->SetBounds(size
);
23 root_picture_layer_
= FakePictureLayer::Create(&client_
);
24 root_picture_layer_
->SetBounds(size
);
25 root
->AddChild(root_picture_layer_
);
27 layer_tree_host()->SetRootLayer(root
);
30 scoped_refptr
<FakePictureLayer
> root_picture_layer_
;
31 FakeContentLayerClient client_
;
34 class LayerTreeHostPictureTestTwinLayer
35 : public LayerTreeHostPictureTest
{
36 void SetupTree() override
{
37 SetupTreeWithSinglePictureLayer(gfx::Size(1, 1));
40 void BeginTest() override
{
42 PostSetNeedsCommitToMainThread();
45 void DidCommit() override
{
46 switch (layer_tree_host()->source_frame_number()) {
48 // Activate while there are pending and active twins in place.
49 layer_tree_host()->SetNeedsCommit();
52 // Drop the picture layer from the tree so the activate will have an
53 // active layer without a pending twin.
54 layer_tree_host()->root_layer()->children()[0]->RemoveFromParent();
57 // Add a new picture layer so the activate will have a pending layer
58 // without an active twin.
59 scoped_refptr
<FakePictureLayer
> picture
=
60 FakePictureLayer::Create(&client_
);
61 layer_tree_host()->root_layer()->AddChild(picture
);
65 // Active while there are pending and active twins again.
66 layer_tree_host()->SetNeedsCommit();
74 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
75 LayerImpl
* pending_root_impl
= impl
->pending_tree()->root_layer();
76 LayerImpl
* active_root_impl
= impl
->active_tree()->root_layer();
78 if (pending_root_impl
->children().empty()) {
79 EXPECT_EQ(2, activates_
);
83 FakePictureLayerImpl
* pending_picture_impl
=
84 static_cast<FakePictureLayerImpl
*>(pending_root_impl
->children()[0]);
86 if (!active_root_impl
) {
87 EXPECT_EQ(0, activates_
);
88 EXPECT_EQ(nullptr, pending_picture_impl
->GetPendingOrActiveTwinLayer());
92 if (active_root_impl
->children().empty()) {
93 EXPECT_EQ(3, activates_
);
94 EXPECT_EQ(nullptr, pending_picture_impl
->GetPendingOrActiveTwinLayer());
98 FakePictureLayerImpl
* active_picture_impl
=
99 static_cast<FakePictureLayerImpl
*>(active_root_impl
->children()[0]);
101 // After the first activation, when we commit again, we'll have a pending
102 // and active layer. Then we recreate a picture layer in the 4th activate
103 // and the next commit will have a pending and active twin again.
104 EXPECT_TRUE(activates_
== 1 || activates_
== 4) << activates_
;
106 EXPECT_EQ(pending_picture_impl
,
107 active_picture_impl
->GetPendingOrActiveTwinLayer());
108 EXPECT_EQ(active_picture_impl
,
109 pending_picture_impl
->GetPendingOrActiveTwinLayer());
110 EXPECT_EQ(nullptr, active_picture_impl
->GetRecycledTwinLayer());
113 void DidActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
114 LayerImpl
* active_root_impl
= impl
->active_tree()->root_layer();
115 LayerImpl
* recycle_root_impl
= impl
->recycle_tree()->root_layer();
117 if (active_root_impl
->children().empty()) {
118 EXPECT_EQ(2, activates_
);
120 FakePictureLayerImpl
* active_picture_impl
=
121 static_cast<FakePictureLayerImpl
*>(active_root_impl
->children()[0]);
122 FakePictureLayerImpl
* recycle_picture_impl
=
123 static_cast<FakePictureLayerImpl
*>(recycle_root_impl
->children()[0]);
125 EXPECT_EQ(nullptr, active_picture_impl
->GetPendingOrActiveTwinLayer());
126 EXPECT_EQ(recycle_picture_impl
,
127 active_picture_impl
->GetRecycledTwinLayer());
133 void AfterTest() override
{ EXPECT_EQ(5, activates_
); }
138 // There is no pending layers in single thread mode.
139 MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestTwinLayer
);
141 class LayerTreeHostPictureTestResizeViewportWithGpuRaster
142 : public LayerTreeHostPictureTest
{
143 void InitializeSettings(LayerTreeSettings
* settings
) override
{
144 settings
->gpu_rasterization_forced
= true;
147 void SetupTree() override
{
148 scoped_refptr
<Layer
> root
= Layer::Create();
149 root
->SetBounds(gfx::Size(768, 960));
151 client_
.set_fill_with_nonsolid_color(true);
152 picture_
= FakePictureLayer::Create(&client_
);
153 picture_
->SetBounds(gfx::Size(768, 960));
154 root
->AddChild(picture_
);
156 layer_tree_host()->SetRootLayer(root
);
157 LayerTreeHostPictureTest::SetupTree();
160 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
162 void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) override
{
163 LayerImpl
* child
= impl
->sync_tree()->root_layer()->children()[0];
164 FakePictureLayerImpl
* picture_impl
=
165 static_cast<FakePictureLayerImpl
*>(child
);
166 gfx::Size tile_size
=
167 picture_impl
->HighResTiling()->TileAt(0, 0)->content_rect().size();
169 switch (impl
->sync_tree()->source_frame_number()) {
171 tile_size_
= tile_size
;
172 // GPU Raster picks a tile size based on the viewport size.
173 EXPECT_EQ(gfx::Size(768, 256), tile_size
);
176 // When the viewport changed size, the new frame's tiles should change
178 EXPECT_NE(gfx::Size(768, 256), tile_size
);
182 void DidCommit() override
{
183 switch (layer_tree_host()->source_frame_number()) {
185 // Change the picture layer's size along with the viewport, so it will
186 // consider picking a new tile size.
187 picture_
->SetBounds(gfx::Size(768, 1056));
188 layer_tree_host()->SetViewportSize(gfx::Size(768, 1056));
195 void AfterTest() override
{}
197 gfx::Size tile_size_
;
198 FakeContentLayerClient client_
;
199 scoped_refptr
<FakePictureLayer
> picture_
;
202 SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(
203 LayerTreeHostPictureTestResizeViewportWithGpuRaster
);
205 class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree
206 : public LayerTreeHostPictureTest
{
207 void SetupTree() override
{
209 did_post_commit_
= false;
211 scoped_refptr
<Layer
> root
= Layer::Create();
212 root
->SetBounds(gfx::Size(100, 100));
214 // The layer is big enough that the live tiles rect won't cover the full
216 client_
.set_fill_with_nonsolid_color(true);
217 picture_
= FakePictureLayer::Create(&client_
);
218 picture_
->SetBounds(gfx::Size(100, 100000));
219 root
->AddChild(picture_
);
221 layer_tree_host()->SetRootLayer(root
);
222 LayerTreeHostPictureTest::SetupTree();
225 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
227 void DrawLayersOnThread(LayerTreeHostImpl
* impl
) override
{
228 LayerImpl
* child
= impl
->active_tree()->root_layer()->children()[0];
229 FakePictureLayerImpl
* picture_impl
=
230 static_cast<FakePictureLayerImpl
*>(child
);
231 FakePictureLayerImpl
* recycled_impl
= static_cast<FakePictureLayerImpl
*>(
232 picture_impl
->GetRecycledTwinLayer());
236 PictureLayerTiling
* tiling
= picture_impl
->HighResTiling();
237 PictureLayerTiling
* recycled_tiling
= recycled_impl
->HighResTiling();
238 int num_tiles_y
= tiling
->TilingDataForTesting().num_tiles_y();
240 // There should be tiles at the top of the picture layer but not at the
242 EXPECT_TRUE(tiling
->TileAt(0, 0));
243 EXPECT_FALSE(tiling
->TileAt(0, num_tiles_y
));
245 // The recycled tiling matches it.
246 EXPECT_TRUE(recycled_tiling
->TileAt(0, 0));
247 EXPECT_FALSE(recycled_tiling
->TileAt(0, num_tiles_y
));
249 // The live tiles rect matches on the recycled tree.
250 EXPECT_EQ(tiling
->live_tiles_rect(),
251 recycled_tiling
->live_tiles_rect());
253 // Make the bottom of the layer visible.
254 picture_impl
->SetPosition(gfx::PointF(0.f
, -100000.f
+ 100.f
));
255 impl
->SetNeedsRedraw();
259 PictureLayerTiling
* tiling
= picture_impl
->HighResTiling();
260 PictureLayerTiling
* recycled_tiling
= recycled_impl
->HighResTiling();
262 // There not be tiles at the top of the layer now.
263 EXPECT_FALSE(tiling
->TileAt(0, 0));
265 // The recycled twin tiling should not have unshared tiles at the top
267 EXPECT_FALSE(recycled_tiling
->TileAt(0, 0));
269 // The live tiles rect matches on the recycled tree.
270 EXPECT_EQ(tiling
->live_tiles_rect(),
271 recycled_tiling
->live_tiles_rect());
273 // Make the top of the layer visible again.
274 picture_impl
->SetPosition(gfx::PointF());
275 impl
->SetNeedsRedraw();
279 PictureLayerTiling
* tiling
= picture_impl
->HighResTiling();
280 PictureLayerTiling
* recycled_tiling
= recycled_impl
->HighResTiling();
281 int num_tiles_y
= tiling
->TilingDataForTesting().num_tiles_y();
283 // There should be tiles at the top of the picture layer again.
284 EXPECT_TRUE(tiling
->TileAt(0, 0));
285 EXPECT_FALSE(tiling
->TileAt(0, num_tiles_y
));
287 // The recycled tiling should also have tiles at the top.
288 EXPECT_TRUE(recycled_tiling
->TileAt(0, 0));
289 EXPECT_FALSE(recycled_tiling
->TileAt(0, num_tiles_y
));
291 // The live tiles rect matches on the recycled tree.
292 EXPECT_EQ(tiling
->live_tiles_rect(),
293 recycled_tiling
->live_tiles_rect());
295 // Make a new main frame without changing the picture layer at all, so
296 // it won't need to update or push properties.
297 did_post_commit_
= true;
298 PostSetNeedsCommitToMainThread();
304 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
305 LayerImpl
* child
= impl
->sync_tree()->root_layer()->children()[0];
306 FakePictureLayerImpl
* picture_impl
=
307 static_cast<FakePictureLayerImpl
*>(child
);
308 PictureLayerTiling
* tiling
= picture_impl
->HighResTiling();
309 int num_tiles_y
= tiling
->TilingDataForTesting().num_tiles_y();
311 // The pending layer should always have tiles at the top of it each commit.
312 // The tile is part of the required for activation set so it should exist.
313 EXPECT_TRUE(tiling
->TileAt(0, 0));
314 EXPECT_FALSE(tiling
->TileAt(0, num_tiles_y
));
316 if (did_post_commit_
)
320 void AfterTest() override
{}
323 bool did_post_commit_
;
324 FakeContentLayerClient client_
;
325 scoped_refptr
<FakePictureLayer
> picture_
;
328 // Multi-thread only since there is no recycle tree in single thread.
329 MULTI_THREAD_IMPL_TEST_F(
330 LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree
);
332 class LayerTreeHostPictureTestRSLLMembership
: public LayerTreeHostPictureTest
{
333 void SetupTree() override
{
334 scoped_refptr
<Layer
> root
= Layer::Create();
335 root
->SetBounds(gfx::Size(100, 100));
337 child_
= Layer::Create();
338 root
->AddChild(child_
);
340 // Don't be solid color so the layer has tilings/tiles.
341 client_
.set_fill_with_nonsolid_color(true);
342 picture_
= FakePictureLayer::Create(&client_
);
343 picture_
->SetBounds(gfx::Size(100, 100));
344 child_
->AddChild(picture_
);
346 layer_tree_host()->SetRootLayer(root
);
347 LayerTreeHostPictureTest::SetupTree();
350 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
352 void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) override
{
353 LayerImpl
* root
= impl
->sync_tree()->root_layer();
354 LayerImpl
* child
= root
->children()[0];
355 LayerImpl
* gchild
= child
->children()[0];
356 FakePictureLayerImpl
* picture
= static_cast<FakePictureLayerImpl
*>(gchild
);
358 switch (impl
->sync_tree()->source_frame_number()) {
360 // On 1st commit the layer has tilings.
361 EXPECT_GT(picture
->tilings()->num_tilings(), 0u);
364 // On 2nd commit, the layer is transparent, but its tilings are left
366 EXPECT_GT(picture
->tilings()->num_tilings(), 0u);
369 // On 3rd commit, the layer is visible again, so has tilings.
370 EXPECT_GT(picture
->tilings()->num_tilings(), 0u);
374 void DidActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
375 LayerImpl
* root
= impl
->active_tree()->root_layer();
376 LayerImpl
* child
= root
->children()[0];
377 LayerImpl
* gchild
= child
->children()[0];
378 FakePictureLayerImpl
* picture
= static_cast<FakePictureLayerImpl
*>(gchild
);
380 switch (impl
->active_tree()->source_frame_number()) {
382 // On 1st commit the layer has tilings.
383 EXPECT_GT(picture
->tilings()->num_tilings(), 0u);
386 // On 2nd commit, the layer is transparent, but its tilings are left
388 EXPECT_GT(picture
->tilings()->num_tilings(), 0u);
391 // On 3rd commit, the layer is visible again, so has tilings.
392 EXPECT_GT(picture
->tilings()->num_tilings(), 0u);
397 void DidCommit() override
{
398 switch (layer_tree_host()->source_frame_number()) {
400 // For the 2nd commit, change opacity to 0 so that the layer will not be
401 // part of the visible frame.
402 child_
->SetOpacity(0.f
);
405 // For the 3rd commit, change opacity to 1 so that the layer will again
406 // be part of the visible frame.
407 child_
->SetOpacity(1.f
);
411 void AfterTest() override
{}
413 FakeContentLayerClient client_
;
414 scoped_refptr
<Layer
> child_
;
415 scoped_refptr
<FakePictureLayer
> picture_
;
418 SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestRSLLMembership
);
420 class LayerTreeHostPictureTestRSLLMembershipWithScale
421 : public LayerTreeHostPictureTest
{
422 void SetupTree() override
{
423 scoped_refptr
<Layer
> root
= Layer::Create();
424 root
->SetBounds(gfx::Size(100, 100));
426 pinch_
= Layer::Create();
427 pinch_
->SetBounds(gfx::Size(500, 500));
428 pinch_
->SetScrollClipLayerId(root
->id());
429 pinch_
->SetIsContainerForFixedPositionLayers(true);
430 root
->AddChild(pinch_
);
432 // Don't be solid color so the layer has tilings/tiles.
433 client_
.set_fill_with_nonsolid_color(true);
434 picture_
= FakePictureLayer::Create(&client_
);
435 picture_
->SetBounds(gfx::Size(100, 100));
436 pinch_
->AddChild(picture_
);
438 layer_tree_host()->RegisterViewportLayers(NULL
, root
, pinch_
, pinch_
);
439 layer_tree_host()->SetPageScaleFactorAndLimits(1.f
, 1.f
, 4.f
);
440 layer_tree_host()->SetRootLayer(root
);
441 LayerTreeHostPictureTest::SetupTree();
444 void InitializeSettings(LayerTreeSettings
* settings
) override
{
445 settings
->layer_transforms_should_scale_layer_contents
= true;
448 void BeginTest() override
{
451 last_frame_drawn_
= -1;
452 PostSetNeedsCommitToMainThread();
455 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
456 LayerImpl
* root
= impl
->sync_tree()->root_layer();
457 LayerImpl
* pinch
= root
->children()[0];
458 LayerImpl
* gchild
= pinch
->children()[0];
459 FakePictureLayerImpl
* picture
= static_cast<FakePictureLayerImpl
*>(gchild
);
463 // On 1st commit the layer has tilings.
464 EXPECT_GT(picture
->tilings()->num_tilings(), 0u);
467 // On 2nd commit, the layer is transparent, so does not have tilings.
468 EXPECT_EQ(0u, picture
->tilings()->num_tilings());
471 // On 3rd commit, the layer is visible again, so has tilings.
472 EXPECT_GT(picture
->tilings()->num_tilings(), 0u);
476 void DrawLayersOnThread(LayerTreeHostImpl
* impl
) override
{
477 LayerImpl
* root
= impl
->active_tree()->root_layer();
478 LayerImpl
* pinch
= root
->children()[0];
479 LayerImpl
* gchild
= pinch
->children()[0];
480 FakePictureLayerImpl
* picture
= static_cast<FakePictureLayerImpl
*>(gchild
);
482 if (frame_
!= last_frame_drawn_
)
485 last_frame_drawn_
= frame_
;
489 if (draws_in_frame_
== 1) {
490 // On 1st commit the layer has tilings.
491 EXPECT_GT(picture
->tilings()->num_tilings(), 0u);
492 EXPECT_EQ(1.f
, picture
->HighResTiling()->contents_scale());
494 // Pinch zoom in to change the scale on the active tree.
495 impl
->PinchGestureBegin();
496 impl
->PinchGestureUpdate(2.f
, gfx::Point(1, 1));
497 impl
->PinchGestureEnd();
498 } else if (picture
->tilings()->num_tilings() == 1) {
499 // If the pinch gesture caused a commit we could get here with a
501 EXPECT_FALSE(impl
->pending_tree());
502 // The active layer now has only a 2.f scale tiling, which means the
503 // recycled layer's tiling is destroyed.
504 EXPECT_EQ(2.f
, picture
->HighResTiling()->contents_scale());
505 EXPECT_EQ(0u, picture
->GetRecycledTwinLayer()
506 ->picture_layer_tiling_set()
510 MainThreadTaskRunner()->PostTask(
513 &LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep
,
514 base::Unretained(this)));
518 EXPECT_EQ(1, draws_in_frame_
);
519 // On 2nd commit, the layer is transparent, so does not create
520 // tilings. Since the 1.f tiling was destroyed in the recycle tree, it
521 // has no tilings left. This is propogated to the active tree.
522 EXPECT_EQ(0u, picture
->picture_layer_tiling_set()->num_tilings());
523 EXPECT_EQ(0u, picture
->GetRecycledTwinLayer()
524 ->picture_layer_tiling_set()
527 MainThreadTaskRunner()->PostTask(
530 &LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep
,
531 base::Unretained(this)));
534 EXPECT_EQ(1, draws_in_frame_
);
535 // On 3rd commit, the layer is visible again, so has tilings.
536 EXPECT_GT(picture
->tilings()->num_tilings(), 0u);
544 // For the 2nd commit, change opacity to 0 so that the layer will not be
545 // part of the visible frame.
546 pinch_
->SetOpacity(0.f
);
549 // For the 3rd commit, change opacity to 1 so that the layer will again
550 // be part of the visible frame.
551 pinch_
->SetOpacity(1.f
);
556 void AfterTest() override
{}
558 FakeContentLayerClient client_
;
559 scoped_refptr
<Layer
> pinch_
;
560 scoped_refptr
<FakePictureLayer
> picture_
;
563 int last_frame_drawn_
;
566 // Multi-thread only because in single thread you can't pinch zoom on the
567 // compositor thread.
568 MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestRSLLMembershipWithScale
);