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.
7 #include "LayerChromium.h"
9 #include "CCGeometryTestUtils.h"
10 #include "CCKeyframedAnimationCurve.h"
11 #include "CCLayerImpl.h"
12 #include "CCLayerTreeHost.h"
13 #include "CCSingleThreadProxy.h"
14 #include "FakeCCLayerTreeHostClient.h"
15 #include "LayerPainterChromium.h"
16 #include "WebCompositorInitializer.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include <public/WebTransformationMatrix.h>
22 using namespace WebKitTests
;
23 using WebKit::WebTransformationMatrix
;
24 using ::testing::Mock
;
26 using ::testing::AtLeast
;
27 using ::testing::AnyNumber
;
29 #define EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(numTimesExpectedSetNeedsCommit, codeToTest) do { \
30 EXPECT_CALL(*m_layerTreeHost, setNeedsCommit()).Times((numTimesExpectedSetNeedsCommit)); \
32 Mock::VerifyAndClearExpectations(m_layerTreeHost.get()); \
37 class MockCCLayerTreeHost
: public CCLayerTreeHost
{
40 : CCLayerTreeHost(&m_fakeClient
, CCLayerTreeSettings())
45 MOCK_METHOD0(setNeedsCommit
, void());
48 FakeCCLayerTreeHostClient m_fakeClient
;
51 class MockLayerPainterChromium
: public LayerPainterChromium
{
53 virtual void paint(SkCanvas
*, const IntRect
&, FloatRect
&) OVERRIDE
{ }
57 class LayerChromiumTest
: public testing::Test
{
60 : m_compositorInitializer(0)
67 m_layerTreeHost
= scoped_ptr
<MockCCLayerTreeHost
>(new MockCCLayerTreeHost
);
70 virtual void TearDown()
72 Mock::VerifyAndClearExpectations(m_layerTreeHost
.get());
73 EXPECT_CALL(*m_layerTreeHost
, setNeedsCommit()).Times(AnyNumber());
82 m_layerTreeHost
->setRootLayer(0);
83 m_layerTreeHost
.reset();
86 void verifyTestTreeInitialState() const
88 ASSERT_EQ(static_cast<size_t>(3), m_parent
->children().size());
89 EXPECT_EQ(m_child1
, m_parent
->children()[0]);
90 EXPECT_EQ(m_child2
, m_parent
->children()[1]);
91 EXPECT_EQ(m_child3
, m_parent
->children()[2]);
92 EXPECT_EQ(m_parent
.get(), m_child1
->parent());
93 EXPECT_EQ(m_parent
.get(), m_child2
->parent());
94 EXPECT_EQ(m_parent
.get(), m_child3
->parent());
96 ASSERT_EQ(static_cast<size_t>(2), m_child1
->children().size());
97 EXPECT_EQ(m_grandChild1
, m_child1
->children()[0]);
98 EXPECT_EQ(m_grandChild2
, m_child1
->children()[1]);
99 EXPECT_EQ(m_child1
.get(), m_grandChild1
->parent());
100 EXPECT_EQ(m_child1
.get(), m_grandChild2
->parent());
102 ASSERT_EQ(static_cast<size_t>(1), m_child2
->children().size());
103 EXPECT_EQ(m_grandChild3
, m_child2
->children()[0]);
104 EXPECT_EQ(m_child2
.get(), m_grandChild3
->parent());
106 ASSERT_EQ(static_cast<size_t>(0), m_child3
->children().size());
109 void createSimpleTestTree()
111 m_parent
= LayerChromium::create();
112 m_child1
= LayerChromium::create();
113 m_child2
= LayerChromium::create();
114 m_child3
= LayerChromium::create();
115 m_grandChild1
= LayerChromium::create();
116 m_grandChild2
= LayerChromium::create();
117 m_grandChild3
= LayerChromium::create();
119 EXPECT_CALL(*m_layerTreeHost
, setNeedsCommit()).Times(AnyNumber());
120 m_layerTreeHost
->setRootLayer(m_parent
);
122 m_parent
->addChild(m_child1
);
123 m_parent
->addChild(m_child2
);
124 m_parent
->addChild(m_child3
);
125 m_child1
->addChild(m_grandChild1
);
126 m_child1
->addChild(m_grandChild2
);
127 m_child2
->addChild(m_grandChild3
);
129 Mock::VerifyAndClearExpectations(m_layerTreeHost
.get());
131 verifyTestTreeInitialState();
134 scoped_ptr
<MockCCLayerTreeHost
> m_layerTreeHost
;
135 scoped_refptr
<LayerChromium
> m_parent
, m_child1
, m_child2
, m_child3
, m_grandChild1
, m_grandChild2
, m_grandChild3
;
136 WebCompositorInitializer m_compositorInitializer
;
139 TEST_F(LayerChromiumTest
, basicCreateAndDestroy
)
141 scoped_refptr
<LayerChromium
> testLayer
= LayerChromium::create();
142 ASSERT_TRUE(testLayer
);
144 EXPECT_CALL(*m_layerTreeHost
, setNeedsCommit()).Times(0);
145 testLayer
->setLayerTreeHost(m_layerTreeHost
.get());
148 TEST_F(LayerChromiumTest
, addAndRemoveChild
)
150 scoped_refptr
<LayerChromium
> parent
= LayerChromium::create();
151 scoped_refptr
<LayerChromium
> child
= LayerChromium::create();
153 // Upon creation, layers should not have children or parent.
154 ASSERT_EQ(static_cast<size_t>(0), parent
->children().size());
155 EXPECT_FALSE(child
->parent());
157 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, m_layerTreeHost
->setRootLayer(parent
));
159 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, parent
->addChild(child
));
161 ASSERT_EQ(static_cast<size_t>(1), parent
->children().size());
162 EXPECT_EQ(child
.get(), parent
->children()[0]);
163 EXPECT_EQ(parent
.get(), child
->parent());
164 EXPECT_EQ(parent
.get(), child
->rootLayer());
166 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(AtLeast(1), child
->removeFromParent());
169 TEST_F(LayerChromiumTest
, insertChild
)
171 scoped_refptr
<LayerChromium
> parent
= LayerChromium::create();
172 scoped_refptr
<LayerChromium
> child1
= LayerChromium::create();
173 scoped_refptr
<LayerChromium
> child2
= LayerChromium::create();
174 scoped_refptr
<LayerChromium
> child3
= LayerChromium::create();
175 scoped_refptr
<LayerChromium
> child4
= LayerChromium::create();
177 parent
->setLayerTreeHost(m_layerTreeHost
.get());
179 ASSERT_EQ(static_cast<size_t>(0), parent
->children().size());
181 // Case 1: inserting to empty list.
182 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, parent
->insertChild(child3
, 0));
183 ASSERT_EQ(static_cast<size_t>(1), parent
->children().size());
184 EXPECT_EQ(child3
, parent
->children()[0]);
185 EXPECT_EQ(parent
.get(), child3
->parent());
187 // Case 2: inserting to beginning of list
188 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, parent
->insertChild(child1
, 0));
189 ASSERT_EQ(static_cast<size_t>(2), parent
->children().size());
190 EXPECT_EQ(child1
, parent
->children()[0]);
191 EXPECT_EQ(child3
, parent
->children()[1]);
192 EXPECT_EQ(parent
.get(), child1
->parent());
194 // Case 3: inserting to middle of list
195 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, parent
->insertChild(child2
, 1));
196 ASSERT_EQ(static_cast<size_t>(3), parent
->children().size());
197 EXPECT_EQ(child1
, parent
->children()[0]);
198 EXPECT_EQ(child2
, parent
->children()[1]);
199 EXPECT_EQ(child3
, parent
->children()[2]);
200 EXPECT_EQ(parent
.get(), child2
->parent());
202 // Case 4: inserting to end of list
203 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, parent
->insertChild(child4
, 3));
205 ASSERT_EQ(static_cast<size_t>(4), parent
->children().size());
206 EXPECT_EQ(child1
, parent
->children()[0]);
207 EXPECT_EQ(child2
, parent
->children()[1]);
208 EXPECT_EQ(child3
, parent
->children()[2]);
209 EXPECT_EQ(child4
, parent
->children()[3]);
210 EXPECT_EQ(parent
.get(), child4
->parent());
212 EXPECT_CALL(*m_layerTreeHost
, setNeedsCommit()).Times(AtLeast(1));
215 TEST_F(LayerChromiumTest
, insertChildPastEndOfList
)
217 scoped_refptr
<LayerChromium
> parent
= LayerChromium::create();
218 scoped_refptr
<LayerChromium
> child1
= LayerChromium::create();
219 scoped_refptr
<LayerChromium
> child2
= LayerChromium::create();
221 ASSERT_EQ(static_cast<size_t>(0), parent
->children().size());
223 // insert to an out-of-bounds index
224 parent
->insertChild(child1
, 53);
226 ASSERT_EQ(static_cast<size_t>(1), parent
->children().size());
227 EXPECT_EQ(child1
, parent
->children()[0]);
229 // insert another child to out-of-bounds, when list is not already empty.
230 parent
->insertChild(child2
, 2459);
232 ASSERT_EQ(static_cast<size_t>(2), parent
->children().size());
233 EXPECT_EQ(child1
, parent
->children()[0]);
234 EXPECT_EQ(child2
, parent
->children()[1]);
237 TEST_F(LayerChromiumTest
, insertSameChildTwice
)
239 scoped_refptr
<LayerChromium
> parent
= LayerChromium::create();
240 scoped_refptr
<LayerChromium
> child1
= LayerChromium::create();
241 scoped_refptr
<LayerChromium
> child2
= LayerChromium::create();
243 parent
->setLayerTreeHost(m_layerTreeHost
.get());
245 ASSERT_EQ(static_cast<size_t>(0), parent
->children().size());
247 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, parent
->insertChild(child1
, 0));
248 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, parent
->insertChild(child2
, 1));
250 ASSERT_EQ(static_cast<size_t>(2), parent
->children().size());
251 EXPECT_EQ(child1
, parent
->children()[0]);
252 EXPECT_EQ(child2
, parent
->children()[1]);
254 // Inserting the same child again should cause the child to be removed and re-inserted at the new location.
255 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(AtLeast(1), parent
->insertChild(child1
, 1));
257 // child1 should now be at the end of the list.
258 ASSERT_EQ(static_cast<size_t>(2), parent
->children().size());
259 EXPECT_EQ(child2
, parent
->children()[0]);
260 EXPECT_EQ(child1
, parent
->children()[1]);
262 EXPECT_CALL(*m_layerTreeHost
, setNeedsCommit()).Times(AtLeast(1));
265 TEST_F(LayerChromiumTest
, replaceChildWithNewChild
)
267 createSimpleTestTree();
268 scoped_refptr
<LayerChromium
> child4
= LayerChromium::create();
270 EXPECT_FALSE(child4
->parent());
272 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(AtLeast(1), m_parent
->replaceChild(m_child2
.get(), child4
));
274 ASSERT_EQ(static_cast<size_t>(3), m_parent
->children().size());
275 EXPECT_EQ(m_child1
, m_parent
->children()[0]);
276 EXPECT_EQ(child4
, m_parent
->children()[1]);
277 EXPECT_EQ(m_child3
, m_parent
->children()[2]);
278 EXPECT_EQ(m_parent
.get(), child4
->parent());
280 EXPECT_FALSE(m_child2
->parent());
283 TEST_F(LayerChromiumTest
, replaceChildWithNewChildThatHasOtherParent
)
285 createSimpleTestTree();
287 // create another simple tree with testLayer and child4.
288 scoped_refptr
<LayerChromium
> testLayer
= LayerChromium::create();
289 scoped_refptr
<LayerChromium
> child4
= LayerChromium::create();
290 testLayer
->addChild(child4
);
291 ASSERT_EQ(static_cast<size_t>(1), testLayer
->children().size());
292 EXPECT_EQ(child4
, testLayer
->children()[0]);
293 EXPECT_EQ(testLayer
.get(), child4
->parent());
295 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(AtLeast(1), m_parent
->replaceChild(m_child2
.get(), child4
));
297 ASSERT_EQ(static_cast<size_t>(3), m_parent
->children().size());
298 EXPECT_EQ(m_child1
, m_parent
->children()[0]);
299 EXPECT_EQ(child4
, m_parent
->children()[1]);
300 EXPECT_EQ(m_child3
, m_parent
->children()[2]);
301 EXPECT_EQ(m_parent
.get(), child4
->parent());
303 // testLayer should no longer have child4,
304 // and child2 should no longer have a parent.
305 ASSERT_EQ(static_cast<size_t>(0), testLayer
->children().size());
306 EXPECT_FALSE(m_child2
->parent());
309 TEST_F(LayerChromiumTest
, replaceChildWithSameChild
)
311 createSimpleTestTree();
313 // setNeedsCommit should not be called because its the same child
314 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(0, m_parent
->replaceChild(m_child2
.get(), m_child2
));
316 verifyTestTreeInitialState();
319 TEST_F(LayerChromiumTest
, removeAllChildren
)
321 createSimpleTestTree();
323 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(AtLeast(3), m_parent
->removeAllChildren());
325 ASSERT_EQ(static_cast<size_t>(0), m_parent
->children().size());
326 EXPECT_FALSE(m_child1
->parent());
327 EXPECT_FALSE(m_child2
->parent());
328 EXPECT_FALSE(m_child3
->parent());
331 TEST_F(LayerChromiumTest
, setChildren
)
333 scoped_refptr
<LayerChromium
> oldParent
= LayerChromium::create();
334 scoped_refptr
<LayerChromium
> newParent
= LayerChromium::create();
336 scoped_refptr
<LayerChromium
> child1
= LayerChromium::create();
337 scoped_refptr
<LayerChromium
> child2
= LayerChromium::create();
339 std::vector
<scoped_refptr
<LayerChromium
> > newChildren
;
340 newChildren
.push_back(child1
);
341 newChildren
.push_back(child2
);
343 // Set up and verify initial test conditions: child1 has a parent, child2 has no parent.
344 oldParent
->addChild(child1
);
345 ASSERT_EQ(static_cast<size_t>(0), newParent
->children().size());
346 EXPECT_EQ(oldParent
.get(), child1
->parent());
347 EXPECT_FALSE(child2
->parent());
349 newParent
->setLayerTreeHost(m_layerTreeHost
.get());
351 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(AtLeast(1), newParent
->setChildren(newChildren
));
353 ASSERT_EQ(static_cast<size_t>(2), newParent
->children().size());
354 EXPECT_EQ(newParent
.get(), child1
->parent());
355 EXPECT_EQ(newParent
.get(), child2
->parent());
357 EXPECT_CALL(*m_layerTreeHost
, setNeedsCommit()).Times(AtLeast(1));
360 TEST_F(LayerChromiumTest
, getRootLayerAfterTreeManipulations
)
362 createSimpleTestTree();
364 // For this test we don't care about setNeedsCommit calls.
365 EXPECT_CALL(*m_layerTreeHost
, setNeedsCommit()).Times(AtLeast(1));
367 scoped_refptr
<LayerChromium
> child4
= LayerChromium::create();
369 EXPECT_EQ(m_parent
.get(), m_parent
->rootLayer());
370 EXPECT_EQ(m_parent
.get(), m_child1
->rootLayer());
371 EXPECT_EQ(m_parent
.get(), m_child2
->rootLayer());
372 EXPECT_EQ(m_parent
.get(), m_child3
->rootLayer());
373 EXPECT_EQ(child4
.get(), child4
->rootLayer());
374 EXPECT_EQ(m_parent
.get(), m_grandChild1
->rootLayer());
375 EXPECT_EQ(m_parent
.get(), m_grandChild2
->rootLayer());
376 EXPECT_EQ(m_parent
.get(), m_grandChild3
->rootLayer());
378 m_child1
->removeFromParent();
380 // child1 and its children, grandChild1 and grandChild2 are now on a separate subtree.
381 EXPECT_EQ(m_parent
.get(), m_parent
->rootLayer());
382 EXPECT_EQ(m_child1
.get(), m_child1
->rootLayer());
383 EXPECT_EQ(m_parent
.get(), m_child2
->rootLayer());
384 EXPECT_EQ(m_parent
.get(), m_child3
->rootLayer());
385 EXPECT_EQ(child4
.get(), child4
->rootLayer());
386 EXPECT_EQ(m_child1
.get(), m_grandChild1
->rootLayer());
387 EXPECT_EQ(m_child1
.get(), m_grandChild2
->rootLayer());
388 EXPECT_EQ(m_parent
.get(), m_grandChild3
->rootLayer());
390 m_grandChild3
->addChild(child4
);
392 EXPECT_EQ(m_parent
.get(), m_parent
->rootLayer());
393 EXPECT_EQ(m_child1
.get(), m_child1
->rootLayer());
394 EXPECT_EQ(m_parent
.get(), m_child2
->rootLayer());
395 EXPECT_EQ(m_parent
.get(), m_child3
->rootLayer());
396 EXPECT_EQ(m_parent
.get(), child4
->rootLayer());
397 EXPECT_EQ(m_child1
.get(), m_grandChild1
->rootLayer());
398 EXPECT_EQ(m_child1
.get(), m_grandChild2
->rootLayer());
399 EXPECT_EQ(m_parent
.get(), m_grandChild3
->rootLayer());
401 m_child2
->replaceChild(m_grandChild3
.get(), m_child1
);
403 // grandChild3 gets orphaned and the child1 subtree gets planted back into the tree under child2.
404 EXPECT_EQ(m_parent
.get(), m_parent
->rootLayer());
405 EXPECT_EQ(m_parent
.get(), m_child1
->rootLayer());
406 EXPECT_EQ(m_parent
.get(), m_child2
->rootLayer());
407 EXPECT_EQ(m_parent
.get(), m_child3
->rootLayer());
408 EXPECT_EQ(m_grandChild3
.get(), child4
->rootLayer());
409 EXPECT_EQ(m_parent
.get(), m_grandChild1
->rootLayer());
410 EXPECT_EQ(m_parent
.get(), m_grandChild2
->rootLayer());
411 EXPECT_EQ(m_grandChild3
.get(), m_grandChild3
->rootLayer());
414 TEST_F(LayerChromiumTest
, checkSetNeedsDisplayCausesCorrectBehavior
)
416 // The semantics for setNeedsDisplay which are tested here:
417 // 1. sets needsDisplay flag appropriately.
418 // 2. indirectly calls setNeedsCommit, exactly once for each call to setNeedsDisplay.
420 scoped_refptr
<LayerChromium
> testLayer
= LayerChromium::create();
421 testLayer
->setLayerTreeHost(m_layerTreeHost
.get());
423 IntSize testBounds
= IntSize(501, 508);
425 FloatRect dirty1
= FloatRect(10, 15, 1, 2);
426 FloatRect dirty2
= FloatRect(20, 25, 3, 4);
427 FloatRect emptyDirtyRect
= FloatRect(40, 45, 0, 0);
428 FloatRect outOfBoundsDirtyRect
= FloatRect(400, 405, 500, 502);
430 // Before anything, testLayer should not be dirty.
431 EXPECT_FALSE(testLayer
->needsDisplay());
433 // This is just initialization, but setNeedsCommit behavior is verified anyway to avoid warnings.
434 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setBounds(testBounds
));
435 testLayer
= LayerChromium::create();
436 testLayer
->setLayerTreeHost(m_layerTreeHost
.get());
437 EXPECT_FALSE(testLayer
->needsDisplay());
439 // The real test begins here.
441 // Case 1: needsDisplay flag should not change because of an empty dirty rect.
442 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setNeedsDisplayRect(emptyDirtyRect
));
443 EXPECT_FALSE(testLayer
->needsDisplay());
446 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setNeedsDisplayRect(dirty1
));
447 EXPECT_TRUE(testLayer
->needsDisplay());
449 // Case 3: a second dirty rect.
450 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setNeedsDisplayRect(dirty2
));
451 EXPECT_TRUE(testLayer
->needsDisplay());
453 // Case 4: LayerChromium should accept dirty rects that go beyond its bounds.
454 testLayer
= LayerChromium::create();
455 testLayer
->setLayerTreeHost(m_layerTreeHost
.get());
456 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setBounds(testBounds
));
457 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setNeedsDisplayRect(outOfBoundsDirtyRect
));
458 EXPECT_TRUE(testLayer
->needsDisplay());
460 // Case 5: setNeedsDisplay() without the dirty rect arg.
461 testLayer
= LayerChromium::create();
462 testLayer
->setLayerTreeHost(m_layerTreeHost
.get());
463 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setBounds(testBounds
));
464 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setNeedsDisplay());
465 EXPECT_TRUE(testLayer
->needsDisplay());
468 TEST_F(LayerChromiumTest
, checkPropertyChangeCausesCorrectBehavior
)
470 scoped_refptr
<LayerChromium
> testLayer
= LayerChromium::create();
471 testLayer
->setLayerTreeHost(m_layerTreeHost
.get());
473 scoped_refptr
<LayerChromium
> dummyLayer
= LayerChromium::create(); // just a dummy layer for this test case.
475 // sanity check of initial test condition
476 EXPECT_FALSE(testLayer
->needsDisplay());
478 // Test properties that should not call needsDisplay and needsCommit when changed.
479 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(0, testLayer
->setVisibleContentRect(IntRect(0, 0, 40, 50)));
480 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(0, testLayer
->setUseLCDText(true));
481 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(0, testLayer
->setDrawOpacity(0.5));
482 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(0, testLayer
->setRenderTarget(0));
483 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(0, testLayer
->setDrawTransform(WebTransformationMatrix()));
484 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(0, testLayer
->setScreenSpaceTransform(WebTransformationMatrix()));
485 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(0, testLayer
->setDrawableContentRect(IntRect(4, 5, 6, 7)));
486 EXPECT_FALSE(testLayer
->needsDisplay());
488 // Next, test properties that should call setNeedsCommit (but not setNeedsDisplay)
489 // All properties need to be set to new values in order for setNeedsCommit to be called.
490 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setAnchorPoint(FloatPoint(1.23f
, 4.56f
)));
491 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setAnchorPointZ(0.7f
));
492 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setBackgroundColor(SK_ColorLTGRAY
));
493 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setMasksToBounds(true));
494 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setMaskLayer(dummyLayer
.get()));
495 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setOpacity(0.5));
496 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setContentsOpaque(true));
497 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setPosition(FloatPoint(4, 9)));
498 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setReplicaLayer(dummyLayer
.get()));
499 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setSublayerTransform(WebTransformationMatrix(0, 0, 0, 0, 0, 0)));
500 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setScrollable(true));
501 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setShouldScrollOnMainThread(true));
502 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setNonFastScrollableRegion(Region(IntRect(1, 1, 2, 2))));
503 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setHaveWheelEventHandlers(true));
504 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setScrollPosition(IntPoint(10, 10)));
505 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setTransform(WebTransformationMatrix(0, 0, 0, 0, 0, 0)));
506 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setDoubleSided(false));
507 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setDebugName("Test Layer"));
508 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setDrawCheckerboardForMissingTiles(!testLayer
->drawCheckerboardForMissingTiles()));
509 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setForceRenderSurface(true));
511 // The above tests should not have caused a change to the needsDisplay flag.
512 EXPECT_FALSE(testLayer
->needsDisplay());
514 // Test properties that should call setNeedsDisplay and setNeedsCommit
515 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setBounds(IntSize(5, 10)));
516 EXPECT_TRUE(testLayer
->needsDisplay());
519 TEST_F(LayerChromiumTest
, verifyPushPropertiesAccumulatesUpdateRect
)
521 DebugScopedSetImplThread setImplThread
;
523 scoped_refptr
<LayerChromium
> testLayer
= LayerChromium::create();
524 OwnPtr
<CCLayerImpl
> implLayer
= CCLayerImpl::create(1);
526 testLayer
->setNeedsDisplayRect(FloatRect(FloatPoint::zero(), FloatSize(5, 5)));
527 testLayer
->pushPropertiesTo(implLayer
.get());
528 EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint::zero(), FloatSize(5, 5)), implLayer
->updateRect());
530 // The CCLayerImpl's updateRect should be accumulated here, since we did not do anything to clear it.
531 testLayer
->setNeedsDisplayRect(FloatRect(FloatPoint(10, 10), FloatSize(5, 5)));
532 testLayer
->pushPropertiesTo(implLayer
.get());
533 EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint::zero(), FloatSize(15, 15)), implLayer
->updateRect());
535 // If we do clear the CCLayerImpl side, then the next updateRect should be fresh without accumulation.
536 implLayer
->resetAllChangeTrackingForSubtree();
537 testLayer
->setNeedsDisplayRect(FloatRect(FloatPoint(10, 10), FloatSize(5, 5)));
538 testLayer
->pushPropertiesTo(implLayer
.get());
539 EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint(10, 10), FloatSize(5, 5)), implLayer
->updateRect());
542 class LayerChromiumWithContentScaling
: public LayerChromium
{
544 explicit LayerChromiumWithContentScaling()
549 virtual bool needsContentsScale() const OVERRIDE
554 virtual void setNeedsDisplayRect(const FloatRect
& dirtyRect
) OVERRIDE
556 m_lastNeedsDisplayRect
= dirtyRect
;
557 LayerChromium::setNeedsDisplayRect(dirtyRect
);
560 void resetNeedsDisplay()
562 m_needsDisplay
= false;
565 const FloatRect
& lastNeedsDisplayRect() const { return m_lastNeedsDisplayRect
; }
568 virtual ~LayerChromiumWithContentScaling()
572 FloatRect m_lastNeedsDisplayRect
;
575 TEST_F(LayerChromiumTest
, checkContentsScaleChangeTriggersNeedsDisplay
)
577 scoped_refptr
<LayerChromiumWithContentScaling
> testLayer
= make_scoped_refptr(new LayerChromiumWithContentScaling());
578 testLayer
->setLayerTreeHost(m_layerTreeHost
.get());
580 IntSize testBounds
= IntSize(320, 240);
581 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setBounds(testBounds
));
583 testLayer
->resetNeedsDisplay();
584 EXPECT_FALSE(testLayer
->needsDisplay());
586 EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer
->setContentsScale(testLayer
->contentsScale() + 1.f
));
587 EXPECT_TRUE(testLayer
->needsDisplay());
588 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 320, 240), testLayer
->lastNeedsDisplayRect());
591 class FakeCCLayerTreeHost
: public CCLayerTreeHost
{
593 static scoped_ptr
<FakeCCLayerTreeHost
> create()
595 scoped_ptr
<FakeCCLayerTreeHost
> host(new FakeCCLayerTreeHost
);
596 // The initialize call will fail, since our client doesn't provide a valid GraphicsContext3D, but it doesn't matter in the tests that use this fake so ignore the return value.
602 FakeCCLayerTreeHost()
603 : CCLayerTreeHost(&m_client
, CCLayerTreeSettings())
607 FakeCCLayerTreeHostClient m_client
;
610 void assertLayerTreeHostMatchesForSubtree(LayerChromium
* layer
, CCLayerTreeHost
* host
)
612 EXPECT_EQ(host
, layer
->layerTreeHost());
614 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
615 assertLayerTreeHostMatchesForSubtree(layer
->children()[i
].get(), host
);
617 if (layer
->maskLayer())
618 assertLayerTreeHostMatchesForSubtree(layer
->maskLayer(), host
);
620 if (layer
->replicaLayer())
621 assertLayerTreeHostMatchesForSubtree(layer
->replicaLayer(), host
);
625 TEST(LayerChromiumLayerTreeHostTest
, enteringTree
)
627 WebCompositorInitializer
compositorInitializer(0);
628 scoped_refptr
<LayerChromium
> parent
= LayerChromium::create();
629 scoped_refptr
<LayerChromium
> child
= LayerChromium::create();
630 scoped_refptr
<LayerChromium
> mask
= LayerChromium::create();
631 scoped_refptr
<LayerChromium
> replica
= LayerChromium::create();
632 scoped_refptr
<LayerChromium
> replicaMask
= LayerChromium::create();
634 // Set up a detached tree of layers. The host pointer should be nil for these layers.
635 parent
->addChild(child
);
636 child
->setMaskLayer(mask
.get());
637 child
->setReplicaLayer(replica
.get());
638 replica
->setMaskLayer(mask
.get());
640 assertLayerTreeHostMatchesForSubtree(parent
.get(), 0);
642 scoped_ptr
<FakeCCLayerTreeHost
> layerTreeHost(FakeCCLayerTreeHost::create());
643 // Setting the root layer should set the host pointer for all layers in the tree.
644 layerTreeHost
->setRootLayer(parent
.get());
646 assertLayerTreeHostMatchesForSubtree(parent
.get(), layerTreeHost
.get());
648 // Clearing the root layer should also clear out the host pointers for all layers in the tree.
649 layerTreeHost
->setRootLayer(0);
651 assertLayerTreeHostMatchesForSubtree(parent
.get(), 0);
654 TEST(LayerChromiumLayerTreeHostTest
, addingLayerSubtree
)
656 WebCompositorInitializer
compositorInitializer(0);
657 scoped_refptr
<LayerChromium
> parent
= LayerChromium::create();
658 scoped_ptr
<FakeCCLayerTreeHost
> layerTreeHost(FakeCCLayerTreeHost::create());
660 layerTreeHost
->setRootLayer(parent
.get());
662 EXPECT_EQ(parent
->layerTreeHost(), layerTreeHost
.get());
664 // Adding a subtree to a layer already associated with a host should set the host pointer on all layers in that subtree.
665 scoped_refptr
<LayerChromium
> child
= LayerChromium::create();
666 scoped_refptr
<LayerChromium
> grandChild
= LayerChromium::create();
667 child
->addChild(grandChild
);
669 // Masks, replicas, and replica masks should pick up the new host too.
670 scoped_refptr
<LayerChromium
> childMask
= LayerChromium::create();
671 child
->setMaskLayer(childMask
.get());
672 scoped_refptr
<LayerChromium
> childReplica
= LayerChromium::create();
673 child
->setReplicaLayer(childReplica
.get());
674 scoped_refptr
<LayerChromium
> childReplicaMask
= LayerChromium::create();
675 childReplica
->setMaskLayer(childReplicaMask
.get());
677 parent
->addChild(child
);
678 assertLayerTreeHostMatchesForSubtree(parent
.get(), layerTreeHost
.get());
680 layerTreeHost
->setRootLayer(0);
683 TEST(LayerChromiumLayerTreeHostTest
, changeHost
)
685 WebCompositorInitializer
compositorInitializer(0);
686 scoped_refptr
<LayerChromium
> parent
= LayerChromium::create();
687 scoped_refptr
<LayerChromium
> child
= LayerChromium::create();
688 scoped_refptr
<LayerChromium
> mask
= LayerChromium::create();
689 scoped_refptr
<LayerChromium
> replica
= LayerChromium::create();
690 scoped_refptr
<LayerChromium
> replicaMask
= LayerChromium::create();
692 // Same setup as the previous test.
693 parent
->addChild(child
);
694 child
->setMaskLayer(mask
.get());
695 child
->setReplicaLayer(replica
.get());
696 replica
->setMaskLayer(mask
.get());
698 scoped_ptr
<FakeCCLayerTreeHost
> firstLayerTreeHost(FakeCCLayerTreeHost::create());
699 firstLayerTreeHost
->setRootLayer(parent
.get());
701 assertLayerTreeHostMatchesForSubtree(parent
.get(), firstLayerTreeHost
.get());
703 // Now re-root the tree to a new host (simulating what we do on a context lost event).
704 // This should update the host pointers for all layers in the tree.
705 scoped_ptr
<FakeCCLayerTreeHost
> secondLayerTreeHost(FakeCCLayerTreeHost::create());
706 secondLayerTreeHost
->setRootLayer(parent
.get());
708 assertLayerTreeHostMatchesForSubtree(parent
.get(), secondLayerTreeHost
.get());
710 secondLayerTreeHost
->setRootLayer(0);
713 TEST(LayerChromiumLayerTreeHostTest
, changeHostInSubtree
)
715 WebCompositorInitializer
compositorInitializer(0);
716 scoped_refptr
<LayerChromium
> firstParent
= LayerChromium::create();
717 scoped_refptr
<LayerChromium
> firstChild
= LayerChromium::create();
718 scoped_refptr
<LayerChromium
> secondParent
= LayerChromium::create();
719 scoped_refptr
<LayerChromium
> secondChild
= LayerChromium::create();
720 scoped_refptr
<LayerChromium
> secondGrandChild
= LayerChromium::create();
722 // First put all children under the first parent and set the first host.
723 firstParent
->addChild(firstChild
);
724 secondChild
->addChild(secondGrandChild
);
725 firstParent
->addChild(secondChild
);
727 scoped_ptr
<FakeCCLayerTreeHost
> firstLayerTreeHost(FakeCCLayerTreeHost::create());
728 firstLayerTreeHost
->setRootLayer(firstParent
.get());
730 assertLayerTreeHostMatchesForSubtree(firstParent
.get(), firstLayerTreeHost
.get());
732 // Now reparent the subtree starting at secondChild to a layer in a different tree.
733 scoped_ptr
<FakeCCLayerTreeHost
> secondLayerTreeHost(FakeCCLayerTreeHost::create());
734 secondLayerTreeHost
->setRootLayer(secondParent
.get());
736 secondParent
->addChild(secondChild
);
738 // The moved layer and its children should point to the new host.
739 EXPECT_EQ(secondLayerTreeHost
.get(), secondChild
->layerTreeHost());
740 EXPECT_EQ(secondLayerTreeHost
.get(), secondGrandChild
->layerTreeHost());
742 // Test over, cleanup time.
743 firstLayerTreeHost
->setRootLayer(0);
744 secondLayerTreeHost
->setRootLayer(0);
747 TEST(LayerChromiumLayerTreeHostTest
, replaceMaskAndReplicaLayer
)
749 WebCompositorInitializer
compositorInitializer(0);
750 scoped_refptr
<LayerChromium
> parent
= LayerChromium::create();
751 scoped_refptr
<LayerChromium
> mask
= LayerChromium::create();
752 scoped_refptr
<LayerChromium
> replica
= LayerChromium::create();
753 scoped_refptr
<LayerChromium
> maskChild
= LayerChromium::create();
754 scoped_refptr
<LayerChromium
> replicaChild
= LayerChromium::create();
755 scoped_refptr
<LayerChromium
> maskReplacement
= LayerChromium::create();
756 scoped_refptr
<LayerChromium
> replicaReplacement
= LayerChromium::create();
758 parent
->setMaskLayer(mask
.get());
759 parent
->setReplicaLayer(replica
.get());
760 mask
->addChild(maskChild
);
761 replica
->addChild(replicaChild
);
763 scoped_ptr
<FakeCCLayerTreeHost
> layerTreeHost(FakeCCLayerTreeHost::create());
764 layerTreeHost
->setRootLayer(parent
.get());
766 assertLayerTreeHostMatchesForSubtree(parent
.get(), layerTreeHost
.get());
768 // Replacing the mask should clear out the old mask's subtree's host pointers.
769 parent
->setMaskLayer(maskReplacement
.get());
770 EXPECT_EQ(0, mask
->layerTreeHost());
771 EXPECT_EQ(0, maskChild
->layerTreeHost());
773 // Same for replacing a replica layer.
774 parent
->setReplicaLayer(replicaReplacement
.get());
775 EXPECT_EQ(0, replica
->layerTreeHost());
776 EXPECT_EQ(0, replicaChild
->layerTreeHost());
778 // Test over, cleanup time.
779 layerTreeHost
->setRootLayer(0);
782 TEST(LayerChromiumLayerTreeHostTest
, destroyHostWithNonNullRootLayer
)
784 WebCompositorInitializer
compositorInitializer(0);
785 scoped_refptr
<LayerChromium
> root
= LayerChromium::create();
786 scoped_refptr
<LayerChromium
> child
= LayerChromium::create();
787 root
->addChild(child
);
788 scoped_ptr
<FakeCCLayerTreeHost
> layerTreeHost(FakeCCLayerTreeHost::create());
789 layerTreeHost
->setRootLayer(root
);
792 static bool addTestAnimation(LayerChromium
* layer
)
794 OwnPtr
<CCKeyframedFloatAnimationCurve
> curve(CCKeyframedFloatAnimationCurve::create());
795 curve
->addKeyframe(CCFloatKeyframe::create(0, 0.3f
, nullptr));
796 curve
->addKeyframe(CCFloatKeyframe::create(1, 0.7f
, nullptr));
797 OwnPtr
<CCActiveAnimation
> animation(CCActiveAnimation::create(curve
.release(), 0, 0, CCActiveAnimation::Opacity
));
799 return layer
->addAnimation(animation
.release());
802 TEST(LayerChromiumLayerTreeHostTest
, shouldNotAddAnimationWithoutLayerTreeHost
)
804 // Currently, WebCore assumes that animations will be started immediately / very soon
805 // if a composited layer's addAnimation() returns true. However, without a layerTreeHost,
806 // layers cannot actually animate yet. So, to prevent violating this WebCore assumption,
807 // the animation should not be accepted if the layer doesn't already have a layerTreeHost.
809 WebKit::Platform::current()->compositorSupport()->setAcceleratedAnimationEnabled(true);
811 WebCompositorInitializer
compositorInitializer(0);
812 scoped_refptr
<LayerChromium
> layer
= LayerChromium::create();
814 // Case 1: without a layerTreeHost, the animation should not be accepted.
815 EXPECT_FALSE(addTestAnimation(layer
.get()));
817 scoped_ptr
<FakeCCLayerTreeHost
> layerTreeHost(FakeCCLayerTreeHost::create());
818 layerTreeHost
->setRootLayer(layer
.get());
819 layer
->setLayerTreeHost(layerTreeHost
.get());
820 assertLayerTreeHostMatchesForSubtree(layer
.get(), layerTreeHost
.get());
822 // Case 2: with a layerTreeHost, the animation should be accepted.
823 EXPECT_TRUE(addTestAnimation(layer
.get()));
826 class MockLayerChromium
: public LayerChromium
{
828 bool needsDisplay() const { return m_needsDisplay
; }
831 virtual ~MockLayerChromium()
836 TEST(LayerChromiumTestWithoutFixture
, setBoundsTriggersSetNeedsRedrawAfterGettingNonEmptyBounds
)
838 scoped_refptr
<MockLayerChromium
> layer(new MockLayerChromium
);
839 EXPECT_FALSE(layer
->needsDisplay());
840 layer
->setBounds(IntSize(0, 10));
841 EXPECT_FALSE(layer
->needsDisplay());
842 layer
->setBounds(IntSize(10, 10));
843 EXPECT_TRUE(layer
->needsDisplay());