[Chromium] New CCOcclusionTracker class with tests
[WebKit-https.git] / Source / WebKit / chromium / tests / CCLayerTreeHostCommonTest.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "cc/CCLayerTreeHostCommon.h"
28
29 #include "CCLayerTreeTestCommon.h"
30 #include "LayerChromium.h"
31 #include "TransformationMatrix.h"
32
33 #include <gmock/gmock.h>
34 #include <gtest/gtest.h>
35
36 using namespace WebCore;
37
38 namespace {
39
40 void setLayerPropertiesForTesting(LayerChromium* layer, const TransformationMatrix& transform, const TransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool preserves3D)
41 {
42     layer->setTransform(transform);
43     layer->setSublayerTransform(sublayerTransform);
44     layer->setAnchorPoint(anchor);
45     layer->setPosition(position);
46     layer->setBounds(bounds);
47     layer->setPreserves3D(preserves3D);
48 }
49
50 void executeCalculateDrawTransformsAndVisibility(LayerChromium* rootLayer)
51 {
52     TransformationMatrix identityMatrix;
53     Vector<RefPtr<LayerChromium> > dummyRenderSurfaceLayerList;
54     Vector<RefPtr<LayerChromium> > dummyLayerList;
55     int dummyMaxTextureSize = 512;
56     CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer, rootLayer, identityMatrix, identityMatrix, dummyRenderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
57 }
58
59 TransformationMatrix remove3DComponentOfMatrix(const TransformationMatrix& mat)
60 {
61     TransformationMatrix ret = mat;
62     ret.setM13(0);
63     ret.setM23(0);
64     ret.setM31(0);
65     ret.setM32(0);
66     ret.setM33(1);
67     ret.setM34(0);
68     ret.setM43(0);
69     return ret;
70 }
71
72 class LayerChromiumWithForcedDrawsContent : public LayerChromium {
73 public:
74     LayerChromiumWithForcedDrawsContent()
75         : LayerChromium()
76     {
77     }
78
79     virtual bool drawsContent() const { return true; }
80 };
81
82 TEST(CCLayerTreeHostCommonTest, verifyTransformsForNoOpLayer)
83 {
84     // Sanity check: For layers positioned at zero, with zero size,
85     // and with identity transforms, then the drawTransform,
86     // screenSpaceTransform, and the hierarchy passed on to children
87     // layers should also be identity transforms.
88
89     RefPtr<LayerChromium> parent = LayerChromium::create();
90     RefPtr<LayerChromium> child = LayerChromium::create();
91     RefPtr<LayerChromium> grandChild = LayerChromium::create();
92     parent->createRenderSurface();
93     parent->addChild(child);
94     child->addChild(grandChild);
95
96     TransformationMatrix identityMatrix;
97     setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(0, 0), false);
98     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(0, 0), false);
99     setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(0, 0), false);
100
101     executeCalculateDrawTransformsAndVisibility(parent.get());
102
103     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, parent->drawTransform());
104     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, parent->screenSpaceTransform());
105     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->drawTransform());
106     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->screenSpaceTransform());
107     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, grandChild->drawTransform());
108     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, grandChild->screenSpaceTransform());
109 }
110
111 TEST(CCLayerTreeHostCommonTest, verifyTransformsForSingleLayer)
112 {
113     // NOTE CAREFULLY:
114     // LayerChromium::position is actually the sum of anchorPoint (in pixel space) and actual position. Because of this, the
115     // value of LayerChromium::position() changes if the anchor changes, even though the layer is not actually located in a
116     // different position. When we initialize layers for testing here, we need to initialize that unintutive position value.
117
118     TransformationMatrix identityMatrix;
119     RefPtr<LayerChromium> layer = LayerChromium::create();
120     layer->createRenderSurface();
121
122     // Case 1: setting the sublayer transform should not affect this layer's draw transform or screen-space transform.
123     TransformationMatrix arbitraryTranslation;
124     arbitraryTranslation.translate(10.0, 20.0);
125     setLayerPropertiesForTesting(layer.get(), identityMatrix, arbitraryTranslation, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(0, 0), false);
126     executeCalculateDrawTransformsAndVisibility(layer.get());
127     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, layer->drawTransform());
128     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, layer->screenSpaceTransform());
129
130     // Case 2: setting the bounds of the layer should result in a draw transform that translates to half the width and height.
131     //         The screen-space transform should remain as the identity, because it does not deal with transforming to/from the center of the layer.
132     TransformationMatrix translationToCenter;
133     translationToCenter.translate(5.0, 6.0);
134     setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(10, 12), false);
135     executeCalculateDrawTransformsAndVisibility(layer.get());
136     EXPECT_TRANSFORMATION_MATRIX_EQ(translationToCenter, layer->drawTransform());
137     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, layer->screenSpaceTransform());
138
139     // Case 3: The anchor point by itself (without a layer transform) should have no effect on the transforms.
140     setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0.25f, 0.25f), FloatPoint(2.5f, 3.0f), IntSize(10, 12), false);
141     executeCalculateDrawTransformsAndVisibility(layer.get());
142     EXPECT_TRANSFORMATION_MATRIX_EQ(translationToCenter, layer->drawTransform());
143     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, layer->screenSpaceTransform());
144
145     // Case 4: A change in "actual" position affects both the draw transform and screen space transform.
146     TransformationMatrix positionTransform;
147     positionTransform.translate(0.0, 1.2);
148     setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0.25f, 0.25f), FloatPoint(2.5f, 4.2f), IntSize(10, 12), false);
149     executeCalculateDrawTransformsAndVisibility(layer.get());
150     EXPECT_TRANSFORMATION_MATRIX_EQ(positionTransform * translationToCenter, layer->drawTransform());
151     EXPECT_TRANSFORMATION_MATRIX_EQ(positionTransform, layer->screenSpaceTransform());
152
153     // Case 5: In the correct sequence of transforms, the layer transform should pre-multiply the translationToCenter. This is easily tested by
154     //         using a scale transform, because scale and translation are not commutative.
155     TransformationMatrix layerTransform;
156     layerTransform.scale3d(2.0, 2.0, 1.0);
157     setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(10, 12), false);
158     executeCalculateDrawTransformsAndVisibility(layer.get());
159     EXPECT_TRANSFORMATION_MATRIX_EQ(layerTransform * translationToCenter, layer->drawTransform());
160     EXPECT_TRANSFORMATION_MATRIX_EQ(layerTransform, layer->screenSpaceTransform());
161
162     // Case 6: The layer transform should occur with respect to the anchor point.
163     TransformationMatrix translationToAnchor;
164     translationToAnchor.translate(5.0, 0.0);
165     TransformationMatrix expectedResult = translationToAnchor * layerTransform * translationToAnchor.inverse();
166     setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0.5f, 0.0f), FloatPoint(5.0f, 0.0f), IntSize(10, 12), false);
167     executeCalculateDrawTransformsAndVisibility(layer.get());
168     EXPECT_TRANSFORMATION_MATRIX_EQ(expectedResult * translationToCenter, layer->drawTransform());
169     EXPECT_TRANSFORMATION_MATRIX_EQ(expectedResult, layer->screenSpaceTransform());
170
171     // Case 7: Verify that position pre-multiplies the layer transform.
172     //         The current implementation of calculateDrawTransformsAndVisibility does this implicitly, but it is
173     //         still worth testing to detect accidental regressions.
174     expectedResult = positionTransform * translationToAnchor * layerTransform * translationToAnchor.inverse();
175     setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0.5f, 0.0f), FloatPoint(5.0f, 1.2f), IntSize(10, 12), false);
176     executeCalculateDrawTransformsAndVisibility(layer.get());
177     EXPECT_TRANSFORMATION_MATRIX_EQ(expectedResult * translationToCenter, layer->drawTransform());
178     EXPECT_TRANSFORMATION_MATRIX_EQ(expectedResult, layer->screenSpaceTransform());
179 }
180
181 TEST(CCLayerTreeHostCommonTest, verifyTransformsForSimpleHierarchy)
182 {
183     TransformationMatrix identityMatrix;
184     RefPtr<LayerChromium> parent = LayerChromium::create();
185     RefPtr<LayerChromium> child = LayerChromium::create();
186     RefPtr<LayerChromium> grandChild = LayerChromium::create();
187     parent->createRenderSurface();
188     parent->addChild(child);
189     child->addChild(grandChild);
190
191     // Case 1: parent's anchorPoint should not affect child or grandChild.
192     TransformationMatrix childTranslationToCenter, grandChildTranslationToCenter;
193     childTranslationToCenter.translate(8.0, 9.0);
194     grandChildTranslationToCenter.translate(38.0, 39.0);
195     setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0.25f, 0.25f), FloatPoint(2.5f, 3.0f), IntSize(10, 12), false);
196     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(16, 18), false);
197     setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(76, 78), false);
198     executeCalculateDrawTransformsAndVisibility(parent.get());
199     EXPECT_TRANSFORMATION_MATRIX_EQ(childTranslationToCenter, child->drawTransform());
200     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->screenSpaceTransform());
201     EXPECT_TRANSFORMATION_MATRIX_EQ(grandChildTranslationToCenter, grandChild->drawTransform());
202     EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, grandChild->screenSpaceTransform());
203
204     // Case 2: parent's position affects child and grandChild.
205     TransformationMatrix parentPositionTransform;
206     parentPositionTransform.translate(0.0, 1.2);
207     setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0.25f, 0.25f), FloatPoint(2.5f, 4.2f), IntSize(10, 12), false);
208     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(16, 18), false);
209     setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(76, 78), false);
210     executeCalculateDrawTransformsAndVisibility(parent.get());
211     EXPECT_TRANSFORMATION_MATRIX_EQ(parentPositionTransform * childTranslationToCenter, child->drawTransform());
212     EXPECT_TRANSFORMATION_MATRIX_EQ(parentPositionTransform, child->screenSpaceTransform());
213     EXPECT_TRANSFORMATION_MATRIX_EQ(parentPositionTransform * grandChildTranslationToCenter, grandChild->drawTransform());
214     EXPECT_TRANSFORMATION_MATRIX_EQ(parentPositionTransform, grandChild->screenSpaceTransform());
215
216     // Case 3: parent's local transform affects child and grandchild
217     TransformationMatrix parentLayerTransform;
218     parentLayerTransform.scale3d(2.0, 2.0, 1.0);
219     TransformationMatrix parentTranslationToAnchor;
220     parentTranslationToAnchor.translate(2.5, 3.0);
221     TransformationMatrix parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * parentTranslationToAnchor.inverse();
222     setLayerPropertiesForTesting(parent.get(), parentLayerTransform, identityMatrix, FloatPoint(0.25f, 0.25f), FloatPoint(2.5f, 3.0f), IntSize(10, 12), false);
223     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(16, 18), false);
224     setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(76, 78), false);
225     executeCalculateDrawTransformsAndVisibility(parent.get());
226     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform * childTranslationToCenter, child->drawTransform());
227     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->screenSpaceTransform());
228     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform * grandChildTranslationToCenter, grandChild->drawTransform());
229     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, grandChild->screenSpaceTransform());
230
231     // Case 4: parent's sublayerMatrix affects child and grandchild
232     //         scaling is used here again so that the correct sequence of transforms is properly tested.
233     //         Note that preserves3D is false, but the sublayer matrix should retain its 3D properties when given to child.
234     //         But then, the child also does not preserve3D. When it gives its hierarchy to the grandChild, it should be flattened to 2D.
235     TransformationMatrix parentSublayerMatrix;
236     parentSublayerMatrix.scale3d(10.0, 10.0, 3.3);
237     TransformationMatrix parentTranslationToCenter;
238     parentTranslationToCenter.translate(5.0, 6.0);
239     // Sublayer matrix is applied to the center of the parent layer.
240     parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * parentTranslationToAnchor.inverse()
241             * parentTranslationToCenter * parentSublayerMatrix * parentTranslationToCenter.inverse();
242     TransformationMatrix flattenedCompositeTransform = remove3DComponentOfMatrix(parentCompositeTransform);
243     setLayerPropertiesForTesting(parent.get(), parentLayerTransform, parentSublayerMatrix, FloatPoint(0.25f, 0.25f), FloatPoint(2.5f, 3.0f), IntSize(10, 12), false);
244     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(16, 18), false);
245     setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(76, 78), false);
246     executeCalculateDrawTransformsAndVisibility(parent.get());
247     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform * childTranslationToCenter, child->drawTransform());
248     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->screenSpaceTransform());
249     EXPECT_TRANSFORMATION_MATRIX_EQ(flattenedCompositeTransform * grandChildTranslationToCenter, grandChild->drawTransform());
250     EXPECT_TRANSFORMATION_MATRIX_EQ(flattenedCompositeTransform, grandChild->screenSpaceTransform());
251
252     // Case 5: same as Case 4, except that child does preserve 3D, so the grandChild should receive the non-flattened composite transform.
253     //
254     setLayerPropertiesForTesting(parent.get(), parentLayerTransform, parentSublayerMatrix, FloatPoint(0.25f, 0.25f), FloatPoint(2.5f, 3.0f), IntSize(10, 12), false);
255     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(16, 18), true);
256     setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(76, 78), false);
257     executeCalculateDrawTransformsAndVisibility(parent.get());
258     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform * childTranslationToCenter, child->drawTransform());
259     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->screenSpaceTransform());
260     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform * grandChildTranslationToCenter, grandChild->drawTransform());
261     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, grandChild->screenSpaceTransform());
262 }
263
264 TEST(CCLayerTreeHostCommonTest, verifyTransformsForSingleRenderSurface)
265 {
266     RefPtr<LayerChromium> parent = LayerChromium::create();
267     RefPtr<LayerChromium> child = LayerChromium::create();
268     RefPtr<LayerChromiumWithForcedDrawsContent> grandChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
269     parent->createRenderSurface();
270     parent->addChild(child);
271     child->addChild(grandChild);
272
273     // Child is set up so that a new render surface should be created.
274     child->setOpacity(0.5f);
275
276     TransformationMatrix identityMatrix;
277     TransformationMatrix parentLayerTransform;
278     parentLayerTransform.scale3d(2.0, 2.0, 1.0);
279     TransformationMatrix parentTranslationToAnchor;
280     parentTranslationToAnchor.translate(2.5, 3.0);
281     TransformationMatrix parentSublayerMatrix;
282     parentSublayerMatrix.scale3d(10.0, 10.0, 3.3);
283     TransformationMatrix parentTranslationToCenter;
284     parentTranslationToCenter.translate(5.0, 6.0);
285     TransformationMatrix parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * parentTranslationToAnchor.inverse()
286             * parentTranslationToCenter * parentSublayerMatrix * parentTranslationToCenter.inverse();
287     TransformationMatrix childTranslationToCenter;
288     childTranslationToCenter.translate(8.0, 9.0);
289
290     // Child's render surface should not exist yet.
291     ASSERT_FALSE(child->renderSurface());
292
293     setLayerPropertiesForTesting(parent.get(), parentLayerTransform, parentSublayerMatrix, FloatPoint(0.25f, 0.25f), FloatPoint(2.5f, 3.0f), IntSize(10, 12), false);
294     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(16, 18), false);
295     setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(-0.5f, -0.5f), IntSize(1, 1), false);
296     executeCalculateDrawTransformsAndVisibility(parent.get());
297
298     // Render surface should have been created now.
299     ASSERT_TRUE(child->renderSurface());
300     ASSERT_EQ(child->renderSurface(), child->targetRenderSurface());
301
302     // The child layer's draw transform should refer to its new render surface; they only differ by a translation to center.
303     // The screen-space transform, however, should still refer to the root.
304     EXPECT_TRANSFORMATION_MATRIX_EQ(childTranslationToCenter, child->drawTransform());
305     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->screenSpaceTransform());
306
307     // Without clipping, the origin transform and draw transform (in this particular case) should be the same.
308     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->targetRenderSurface()->originTransform());
309     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->targetRenderSurface()->drawTransform());
310
311 }
312
313 TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
314 {
315     // This test creates a more complex tree and verifies it all at once. This covers the following cases:
316     //   - layers that are described w.r.t. a render surface: should have draw transforms described w.r.t. that surface
317     //   - A render surface described w.r.t. an ancestor render surface: should have a draw transform described w.r.t. that ancestor surface
318     //   - Sanity check on recursion: verify transforms of layers described w.r.t. a render surface that is described w.r.t. an ancestor render surface.
319     //   - verifying that each layer has a reference to the correct renderSurface and targetRenderSurface values.
320
321     RefPtr<LayerChromium> parent = LayerChromium::create();
322     RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
323     RefPtr<LayerChromium> renderSurface2 = LayerChromium::create();
324     RefPtr<LayerChromium> childOfRoot = LayerChromium::create();
325     RefPtr<LayerChromium> childOfRS1 = LayerChromium::create();
326     RefPtr<LayerChromium> childOfRS2 = LayerChromium::create();
327     RefPtr<LayerChromium> grandChildOfRoot = LayerChromium::create();
328     RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
329     RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
330     parent->createRenderSurface();
331     parent->addChild(renderSurface1);
332     parent->addChild(childOfRoot);
333     renderSurface1->addChild(childOfRS1);
334     renderSurface1->addChild(renderSurface2);
335     renderSurface2->addChild(childOfRS2);
336     childOfRoot->addChild(grandChildOfRoot);
337     childOfRS1->addChild(grandChildOfRS1);
338     childOfRS2->addChild(grandChildOfRS2);
339
340     // In combination with descendantDrawsContent, opacity != 1 forces the layer to have a new renderSurface.
341     renderSurface1->setOpacity(0.5f);
342     renderSurface2->setOpacity(0.33f);
343
344     // All layers in the tree are initialized with an anchor at 2.5 and a size of (10,10).
345     // matrix "A" is the composite layer transform used in all layers, centered about the anchor point
346     // matrix "B" is the sublayer transform used in all layers, centered about the center position of the layer.
347     //
348     // x component tests that layerTransform and sublayerTransform are done in the right order (translation and scale are noncommutative).
349     // y component has a translation by 1.0 for every ancestor, which indicates the "depth" of the layer in the hierarchy.
350     TransformationMatrix translationToAnchor;
351     translationToAnchor.translate(2.5, 0.0);
352     TransformationMatrix translationToCenter;
353     translationToCenter.translate(5.0, 5.0);
354     TransformationMatrix layerTransform;
355     layerTransform.translate(1.0, 1.0);
356     TransformationMatrix sublayerTransform;
357     sublayerTransform.scale3d(10.0, 1.0, 1.0);
358
359     TransformationMatrix A = translationToAnchor * layerTransform * translationToAnchor.inverse();
360     TransformationMatrix B = translationToCenter * sublayerTransform * translationToCenter.inverse();
361
362     setLayerPropertiesForTesting(parent.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
363     setLayerPropertiesForTesting(renderSurface1.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
364     setLayerPropertiesForTesting(renderSurface2.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
365     setLayerPropertiesForTesting(childOfRoot.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
366     setLayerPropertiesForTesting(childOfRS1.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
367     setLayerPropertiesForTesting(childOfRS2.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
368     setLayerPropertiesForTesting(grandChildOfRoot.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
369     setLayerPropertiesForTesting(grandChildOfRS1.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
370     setLayerPropertiesForTesting(grandChildOfRS2.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
371
372     executeCalculateDrawTransformsAndVisibility(parent.get());
373
374     // Only layers that are associated with render surfaces should have an actual renderSurface() value.
375     //
376     ASSERT_TRUE(parent->renderSurface());
377     ASSERT_FALSE(childOfRoot->renderSurface());
378     ASSERT_FALSE(grandChildOfRoot->renderSurface());
379
380     ASSERT_TRUE(renderSurface1->renderSurface());
381     ASSERT_FALSE(childOfRS1->renderSurface());
382     ASSERT_FALSE(grandChildOfRS1->renderSurface());
383
384     ASSERT_TRUE(renderSurface2->renderSurface());
385     ASSERT_FALSE(childOfRS2->renderSurface());
386     ASSERT_FALSE(grandChildOfRS2->renderSurface());
387
388     // Verify all targetRenderSurface accessors
389     //
390     EXPECT_EQ(parent->renderSurface(), parent->targetRenderSurface());
391     EXPECT_EQ(parent->renderSurface(), childOfRoot->targetRenderSurface());
392     EXPECT_EQ(parent->renderSurface(), grandChildOfRoot->targetRenderSurface());
393
394     EXPECT_EQ(renderSurface1->renderSurface(), renderSurface1->targetRenderSurface());
395     EXPECT_EQ(renderSurface1->renderSurface(), childOfRS1->targetRenderSurface());
396     EXPECT_EQ(renderSurface1->renderSurface(), grandChildOfRS1->targetRenderSurface());
397
398     EXPECT_EQ(renderSurface2->renderSurface(), renderSurface2->targetRenderSurface());
399     EXPECT_EQ(renderSurface2->renderSurface(), childOfRS2->targetRenderSurface());
400     EXPECT_EQ(renderSurface2->renderSurface(), grandChildOfRS2->targetRenderSurface());
401
402     // Verify layer draw transforms
403     //  note that draw transforms are described with respect to the nearest ancestor render surface
404     //  but screen space transforms are described with respect to the root.
405     //
406     EXPECT_TRANSFORMATION_MATRIX_EQ(A * translationToCenter, parent->drawTransform());
407     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * translationToCenter, childOfRoot->drawTransform());
408     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A * translationToCenter, grandChildOfRoot->drawTransform());
409
410     EXPECT_TRANSFORMATION_MATRIX_EQ(translationToCenter, renderSurface1->drawTransform());
411     EXPECT_TRANSFORMATION_MATRIX_EQ(B * A * translationToCenter, childOfRS1->drawTransform());
412     EXPECT_TRANSFORMATION_MATRIX_EQ(B * A * B * A * translationToCenter, grandChildOfRS1->drawTransform());
413
414     EXPECT_TRANSFORMATION_MATRIX_EQ(translationToCenter, renderSurface2->drawTransform());
415     EXPECT_TRANSFORMATION_MATRIX_EQ(B * A * translationToCenter, childOfRS2->drawTransform());
416     EXPECT_TRANSFORMATION_MATRIX_EQ(B * A * B * A * translationToCenter, grandChildOfRS2->drawTransform());
417
418     // Verify layer screen-space transforms
419     //
420     EXPECT_TRANSFORMATION_MATRIX_EQ(A, parent->screenSpaceTransform());
421     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, childOfRoot->screenSpaceTransform());
422     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, grandChildOfRoot->screenSpaceTransform());
423
424     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, renderSurface1->screenSpaceTransform());
425     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, childOfRS1->screenSpaceTransform());
426     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A * B * A, grandChildOfRS1->screenSpaceTransform());
427
428     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, renderSurface2->screenSpaceTransform());
429     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A * B * A, childOfRS2->screenSpaceTransform());
430     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A * B * A * B * A, grandChildOfRS2->screenSpaceTransform());
431
432     // Verify render surface transforms.
433     //
434     // Origin transform of render surface 1 is described with respect to root.
435     EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, renderSurface1->renderSurface()->originTransform());
436     // Origin transform of render surface 2 is described with respect to render surface 2.
437     EXPECT_TRANSFORMATION_MATRIX_EQ(B * A, renderSurface2->renderSurface()->originTransform());
438
439     // Sanity check. If these fail there is probably a bug in the test itself.
440     // It is expected that we correctly set up transforms so that the y-component of the screen-space transform
441     // encodes the "depth" of the layer in the tree.
442     EXPECT_FLOAT_EQ(1.0, parent->screenSpaceTransform().m42());
443     EXPECT_FLOAT_EQ(2.0, childOfRoot->screenSpaceTransform().m42());
444     EXPECT_FLOAT_EQ(3.0, grandChildOfRoot->screenSpaceTransform().m42());
445
446     EXPECT_FLOAT_EQ(2.0, renderSurface1->screenSpaceTransform().m42());
447     EXPECT_FLOAT_EQ(3.0, childOfRS1->screenSpaceTransform().m42());
448     EXPECT_FLOAT_EQ(4.0, grandChildOfRS1->screenSpaceTransform().m42());
449
450     EXPECT_FLOAT_EQ(3.0, renderSurface2->screenSpaceTransform().m42());
451     EXPECT_FLOAT_EQ(4.0, childOfRS2->screenSpaceTransform().m42());
452     EXPECT_FLOAT_EQ(5.0, grandChildOfRS2->screenSpaceTransform().m42());
453 }
454
455 TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceListForClipLayer)
456 {
457     RefPtr<LayerChromium> parent = LayerChromium::create();
458     RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
459     RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent());
460     renderSurface1->setOpacity(0.9);
461
462     const TransformationMatrix identityMatrix;
463     setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
464     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint(30, 30), IntSize(10, 10), false);
465
466     parent->createRenderSurface();
467     parent->setClipRect(IntRect(0, 0, 10, 10));
468     parent->addChild(renderSurface1);
469     renderSurface1->createRenderSurface();
470     renderSurface1->addChild(child);
471
472     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
473     Vector<RefPtr<LayerChromium> > dummyLayerList;
474     int dummyMaxTextureSize = 512;
475     CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
476
477     // The child layer's content is entirely outside the parent's clip rect, so the intermediate
478     // render surface should have been removed. Render surfaces without children or visible
479     // content are unexpected at draw time (e.g. we might try to create a content texture of size 0).
480     ASSERT_FALSE(renderSurface1->renderSurface());
481     EXPECT_EQ(renderSurfaceLayerList.size(), 0U);
482 }
483
484 TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceListForTransparentChild)
485 {
486     RefPtr<LayerChromium> parent = LayerChromium::create();
487     RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
488     RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent());
489     renderSurface1->setOpacity(0);
490
491     const TransformationMatrix identityMatrix;
492     setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
493     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
494
495     parent->createRenderSurface();
496     parent->addChild(renderSurface1);
497     renderSurface1->createRenderSurface();
498     renderSurface1->addChild(child);
499
500     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
501     Vector<RefPtr<LayerChromium> > dummyLayerList;
502     int dummyMaxTextureSize = 512;
503     CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
504
505     // Since the layer is transparent, renderSurface1->renderSurface() should not have gotten added anywhere.
506     // Also, the drawable content rect should not have been extended by the children.
507     EXPECT_EQ(parent->renderSurface()->layerList().size(), 0U);
508     EXPECT_EQ(renderSurfaceLayerList.size(), 0U);
509     EXPECT_EQ(parent->drawableContentRect(), IntRect());
510 }
511
512 TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces)
513 {
514     // The entire subtree of layers that are outside the clipRect should be culled away,
515     // and should not affect the renderSurfaceLayerList.
516     //
517     // The test tree is set up as follows:
518     //  - all layers except the leafNodes are forced to be a new renderSurface that have something to draw.
519     //  - parent is a large container layer.
520     //  - child has masksToBounds=true to cause clipping.
521     //  - grandChild is positioned outside of the child's bounds
522     //  - greatGrandChild is also kept outside child's bounds.
523     //
524     // In this configuration, grandChild and greatGrandChild are completely outside the
525     // clipRect, and they should never get scheduled on the list of renderSurfaces.
526     //
527
528     const TransformationMatrix identityMatrix;
529     RefPtr<LayerChromium> parent = LayerChromium::create();
530     RefPtr<LayerChromium> child = LayerChromium::create();
531     RefPtr<LayerChromium> grandChild = LayerChromium::create();
532     RefPtr<LayerChromium> greatGrandChild = LayerChromium::create();
533     RefPtr<LayerChromiumWithForcedDrawsContent> leafNode1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
534     RefPtr<LayerChromiumWithForcedDrawsContent> leafNode2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
535     parent->createRenderSurface();
536     parent->addChild(child);
537     child->addChild(grandChild);
538     grandChild->addChild(greatGrandChild);
539
540     // leafNode1 ensures that parent and child are kept on the renderSurfaceLayerList,
541     // even though grandChild and greatGrandChild should be clipped.
542     child->addChild(leafNode1);
543     greatGrandChild->addChild(leafNode2);
544
545     setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
546     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
547     setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(45, 45), IntSize(10, 10), false);
548     setLayerPropertiesForTesting(greatGrandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
549     setLayerPropertiesForTesting(leafNode1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
550     setLayerPropertiesForTesting(leafNode2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
551
552     child->setMasksToBounds(true);
553     child->setOpacity(0.4);
554     grandChild->setOpacity(0.5);
555     greatGrandChild->setOpacity(0.4);
556
557     // Contaminate the grandChild and greatGrandChild's clipRect to reproduce the crash
558     // bug found in http://code.google.com/p/chromium/issues/detail?id=106734. In this
559     // bug, the clipRect was not re-computed for layers that create RenderSurfaces, and
560     // therefore leafNode2 thinks it should draw itself. As a result, an extra
561     // renderSurface remains on the renderSurfaceLayerList, which violates the assumption
562     // that an empty renderSurface will always be the last item on the list, which
563     // ultimately caused the crash.
564     //
565     // FIXME: it is also useful to test with this commented out. Eventually we should
566     // create several test cases that test clipRect/drawableContentRect computation.
567     child->setClipRect(IntRect(IntPoint::zero(), IntSize(20, 20)));
568     greatGrandChild->setClipRect(IntRect(IntPoint::zero(), IntSize(1234, 1234)));
569
570     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
571     Vector<RefPtr<LayerChromium> > dummyLayerList;
572     int dummyMaxTextureSize = 512;
573
574     // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too.
575     parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
576     renderSurfaceLayerList.append(parent);
577
578     CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
579
580     ASSERT_EQ(2U, renderSurfaceLayerList.size());
581     EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
582     EXPECT_EQ(child->id(), renderSurfaceLayerList[1]->id());
583 }
584
585 // FIXME:
586 // continue working on https://bugs.webkit.org/show_bug.cgi?id=68942
587 //  - add a test to verify clipping that changes the "center point"
588 //  - add a case that checks if a render surface's drawTransform is computed correctly. For the general case, and for special cases when clipping.
589 //  - add a case that checks if a render surface's replicaTransform is computed correctly.
590 //  - test all the conditions under which render surfaces are created
591 //  - if possible, test all conditions under which render surfaces are not created
592 //  - verify that the layer lists of render surfaces are correct, verify that "targetRenderSurface" values for each layer are correct.
593 //  - test the computation of clip rects and content rects
594 //  - test the special cases for mask layers and replica layers
595 //  - test the other functions in CCLayerTreeHostCommon
596 //
597
598 } // namespace