blob: 02df09fd07ef66c713d5410859c6113dfdd4ea0b [file] [log] [blame]
[email protected]94f206c12012-08-25 00:09:141// 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.
4
5#include "config.h"
6
7#include "CCLayerTreeHostCommon.h"
8
9#include "CCAnimationTestCommon.h"
[email protected]022cbf162012-09-01 01:15:1710#include "CCGeometryTestUtils.h"
[email protected]94f206c12012-08-25 00:09:1411#include "CCLayerAnimationController.h"
12#include "CCLayerImpl.h"
13#include "CCLayerSorter.h"
[email protected]94f206c12012-08-25 00:09:1414#include "CCMathUtil.h"
15#include "CCProxy.h"
16#include "CCSingleThreadProxy.h"
17#include "CCThread.h"
18#include "ContentLayerChromium.h"
[email protected]be3aa6f2012-08-31 23:55:4019#include "ContentLayerChromiumClient.h"
[email protected]94f206c12012-08-25 00:09:1420#include "LayerChromium.h"
21
22#include <gmock/gmock.h>
23#include <gtest/gtest.h>
24#include <public/WebTransformationMatrix.h>
25
26using namespace WebCore;
27using namespace WebKitTests;
28using WebKit::WebTransformationMatrix;
29
[email protected]94f206c12012-08-25 00:09:1430namespace {
31
32template<typename LayerType>
33void setLayerPropertiesForTesting(LayerType* layer, const WebTransformationMatrix& transform, const WebTransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool preserves3D)
34{
35 layer->setTransform(transform);
36 layer->setSublayerTransform(sublayerTransform);
37 layer->setAnchorPoint(anchor);
38 layer->setPosition(position);
39 layer->setBounds(bounds);
40 layer->setPreserves3D(preserves3D);
41}
42
43void setLayerPropertiesForTesting(LayerChromium* layer, const WebTransformationMatrix& transform, const WebTransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool preserves3D)
44{
45 setLayerPropertiesForTesting<LayerChromium>(layer, transform, sublayerTransform, anchor, position, bounds, preserves3D);
46}
47
48void setLayerPropertiesForTesting(CCLayerImpl* layer, const WebTransformationMatrix& transform, const WebTransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool preserves3D)
49{
50 setLayerPropertiesForTesting<CCLayerImpl>(layer, transform, sublayerTransform, anchor, position, bounds, preserves3D);
51 layer->setContentBounds(bounds);
52}
53
54void executeCalculateDrawTransformsAndVisibility(LayerChromium* rootLayer)
55{
56 WebTransformationMatrix identityMatrix;
57 Vector<RefPtr<LayerChromium> > dummyRenderSurfaceLayerList;
58 int dummyMaxTextureSize = 512;
59
60 // We are probably not testing what is intended if the rootLayer bounds are empty.
61 ASSERT(!rootLayer->bounds().isEmpty());
62 CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, rootLayer->bounds(), 1, dummyMaxTextureSize, dummyRenderSurfaceLayerList);
63 CCLayerTreeHostCommon::calculateVisibleRects(dummyRenderSurfaceLayerList);
64}
65
66void executeCalculateDrawTransformsAndVisibility(CCLayerImpl* rootLayer)
67{
68 // Note: this version skips layer sorting.
69
70 WebTransformationMatrix identityMatrix;
71 Vector<CCLayerImpl*> dummyRenderSurfaceLayerList;
72 int dummyMaxTextureSize = 512;
73
74 // We are probably not testing what is intended if the rootLayer bounds are empty.
75 ASSERT(!rootLayer->bounds().isEmpty());
76 CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, rootLayer->bounds(), 1, 0, dummyMaxTextureSize, dummyRenderSurfaceLayerList);
77 CCLayerTreeHostCommon::calculateVisibleRects(dummyRenderSurfaceLayerList);
78}
79
80WebTransformationMatrix remove3DComponentOfMatrix(const WebTransformationMatrix& mat)
81{
82 WebTransformationMatrix ret = mat;
83 ret.setM13(0);
84 ret.setM23(0);
85 ret.setM31(0);
86 ret.setM32(0);
87 ret.setM33(1);
88 ret.setM34(0);
89 ret.setM43(0);
90 return ret;
91}
92
93PassOwnPtr<CCLayerImpl> createTreeForFixedPositionTests()
94{
95 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
96 OwnPtr<CCLayerImpl> child = CCLayerImpl::create(2);
97 OwnPtr<CCLayerImpl> grandChild = CCLayerImpl::create(3);
98 OwnPtr<CCLayerImpl> greatGrandChild = CCLayerImpl::create(4);
99
100 WebTransformationMatrix IdentityMatrix;
101 FloatPoint anchor(0, 0);
102 FloatPoint position(0, 0);
103 IntSize bounds(100, 100);
104 setLayerPropertiesForTesting(root.get(), IdentityMatrix, IdentityMatrix, anchor, position, bounds, false);
105 setLayerPropertiesForTesting(child.get(), IdentityMatrix, IdentityMatrix, anchor, position, bounds, false);
106 setLayerPropertiesForTesting(grandChild.get(), IdentityMatrix, IdentityMatrix, anchor, position, bounds, false);
107 setLayerPropertiesForTesting(greatGrandChild.get(), IdentityMatrix, IdentityMatrix, anchor, position, bounds, false);
108
109 grandChild->addChild(greatGrandChild.release());
110 child->addChild(grandChild.release());
111 root->addChild(child.release());
112
113 return root.release();
114}
115
116class LayerChromiumWithForcedDrawsContent : public LayerChromium {
117public:
118 LayerChromiumWithForcedDrawsContent()
119 : LayerChromium()
120 {
121 }
122
123 virtual bool drawsContent() const OVERRIDE { return true; }
124};
125
126TEST(CCLayerTreeHostCommonTest, verifyTransformsForNoOpLayer)
127{
128 // Sanity check: For layers positioned at zero, with zero size,
129 // and with identity transforms, then the drawTransform,
130 // screenSpaceTransform, and the hierarchy passed on to children
131 // layers should also be identity transforms.
132
133 RefPtr<LayerChromium> parent = LayerChromium::create();
134 RefPtr<LayerChromium> child = LayerChromium::create();
135 RefPtr<LayerChromium> grandChild = LayerChromium::create();
136 parent->addChild(child);
137 child->addChild(grandChild);
138
139 WebTransformationMatrix identityMatrix;
140 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
141 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(0, 0), false);
142 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(0, 0), false);
143
144 executeCalculateDrawTransformsAndVisibility(parent.get());
145
146 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->drawTransform());
147 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->screenSpaceTransform());
148 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, grandChild->drawTransform());
149 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, grandChild->screenSpaceTransform());
150}
151
152TEST(CCLayerTreeHostCommonTest, verifyTransformsForSingleLayer)
153{
154 WebTransformationMatrix identityMatrix;
155 RefPtr<LayerChromium> layer = LayerChromium::create();
156
157 // Case 1: setting the sublayer transform should not affect this layer's draw transform or screen-space transform.
158 WebTransformationMatrix arbitraryTranslation;
159 arbitraryTranslation.translate(10, 20);
160 setLayerPropertiesForTesting(layer.get(), identityMatrix, arbitraryTranslation, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
161 executeCalculateDrawTransformsAndVisibility(layer.get());
162 WebTransformationMatrix expectedDrawTransform = identityMatrix;
163 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedDrawTransform, layer->drawTransform());
164 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, layer->screenSpaceTransform());
165
166 // Case 2: Setting the bounds of the layer should not affect either the draw transform or the screenspace transform.
167 WebTransformationMatrix translationToCenter;
168 translationToCenter.translate(5, 6);
169 setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 12), false);
170 executeCalculateDrawTransformsAndVisibility(layer.get());
171 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, layer->drawTransform());
172 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, layer->screenSpaceTransform());
173
174 // Case 3: The anchor point by itself (without a layer transform) should have no effect on the transforms.
175 setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0.25, 0.25), FloatPoint(0, 0), IntSize(10, 12), false);
176 executeCalculateDrawTransformsAndVisibility(layer.get());
177 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, layer->drawTransform());
178 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, layer->screenSpaceTransform());
179
180 // Case 4: A change in actual position affects both the draw transform and screen space transform.
181 WebTransformationMatrix positionTransform;
182 positionTransform.translate(0, 1.2);
183 setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0.25, 0.25), FloatPoint(0, 1.2f), IntSize(10, 12), false);
184 executeCalculateDrawTransformsAndVisibility(layer.get());
185 EXPECT_TRANSFORMATION_MATRIX_EQ(positionTransform, layer->drawTransform());
186 EXPECT_TRANSFORMATION_MATRIX_EQ(positionTransform, layer->screenSpaceTransform());
187
188 // Case 5: In the correct sequence of transforms, the layer transform should pre-multiply the translationToCenter. This is easily tested by
189 // using a scale transform, because scale and translation are not commutative.
190 WebTransformationMatrix layerTransform;
191 layerTransform.scale3d(2, 2, 1);
192 setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 12), false);
193 executeCalculateDrawTransformsAndVisibility(layer.get());
194 EXPECT_TRANSFORMATION_MATRIX_EQ(layerTransform, layer->drawTransform());
195 EXPECT_TRANSFORMATION_MATRIX_EQ(layerTransform, layer->screenSpaceTransform());
196
197 // Case 6: The layer transform should occur with respect to the anchor point.
198 WebTransformationMatrix translationToAnchor;
199 translationToAnchor.translate(5, 0);
200 WebTransformationMatrix expectedResult = translationToAnchor * layerTransform * translationToAnchor.inverse();
201 setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0.5, 0), FloatPoint(0, 0), IntSize(10, 12), false);
202 executeCalculateDrawTransformsAndVisibility(layer.get());
203 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedResult, layer->drawTransform());
204 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedResult, layer->screenSpaceTransform());
205
206 // Case 7: Verify that position pre-multiplies the layer transform.
207 // The current implementation of calculateDrawTransforms does this implicitly, but it is
208 // still worth testing to detect accidental regressions.
209 expectedResult = positionTransform * translationToAnchor * layerTransform * translationToAnchor.inverse();
210 setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0.5, 0), FloatPoint(0, 1.2f), IntSize(10, 12), false);
211 executeCalculateDrawTransformsAndVisibility(layer.get());
212 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedResult, layer->drawTransform());
213 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedResult, layer->screenSpaceTransform());
214}
215
216TEST(CCLayerTreeHostCommonTest, verifyTransformsForSimpleHierarchy)
217{
218 WebTransformationMatrix identityMatrix;
219 RefPtr<LayerChromium> parent = LayerChromium::create();
220 RefPtr<LayerChromium> child = LayerChromium::create();
221 RefPtr<LayerChromium> grandChild = LayerChromium::create();
222 parent->addChild(child);
223 child->addChild(grandChild);
224
225 // Case 1: parent's anchorPoint should not affect child or grandChild.
226 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0.25, 0.25), FloatPoint(0, 0), IntSize(10, 12), false);
227 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(16, 18), false);
228 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(76, 78), false);
229 executeCalculateDrawTransformsAndVisibility(parent.get());
230 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->drawTransform());
231 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->screenSpaceTransform());
232 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, grandChild->drawTransform());
233 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, grandChild->screenSpaceTransform());
234
235 // Case 2: parent's position affects child and grandChild.
236 WebTransformationMatrix parentPositionTransform;
237 parentPositionTransform.translate(0, 1.2);
238 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0.25, 0.25), FloatPoint(0, 1.2f), IntSize(10, 12), false);
239 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(16, 18), false);
240 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(76, 78), false);
241 executeCalculateDrawTransformsAndVisibility(parent.get());
242 EXPECT_TRANSFORMATION_MATRIX_EQ(parentPositionTransform, child->drawTransform());
243 EXPECT_TRANSFORMATION_MATRIX_EQ(parentPositionTransform, child->screenSpaceTransform());
244 EXPECT_TRANSFORMATION_MATRIX_EQ(parentPositionTransform, grandChild->drawTransform());
245 EXPECT_TRANSFORMATION_MATRIX_EQ(parentPositionTransform, grandChild->screenSpaceTransform());
246
247 // Case 3: parent's local transform affects child and grandchild
248 WebTransformationMatrix parentLayerTransform;
249 parentLayerTransform.scale3d(2, 2, 1);
250 WebTransformationMatrix parentTranslationToAnchor;
251 parentTranslationToAnchor.translate(2.5, 3);
252 WebTransformationMatrix parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * parentTranslationToAnchor.inverse();
253 setLayerPropertiesForTesting(parent.get(), parentLayerTransform, identityMatrix, FloatPoint(0.25, 0.25), FloatPoint(0, 0), IntSize(10, 12), false);
254 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(16, 18), false);
255 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(76, 78), false);
256 executeCalculateDrawTransformsAndVisibility(parent.get());
257 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->drawTransform());
258 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->screenSpaceTransform());
259 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, grandChild->drawTransform());
260 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, grandChild->screenSpaceTransform());
261
262 // Case 4: parent's sublayerMatrix affects child and grandchild
263 // scaling is used here again so that the correct sequence of transforms is properly tested.
264 // Note that preserves3D is false, but the sublayer matrix should retain its 3D properties when given to child.
265 // But then, the child also does not preserve3D. When it gives its hierarchy to the grandChild, it should be flattened to 2D.
266 WebTransformationMatrix parentSublayerMatrix;
267 parentSublayerMatrix.scale3d(10, 10, 3.3);
268 WebTransformationMatrix parentTranslationToCenter;
269 parentTranslationToCenter.translate(5, 6);
270 // Sublayer matrix is applied to the center of the parent layer.
271 parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * parentTranslationToAnchor.inverse()
272 * parentTranslationToCenter * parentSublayerMatrix * parentTranslationToCenter.inverse();
273 WebTransformationMatrix flattenedCompositeTransform = remove3DComponentOfMatrix(parentCompositeTransform);
274 setLayerPropertiesForTesting(parent.get(), parentLayerTransform, parentSublayerMatrix, FloatPoint(0.25, 0.25), FloatPoint(0, 0), IntSize(10, 12), false);
275 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(16, 18), false);
276 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(76, 78), false);
277 executeCalculateDrawTransformsAndVisibility(parent.get());
278 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->drawTransform());
279 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->screenSpaceTransform());
280 EXPECT_TRANSFORMATION_MATRIX_EQ(flattenedCompositeTransform, grandChild->drawTransform());
281 EXPECT_TRANSFORMATION_MATRIX_EQ(flattenedCompositeTransform, grandChild->screenSpaceTransform());
282
283 // Case 5: same as Case 4, except that child does preserve 3D, so the grandChild should receive the non-flattened composite transform.
284 //
285 setLayerPropertiesForTesting(parent.get(), parentLayerTransform, parentSublayerMatrix, FloatPoint(0.25, 0.25), FloatPoint(0, 0), IntSize(10, 12), false);
286 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(16, 18), true);
287 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(76, 78), false);
288 executeCalculateDrawTransformsAndVisibility(parent.get());
289 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->drawTransform());
290 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->screenSpaceTransform());
291 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, grandChild->drawTransform());
292 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, grandChild->screenSpaceTransform());
293}
294
295TEST(CCLayerTreeHostCommonTest, verifyTransformsForSingleRenderSurface)
296{
297 RefPtr<LayerChromium> parent = LayerChromium::create();
298 RefPtr<LayerChromium> child = LayerChromium::create();
299 RefPtr<LayerChromiumWithForcedDrawsContent> grandChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
300 parent->addChild(child);
301 child->addChild(grandChild);
302
303 // Child is set up so that a new render surface should be created.
304 child->setOpacity(0.5);
305
306 WebTransformationMatrix identityMatrix;
307 WebTransformationMatrix parentLayerTransform;
308 parentLayerTransform.scale3d(1, 0.9, 1);
309 WebTransformationMatrix parentTranslationToAnchor;
310 parentTranslationToAnchor.translate(25, 30);
311 WebTransformationMatrix parentSublayerMatrix;
312 parentSublayerMatrix.scale3d(0.9, 1, 3.3);
313 WebTransformationMatrix parentTranslationToCenter;
314 parentTranslationToCenter.translate(50, 60);
315 WebTransformationMatrix parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * parentTranslationToAnchor.inverse()
316 * parentTranslationToCenter * parentSublayerMatrix * parentTranslationToCenter.inverse();
317
318 // Child's render surface should not exist yet.
319 ASSERT_FALSE(child->renderSurface());
320
321 setLayerPropertiesForTesting(parent.get(), parentLayerTransform, parentSublayerMatrix, FloatPoint(0.25, 0.25), FloatPoint(0, 0), IntSize(100, 120), false);
322 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(16, 18), false);
323 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(8, 10), false);
324 executeCalculateDrawTransformsAndVisibility(parent.get());
325
326 // Render surface should have been created now.
327 ASSERT_TRUE(child->renderSurface());
328 ASSERT_EQ(child, child->renderTarget());
329
330 // The child layer's draw transform should refer to its new render surface.
331 // The screen-space transform, however, should still refer to the root.
332 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->drawTransform());
333 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->screenSpaceTransform());
334
335 // Because the grandChild is the only drawable content, the child's renderSurface will tighten its bounds to the grandChild.
336 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->renderTarget()->renderSurface()->drawTransform());
337
338 // The screen space is the same as the target since the child surface draws into the root.
339 EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->renderTarget()->renderSurface()->screenSpaceTransform());
340}
341
342TEST(CCLayerTreeHostCommonTest, verifyTransformsForReplica)
343{
344 RefPtr<LayerChromium> parent = LayerChromium::create();
345 RefPtr<LayerChromium> child = LayerChromium::create();
346 RefPtr<LayerChromium> childReplica = LayerChromium::create();
347 RefPtr<LayerChromiumWithForcedDrawsContent> grandChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
348 parent->addChild(child);
349 child->addChild(grandChild);
350 child->setReplicaLayer(childReplica.get());
351
352 // Child is set up so that a new render surface should be created.
353 child->setOpacity(0.5);
354
355 WebTransformationMatrix identityMatrix;
356 WebTransformationMatrix parentLayerTransform;
357 parentLayerTransform.scale3d(2, 2, 1);
358 WebTransformationMatrix parentTranslationToAnchor;
359 parentTranslationToAnchor.translate(2.5, 3);
360 WebTransformationMatrix parentSublayerMatrix;
361 parentSublayerMatrix.scale3d(10, 10, 3.3);
362 WebTransformationMatrix parentTranslationToCenter;
363 parentTranslationToCenter.translate(5, 6);
364 WebTransformationMatrix parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * parentTranslationToAnchor.inverse()
365 * parentTranslationToCenter * parentSublayerMatrix * parentTranslationToCenter.inverse();
366 WebTransformationMatrix childTranslationToCenter;
367 childTranslationToCenter.translate(8, 9);
368 WebTransformationMatrix replicaLayerTransform;
369 replicaLayerTransform.scale3d(3, 3, 1);
370 WebTransformationMatrix replicaCompositeTransform = parentCompositeTransform * replicaLayerTransform;
371
372 // Child's render surface should not exist yet.
373 ASSERT_FALSE(child->renderSurface());
374
375 setLayerPropertiesForTesting(parent.get(), parentLayerTransform, parentSublayerMatrix, FloatPoint(0.25, 0.25), FloatPoint(0, 0), IntSize(10, 12), false);
376 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(16, 18), false);
377 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(-0.5, -0.5), IntSize(1, 1), false);
378 setLayerPropertiesForTesting(childReplica.get(), replicaLayerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(0, 0), false);
379 executeCalculateDrawTransformsAndVisibility(parent.get());
380
381 // Render surface should have been created now.
382 ASSERT_TRUE(child->renderSurface());
383 ASSERT_EQ(child, child->renderTarget());
384
385 EXPECT_TRANSFORMATION_MATRIX_EQ(replicaCompositeTransform, child->renderTarget()->renderSurface()->replicaDrawTransform());
386 EXPECT_TRANSFORMATION_MATRIX_EQ(replicaCompositeTransform, child->renderTarget()->renderSurface()->replicaScreenSpaceTransform());
387}
388
389TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
390{
391 // This test creates a more complex tree and verifies it all at once. This covers the following cases:
392 // - layers that are described w.r.t. a render surface: should have draw transforms described w.r.t. that surface
393 // - A render surface described w.r.t. an ancestor render surface: should have a draw transform described w.r.t. that ancestor surface
394 // - Replicas of a render surface are described w.r.t. the replica's transform around its anchor, along with the surface itself.
395 // - 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.
396 // - verifying that each layer has a reference to the correct renderSurface and renderTarget values.
397
398 RefPtr<LayerChromium> parent = LayerChromium::create();
399 RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
400 RefPtr<LayerChromium> renderSurface2 = LayerChromium::create();
401 RefPtr<LayerChromium> childOfRoot = LayerChromium::create();
402 RefPtr<LayerChromium> childOfRS1 = LayerChromium::create();
403 RefPtr<LayerChromium> childOfRS2 = LayerChromium::create();
404 RefPtr<LayerChromium> replicaOfRS1 = LayerChromium::create();
405 RefPtr<LayerChromium> replicaOfRS2 = LayerChromium::create();
406 RefPtr<LayerChromium> grandChildOfRoot = LayerChromium::create();
407 RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
408 RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
409 parent->addChild(renderSurface1);
410 parent->addChild(childOfRoot);
411 renderSurface1->addChild(childOfRS1);
412 renderSurface1->addChild(renderSurface2);
413 renderSurface2->addChild(childOfRS2);
414 childOfRoot->addChild(grandChildOfRoot);
415 childOfRS1->addChild(grandChildOfRS1);
416 childOfRS2->addChild(grandChildOfRS2);
417 renderSurface1->setReplicaLayer(replicaOfRS1.get());
418 renderSurface2->setReplicaLayer(replicaOfRS2.get());
419
420 // In combination with descendantDrawsContent, opacity != 1 forces the layer to have a new renderSurface.
421 renderSurface1->setOpacity(0.5);
422 renderSurface2->setOpacity(0.33f);
423
424 // All layers in the tree are initialized with an anchor at .25 and a size of (10,10).
425 // matrix "A" is the composite layer transform used in all layers, centered about the anchor point
426 // matrix "B" is the sublayer transform used in all layers, centered about the center position of the layer.
427 // matrix "R" is the composite replica transform used in all replica layers.
428 //
429 // x component tests that layerTransform and sublayerTransform are done in the right order (translation and scale are noncommutative).
430 // y component has a translation by 1 for every ancestor, which indicates the "depth" of the layer in the hierarchy.
431 WebTransformationMatrix translationToAnchor;
432 translationToAnchor.translate(2.5, 0);
433 WebTransformationMatrix translationToCenter;
434 translationToCenter.translate(5, 5);
435 WebTransformationMatrix layerTransform;
436 layerTransform.translate(1, 1);
437 WebTransformationMatrix sublayerTransform;
438 sublayerTransform.scale3d(10, 1, 1);
439 WebTransformationMatrix replicaLayerTransform;
440 replicaLayerTransform.scale3d(-2, 5, 1);
441
442 WebTransformationMatrix A = translationToAnchor * layerTransform * translationToAnchor.inverse();
443 WebTransformationMatrix B = translationToCenter * sublayerTransform * translationToCenter.inverse();
444 WebTransformationMatrix R = A * translationToAnchor * replicaLayerTransform * translationToAnchor.inverse();
445 WebTransformationMatrix identityMatrix;
446
447 setLayerPropertiesForTesting(parent.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false);
448 setLayerPropertiesForTesting(renderSurface1.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false);
449 setLayerPropertiesForTesting(renderSurface2.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false);
450 setLayerPropertiesForTesting(childOfRoot.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false);
451 setLayerPropertiesForTesting(childOfRS1.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false);
452 setLayerPropertiesForTesting(childOfRS2.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false);
453 setLayerPropertiesForTesting(grandChildOfRoot.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false);
454 setLayerPropertiesForTesting(grandChildOfRS1.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false);
455 setLayerPropertiesForTesting(grandChildOfRS2.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false);
456 setLayerPropertiesForTesting(replicaOfRS1.get(), replicaLayerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(), false);
457 setLayerPropertiesForTesting(replicaOfRS2.get(), replicaLayerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(), false);
458
459 executeCalculateDrawTransformsAndVisibility(parent.get());
460
461 // Only layers that are associated with render surfaces should have an actual renderSurface() value.
462 //
463 ASSERT_TRUE(parent->renderSurface());
464 ASSERT_FALSE(childOfRoot->renderSurface());
465 ASSERT_FALSE(grandChildOfRoot->renderSurface());
466
467 ASSERT_TRUE(renderSurface1->renderSurface());
468 ASSERT_FALSE(childOfRS1->renderSurface());
469 ASSERT_FALSE(grandChildOfRS1->renderSurface());
470
471 ASSERT_TRUE(renderSurface2->renderSurface());
472 ASSERT_FALSE(childOfRS2->renderSurface());
473 ASSERT_FALSE(grandChildOfRS2->renderSurface());
474
475 // Verify all renderTarget accessors
476 //
477 EXPECT_EQ(parent, parent->renderTarget());
478 EXPECT_EQ(parent, childOfRoot->renderTarget());
479 EXPECT_EQ(parent, grandChildOfRoot->renderTarget());
480
481 EXPECT_EQ(renderSurface1, renderSurface1->renderTarget());
482 EXPECT_EQ(renderSurface1, childOfRS1->renderTarget());
483 EXPECT_EQ(renderSurface1, grandChildOfRS1->renderTarget());
484
485 EXPECT_EQ(renderSurface2, renderSurface2->renderTarget());
486 EXPECT_EQ(renderSurface2, childOfRS2->renderTarget());
487 EXPECT_EQ(renderSurface2, grandChildOfRS2->renderTarget());
488
489 // Verify layer draw transforms
490 // note that draw transforms are described with respect to the nearest ancestor render surface
491 // but screen space transforms are described with respect to the root.
492 //
493 EXPECT_TRANSFORMATION_MATRIX_EQ(A, parent->drawTransform());
494 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, childOfRoot->drawTransform());
495 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, grandChildOfRoot->drawTransform());
496
497 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, renderSurface1->drawTransform());
498 EXPECT_TRANSFORMATION_MATRIX_EQ(B * A, childOfRS1->drawTransform());
499 EXPECT_TRANSFORMATION_MATRIX_EQ(B * A * B * A, grandChildOfRS1->drawTransform());
500
501 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, renderSurface2->drawTransform());
502 EXPECT_TRANSFORMATION_MATRIX_EQ(B * A, childOfRS2->drawTransform());
503 EXPECT_TRANSFORMATION_MATRIX_EQ(B * A * B * A, grandChildOfRS2->drawTransform());
504
505 // Verify layer screen-space transforms
506 //
507 EXPECT_TRANSFORMATION_MATRIX_EQ(A, parent->screenSpaceTransform());
508 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, childOfRoot->screenSpaceTransform());
509 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, grandChildOfRoot->screenSpaceTransform());
510
511 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, renderSurface1->screenSpaceTransform());
512 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, childOfRS1->screenSpaceTransform());
513 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A * B * A, grandChildOfRS1->screenSpaceTransform());
514
515 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, renderSurface2->screenSpaceTransform());
516 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A * B * A, childOfRS2->screenSpaceTransform());
517 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A * B * A * B * A, grandChildOfRS2->screenSpaceTransform());
518
519 // Verify render surface transforms.
520 //
521 // Draw transform of render surface 1 is described with respect to root.
522 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, renderSurface1->renderSurface()->drawTransform());
523 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * R, renderSurface1->renderSurface()->replicaDrawTransform());
524 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, renderSurface1->renderSurface()->screenSpaceTransform());
525 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * R, renderSurface1->renderSurface()->replicaScreenSpaceTransform());
526 // Draw transform of render surface 2 is described with respect to render surface 2.
527 EXPECT_TRANSFORMATION_MATRIX_EQ(B * A, renderSurface2->renderSurface()->drawTransform());
528 EXPECT_TRANSFORMATION_MATRIX_EQ(B * R, renderSurface2->renderSurface()->replicaDrawTransform());
529 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, renderSurface2->renderSurface()->screenSpaceTransform());
530 EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * R, renderSurface2->renderSurface()->replicaScreenSpaceTransform());
531
532 // Sanity check. If these fail there is probably a bug in the test itself.
533 // It is expected that we correctly set up transforms so that the y-component of the screen-space transform
534 // encodes the "depth" of the layer in the tree.
535 EXPECT_FLOAT_EQ(1, parent->screenSpaceTransform().m42());
536 EXPECT_FLOAT_EQ(2, childOfRoot->screenSpaceTransform().m42());
537 EXPECT_FLOAT_EQ(3, grandChildOfRoot->screenSpaceTransform().m42());
538
539 EXPECT_FLOAT_EQ(2, renderSurface1->screenSpaceTransform().m42());
540 EXPECT_FLOAT_EQ(3, childOfRS1->screenSpaceTransform().m42());
541 EXPECT_FLOAT_EQ(4, grandChildOfRS1->screenSpaceTransform().m42());
542
543 EXPECT_FLOAT_EQ(3, renderSurface2->screenSpaceTransform().m42());
544 EXPECT_FLOAT_EQ(4, childOfRS2->screenSpaceTransform().m42());
545 EXPECT_FLOAT_EQ(5, grandChildOfRS2->screenSpaceTransform().m42());
546}
547
548TEST(CCLayerTreeHostCommonTest, verifyTransformsForFlatteningLayer)
549{
550 // For layers that flatten their subtree, there should be an orthographic projection
551 // (for x and y values) in the middle of the transform sequence. Note that the way the
552 // code is currently implemented, it is not expected to use a canonical orthographic
553 // projection.
554
555 RefPtr<LayerChromium> root = LayerChromium::create();
556 RefPtr<LayerChromium> child = LayerChromium::create();
557 RefPtr<LayerChromiumWithForcedDrawsContent> grandChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
558
559 WebTransformationMatrix rotationAboutYAxis;
560 rotationAboutYAxis.rotate3d(0, 30, 0);
561
562 const WebTransformationMatrix identityMatrix;
563 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(100, 100), false);
564 setLayerPropertiesForTesting(child.get(), rotationAboutYAxis, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
565 setLayerPropertiesForTesting(grandChild.get(), rotationAboutYAxis, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
566
567 root->addChild(child);
568 child->addChild(grandChild);
569 child->setForceRenderSurface(true);
570
571 // No layers in this test should preserve 3d.
572 ASSERT_FALSE(root->preserves3D());
573 ASSERT_FALSE(child->preserves3D());
574 ASSERT_FALSE(grandChild->preserves3D());
575
576 WebTransformationMatrix expectedChildDrawTransform = rotationAboutYAxis;
577 WebTransformationMatrix expectedChildScreenSpaceTransform = rotationAboutYAxis;
578 WebTransformationMatrix expectedGrandChildDrawTransform = rotationAboutYAxis; // draws onto child's renderSurface
579 WebTransformationMatrix expectedGrandChildScreenSpaceTransform = rotationAboutYAxis.to2dTransform() * rotationAboutYAxis;
580
581 executeCalculateDrawTransformsAndVisibility(root.get());
582
583 // The child's drawTransform should have been taken by its surface.
584 ASSERT_TRUE(child->renderSurface());
585 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildDrawTransform, child->renderSurface()->drawTransform());
586 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildScreenSpaceTransform, child->renderSurface()->screenSpaceTransform());
587 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->drawTransform());
588 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildScreenSpaceTransform, child->screenSpaceTransform());
589 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildDrawTransform, grandChild->drawTransform());
590 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildScreenSpaceTransform, grandChild->screenSpaceTransform());
591}
592
593TEST(CCLayerTreeHostCommonTest, verifyTransformsForDegenerateIntermediateLayer)
594{
595 // A layer that is empty in one axis, but not the other, was accidentally skipping a necessary translation.
596 // Without that translation, the coordinate space of the layer's drawTransform is incorrect.
597 //
598 // Normally this isn't a problem, because the layer wouldn't be drawn anyway, but if that layer becomes a renderSurface, then
599 // its drawTransform is implicitly inherited by the rest of the subtree, which then is positioned incorrectly as a result.
600
601 RefPtr<LayerChromium> root = LayerChromium::create();
602 RefPtr<LayerChromium> child = LayerChromium::create();
603 RefPtr<LayerChromiumWithForcedDrawsContent> grandChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
604
605 // The child height is zero, but has non-zero width that should be accounted for while computing drawTransforms.
606 const WebTransformationMatrix identityMatrix;
607 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(100, 100), false);
608 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 0), false);
609 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
610
611 root->addChild(child);
612 child->addChild(grandChild);
613 child->setForceRenderSurface(true);
614
615 executeCalculateDrawTransformsAndVisibility(root.get());
616
617 ASSERT_TRUE(child->renderSurface());
618 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->renderSurface()->drawTransform()); // This is the real test, the rest are sanity checks.
619 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->drawTransform());
620 EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, grandChild->drawTransform());
621}
622
623TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceListForRenderSurfaceWithClippedLayer)
624{
625 RefPtr<LayerChromium> parent = LayerChromium::create();
626 RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
627 RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent());
628
629 const WebTransformationMatrix identityMatrix;
630 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
631 setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
632 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint(30, 30), IntSize(10, 10), false);
633
634 parent->addChild(renderSurface1);
[email protected]23bbb412012-08-30 20:03:38635 parent->setMasksToBounds(true);
[email protected]94f206c12012-08-25 00:09:14636 renderSurface1->addChild(child);
637 renderSurface1->setForceRenderSurface(true);
638
639 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
640 int dummyMaxTextureSize = 512;
641 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
642 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
643
644 // The child layer's content is entirely outside the parent's clip rect, so the intermediate
645 // render surface should not be listed here, even if it was forced to be created. Render surfaces without children or visible
646 // content are unexpected at draw time (e.g. we might try to create a content texture of size 0).
647 ASSERT_TRUE(parent->renderSurface());
648 ASSERT_FALSE(renderSurface1->renderSurface());
649 EXPECT_EQ(1U, renderSurfaceLayerList.size());
650}
651
652TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceListForTransparentChild)
653{
654 RefPtr<LayerChromium> parent = LayerChromium::create();
655 RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
656 RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent());
657
658 const WebTransformationMatrix identityMatrix;
659 setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
660 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
661
662 parent->addChild(renderSurface1);
663 renderSurface1->addChild(child);
664 renderSurface1->setForceRenderSurface(true);
665 renderSurface1->setOpacity(0);
666
667 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
668 int dummyMaxTextureSize = 512;
669 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
670 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
671
672 // Since the layer is transparent, renderSurface1->renderSurface() should not have gotten added anywhere.
673 // Also, the drawable content rect should not have been extended by the children.
674 ASSERT_TRUE(parent->renderSurface());
675 EXPECT_EQ(0U, parent->renderSurface()->layerList().size());
676 EXPECT_EQ(1U, renderSurfaceLayerList.size());
677 EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
678 EXPECT_EQ(IntRect(), parent->drawableContentRect());
679}
680
681TEST(CCLayerTreeHostCommonTest, verifyForceRenderSurface)
682{
683 RefPtr<LayerChromium> parent = LayerChromium::create();
684 RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
685 RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent());
686 renderSurface1->setForceRenderSurface(true);
687
688 const WebTransformationMatrix identityMatrix;
689 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
690 setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
691 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
692
693 parent->addChild(renderSurface1);
694 renderSurface1->addChild(child);
695
696 // Sanity check before the actual test
697 EXPECT_FALSE(parent->renderSurface());
698 EXPECT_FALSE(renderSurface1->renderSurface());
699
700 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
701 int dummyMaxTextureSize = 512;
702 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
703
704 // The root layer always creates a renderSurface
705 EXPECT_TRUE(parent->renderSurface());
706 EXPECT_TRUE(renderSurface1->renderSurface());
707 EXPECT_EQ(2U, renderSurfaceLayerList.size());
708
709 renderSurfaceLayerList.clear();
710 renderSurface1->setForceRenderSurface(false);
711 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
712 EXPECT_TRUE(parent->renderSurface());
713 EXPECT_FALSE(renderSurface1->renderSurface());
714 EXPECT_EQ(1U, renderSurfaceLayerList.size());
715}
716
717TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWithDirectContainer)
718{
719 // This test checks for correct scroll compensation when the fixed-position container
720 // is the direct parent of the fixed-position layer.
721
722 DebugScopedSetImplThread scopedImplThread;
723 OwnPtr<CCLayerImpl> root = createTreeForFixedPositionTests();
724 CCLayerImpl* child = root->children()[0].get();
725 CCLayerImpl* grandChild = child->children()[0].get();
726
727 child->setIsContainerForFixedPositionLayers(true);
728 grandChild->setFixedToContainerLayer(true);
729
730 // Case 1: scrollDelta of 0, 0
731 child->setScrollDelta(IntSize(0, 0));
732 executeCalculateDrawTransformsAndVisibility(root.get());
733
734 WebTransformationMatrix expectedChildTransform;
735 WebTransformationMatrix expectedGrandChildTransform = expectedChildTransform;
736
737 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
738 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
739
740 // Case 2: scrollDelta of 10, 10
741 child->setScrollDelta(IntSize(10, 10));
742 executeCalculateDrawTransformsAndVisibility(root.get());
743
744 // Here the child is affected by scrollDelta, but the fixed position grandChild should not be affected.
745 expectedChildTransform.makeIdentity();
746 expectedChildTransform.translate(-10, -10);
747
748 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
749 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
750}
751
752TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWithTransformedDirectContainer)
753{
754 // This test checks for correct scroll compensation when the fixed-position container
755 // is the direct parent of the fixed-position layer, but that container is transformed.
756 // In this case, the fixed position element inherits the container's transform,
757 // but the scrollDelta that has to be undone should not be affected by that transform.
758 //
759 // Transforms are in general non-commutative; using something like a non-uniform scale
760 // helps to verify that translations and non-uniform scales are applied in the correct
761 // order.
762
763 DebugScopedSetImplThread scopedImplThread;
764 OwnPtr<CCLayerImpl> root = createTreeForFixedPositionTests();
765 CCLayerImpl* child = root->children()[0].get();
766 CCLayerImpl* grandChild = child->children()[0].get();
767
768 // This scale will cause child and grandChild to be effectively 200 x 800 with respect to the renderTarget.
769 WebTransformationMatrix nonUniformScale;
770 nonUniformScale.scaleNonUniform(2, 8);
771 child->setTransform(nonUniformScale);
772
773 child->setIsContainerForFixedPositionLayers(true);
774 grandChild->setFixedToContainerLayer(true);
775
776 // Case 1: scrollDelta of 0, 0
777 child->setScrollDelta(IntSize(0, 0));
778 executeCalculateDrawTransformsAndVisibility(root.get());
779
780 WebTransformationMatrix expectedChildTransform;
781 expectedChildTransform.multiply(nonUniformScale);
782
783 WebTransformationMatrix expectedGrandChildTransform = expectedChildTransform;
784
785 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
786 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
787
788 // Case 2: scrollDelta of 10, 20
789 child->setScrollDelta(IntSize(10, 20));
790 executeCalculateDrawTransformsAndVisibility(root.get());
791
792 // The child should be affected by scrollDelta, but the fixed position grandChild should not be affected.
793 expectedChildTransform.makeIdentity();
794 expectedChildTransform.translate(-10, -20); // scrollDelta
795 expectedChildTransform.multiply(nonUniformScale);
796
797 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
798 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
799}
800
801TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWithDistantContainer)
802{
803 // This test checks for correct scroll compensation when the fixed-position container
804 // is NOT the direct parent of the fixed-position layer.
805 DebugScopedSetImplThread scopedImplThread;
806
807 OwnPtr<CCLayerImpl> root = createTreeForFixedPositionTests();
808 CCLayerImpl* child = root->children()[0].get();
809 CCLayerImpl* grandChild = child->children()[0].get();
810 CCLayerImpl* greatGrandChild = grandChild->children()[0].get();
811
812 child->setIsContainerForFixedPositionLayers(true);
813 grandChild->setPosition(FloatPoint(8, 6));
814 greatGrandChild->setFixedToContainerLayer(true);
815
816 // Case 1: scrollDelta of 0, 0
817 child->setScrollDelta(IntSize(0, 0));
818 executeCalculateDrawTransformsAndVisibility(root.get());
819
820 WebTransformationMatrix expectedChildTransform;
821 WebTransformationMatrix expectedGrandChildTransform;
822 expectedGrandChildTransform.translate(8, 6);
823
824 WebTransformationMatrix expectedGreatGrandChildTransform = expectedGrandChildTransform;
825
826 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
827 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
828 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildTransform, greatGrandChild->drawTransform());
829
830 // Case 2: scrollDelta of 10, 10
831 child->setScrollDelta(IntSize(10, 10));
832 executeCalculateDrawTransformsAndVisibility(root.get());
833
834 // Here the child and grandChild are affected by scrollDelta, but the fixed position greatGrandChild should not be affected.
835 expectedChildTransform.makeIdentity();
836 expectedChildTransform.translate(-10, -10);
837 expectedGrandChildTransform.makeIdentity();
838 expectedGrandChildTransform.translate(-2, -4);
839 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
840 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
841 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildTransform, greatGrandChild->drawTransform());
842}
843
844TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWithDistantContainerAndTransforms)
845{
846 // This test checks for correct scroll compensation when the fixed-position container
847 // is NOT the direct parent of the fixed-position layer, and the hierarchy has various
848 // transforms that have to be processed in the correct order.
849 DebugScopedSetImplThread scopedImplThread;
850
851 OwnPtr<CCLayerImpl> root = createTreeForFixedPositionTests();
852 CCLayerImpl* child = root->children()[0].get();
853 CCLayerImpl* grandChild = child->children()[0].get();
854 CCLayerImpl* greatGrandChild = grandChild->children()[0].get();
855
856 WebTransformationMatrix rotationAboutZ;
857 rotationAboutZ.rotate3d(0, 0, 90);
858
859 child->setIsContainerForFixedPositionLayers(true);
860 child->setTransform(rotationAboutZ);
861 grandChild->setPosition(FloatPoint(8, 6));
862 grandChild->setTransform(rotationAboutZ);
863 greatGrandChild->setFixedToContainerLayer(true); // greatGrandChild is positioned upside-down with respect to the renderTarget.
864
865 // Case 1: scrollDelta of 0, 0
866 child->setScrollDelta(IntSize(0, 0));
867 executeCalculateDrawTransformsAndVisibility(root.get());
868
869 WebTransformationMatrix expectedChildTransform;
870 expectedChildTransform.multiply(rotationAboutZ);
871
872 WebTransformationMatrix expectedGrandChildTransform;
873 expectedGrandChildTransform.multiply(rotationAboutZ); // child's local transform is inherited
874 expectedGrandChildTransform.translate(8, 6); // translation because of position occurs before layer's local transform.
875 expectedGrandChildTransform.multiply(rotationAboutZ); // grandChild's local transform
876
877 WebTransformationMatrix expectedGreatGrandChildTransform = expectedGrandChildTransform;
878
879 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
880 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
881 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildTransform, greatGrandChild->drawTransform());
882
883 // Case 2: scrollDelta of 10, 20
884 child->setScrollDelta(IntSize(10, 20));
885 executeCalculateDrawTransformsAndVisibility(root.get());
886
887 // Here the child and grandChild are affected by scrollDelta, but the fixed position greatGrandChild should not be affected.
888 expectedChildTransform.makeIdentity();
889 expectedChildTransform.translate(-10, -20); // scrollDelta
890 expectedChildTransform.multiply(rotationAboutZ);
891
892 expectedGrandChildTransform.makeIdentity();
893 expectedGrandChildTransform.translate(-10, -20); // child's scrollDelta is inherited
894 expectedGrandChildTransform.multiply(rotationAboutZ); // child's local transform is inherited
895 expectedGrandChildTransform.translate(8, 6); // translation because of position occurs before layer's local transform.
896 expectedGrandChildTransform.multiply(rotationAboutZ); // grandChild's local transform
897
898 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
899 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
900 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildTransform, greatGrandChild->drawTransform());
901}
902
903TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWithMultipleScrollDeltas)
904{
905 // This test checks for correct scroll compensation when the fixed-position container
906 // has multiple ancestors that have nonzero scrollDelta before reaching the space where the layer is fixed.
907 // In this test, each scrollDelta occurs in a different space because of each layer's local transform.
908 // This test checks for correct scroll compensation when the fixed-position container
909 // is NOT the direct parent of the fixed-position layer, and the hierarchy has various
910 // transforms that have to be processed in the correct order.
911 DebugScopedSetImplThread scopedImplThread;
912
913 OwnPtr<CCLayerImpl> root = createTreeForFixedPositionTests();
914 CCLayerImpl* child = root->children()[0].get();
915 CCLayerImpl* grandChild = child->children()[0].get();
916 CCLayerImpl* greatGrandChild = grandChild->children()[0].get();
917
918 WebTransformationMatrix rotationAboutZ;
919 rotationAboutZ.rotate3d(0, 0, 90);
920
921 child->setIsContainerForFixedPositionLayers(true);
922 child->setTransform(rotationAboutZ);
923 grandChild->setPosition(FloatPoint(8, 6));
924 grandChild->setTransform(rotationAboutZ);
925 greatGrandChild->setFixedToContainerLayer(true); // greatGrandChild is positioned upside-down with respect to the renderTarget.
926
927 // Case 1: scrollDelta of 0, 0
928 child->setScrollDelta(IntSize(0, 0));
929 executeCalculateDrawTransformsAndVisibility(root.get());
930
931 WebTransformationMatrix expectedChildTransform;
932 expectedChildTransform.multiply(rotationAboutZ);
933
934 WebTransformationMatrix expectedGrandChildTransform;
935 expectedGrandChildTransform.multiply(rotationAboutZ); // child's local transform is inherited
936 expectedGrandChildTransform.translate(8, 6); // translation because of position occurs before layer's local transform.
937 expectedGrandChildTransform.multiply(rotationAboutZ); // grandChild's local transform
938
939 WebTransformationMatrix expectedGreatGrandChildTransform = expectedGrandChildTransform;
940
941 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
942 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
943 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildTransform, greatGrandChild->drawTransform());
944
945 // Case 2: scrollDelta of 10, 20
946 child->setScrollDelta(IntSize(10, 0));
947 grandChild->setScrollDelta(IntSize(5, 0));
948 executeCalculateDrawTransformsAndVisibility(root.get());
949
950 // Here the child and grandChild are affected by scrollDelta, but the fixed position greatGrandChild should not be affected.
951 expectedChildTransform.makeIdentity();
952 expectedChildTransform.translate(-10, 0); // scrollDelta
953 expectedChildTransform.multiply(rotationAboutZ);
954
955 expectedGrandChildTransform.makeIdentity();
956 expectedGrandChildTransform.translate(-10, 0); // child's scrollDelta is inherited
957 expectedGrandChildTransform.multiply(rotationAboutZ); // child's local transform is inherited
958 expectedGrandChildTransform.translate(-5, 0); // grandChild's scrollDelta
959 expectedGrandChildTransform.translate(8, 6); // translation because of position occurs before layer's local transform.
960 expectedGrandChildTransform.multiply(rotationAboutZ); // grandChild's local transform
961
962 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
963 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
964 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildTransform, greatGrandChild->drawTransform());
965}
966
967TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWithIntermediateSurfaceAndTransforms)
968{
969 // This test checks for correct scroll compensation when the fixed-position container
970 // contributes to a different renderSurface than the fixed-position layer. In this
971 // case, the surface drawTransforms also have to be accounted for when checking the
972 // scrollDelta.
973 DebugScopedSetImplThread scopedImplThread;
974
975 OwnPtr<CCLayerImpl> root = createTreeForFixedPositionTests();
976 CCLayerImpl* child = root->children()[0].get();
977 CCLayerImpl* grandChild = child->children()[0].get();
978 CCLayerImpl* greatGrandChild = grandChild->children()[0].get();
979
980 child->setIsContainerForFixedPositionLayers(true);
981 grandChild->setPosition(FloatPoint(8, 6));
982 grandChild->setForceRenderSurface(true);
983 greatGrandChild->setFixedToContainerLayer(true);
984 greatGrandChild->setDrawsContent(true);
985
986 WebTransformationMatrix rotationAboutZ;
987 rotationAboutZ.rotate3d(0, 0, 90);
988 grandChild->setTransform(rotationAboutZ);
989
990 // Case 1: scrollDelta of 0, 0
991 child->setScrollDelta(IntSize(0, 0));
992 executeCalculateDrawTransformsAndVisibility(root.get());
993
994 WebTransformationMatrix expectedChildTransform;
995 WebTransformationMatrix expectedSurfaceDrawTransform;
996 expectedSurfaceDrawTransform.translate(8, 6);
997 expectedSurfaceDrawTransform.multiply(rotationAboutZ);
998 WebTransformationMatrix expectedGrandChildTransform;
999 WebTransformationMatrix expectedGreatGrandChildTransform;
1000 ASSERT_TRUE(grandChild->renderSurface());
1001 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
1002 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedSurfaceDrawTransform, grandChild->renderSurface()->drawTransform());
1003 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
1004 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildTransform, greatGrandChild->drawTransform());
1005
1006 // Case 2: scrollDelta of 10, 30
1007 child->setScrollDelta(IntSize(10, 30));
1008 executeCalculateDrawTransformsAndVisibility(root.get());
1009
1010 // Here the grandChild remains unchanged, because it scrolls along with the
1011 // renderSurface, and the translation is actually in the renderSurface. But, the fixed
1012 // position greatGrandChild is more awkward: its actually being drawn with respect to
1013 // the renderSurface, but it needs to remain fixed with resepct to a container beyond
1014 // that surface. So, the net result is that, unlike previous tests where the fixed
1015 // position layer's transform remains unchanged, here the fixed position layer's
1016 // transform explicitly contains the translation that cancels out the scroll.
1017 expectedChildTransform.makeIdentity();
1018 expectedChildTransform.translate(-10, -30); // scrollDelta
1019
1020 expectedSurfaceDrawTransform.makeIdentity();
1021 expectedSurfaceDrawTransform.translate(-10, -30); // scrollDelta
1022 expectedSurfaceDrawTransform.translate(8, 6);
1023 expectedSurfaceDrawTransform.multiply(rotationAboutZ);
1024
1025 // The rotation and its inverse are needed to place the scrollDelta compensation in
1026 // the correct space. This test will fail if the rotation/inverse are backwards, too,
1027 // so it requires perfect order of operations.
1028 expectedGreatGrandChildTransform.makeIdentity();
1029 expectedGreatGrandChildTransform.multiply(rotationAboutZ.inverse());
1030 expectedGreatGrandChildTransform.translate(10, 30); // explicit canceling out the scrollDelta that gets embedded in the fixed position layer's surface.
1031 expectedGreatGrandChildTransform.multiply(rotationAboutZ);
1032
1033 ASSERT_TRUE(grandChild->renderSurface());
1034 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
1035 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedSurfaceDrawTransform, grandChild->renderSurface()->drawTransform());
1036 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
1037 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildTransform, greatGrandChild->drawTransform());
1038}
1039
1040TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWithMultipleIntermediateSurfaces)
1041{
1042 // This test checks for correct scroll compensation when the fixed-position container
1043 // contributes to a different renderSurface than the fixed-position layer, with
1044 // additional renderSurfaces in-between. This checks that the conversion to ancestor
1045 // surfaces is accumulated properly in the final matrix transform.
1046 DebugScopedSetImplThread scopedImplThread;
1047
1048 OwnPtr<CCLayerImpl> root = createTreeForFixedPositionTests();
1049 CCLayerImpl* child = root->children()[0].get();
1050 CCLayerImpl* grandChild = child->children()[0].get();
1051 CCLayerImpl* greatGrandChild = grandChild->children()[0].get();
1052
1053 // Add one more layer to the test tree for this scenario.
1054 {
1055 WebTransformationMatrix identity;
1056 OwnPtr<CCLayerImpl> fixedPositionChild = CCLayerImpl::create(5);
1057 setLayerPropertiesForTesting(fixedPositionChild.get(), identity, identity, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
1058 greatGrandChild->addChild(fixedPositionChild.release());
1059 }
1060 CCLayerImpl* fixedPositionChild = greatGrandChild->children()[0].get();
1061
1062 // Actually set up the scenario here.
1063 child->setIsContainerForFixedPositionLayers(true);
1064 grandChild->setPosition(FloatPoint(8, 6));
1065 grandChild->setForceRenderSurface(true);
1066 greatGrandChild->setPosition(FloatPoint(40, 60));
1067 greatGrandChild->setForceRenderSurface(true);
1068 fixedPositionChild->setFixedToContainerLayer(true);
1069 fixedPositionChild->setDrawsContent(true);
1070
1071 // The additional rotations, which are non-commutative with translations, help to
1072 // verify that we have correct order-of-operations in the final scroll compensation.
1073 // Note that rotating about the center of the layer ensures we do not accidentally
1074 // clip away layers that we want to test.
1075 WebTransformationMatrix rotationAboutZ;
1076 rotationAboutZ.translate(50, 50);
1077 rotationAboutZ.rotate3d(0, 0, 90);
1078 rotationAboutZ.translate(-50, -50);
1079 grandChild->setTransform(rotationAboutZ);
1080 greatGrandChild->setTransform(rotationAboutZ);
1081
1082 // Case 1: scrollDelta of 0, 0
1083 child->setScrollDelta(IntSize(0, 0));
1084 executeCalculateDrawTransformsAndVisibility(root.get());
1085
1086 WebTransformationMatrix expectedChildTransform;
1087
1088 WebTransformationMatrix expectedGrandChildSurfaceDrawTransform;
1089 expectedGrandChildSurfaceDrawTransform.translate(8, 6);
1090 expectedGrandChildSurfaceDrawTransform.multiply(rotationAboutZ);
1091
1092 WebTransformationMatrix expectedGrandChildTransform;
1093
1094 WebTransformationMatrix expectedGreatGrandChildSurfaceDrawTransform;
1095 expectedGreatGrandChildSurfaceDrawTransform.translate(40, 60);
1096 expectedGreatGrandChildSurfaceDrawTransform.multiply(rotationAboutZ);
1097
1098 WebTransformationMatrix expectedGreatGrandChildTransform;
1099
1100 WebTransformationMatrix expectedFixedPositionChildTransform;
1101
1102 ASSERT_TRUE(grandChild->renderSurface());
1103 ASSERT_TRUE(greatGrandChild->renderSurface());
1104 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
1105 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildSurfaceDrawTransform, grandChild->renderSurface()->drawTransform());
1106 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
1107 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildSurfaceDrawTransform, greatGrandChild->renderSurface()->drawTransform());
1108 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildTransform, greatGrandChild->drawTransform());
1109 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedFixedPositionChildTransform, fixedPositionChild->drawTransform());
1110
1111 // Case 2: scrollDelta of 10, 30
1112 child->setScrollDelta(IntSize(10, 30));
1113 executeCalculateDrawTransformsAndVisibility(root.get());
1114
1115 expectedChildTransform.makeIdentity();
1116 expectedChildTransform.translate(-10, -30); // scrollDelta
1117
1118 expectedGrandChildSurfaceDrawTransform.makeIdentity();
1119 expectedGrandChildSurfaceDrawTransform.translate(-10, -30); // scrollDelta
1120 expectedGrandChildSurfaceDrawTransform.translate(8, 6);
1121 expectedGrandChildSurfaceDrawTransform.multiply(rotationAboutZ);
1122
1123 // grandChild, greatGrandChild, and greatGrandChild's surface are not expected to
1124 // change, since they are all not fixed, and they are all drawn with respect to
1125 // grandChild's surface that already has the scrollDelta accounted for.
1126
1127 // But the great-great grandchild, "fixedPositionChild", should have a transform that explicitly cancels out the scrollDelta.
1128 // The expected transform is:
1129 // compoundDrawTransform.inverse() * translate(positive scrollDelta) * compoundOriginTransform
1130 WebTransformationMatrix compoundDrawTransform; // transform from greatGrandChildSurface's origin to the root surface.
1131 compoundDrawTransform.translate(8, 6); // origin translation of grandChild
1132 compoundDrawTransform.multiply(rotationAboutZ); // rotation of grandChild
1133 compoundDrawTransform.translate(40, 60); // origin translation of greatGrandChild
1134 compoundDrawTransform.multiply(rotationAboutZ); // rotation of greatGrandChild
1135
1136 expectedFixedPositionChildTransform.makeIdentity();
1137 expectedFixedPositionChildTransform.multiply(compoundDrawTransform.inverse());
1138 expectedFixedPositionChildTransform.translate(10, 30); // explicit canceling out the scrollDelta that gets embedded in the fixed position layer's surface.
1139 expectedFixedPositionChildTransform.multiply(compoundDrawTransform);
1140
1141 ASSERT_TRUE(grandChild->renderSurface());
1142 ASSERT_TRUE(greatGrandChild->renderSurface());
1143 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
1144 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildSurfaceDrawTransform, grandChild->renderSurface()->drawTransform());
1145 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
1146 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildSurfaceDrawTransform, greatGrandChild->renderSurface()->drawTransform());
1147 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGreatGrandChildTransform, greatGrandChild->drawTransform());
1148 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedFixedPositionChildTransform, fixedPositionChild->drawTransform());
1149}
1150
1151TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerWithContainerLayerThatHasSurface)
1152{
1153 // This test checks for correct scroll compensation when the fixed-position container
1154 // itself has a renderSurface. In this case, the container layer should be treated
1155 // like a layer that contributes to a renderTarget, and that renderTarget
1156 // is completely irrelevant; it should not affect the scroll compensation.
1157 DebugScopedSetImplThread scopedImplThread;
1158
1159 OwnPtr<CCLayerImpl> root = createTreeForFixedPositionTests();
1160 CCLayerImpl* child = root->children()[0].get();
1161 CCLayerImpl* grandChild = child->children()[0].get();
1162
1163 child->setIsContainerForFixedPositionLayers(true);
1164 child->setForceRenderSurface(true);
1165 grandChild->setFixedToContainerLayer(true);
1166 grandChild->setDrawsContent(true);
1167
1168 // Case 1: scrollDelta of 0, 0
1169 child->setScrollDelta(IntSize(0, 0));
1170 executeCalculateDrawTransformsAndVisibility(root.get());
1171
1172 WebTransformationMatrix expectedSurfaceDrawTransform;
1173 expectedSurfaceDrawTransform.translate(0, 0);
1174 WebTransformationMatrix expectedChildTransform;
1175 WebTransformationMatrix expectedGrandChildTransform;
1176 ASSERT_TRUE(child->renderSurface());
1177 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedSurfaceDrawTransform, child->renderSurface()->drawTransform());
1178 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
1179 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
1180
1181 // Case 2: scrollDelta of 10, 10
1182 child->setScrollDelta(IntSize(10, 10));
1183 executeCalculateDrawTransformsAndVisibility(root.get());
1184
1185 // The surface is translated by scrollDelta, the child transform doesn't change
1186 // because it scrolls along with the surface, but the fixed position grandChild
1187 // needs to compensate for the scroll translation.
1188 expectedSurfaceDrawTransform.makeIdentity();
1189 expectedSurfaceDrawTransform.translate(-10, -10);
1190 expectedGrandChildTransform.makeIdentity();
1191 expectedGrandChildTransform.translate(10, 10);
1192
1193 ASSERT_TRUE(child->renderSurface());
1194 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedSurfaceDrawTransform, child->renderSurface()->drawTransform());
1195 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
1196 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
1197}
1198
1199TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerThatIsAlsoFixedPositionContainer)
1200{
1201 // This test checks the scenario where a fixed-position layer also happens to be a
1202 // container itself for a descendant fixed position layer. In particular, the layer
1203 // should not accidentally be fixed to itself.
1204 DebugScopedSetImplThread scopedImplThread;
1205
1206 OwnPtr<CCLayerImpl> root = createTreeForFixedPositionTests();
1207 CCLayerImpl* child = root->children()[0].get();
1208 CCLayerImpl* grandChild = child->children()[0].get();
1209
1210 child->setIsContainerForFixedPositionLayers(true);
1211 grandChild->setFixedToContainerLayer(true);
1212
1213 // This should not confuse the grandChild. If correct, the grandChild would still be considered fixed to its container (i.e. "child").
1214 grandChild->setIsContainerForFixedPositionLayers(true);
1215
1216 // Case 1: scrollDelta of 0, 0
1217 child->setScrollDelta(IntSize(0, 0));
1218 executeCalculateDrawTransformsAndVisibility(root.get());
1219
1220 WebTransformationMatrix expectedChildTransform;
1221 WebTransformationMatrix expectedGrandChildTransform;
1222 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
1223 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
1224
1225 // Case 2: scrollDelta of 10, 10
1226 child->setScrollDelta(IntSize(10, 10));
1227 executeCalculateDrawTransformsAndVisibility(root.get());
1228
1229 // Here the child is affected by scrollDelta, but the fixed position grandChild should not be affected.
1230 expectedChildTransform.makeIdentity();
1231 expectedChildTransform.translate(-10, -10);
1232 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
1233 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
1234}
1235
1236TEST(CCLayerTreeHostCommonTest, verifyScrollCompensationForFixedPositionLayerThatHasNoContainer)
1237{
1238 // This test checks scroll compensation when a fixed-position layer does not find any
1239 // ancestor that is a "containerForFixedPositionLayers". In this situation, the layer should
1240 // be fixed to the viewport -- not the rootLayer, which may have transforms of its own.
1241 DebugScopedSetImplThread scopedImplThread;
1242
1243 OwnPtr<CCLayerImpl> root = createTreeForFixedPositionTests();
1244 CCLayerImpl* child = root->children()[0].get();
1245 CCLayerImpl* grandChild = child->children()[0].get();
1246
1247 WebTransformationMatrix rotationByZ;
1248 rotationByZ.rotate3d(0, 0, 90);
1249
1250 root->setTransform(rotationByZ);
1251 grandChild->setFixedToContainerLayer(true);
1252
1253 // Case 1: root scrollDelta of 0, 0
1254 root->setScrollDelta(IntSize(0, 0));
1255 executeCalculateDrawTransformsAndVisibility(root.get());
1256
1257 WebTransformationMatrix expectedChildTransform;
1258 expectedChildTransform.multiply(rotationByZ);
1259
1260 WebTransformationMatrix expectedGrandChildTransform;
1261 expectedGrandChildTransform.multiply(rotationByZ);
1262
1263 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
1264 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
1265
1266 // Case 2: root scrollDelta of 10, 10
1267 root->setScrollDelta(IntSize(10, 10));
1268 executeCalculateDrawTransformsAndVisibility(root.get());
1269
1270 // Here the child is affected by scrollDelta, but the fixed position grandChild should not be affected.
1271 expectedChildTransform.makeIdentity();
1272 expectedChildTransform.translate(-10, -10); // the scrollDelta
1273 expectedChildTransform.multiply(rotationByZ);
1274
1275 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
1276 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedGrandChildTransform, grandChild->drawTransform());
1277}
1278
1279TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces)
1280{
1281 // The entire subtree of layers that are outside the clipRect should be culled away,
1282 // and should not affect the renderSurfaceLayerList.
1283 //
1284 // The test tree is set up as follows:
1285 // - all layers except the leafNodes are forced to be a new renderSurface that have something to draw.
1286 // - parent is a large container layer.
1287 // - child has masksToBounds=true to cause clipping.
1288 // - grandChild is positioned outside of the child's bounds
1289 // - greatGrandChild is also kept outside child's bounds.
1290 //
1291 // In this configuration, grandChild and greatGrandChild are completely outside the
1292 // clipRect, and they should never get scheduled on the list of renderSurfaces.
1293 //
1294
1295 const WebTransformationMatrix identityMatrix;
1296 RefPtr<LayerChromium> parent = LayerChromium::create();
1297 RefPtr<LayerChromium> child = LayerChromium::create();
1298 RefPtr<LayerChromium> grandChild = LayerChromium::create();
1299 RefPtr<LayerChromium> greatGrandChild = LayerChromium::create();
1300 RefPtr<LayerChromiumWithForcedDrawsContent> leafNode1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1301 RefPtr<LayerChromiumWithForcedDrawsContent> leafNode2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1302 parent->addChild(child);
1303 child->addChild(grandChild);
1304 grandChild->addChild(greatGrandChild);
1305
1306 // leafNode1 ensures that parent and child are kept on the renderSurfaceLayerList,
1307 // even though grandChild and greatGrandChild should be clipped.
1308 child->addChild(leafNode1);
1309 greatGrandChild->addChild(leafNode2);
1310
1311 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
1312 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
1313 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(45, 45), IntSize(10, 10), false);
1314 setLayerPropertiesForTesting(greatGrandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
1315 setLayerPropertiesForTesting(leafNode1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
1316 setLayerPropertiesForTesting(leafNode2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
1317
1318 child->setMasksToBounds(true);
1319 child->setOpacity(0.4f);
1320 grandChild->setOpacity(0.5);
1321 greatGrandChild->setOpacity(0.4f);
1322
1323 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
1324 int dummyMaxTextureSize = 512;
1325 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
1326 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
1327
1328
1329 ASSERT_EQ(2U, renderSurfaceLayerList.size());
1330 EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
1331 EXPECT_EQ(child->id(), renderSurfaceLayerList[1]->id());
1332}
1333
1334TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsSurfaceWithoutVisibleContent)
1335{
1336 // When a renderSurface has a clipRect, it is used to clip the contentRect
1337 // of the surface. When the renderSurface is animating its transforms, then
1338 // the contentRect's position in the clipRect is not defined on the main
1339 // thread, and its contentRect should not be clipped.
1340
1341 // The test tree is set up as follows:
1342 // - parent is a container layer that masksToBounds=true to cause clipping.
1343 // - child is a renderSurface, which has a clipRect set to the bounds of the parent.
1344 // - grandChild is a renderSurface, and the only visible content in child. It is positioned outside of the clipRect from parent.
1345
1346 // In this configuration, grandChild should be outside the clipped
1347 // contentRect of the child, making grandChild not appear in the
1348 // renderSurfaceLayerList. However, when we place an animation on the child,
1349 // this clipping should be avoided and we should keep the grandChild
1350 // in the renderSurfaceLayerList.
1351
1352 const WebTransformationMatrix identityMatrix;
1353 RefPtr<LayerChromium> parent = LayerChromium::create();
1354 RefPtr<LayerChromium> child = LayerChromium::create();
1355 RefPtr<LayerChromium> grandChild = LayerChromium::create();
1356 RefPtr<LayerChromiumWithForcedDrawsContent> leafNode = adoptRef(new LayerChromiumWithForcedDrawsContent());
1357 parent->addChild(child);
1358 child->addChild(grandChild);
1359 grandChild->addChild(leafNode);
1360
1361 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
1362 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
1363 setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(200, 200), IntSize(10, 10), false);
1364 setLayerPropertiesForTesting(leafNode.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
1365
1366 parent->setMasksToBounds(true);
1367 child->setOpacity(0.4f);
1368 grandChild->setOpacity(0.4f);
1369
1370 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
1371 int dummyMaxTextureSize = 512;
1372 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
1373
1374 // Without an animation, we should cull child and grandChild from the renderSurfaceLayerList.
1375 ASSERT_EQ(1U, renderSurfaceLayerList.size());
1376 EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
1377
1378 // Now put an animating transform on child.
1379 addAnimatedTransformToController(*child->layerAnimationController(), 10, 30, 0);
1380
1381 parent->clearRenderSurface();
1382 child->clearRenderSurface();
1383 grandChild->clearRenderSurface();
1384 renderSurfaceLayerList.clear();
1385
1386 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
1387
1388 // With an animating transform, we should keep child and grandChild in the renderSurfaceLayerList.
1389 ASSERT_EQ(3U, renderSurfaceLayerList.size());
1390 EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
1391 EXPECT_EQ(child->id(), renderSurfaceLayerList[1]->id());
1392 EXPECT_EQ(grandChild->id(), renderSurfaceLayerList[2]->id());
1393}
1394
1395TEST(CCLayerTreeHostCommonTest, verifyDrawableContentRectForLayers)
1396{
1397 // Verify that layers get the appropriate drawableContentRect when their parent masksToBounds is true.
1398 //
1399 // grandChild1 - completely inside the region; drawableContentRect should be the layer rect expressed in target space.
1400 // grandChild2 - partially clipped but NOT masksToBounds; the clipRect will be the intersection of layerBounds and the mask region.
1401 // grandChild3 - partially clipped and masksToBounds; the drawableContentRect will still be the intersection of layerBounds and the mask region.
1402 // grandChild4 - outside parent's clipRect; the drawableContentRect should be empty.
1403 //
1404
1405 const WebTransformationMatrix identityMatrix;
1406 RefPtr<LayerChromium> parent = LayerChromium::create();
1407 RefPtr<LayerChromium> child = LayerChromium::create();
1408 RefPtr<LayerChromium> grandChild1 = LayerChromium::create();
1409 RefPtr<LayerChromium> grandChild2 = LayerChromium::create();
1410 RefPtr<LayerChromium> grandChild3 = LayerChromium::create();
1411 RefPtr<LayerChromium> grandChild4 = LayerChromium::create();
1412
1413 parent->addChild(child);
1414 child->addChild(grandChild1);
1415 child->addChild(grandChild2);
1416 child->addChild(grandChild3);
1417 child->addChild(grandChild4);
1418
1419 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
1420 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
1421 setLayerPropertiesForTesting(grandChild1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(5, 5), IntSize(10, 10), false);
1422 setLayerPropertiesForTesting(grandChild2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(15, 15), IntSize(10, 10), false);
1423 setLayerPropertiesForTesting(grandChild3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(15, 15), IntSize(10, 10), false);
1424 setLayerPropertiesForTesting(grandChild4.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(45, 45), IntSize(10, 10), false);
1425
1426 child->setMasksToBounds(true);
1427 grandChild3->setMasksToBounds(true);
1428
1429 // Force everyone to be a render surface.
1430 child->setOpacity(0.4f);
1431 grandChild1->setOpacity(0.5);
1432 grandChild2->setOpacity(0.5);
1433 grandChild3->setOpacity(0.5);
1434 grandChild4->setOpacity(0.5);
1435
1436 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
1437 int dummyMaxTextureSize = 512;
1438 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
1439 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
1440
[email protected]022cbf162012-09-01 01:15:171441 EXPECT_RECT_EQ(IntRect(IntPoint(5, 5), IntSize(10, 10)), grandChild1->drawableContentRect());
1442 EXPECT_RECT_EQ(IntRect(IntPoint(15, 15), IntSize(5, 5)), grandChild3->drawableContentRect());
1443 EXPECT_RECT_EQ(IntRect(IntPoint(15, 15), IntSize(5, 5)), grandChild3->drawableContentRect());
[email protected]94f206c12012-08-25 00:09:141444 EXPECT_TRUE(grandChild4->drawableContentRect().isEmpty());
1445}
1446
1447TEST(CCLayerTreeHostCommonTest, verifyClipRectIsPropagatedCorrectlyToSurfaces)
1448{
1449 // Verify that renderSurfaces (and their layers) get the appropriate clipRects when their parent masksToBounds is true.
1450 //
1451 // Layers that own renderSurfaces (at least for now) do not inherit any clipping;
1452 // instead the surface will enforce the clip for the entire subtree. They may still
1453 // have a clipRect of their own layer bounds, however, if masksToBounds was true.
1454 //
1455
1456 const WebTransformationMatrix identityMatrix;
1457 RefPtr<LayerChromium> parent = LayerChromium::create();
1458 RefPtr<LayerChromium> child = LayerChromium::create();
1459 RefPtr<LayerChromium> grandChild1 = LayerChromium::create();
1460 RefPtr<LayerChromium> grandChild2 = LayerChromium::create();
1461 RefPtr<LayerChromium> grandChild3 = LayerChromium::create();
1462 RefPtr<LayerChromium> grandChild4 = LayerChromium::create();
1463 RefPtr<LayerChromiumWithForcedDrawsContent> leafNode1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1464 RefPtr<LayerChromiumWithForcedDrawsContent> leafNode2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1465 RefPtr<LayerChromiumWithForcedDrawsContent> leafNode3 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1466 RefPtr<LayerChromiumWithForcedDrawsContent> leafNode4 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1467
1468 parent->addChild(child);
1469 child->addChild(grandChild1);
1470 child->addChild(grandChild2);
1471 child->addChild(grandChild3);
1472 child->addChild(grandChild4);
1473
1474 // the leaf nodes ensure that these grandChildren become renderSurfaces for this test.
1475 grandChild1->addChild(leafNode1);
1476 grandChild2->addChild(leafNode2);
1477 grandChild3->addChild(leafNode3);
1478 grandChild4->addChild(leafNode4);
1479
1480 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
1481 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
1482 setLayerPropertiesForTesting(grandChild1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(5, 5), IntSize(10, 10), false);
1483 setLayerPropertiesForTesting(grandChild2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(15, 15), IntSize(10, 10), false);
1484 setLayerPropertiesForTesting(grandChild3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(15, 15), IntSize(10, 10), false);
1485 setLayerPropertiesForTesting(grandChild4.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(45, 45), IntSize(10, 10), false);
1486 setLayerPropertiesForTesting(leafNode1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
1487 setLayerPropertiesForTesting(leafNode2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
1488 setLayerPropertiesForTesting(leafNode3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
1489 setLayerPropertiesForTesting(leafNode4.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
1490
1491 child->setMasksToBounds(true);
1492 grandChild3->setMasksToBounds(true);
1493 grandChild4->setMasksToBounds(true);
1494
1495 // Force everyone to be a render surface.
1496 child->setOpacity(0.4f);
1497 grandChild1->setOpacity(0.5);
1498 grandChild2->setOpacity(0.5);
1499 grandChild3->setOpacity(0.5);
1500 grandChild4->setOpacity(0.5);
1501
1502 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
1503 int dummyMaxTextureSize = 512;
1504 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
1505 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
1506
1507 ASSERT_TRUE(grandChild1->renderSurface());
1508 ASSERT_TRUE(grandChild2->renderSurface());
1509 ASSERT_TRUE(grandChild3->renderSurface());
1510 EXPECT_FALSE(grandChild4->renderSurface()); // Because grandChild4 is entirely clipped, it is expected to not have a renderSurface.
1511
1512 // Surfaces are clipped by their parent, but un-affected by the owning layer's masksToBounds.
[email protected]022cbf162012-09-01 01:15:171513 EXPECT_RECT_EQ(IntRect(IntPoint(0, 0), IntSize(20, 20)), grandChild1->renderSurface()->clipRect());
1514 EXPECT_RECT_EQ(IntRect(IntPoint(0, 0), IntSize(20, 20)), grandChild2->renderSurface()->clipRect());
1515 EXPECT_RECT_EQ(IntRect(IntPoint(0, 0), IntSize(20, 20)), grandChild3->renderSurface()->clipRect());
[email protected]94f206c12012-08-25 00:09:141516}
1517
1518TEST(CCLayerTreeHostCommonTest, verifyAnimationsForRenderSurfaceHierarchy)
1519{
1520 RefPtr<LayerChromium> parent = LayerChromium::create();
1521 RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
1522 RefPtr<LayerChromium> renderSurface2 = LayerChromium::create();
1523 RefPtr<LayerChromium> childOfRoot = LayerChromium::create();
1524 RefPtr<LayerChromium> childOfRS1 = LayerChromium::create();
1525 RefPtr<LayerChromium> childOfRS2 = LayerChromium::create();
1526 RefPtr<LayerChromium> grandChildOfRoot = LayerChromium::create();
1527 RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1528 RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1529 parent->addChild(renderSurface1);
1530 parent->addChild(childOfRoot);
1531 renderSurface1->addChild(childOfRS1);
1532 renderSurface1->addChild(renderSurface2);
1533 renderSurface2->addChild(childOfRS2);
1534 childOfRoot->addChild(grandChildOfRoot);
1535 childOfRS1->addChild(grandChildOfRS1);
1536 childOfRS2->addChild(grandChildOfRS2);
1537
1538 // Make our render surfaces.
1539 renderSurface1->setForceRenderSurface(true);
1540 renderSurface2->setForceRenderSurface(true);
1541
1542 // Put an animated opacity on the render surface.
1543 addOpacityTransitionToController(*renderSurface1->layerAnimationController(), 10, 1, 0, false);
1544
1545 // Also put an animated opacity on a layer without descendants.
1546 addOpacityTransitionToController(*grandChildOfRoot->layerAnimationController(), 10, 1, 0, false);
1547
1548 WebTransformationMatrix layerTransform;
1549 layerTransform.translate(1, 1);
1550 WebTransformationMatrix sublayerTransform;
1551 sublayerTransform.scale3d(10, 1, 1);
1552
1553 // Put a transform animation on the render surface.
1554 addAnimatedTransformToController(*renderSurface2->layerAnimationController(), 10, 30, 0);
1555
1556 // Also put transform animations on grandChildOfRoot, and grandChildOfRS2
1557 addAnimatedTransformToController(*grandChildOfRoot->layerAnimationController(), 10, 30, 0);
1558 addAnimatedTransformToController(*grandChildOfRS2->layerAnimationController(), 10, 30, 0);
1559
1560 setLayerPropertiesForTesting(parent.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(2.5, 0), IntSize(10, 10), false);
1561 setLayerPropertiesForTesting(renderSurface1.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(2.5, 0), IntSize(10, 10), false);
1562 setLayerPropertiesForTesting(renderSurface2.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(2.5, 0), IntSize(10, 10), false);
1563 setLayerPropertiesForTesting(childOfRoot.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(2.5, 0), IntSize(10, 10), false);
1564 setLayerPropertiesForTesting(childOfRS1.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(2.5, 0), IntSize(10, 10), false);
1565 setLayerPropertiesForTesting(childOfRS2.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(2.5, 0), IntSize(10, 10), false);
1566 setLayerPropertiesForTesting(grandChildOfRoot.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(2.5, 0), IntSize(10, 10), false);
1567 setLayerPropertiesForTesting(grandChildOfRS1.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(2.5, 0), IntSize(10, 10), false);
1568 setLayerPropertiesForTesting(grandChildOfRS2.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(2.5, 0), IntSize(10, 10), false);
1569
1570 executeCalculateDrawTransformsAndVisibility(parent.get());
1571
1572 // Only layers that are associated with render surfaces should have an actual renderSurface() value.
1573 //
1574 ASSERT_TRUE(parent->renderSurface());
1575 ASSERT_FALSE(childOfRoot->renderSurface());
1576 ASSERT_FALSE(grandChildOfRoot->renderSurface());
1577
1578 ASSERT_TRUE(renderSurface1->renderSurface());
1579 ASSERT_FALSE(childOfRS1->renderSurface());
1580 ASSERT_FALSE(grandChildOfRS1->renderSurface());
1581
1582 ASSERT_TRUE(renderSurface2->renderSurface());
1583 ASSERT_FALSE(childOfRS2->renderSurface());
1584 ASSERT_FALSE(grandChildOfRS2->renderSurface());
1585
1586 // Verify all renderTarget accessors
1587 //
1588 EXPECT_EQ(parent, parent->renderTarget());
1589 EXPECT_EQ(parent, childOfRoot->renderTarget());
1590 EXPECT_EQ(parent, grandChildOfRoot->renderTarget());
1591
1592 EXPECT_EQ(renderSurface1, renderSurface1->renderTarget());
1593 EXPECT_EQ(renderSurface1, childOfRS1->renderTarget());
1594 EXPECT_EQ(renderSurface1, grandChildOfRS1->renderTarget());
1595
1596 EXPECT_EQ(renderSurface2, renderSurface2->renderTarget());
1597 EXPECT_EQ(renderSurface2, childOfRS2->renderTarget());
1598 EXPECT_EQ(renderSurface2, grandChildOfRS2->renderTarget());
1599
1600 // Verify drawOpacityIsAnimating values
1601 //
1602 EXPECT_FALSE(parent->drawOpacityIsAnimating());
1603 EXPECT_FALSE(childOfRoot->drawOpacityIsAnimating());
1604 EXPECT_TRUE(grandChildOfRoot->drawOpacityIsAnimating());
1605 EXPECT_FALSE(renderSurface1->drawOpacityIsAnimating());
1606 EXPECT_TRUE(renderSurface1->renderSurface()->drawOpacityIsAnimating());
1607 EXPECT_FALSE(childOfRS1->drawOpacityIsAnimating());
1608 EXPECT_FALSE(grandChildOfRS1->drawOpacityIsAnimating());
1609 EXPECT_FALSE(renderSurface2->drawOpacityIsAnimating());
1610 EXPECT_FALSE(renderSurface2->renderSurface()->drawOpacityIsAnimating());
1611 EXPECT_FALSE(childOfRS2->drawOpacityIsAnimating());
1612 EXPECT_FALSE(grandChildOfRS2->drawOpacityIsAnimating());
1613
1614 // Verify drawTransformsAnimatingInTarget values
1615 //
1616 EXPECT_FALSE(parent->drawTransformIsAnimating());
1617 EXPECT_FALSE(childOfRoot->drawTransformIsAnimating());
1618 EXPECT_TRUE(grandChildOfRoot->drawTransformIsAnimating());
1619 EXPECT_FALSE(renderSurface1->drawTransformIsAnimating());
1620 EXPECT_FALSE(renderSurface1->renderSurface()->targetSurfaceTransformsAreAnimating());
1621 EXPECT_FALSE(childOfRS1->drawTransformIsAnimating());
1622 EXPECT_FALSE(grandChildOfRS1->drawTransformIsAnimating());
1623 EXPECT_FALSE(renderSurface2->drawTransformIsAnimating());
1624 EXPECT_TRUE(renderSurface2->renderSurface()->targetSurfaceTransformsAreAnimating());
1625 EXPECT_FALSE(childOfRS2->drawTransformIsAnimating());
1626 EXPECT_TRUE(grandChildOfRS2->drawTransformIsAnimating());
1627
1628 // Verify drawTransformsAnimatingInScreen values
1629 //
1630 EXPECT_FALSE(parent->screenSpaceTransformIsAnimating());
1631 EXPECT_FALSE(childOfRoot->screenSpaceTransformIsAnimating());
1632 EXPECT_TRUE(grandChildOfRoot->screenSpaceTransformIsAnimating());
1633 EXPECT_FALSE(renderSurface1->screenSpaceTransformIsAnimating());
1634 EXPECT_FALSE(renderSurface1->renderSurface()->screenSpaceTransformsAreAnimating());
1635 EXPECT_FALSE(childOfRS1->screenSpaceTransformIsAnimating());
1636 EXPECT_FALSE(grandChildOfRS1->screenSpaceTransformIsAnimating());
1637 EXPECT_TRUE(renderSurface2->screenSpaceTransformIsAnimating());
1638 EXPECT_TRUE(renderSurface2->renderSurface()->screenSpaceTransformsAreAnimating());
1639 EXPECT_TRUE(childOfRS2->screenSpaceTransformIsAnimating());
1640 EXPECT_TRUE(grandChildOfRS2->screenSpaceTransformIsAnimating());
1641
1642
1643 // Sanity check. If these fail there is probably a bug in the test itself.
1644 // It is expected that we correctly set up transforms so that the y-component of the screen-space transform
1645 // encodes the "depth" of the layer in the tree.
1646 EXPECT_FLOAT_EQ(1, parent->screenSpaceTransform().m42());
1647 EXPECT_FLOAT_EQ(2, childOfRoot->screenSpaceTransform().m42());
1648 EXPECT_FLOAT_EQ(3, grandChildOfRoot->screenSpaceTransform().m42());
1649
1650 EXPECT_FLOAT_EQ(2, renderSurface1->screenSpaceTransform().m42());
1651 EXPECT_FLOAT_EQ(3, childOfRS1->screenSpaceTransform().m42());
1652 EXPECT_FLOAT_EQ(4, grandChildOfRS1->screenSpaceTransform().m42());
1653
1654 EXPECT_FLOAT_EQ(3, renderSurface2->screenSpaceTransform().m42());
1655 EXPECT_FLOAT_EQ(4, childOfRS2->screenSpaceTransform().m42());
1656 EXPECT_FLOAT_EQ(5, grandChildOfRS2->screenSpaceTransform().m42());
1657}
1658
1659TEST(CCLayerTreeHostCommonTest, verifyVisibleRectForIdentityTransform)
1660{
1661 // Test the calculateVisibleRect() function works correctly for identity transforms.
1662
1663 IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
1664 WebTransformationMatrix layerToSurfaceTransform;
1665
1666 // Case 1: Layer is contained within the surface.
1667 IntRect layerContentRect = IntRect(IntPoint(10, 10), IntSize(30, 30));
1668 IntRect expected = IntRect(IntPoint(10, 10), IntSize(30, 30));
1669 IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171670 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141671
1672 // Case 2: Layer is outside the surface rect.
1673 layerContentRect = IntRect(IntPoint(120, 120), IntSize(30, 30));
1674 actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
1675 EXPECT_TRUE(actual.isEmpty());
1676
1677 // Case 3: Layer is partially overlapping the surface rect.
1678 layerContentRect = IntRect(IntPoint(80, 80), IntSize(30, 30));
1679 expected = IntRect(IntPoint(80, 80), IntSize(20, 20));
1680 actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171681 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141682}
1683
1684TEST(CCLayerTreeHostCommonTest, verifyVisibleRectForTranslations)
1685{
1686 // Test the calculateVisibleRect() function works correctly for scaling transforms.
1687
1688 IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
1689 IntRect layerContentRect = IntRect(IntPoint(0, 0), IntSize(30, 30));
1690 WebTransformationMatrix layerToSurfaceTransform;
1691
1692 // Case 1: Layer is contained within the surface.
1693 layerToSurfaceTransform.makeIdentity();
1694 layerToSurfaceTransform.translate(10, 10);
1695 IntRect expected = IntRect(IntPoint(0, 0), IntSize(30, 30));
1696 IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171697 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141698
1699 // Case 2: Layer is outside the surface rect.
1700 layerToSurfaceTransform.makeIdentity();
1701 layerToSurfaceTransform.translate(120, 120);
1702 actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
1703 EXPECT_TRUE(actual.isEmpty());
1704
1705 // Case 3: Layer is partially overlapping the surface rect.
1706 layerToSurfaceTransform.makeIdentity();
1707 layerToSurfaceTransform.translate(80, 80);
1708 expected = IntRect(IntPoint(0, 0), IntSize(20, 20));
1709 actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171710 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141711}
1712
1713TEST(CCLayerTreeHostCommonTest, verifyVisibleRectFor2DRotations)
1714{
1715 // Test the calculateVisibleRect() function works correctly for rotations about z-axis (i.e. 2D rotations).
1716 // Remember that calculateVisibleRect() should return the visible rect in the layer's space.
1717
1718 IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
1719 IntRect layerContentRect = IntRect(IntPoint(0, 0), IntSize(30, 30));
1720 WebTransformationMatrix layerToSurfaceTransform;
1721
1722 // Case 1: Layer is contained within the surface.
1723 layerToSurfaceTransform.makeIdentity();
1724 layerToSurfaceTransform.translate(50, 50);
1725 layerToSurfaceTransform.rotate(45);
1726 IntRect expected = IntRect(IntPoint(0, 0), IntSize(30, 30));
1727 IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171728 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141729
1730 // Case 2: Layer is outside the surface rect.
1731 layerToSurfaceTransform.makeIdentity();
1732 layerToSurfaceTransform.translate(-50, 0);
1733 layerToSurfaceTransform.rotate(45);
1734 actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
1735 EXPECT_TRUE(actual.isEmpty());
1736
1737 // Case 3: The layer is rotated about its top-left corner. In surface space, the layer
1738 // is oriented diagonally, with the left half outside of the renderSurface. In
1739 // this case, the visible rect should still be the entire layer (remember the
1740 // visible rect is computed in layer space); both the top-left and
1741 // bottom-right corners of the layer are still visible.
1742 layerToSurfaceTransform.makeIdentity();
1743 layerToSurfaceTransform.rotate(45);
1744 expected = IntRect(IntPoint(0, 0), IntSize(30, 30));
1745 actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171746 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141747
1748 // Case 4: The layer is rotated about its top-left corner, and translated upwards. In
1749 // surface space, the layer is oriented diagonally, with only the top corner
1750 // of the surface overlapping the layer. In layer space, the render surface
1751 // overlaps the right side of the layer. The visible rect should be the
1752 // layer's right half.
1753 layerToSurfaceTransform.makeIdentity();
1754 layerToSurfaceTransform.translate(0, -sqrt(2.0) * 15);
1755 layerToSurfaceTransform.rotate(45);
1756 expected = IntRect(IntPoint(15, 0), IntSize(15, 30)); // right half of layer bounds.
1757 actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171758 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141759}
1760
1761TEST(CCLayerTreeHostCommonTest, verifyVisibleRectFor3dOrthographicTransform)
1762{
1763 // Test that the calculateVisibleRect() function works correctly for 3d transforms.
1764
1765 IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
1766 IntRect layerContentRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
1767 WebTransformationMatrix layerToSurfaceTransform;
1768
1769 // Case 1: Orthographic projection of a layer rotated about y-axis by 45 degrees, should be fully contained in the renderSurface.
1770 layerToSurfaceTransform.makeIdentity();
1771 layerToSurfaceTransform.rotate3d(0, 45, 0);
1772 IntRect expected = IntRect(IntPoint(0, 0), IntSize(100, 100));
1773 IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171774 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141775
1776 // Case 2: Orthographic projection of a layer rotated about y-axis by 45 degrees, but
1777 // shifted to the side so only the right-half the layer would be visible on
1778 // the surface.
1779 double halfWidthOfRotatedLayer = (100 / sqrt(2.0)) * 0.5; // 100 is the un-rotated layer width; divided by sqrt(2) is the rotated width.
1780 layerToSurfaceTransform.makeIdentity();
1781 layerToSurfaceTransform.translate(-halfWidthOfRotatedLayer, 0);
1782 layerToSurfaceTransform.rotate3d(0, 45, 0); // rotates about the left edge of the layer
1783 expected = IntRect(IntPoint(50, 0), IntSize(50, 100)); // right half of the layer.
1784 actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171785 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141786}
1787
1788TEST(CCLayerTreeHostCommonTest, verifyVisibleRectFor3dPerspectiveTransform)
1789{
1790 // Test the calculateVisibleRect() function works correctly when the layer has a
1791 // perspective projection onto the target surface.
1792
1793 IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
1794 IntRect layerContentRect = IntRect(IntPoint(-50, -50), IntSize(200, 200));
1795 WebTransformationMatrix layerToSurfaceTransform;
1796
1797 // Case 1: Even though the layer is twice as large as the surface, due to perspective
1798 // foreshortening, the layer will fit fully in the surface when its translated
1799 // more than the perspective amount.
1800 layerToSurfaceTransform.makeIdentity();
1801
1802 // The following sequence of transforms applies the perspective about the center of the surface.
1803 layerToSurfaceTransform.translate(50, 50);
1804 layerToSurfaceTransform.applyPerspective(9);
1805 layerToSurfaceTransform.translate(-50, -50);
1806
1807 // This translate places the layer in front of the surface's projection plane.
1808 layerToSurfaceTransform.translate3d(0, 0, -27);
1809
1810 IntRect expected = IntRect(IntPoint(-50, -50), IntSize(200, 200));
1811 IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171812 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141813
1814 // Case 2: same projection as before, except that the layer is also translated to the
1815 // side, so that only the right half of the layer should be visible.
1816 //
1817 // Explanation of expected result:
1818 // The perspective ratio is (z distance between layer and camera origin) / (z distance between projection plane and camera origin) == ((-27 - 9) / 9)
1819 // Then, by similar triangles, if we want to move a layer by translating -50 units in projected surface units (so that only half of it is
1820 // visible), then we would need to translate by (-36 / 9) * -50 == -200 in the layer's units.
1821 //
1822 layerToSurfaceTransform.translate3d(-200, 0, 0);
1823 expected = IntRect(IntPoint(50, -50), IntSize(100, 200)); // The right half of the layer's bounding rect.
1824 actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171825 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141826}
1827
1828TEST(CCLayerTreeHostCommonTest, verifyVisibleRectFor3dOrthographicIsNotClippedBehindSurface)
1829{
1830 // There is currently no explicit concept of an orthographic projection plane in our
1831 // code (nor in the CSS spec to my knowledge). Therefore, layers that are technically
1832 // behind the surface in an orthographic world should not be clipped when they are
1833 // flattened to the surface.
1834
1835 IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
1836 IntRect layerContentRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
1837 WebTransformationMatrix layerToSurfaceTransform;
1838
1839 // This sequence of transforms effectively rotates the layer about the y-axis at the
1840 // center of the layer.
1841 layerToSurfaceTransform.makeIdentity();
1842 layerToSurfaceTransform.translate(50, 0);
1843 layerToSurfaceTransform.rotate3d(0, 45, 0);
1844 layerToSurfaceTransform.translate(-50, 0);
1845
1846 IntRect expected = IntRect(IntPoint(0, 0), IntSize(100, 100));
1847 IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171848 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141849}
1850
1851TEST(CCLayerTreeHostCommonTest, verifyVisibleRectFor3dPerspectiveWhenClippedByW)
1852{
1853 // Test the calculateVisibleRect() function works correctly when projecting a surface
1854 // onto a layer, but the layer is partially behind the camera (not just behind the
1855 // projection plane). In this case, the cartesian coordinates may seem to be valid,
1856 // but actually they are not. The visibleRect needs to be properly clipped by the
1857 // w = 0 plane in homogeneous coordinates before converting to cartesian coordinates.
1858
1859 IntRect targetSurfaceRect = IntRect(IntPoint(-50, -50), IntSize(100, 100));
1860 IntRect layerContentRect = IntRect(IntPoint(-10, -1), IntSize(20, 2));
1861 WebTransformationMatrix layerToSurfaceTransform;
1862
1863 // The layer is positioned so that the right half of the layer should be in front of
1864 // the camera, while the other half is behind the surface's projection plane. The
1865 // following sequence of transforms applies the perspective and rotation about the
1866 // center of the layer.
1867 layerToSurfaceTransform.makeIdentity();
1868 layerToSurfaceTransform.applyPerspective(1);
1869 layerToSurfaceTransform.translate3d(-2, 0, 1);
1870 layerToSurfaceTransform.rotate3d(0, 45, 0);
1871
1872 // Sanity check that this transform does indeed cause w < 0 when applying the
1873 // transform, otherwise this code is not testing the intended scenario.
1874 bool clipped = false;
1875 CCMathUtil::mapQuad(layerToSurfaceTransform, FloatQuad(FloatRect(layerContentRect)), clipped);
1876 ASSERT_TRUE(clipped);
1877
1878 int expectedXPosition = 0;
1879 int expectedWidth = 10;
1880 IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
1881 EXPECT_EQ(expectedXPosition, actual.x());
1882 EXPECT_EQ(expectedWidth, actual.width());
1883}
1884
1885TEST(CCLayerTreeHostCommonTest, verifyVisibleRectForPerspectiveUnprojection)
1886{
1887 // To determine visibleRect in layer space, there needs to be an un-projection from
1888 // surface space to layer space. When the original transform was a perspective
1889 // projection that was clipped, it returns a rect that encloses the clipped bounds.
1890 // Un-projecting this new rect may require clipping again.
1891
1892 // This sequence of transforms causes one corner of the layer to protrude across the w = 0 plane, and should be clipped.
1893 IntRect targetSurfaceRect = IntRect(IntPoint(-50, -50), IntSize(100, 100));
1894 IntRect layerContentRect = IntRect(IntPoint(-10, -10), IntSize(20, 20));
1895 WebTransformationMatrix layerToSurfaceTransform;
1896 layerToSurfaceTransform.makeIdentity();
1897 layerToSurfaceTransform.applyPerspective(1);
1898 layerToSurfaceTransform.translate3d(0, 0, -5);
1899 layerToSurfaceTransform.rotate3d(0, 45, 0);
1900 layerToSurfaceTransform.rotate3d(80, 0, 0);
1901
1902 // Sanity check that un-projection does indeed cause w < 0, otherwise this code is not
1903 // testing the intended scenario.
1904 bool clipped = false;
1905 FloatRect clippedRect = CCMathUtil::mapClippedRect(layerToSurfaceTransform, layerContentRect);
1906 CCMathUtil::projectQuad(layerToSurfaceTransform.inverse(), FloatQuad(clippedRect), clipped);
1907 ASSERT_TRUE(clipped);
1908
1909 // Only the corner of the layer is not visible on the surface because of being
1910 // clipped. But, the net result of rounding visible region to an axis-aligned rect is
1911 // that the entire layer should still be considered visible.
1912 IntRect expected = IntRect(IntPoint(-10, -10), IntSize(20, 20));
1913 IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
[email protected]022cbf162012-09-01 01:15:171914 EXPECT_RECT_EQ(expected, actual);
[email protected]94f206c12012-08-25 00:09:141915}
1916
[email protected]23bbb412012-08-30 20:03:381917TEST(CCLayerTreeHostCommonTest, verifyDrawableAndVisibleContentRectsForSimpleLayers)
1918{
1919 RefPtr<LayerChromium> root = LayerChromium::create();
1920 RefPtr<LayerChromiumWithForcedDrawsContent> child1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1921 RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1922 RefPtr<LayerChromiumWithForcedDrawsContent> child3 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1923 root->addChild(child1);
1924 root->addChild(child2);
1925 root->addChild(child3);
1926
1927 WebTransformationMatrix identityMatrix;
1928 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
1929 setLayerPropertiesForTesting(child1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(50, 50), false);
1930 setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(75, 75), IntSize(50, 50), false);
1931 setLayerPropertiesForTesting(child3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(125, 125), IntSize(50, 50), false);
1932
1933 executeCalculateDrawTransformsAndVisibility(root.get());
1934
[email protected]022cbf162012-09-01 01:15:171935 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->renderSurface()->drawableContentRect());
1936 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:381937
1938 // Layers that do not draw content should have empty visibleContentRects.
[email protected]022cbf162012-09-01 01:15:171939 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), root->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:381940
1941 // layer visibleContentRects are clipped by their targetSurface
[email protected]022cbf162012-09-01 01:15:171942 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), child1->visibleContentRect());
1943 EXPECT_RECT_EQ(IntRect(0, 0, 25, 25), child2->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:381944 EXPECT_TRUE(child3->visibleContentRect().isEmpty());
1945
1946 // layer drawableContentRects are not clipped.
[email protected]022cbf162012-09-01 01:15:171947 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), child1->drawableContentRect());
1948 EXPECT_RECT_EQ(IntRect(75, 75, 50, 50), child2->drawableContentRect());
1949 EXPECT_RECT_EQ(IntRect(125, 125, 50, 50), child3->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:381950}
1951
1952TEST(CCLayerTreeHostCommonTest, verifyDrawableAndVisibleContentRectsForLayersClippedByLayer)
1953{
1954 RefPtr<LayerChromium> root = LayerChromium::create();
1955 RefPtr<LayerChromium> child = LayerChromium::create();
1956 RefPtr<LayerChromiumWithForcedDrawsContent> grandChild1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1957 RefPtr<LayerChromiumWithForcedDrawsContent> grandChild2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1958 RefPtr<LayerChromiumWithForcedDrawsContent> grandChild3 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1959 root->addChild(child);
1960 child->addChild(grandChild1);
1961 child->addChild(grandChild2);
1962 child->addChild(grandChild3);
1963
1964 WebTransformationMatrix identityMatrix;
1965 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
1966 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
1967 setLayerPropertiesForTesting(grandChild1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(5, 5), IntSize(50, 50), false);
1968 setLayerPropertiesForTesting(grandChild2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(75, 75), IntSize(50, 50), false);
1969 setLayerPropertiesForTesting(grandChild3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(125, 125), IntSize(50, 50), false);
1970
1971 child->setMasksToBounds(true);
1972 executeCalculateDrawTransformsAndVisibility(root.get());
1973
1974 ASSERT_FALSE(child->renderSurface());
1975
[email protected]022cbf162012-09-01 01:15:171976 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->renderSurface()->drawableContentRect());
1977 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:381978
1979 // Layers that do not draw content should have empty visibleContentRects.
[email protected]022cbf162012-09-01 01:15:171980 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), root->visibleContentRect());
1981 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), child->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:381982
1983 // All grandchild visibleContentRects should be clipped by child.
[email protected]022cbf162012-09-01 01:15:171984 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), grandChild1->visibleContentRect());
1985 EXPECT_RECT_EQ(IntRect(0, 0, 25, 25), grandChild2->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:381986 EXPECT_TRUE(grandChild3->visibleContentRect().isEmpty());
1987
1988 // All grandchild drawableContentRects should also be clipped by child.
[email protected]022cbf162012-09-01 01:15:171989 EXPECT_RECT_EQ(IntRect(5, 5, 50, 50), grandChild1->drawableContentRect());
1990 EXPECT_RECT_EQ(IntRect(75, 75, 25, 25), grandChild2->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:381991 EXPECT_TRUE(grandChild3->drawableContentRect().isEmpty());
1992}
1993
1994TEST(CCLayerTreeHostCommonTest, verifyDrawableAndVisibleContentRectsForLayersInUnclippedRenderSurface)
1995{
1996 RefPtr<LayerChromium> root = LayerChromium::create();
1997 RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
1998 RefPtr<LayerChromiumWithForcedDrawsContent> child1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
1999 RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2000 RefPtr<LayerChromiumWithForcedDrawsContent> child3 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2001 root->addChild(renderSurface1);
2002 renderSurface1->addChild(child1);
2003 renderSurface1->addChild(child2);
2004 renderSurface1->addChild(child3);
2005
2006 WebTransformationMatrix identityMatrix;
2007 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2008 setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(3, 4), false);
2009 setLayerPropertiesForTesting(child1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(5, 5), IntSize(50, 50), false);
2010 setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(75, 75), IntSize(50, 50), false);
2011 setLayerPropertiesForTesting(child3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(125, 125), IntSize(50, 50), false);
2012
2013 renderSurface1->setForceRenderSurface(true);
2014 executeCalculateDrawTransformsAndVisibility(root.get());
2015
2016 ASSERT_TRUE(renderSurface1->renderSurface());
2017
[email protected]022cbf162012-09-01 01:15:172018 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->renderSurface()->drawableContentRect());
2019 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382020
2021 // Layers that do not draw content should have empty visibleContentRects.
[email protected]022cbf162012-09-01 01:15:172022 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), root->visibleContentRect());
2023 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), renderSurface1->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:382024
2025 // An unclipped surface grows its drawableContentRect to include all drawable regions of the subtree.
[email protected]022cbf162012-09-01 01:15:172026 EXPECT_RECT_EQ(IntRect(5, 5, 170, 170), renderSurface1->renderSurface()->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382027
2028 // All layers that draw content into the unclipped surface are also unclipped.
[email protected]022cbf162012-09-01 01:15:172029 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), child1->visibleContentRect());
2030 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), child2->visibleContentRect());
2031 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), child3->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:382032
[email protected]022cbf162012-09-01 01:15:172033 EXPECT_RECT_EQ(IntRect(5, 5, 50, 50), child1->drawableContentRect());
2034 EXPECT_RECT_EQ(IntRect(75, 75, 50, 50), child2->drawableContentRect());
2035 EXPECT_RECT_EQ(IntRect(125, 125, 50, 50), child3->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382036}
2037
2038TEST(CCLayerTreeHostCommonTest, verifyDrawableAndVisibleContentRectsForLayersInClippedRenderSurface)
2039{
2040 RefPtr<LayerChromium> root = LayerChromium::create();
2041 RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
2042 RefPtr<LayerChromiumWithForcedDrawsContent> child1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2043 RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2044 RefPtr<LayerChromiumWithForcedDrawsContent> child3 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2045 root->addChild(renderSurface1);
2046 renderSurface1->addChild(child1);
2047 renderSurface1->addChild(child2);
2048 renderSurface1->addChild(child3);
2049
2050 WebTransformationMatrix identityMatrix;
2051 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2052 setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(3, 4), false);
2053 setLayerPropertiesForTesting(child1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(5, 5), IntSize(50, 50), false);
2054 setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(75, 75), IntSize(50, 50), false);
2055 setLayerPropertiesForTesting(child3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(125, 125), IntSize(50, 50), false);
2056
2057 root->setMasksToBounds(true);
2058 renderSurface1->setForceRenderSurface(true);
2059 executeCalculateDrawTransformsAndVisibility(root.get());
2060
2061 ASSERT_TRUE(renderSurface1->renderSurface());
2062
[email protected]022cbf162012-09-01 01:15:172063 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->renderSurface()->drawableContentRect());
2064 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382065
2066 // Layers that do not draw content should have empty visibleContentRects.
[email protected]022cbf162012-09-01 01:15:172067 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), root->visibleContentRect());
2068 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), renderSurface1->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:382069
2070 // A clipped surface grows its drawableContentRect to include all drawable regions of the subtree,
2071 // but also gets clamped by the ancestor's clip.
[email protected]022cbf162012-09-01 01:15:172072 EXPECT_RECT_EQ(IntRect(5, 5, 95, 95), renderSurface1->renderSurface()->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382073
2074 // All layers that draw content into the surface have their visibleContentRect clipped by the surface clipRect.
[email protected]022cbf162012-09-01 01:15:172075 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), child1->visibleContentRect());
2076 EXPECT_RECT_EQ(IntRect(0, 0, 25, 25), child2->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:382077 EXPECT_TRUE(child3->visibleContentRect().isEmpty());
2078
2079 // But the drawableContentRects are unclipped.
[email protected]022cbf162012-09-01 01:15:172080 EXPECT_RECT_EQ(IntRect(5, 5, 50, 50), child1->drawableContentRect());
2081 EXPECT_RECT_EQ(IntRect(75, 75, 50, 50), child2->drawableContentRect());
2082 EXPECT_RECT_EQ(IntRect(125, 125, 50, 50), child3->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382083}
2084
2085TEST(CCLayerTreeHostCommonTest, verifyDrawableAndVisibleContentRectsForSurfaceHierarchy)
2086{
2087 // Check that clipping does not propagate down surfaces.
2088 RefPtr<LayerChromium> root = LayerChromium::create();
2089 RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
2090 RefPtr<LayerChromium> renderSurface2 = LayerChromium::create();
2091 RefPtr<LayerChromiumWithForcedDrawsContent> child1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2092 RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2093 RefPtr<LayerChromiumWithForcedDrawsContent> child3 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2094 root->addChild(renderSurface1);
2095 renderSurface1->addChild(renderSurface2);
2096 renderSurface2->addChild(child1);
2097 renderSurface2->addChild(child2);
2098 renderSurface2->addChild(child3);
2099
2100 WebTransformationMatrix identityMatrix;
2101 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2102 setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(3, 4), false);
2103 setLayerPropertiesForTesting(renderSurface2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(7, 13), false);
2104 setLayerPropertiesForTesting(child1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(5, 5), IntSize(50, 50), false);
2105 setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(75, 75), IntSize(50, 50), false);
2106 setLayerPropertiesForTesting(child3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(125, 125), IntSize(50, 50), false);
2107
2108 root->setMasksToBounds(true);
2109 renderSurface1->setForceRenderSurface(true);
2110 renderSurface2->setForceRenderSurface(true);
2111 executeCalculateDrawTransformsAndVisibility(root.get());
2112
2113 ASSERT_TRUE(renderSurface1->renderSurface());
2114 ASSERT_TRUE(renderSurface2->renderSurface());
2115
[email protected]022cbf162012-09-01 01:15:172116 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->renderSurface()->drawableContentRect());
2117 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382118
2119 // Layers that do not draw content should have empty visibleContentRects.
[email protected]022cbf162012-09-01 01:15:172120 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), root->visibleContentRect());
2121 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), renderSurface1->visibleContentRect());
2122 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), renderSurface2->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:382123
2124 // A clipped surface grows its drawableContentRect to include all drawable regions of the subtree,
2125 // but also gets clamped by the ancestor's clip.
[email protected]022cbf162012-09-01 01:15:172126 EXPECT_RECT_EQ(IntRect(5, 5, 95, 95), renderSurface1->renderSurface()->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382127
2128 // renderSurface1 lives in the "unclipped universe" of renderSurface1, and is only
2129 // implicitly clipped by renderSurface1's contentRect. So, renderSurface2 grows to
2130 // enclose all drawable content of its subtree.
[email protected]022cbf162012-09-01 01:15:172131 EXPECT_RECT_EQ(IntRect(5, 5, 170, 170), renderSurface2->renderSurface()->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382132
2133 // All layers that draw content into renderSurface2 think they are unclipped.
[email protected]022cbf162012-09-01 01:15:172134 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), child1->visibleContentRect());
2135 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), child2->visibleContentRect());
2136 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), child3->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:382137
2138 // drawableContentRects are also unclipped.
[email protected]022cbf162012-09-01 01:15:172139 EXPECT_RECT_EQ(IntRect(5, 5, 50, 50), child1->drawableContentRect());
2140 EXPECT_RECT_EQ(IntRect(75, 75, 50, 50), child2->drawableContentRect());
2141 EXPECT_RECT_EQ(IntRect(125, 125, 50, 50), child3->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382142}
2143
2144TEST(CCLayerTreeHostCommonTest, verifyDrawableAndVisibleContentRectsWithTransformOnUnclippedSurface)
2145{
2146 // Layers that have non-axis aligned bounds (due to transforms) have an expanded,
2147 // axis-aligned drawableContentRect and visibleContentRect.
2148
2149 RefPtr<LayerChromium> root = LayerChromium::create();
2150 RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
2151 RefPtr<LayerChromiumWithForcedDrawsContent> child1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2152 root->addChild(renderSurface1);
2153 renderSurface1->addChild(child1);
2154
2155 WebTransformationMatrix identityMatrix;
2156 WebTransformationMatrix childRotation;
2157 childRotation.rotate(45);
2158 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2159 setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(3, 4), false);
2160 setLayerPropertiesForTesting(child1.get(), childRotation, identityMatrix, FloatPoint(0.5, 0.5), FloatPoint(25, 25), IntSize(50, 50), false);
2161
2162 renderSurface1->setForceRenderSurface(true);
2163 executeCalculateDrawTransformsAndVisibility(root.get());
2164
2165 ASSERT_TRUE(renderSurface1->renderSurface());
2166
[email protected]022cbf162012-09-01 01:15:172167 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->renderSurface()->drawableContentRect());
2168 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), root->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382169
2170 // Layers that do not draw content should have empty visibleContentRects.
[email protected]022cbf162012-09-01 01:15:172171 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), root->visibleContentRect());
2172 EXPECT_RECT_EQ(IntRect(0, 0, 0, 0), renderSurface1->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:382173
2174 // The unclipped surface grows its drawableContentRect to include all drawable regions of the subtree.
2175 int diagonalRadius = ceil(sqrt(2.0) * 25);
2176 IntRect expectedSurfaceDrawableContent = IntRect(50 - diagonalRadius, 50 - diagonalRadius, diagonalRadius * 2, diagonalRadius * 2);
[email protected]022cbf162012-09-01 01:15:172177 EXPECT_RECT_EQ(expectedSurfaceDrawableContent, renderSurface1->renderSurface()->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382178
2179 // All layers that draw content into the unclipped surface are also unclipped.
[email protected]022cbf162012-09-01 01:15:172180 EXPECT_RECT_EQ(IntRect(0, 0, 50, 50), child1->visibleContentRect());
2181 EXPECT_RECT_EQ(expectedSurfaceDrawableContent, child1->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382182}
2183
2184TEST(CCLayerTreeHostCommonTest, verifyDrawableAndVisibleContentRectsWithTransformOnClippedSurface)
2185{
2186 // Layers that have non-axis aligned bounds (due to transforms) have an expanded,
2187 // axis-aligned drawableContentRect and visibleContentRect.
2188
2189 RefPtr<LayerChromium> root = LayerChromium::create();
2190 RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
2191 RefPtr<LayerChromiumWithForcedDrawsContent> child1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2192 root->addChild(renderSurface1);
2193 renderSurface1->addChild(child1);
2194
2195 WebTransformationMatrix identityMatrix;
2196 WebTransformationMatrix childRotation;
2197 childRotation.rotate(45);
2198 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(50, 50), false);
2199 setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(3, 4), false);
2200 setLayerPropertiesForTesting(child1.get(), childRotation, identityMatrix, FloatPoint(0.5, 0.5), FloatPoint(25, 25), IntSize(50, 50), false);
2201
2202 root->setMasksToBounds(true);
2203 renderSurface1->setForceRenderSurface(true);
2204 executeCalculateDrawTransformsAndVisibility(root.get());
2205
2206 ASSERT_TRUE(renderSurface1->renderSurface());
2207
2208 // The clipped surface clamps the drawableContentRect that encloses the rotated layer.
2209 int diagonalRadius = ceil(sqrt(2.0) * 25);
2210 IntRect unclippedSurfaceContent = IntRect(50 - diagonalRadius, 50 - diagonalRadius, diagonalRadius * 2, diagonalRadius * 2);
2211 IntRect expectedSurfaceDrawableContent = intersection(unclippedSurfaceContent, IntRect(0, 0, 50, 50));
[email protected]022cbf162012-09-01 01:15:172212 EXPECT_RECT_EQ(expectedSurfaceDrawableContent, renderSurface1->renderSurface()->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382213
2214 // On the clipped surface, only a quarter of the child1 is visible, but when rotating
2215 // it back to child1's content space, the actual enclosing rect ends up covering the
2216 // full left half of child1.
[email protected]022cbf162012-09-01 01:15:172217 EXPECT_RECT_EQ(IntRect(0, 0, 26, 50), child1->visibleContentRect());
[email protected]23bbb412012-08-30 20:03:382218
2219 // The child's drawableContentRect is unclipped.
[email protected]022cbf162012-09-01 01:15:172220 EXPECT_RECT_EQ(unclippedSurfaceContent, child1->drawableContentRect());
[email protected]23bbb412012-08-30 20:03:382221}
2222
[email protected]94f206c12012-08-25 00:09:142223TEST(CCLayerTreeHostCommonTest, verifyBackFaceCullingWithoutPreserves3d)
2224{
2225 // Verify the behavior of back-face culling when there are no preserve-3d layers. Note
2226 // that 3d transforms still apply in this case, but they are "flattened" to each
2227 // parent layer according to current W3C spec.
2228
2229 const WebTransformationMatrix identityMatrix;
2230 RefPtr<LayerChromium> parent = LayerChromium::create();
2231 RefPtr<LayerChromiumWithForcedDrawsContent> frontFacingChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
2232 RefPtr<LayerChromiumWithForcedDrawsContent> backFacingChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
2233 RefPtr<LayerChromiumWithForcedDrawsContent> frontFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2234 RefPtr<LayerChromiumWithForcedDrawsContent> backFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2235 RefPtr<LayerChromiumWithForcedDrawsContent> frontFacingChildOfFrontFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2236 RefPtr<LayerChromiumWithForcedDrawsContent> backFacingChildOfFrontFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2237 RefPtr<LayerChromiumWithForcedDrawsContent> frontFacingChildOfBackFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2238 RefPtr<LayerChromiumWithForcedDrawsContent> backFacingChildOfBackFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2239
2240 parent->addChild(frontFacingChild);
2241 parent->addChild(backFacingChild);
2242 parent->addChild(frontFacingSurface);
2243 parent->addChild(backFacingSurface);
2244 frontFacingSurface->addChild(frontFacingChildOfFrontFacingSurface);
2245 frontFacingSurface->addChild(backFacingChildOfFrontFacingSurface);
2246 backFacingSurface->addChild(frontFacingChildOfBackFacingSurface);
2247 backFacingSurface->addChild(backFacingChildOfBackFacingSurface);
2248
2249 // Nothing is double-sided
2250 frontFacingChild->setDoubleSided(false);
2251 backFacingChild->setDoubleSided(false);
2252 frontFacingSurface->setDoubleSided(false);
2253 backFacingSurface->setDoubleSided(false);
2254 frontFacingChildOfFrontFacingSurface->setDoubleSided(false);
2255 backFacingChildOfFrontFacingSurface->setDoubleSided(false);
2256 frontFacingChildOfBackFacingSurface->setDoubleSided(false);
2257 backFacingChildOfBackFacingSurface->setDoubleSided(false);
2258
2259 WebTransformationMatrix backfaceMatrix;
2260 backfaceMatrix.translate(50, 50);
2261 backfaceMatrix.rotate3d(0, 1, 0, 180);
2262 backfaceMatrix.translate(-50, -50);
2263
2264 // Having a descendant and opacity will force these to have render surfaces.
2265 frontFacingSurface->setOpacity(0.5);
2266 backFacingSurface->setOpacity(0.5);
2267
2268 // Nothing preserves 3d. According to current W3C CSS Transforms spec, these layers
2269 // should blindly use their own local transforms to determine back-face culling.
2270 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2271 setLayerPropertiesForTesting(frontFacingChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2272 setLayerPropertiesForTesting(backFacingChild.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2273 setLayerPropertiesForTesting(frontFacingSurface.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2274 setLayerPropertiesForTesting(backFacingSurface.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2275 setLayerPropertiesForTesting(frontFacingChildOfFrontFacingSurface.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2276 setLayerPropertiesForTesting(backFacingChildOfFrontFacingSurface.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2277 setLayerPropertiesForTesting(frontFacingChildOfBackFacingSurface.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2278 setLayerPropertiesForTesting(backFacingChildOfBackFacingSurface.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2279
2280 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
2281 int dummyMaxTextureSize = 512;
2282 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
2283
2284 // Verify which renderSurfaces were created.
2285 EXPECT_FALSE(frontFacingChild->renderSurface());
2286 EXPECT_FALSE(backFacingChild->renderSurface());
2287 EXPECT_TRUE(frontFacingSurface->renderSurface());
2288 EXPECT_TRUE(backFacingSurface->renderSurface());
2289 EXPECT_FALSE(frontFacingChildOfFrontFacingSurface->renderSurface());
2290 EXPECT_FALSE(backFacingChildOfFrontFacingSurface->renderSurface());
2291 EXPECT_FALSE(frontFacingChildOfBackFacingSurface->renderSurface());
2292 EXPECT_FALSE(backFacingChildOfBackFacingSurface->renderSurface());
2293
2294 // Verify the renderSurfaceLayerList.
2295 ASSERT_EQ(3u, renderSurfaceLayerList.size());
2296 EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
2297 EXPECT_EQ(frontFacingSurface->id(), renderSurfaceLayerList[1]->id());
2298 // Even though the back facing surface LAYER gets culled, the other descendants should still be added, so the SURFACE should not be culled.
2299 EXPECT_EQ(backFacingSurface->id(), renderSurfaceLayerList[2]->id());
2300
2301 // Verify root surface's layerList.
2302 ASSERT_EQ(3u, renderSurfaceLayerList[0]->renderSurface()->layerList().size());
2303 EXPECT_EQ(frontFacingChild->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[0]->id());
2304 EXPECT_EQ(frontFacingSurface->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[1]->id());
2305 EXPECT_EQ(backFacingSurface->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[2]->id());
2306
2307 // Verify frontFacingSurface's layerList.
2308 ASSERT_EQ(2u, renderSurfaceLayerList[1]->renderSurface()->layerList().size());
2309 EXPECT_EQ(frontFacingSurface->id(), renderSurfaceLayerList[1]->renderSurface()->layerList()[0]->id());
2310 EXPECT_EQ(frontFacingChildOfFrontFacingSurface->id(), renderSurfaceLayerList[1]->renderSurface()->layerList()[1]->id());
2311
2312 // Verify backFacingSurface's layerList; its own layer should be culled from the surface list.
2313 ASSERT_EQ(1u, renderSurfaceLayerList[2]->renderSurface()->layerList().size());
2314 EXPECT_EQ(frontFacingChildOfBackFacingSurface->id(), renderSurfaceLayerList[2]->renderSurface()->layerList()[0]->id());
2315}
2316
2317TEST(CCLayerTreeHostCommonTest, verifyBackFaceCullingWithPreserves3d)
2318{
2319 // Verify the behavior of back-face culling when preserves-3d transform style is used.
2320
2321 const WebTransformationMatrix identityMatrix;
2322 RefPtr<LayerChromium> parent = LayerChromium::create();
2323 RefPtr<LayerChromiumWithForcedDrawsContent> frontFacingChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
2324 RefPtr<LayerChromiumWithForcedDrawsContent> backFacingChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
2325 RefPtr<LayerChromiumWithForcedDrawsContent> frontFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2326 RefPtr<LayerChromiumWithForcedDrawsContent> backFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2327 RefPtr<LayerChromiumWithForcedDrawsContent> frontFacingChildOfFrontFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2328 RefPtr<LayerChromiumWithForcedDrawsContent> backFacingChildOfFrontFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2329 RefPtr<LayerChromiumWithForcedDrawsContent> frontFacingChildOfBackFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2330 RefPtr<LayerChromiumWithForcedDrawsContent> backFacingChildOfBackFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2331 RefPtr<LayerChromiumWithForcedDrawsContent> dummyReplicaLayer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2332 RefPtr<LayerChromiumWithForcedDrawsContent> dummyReplicaLayer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2333
2334 parent->addChild(frontFacingChild);
2335 parent->addChild(backFacingChild);
2336 parent->addChild(frontFacingSurface);
2337 parent->addChild(backFacingSurface);
2338 frontFacingSurface->addChild(frontFacingChildOfFrontFacingSurface);
2339 frontFacingSurface->addChild(backFacingChildOfFrontFacingSurface);
2340 backFacingSurface->addChild(frontFacingChildOfBackFacingSurface);
2341 backFacingSurface->addChild(backFacingChildOfBackFacingSurface);
2342
2343 // Nothing is double-sided
2344 frontFacingChild->setDoubleSided(false);
2345 backFacingChild->setDoubleSided(false);
2346 frontFacingSurface->setDoubleSided(false);
2347 backFacingSurface->setDoubleSided(false);
2348 frontFacingChildOfFrontFacingSurface->setDoubleSided(false);
2349 backFacingChildOfFrontFacingSurface->setDoubleSided(false);
2350 frontFacingChildOfBackFacingSurface->setDoubleSided(false);
2351 backFacingChildOfBackFacingSurface->setDoubleSided(false);
2352
2353 WebTransformationMatrix backfaceMatrix;
2354 backfaceMatrix.translate(50, 50);
2355 backfaceMatrix.rotate3d(0, 1, 0, 180);
2356 backfaceMatrix.translate(-50, -50);
2357
2358 // Opacity will not force creation of renderSurfaces in this case because of the
2359 // preserve-3d transform style. Instead, an example of when a surface would be
2360 // created with preserve-3d is when there is a replica layer.
2361 frontFacingSurface->setReplicaLayer(dummyReplicaLayer1.get());
2362 backFacingSurface->setReplicaLayer(dummyReplicaLayer2.get());
2363
2364 // Each surface creates its own new 3d rendering context (as defined by W3C spec).
2365 // According to current W3C CSS Transforms spec, layers in a 3d rendering context
2366 // should use the transform with respect to that context. This 3d rendering context
2367 // occurs when (a) parent's transform style is flat and (b) the layer's transform
2368 // style is preserve-3d.
2369 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); // parent transform style is flat.
2370 setLayerPropertiesForTesting(frontFacingChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2371 setLayerPropertiesForTesting(backFacingChild.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2372 setLayerPropertiesForTesting(frontFacingSurface.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true); // surface transform style is preserve-3d.
2373 setLayerPropertiesForTesting(backFacingSurface.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true); // surface transform style is preserve-3d.
2374 setLayerPropertiesForTesting(frontFacingChildOfFrontFacingSurface.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2375 setLayerPropertiesForTesting(backFacingChildOfFrontFacingSurface.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2376 setLayerPropertiesForTesting(frontFacingChildOfBackFacingSurface.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2377 setLayerPropertiesForTesting(backFacingChildOfBackFacingSurface.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2378
2379 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
2380 int dummyMaxTextureSize = 512;
2381 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
2382
2383 // Verify which renderSurfaces were created.
2384 EXPECT_FALSE(frontFacingChild->renderSurface());
2385 EXPECT_FALSE(backFacingChild->renderSurface());
2386 EXPECT_TRUE(frontFacingSurface->renderSurface());
2387 EXPECT_FALSE(backFacingSurface->renderSurface());
2388 EXPECT_FALSE(frontFacingChildOfFrontFacingSurface->renderSurface());
2389 EXPECT_FALSE(backFacingChildOfFrontFacingSurface->renderSurface());
2390 EXPECT_FALSE(frontFacingChildOfBackFacingSurface->renderSurface());
2391 EXPECT_FALSE(backFacingChildOfBackFacingSurface->renderSurface());
2392
2393 // Verify the renderSurfaceLayerList. The back-facing surface should be culled.
2394 ASSERT_EQ(2u, renderSurfaceLayerList.size());
2395 EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
2396 EXPECT_EQ(frontFacingSurface->id(), renderSurfaceLayerList[1]->id());
2397
2398 // Verify root surface's layerList.
2399 ASSERT_EQ(2u, renderSurfaceLayerList[0]->renderSurface()->layerList().size());
2400 EXPECT_EQ(frontFacingChild->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[0]->id());
2401 EXPECT_EQ(frontFacingSurface->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[1]->id());
2402
2403 // Verify frontFacingSurface's layerList.
2404 ASSERT_EQ(2u, renderSurfaceLayerList[1]->renderSurface()->layerList().size());
2405 EXPECT_EQ(frontFacingSurface->id(), renderSurfaceLayerList[1]->renderSurface()->layerList()[0]->id());
2406 EXPECT_EQ(frontFacingChildOfFrontFacingSurface->id(), renderSurfaceLayerList[1]->renderSurface()->layerList()[1]->id());
2407}
2408
2409TEST(CCLayerTreeHostCommonTest, verifyBackFaceCullingWithAnimatingTransforms)
2410{
2411 // Verify that layers are appropriately culled when their back face is showing and
2412 // they are not double sided, while animations are going on.
2413 //
2414 // Layers that are animating do not get culled on the main thread, as their transforms should be
2415 // treated as "unknown" so we can not be sure that their back face is really showing.
2416 //
2417
2418 const WebTransformationMatrix identityMatrix;
2419 RefPtr<LayerChromium> parent = LayerChromium::create();
2420 RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent());
2421 RefPtr<LayerChromiumWithForcedDrawsContent> animatingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2422 RefPtr<LayerChromiumWithForcedDrawsContent> childOfAnimatingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2423 RefPtr<LayerChromiumWithForcedDrawsContent> animatingChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
2424 RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2425
2426 parent->addChild(child);
2427 parent->addChild(animatingSurface);
2428 animatingSurface->addChild(childOfAnimatingSurface);
2429 parent->addChild(animatingChild);
2430 parent->addChild(child2);
2431
2432 // Nothing is double-sided
2433 child->setDoubleSided(false);
2434 child2->setDoubleSided(false);
2435 animatingSurface->setDoubleSided(false);
2436 childOfAnimatingSurface->setDoubleSided(false);
2437 animatingChild->setDoubleSided(false);
2438
2439 WebTransformationMatrix backfaceMatrix;
2440 backfaceMatrix.translate(50, 50);
2441 backfaceMatrix.rotate3d(0, 1, 0, 180);
2442 backfaceMatrix.translate(-50, -50);
2443
2444 // Make our render surface.
2445 animatingSurface->setForceRenderSurface(true);
2446
2447 // Animate the transform on the render surface.
2448 addAnimatedTransformToController(*animatingSurface->layerAnimationController(), 10, 30, 0);
2449 // This is just an animating layer, not a surface.
2450 addAnimatedTransformToController(*animatingChild->layerAnimationController(), 10, 30, 0);
2451
2452 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2453 setLayerPropertiesForTesting(child.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2454 setLayerPropertiesForTesting(animatingSurface.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2455 setLayerPropertiesForTesting(childOfAnimatingSurface.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2456 setLayerPropertiesForTesting(animatingChild.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2457 setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2458
2459 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
2460 int dummyMaxTextureSize = 512;
2461 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
2462 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
2463
2464 EXPECT_FALSE(child->renderSurface());
2465 EXPECT_TRUE(animatingSurface->renderSurface());
2466 EXPECT_FALSE(childOfAnimatingSurface->renderSurface());
2467 EXPECT_FALSE(animatingChild->renderSurface());
2468 EXPECT_FALSE(child2->renderSurface());
2469
2470 // Verify that the animatingChild and childOfAnimatingSurface were not culled, but that child was.
2471 ASSERT_EQ(2u, renderSurfaceLayerList.size());
2472 EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
2473 EXPECT_EQ(animatingSurface->id(), renderSurfaceLayerList[1]->id());
2474
2475 // The non-animating child be culled from the layer list for the parent render surface.
2476 ASSERT_EQ(3u, renderSurfaceLayerList[0]->renderSurface()->layerList().size());
2477 EXPECT_EQ(animatingSurface->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[0]->id());
2478 EXPECT_EQ(animatingChild->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[1]->id());
2479 EXPECT_EQ(child2->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[2]->id());
2480
2481 ASSERT_EQ(2u, renderSurfaceLayerList[1]->renderSurface()->layerList().size());
2482 EXPECT_EQ(animatingSurface->id(), renderSurfaceLayerList[1]->renderSurface()->layerList()[0]->id());
2483 EXPECT_EQ(childOfAnimatingSurface->id(), renderSurfaceLayerList[1]->renderSurface()->layerList()[1]->id());
2484
2485 EXPECT_FALSE(child2->visibleContentRect().isEmpty());
2486
2487 // The animating layers should have a visibleContentRect that represents the area of the front face that is within the viewport.
2488 EXPECT_EQ(animatingChild->visibleContentRect(), IntRect(IntPoint(), animatingChild->contentBounds()));
2489 EXPECT_EQ(animatingSurface->visibleContentRect(), IntRect(IntPoint(), animatingSurface->contentBounds()));
2490 // And layers in the subtree of the animating layer should have valid visibleContentRects also.
2491 EXPECT_EQ(childOfAnimatingSurface->visibleContentRect(), IntRect(IntPoint(), childOfAnimatingSurface->contentBounds()));
2492}
2493
2494TEST(CCLayerTreeHostCommonTest, verifyBackFaceCullingWithPreserves3dForFlatteningSurface)
2495{
2496 // Verify the behavior of back-face culling for a renderSurface that is created
2497 // when it flattens its subtree, and its parent has preserves-3d.
2498
2499 const WebTransformationMatrix identityMatrix;
2500 RefPtr<LayerChromium> parent = LayerChromium::create();
2501 RefPtr<LayerChromiumWithForcedDrawsContent> frontFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2502 RefPtr<LayerChromiumWithForcedDrawsContent> backFacingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
2503 RefPtr<LayerChromiumWithForcedDrawsContent> child1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2504 RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
2505
2506 parent->addChild(frontFacingSurface);
2507 parent->addChild(backFacingSurface);
2508 frontFacingSurface->addChild(child1);
2509 backFacingSurface->addChild(child2);
2510
2511 // RenderSurfaces are not double-sided
2512 frontFacingSurface->setDoubleSided(false);
2513 backFacingSurface->setDoubleSided(false);
2514
2515 WebTransformationMatrix backfaceMatrix;
2516 backfaceMatrix.translate(50, 50);
2517 backfaceMatrix.rotate3d(0, 1, 0, 180);
2518 backfaceMatrix.translate(-50, -50);
2519
2520 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true); // parent transform style is preserve3d.
2521 setLayerPropertiesForTesting(frontFacingSurface.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); // surface transform style is flat.
2522 setLayerPropertiesForTesting(backFacingSurface.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); // surface transform style is flat.
2523 setLayerPropertiesForTesting(child1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2524 setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
2525
2526 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
2527 int dummyMaxTextureSize = 512;
2528 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
2529
2530 // Verify which renderSurfaces were created.
2531 EXPECT_TRUE(frontFacingSurface->renderSurface());
2532 EXPECT_FALSE(backFacingSurface->renderSurface()); // because it should be culled
2533 EXPECT_FALSE(child1->renderSurface());
2534 EXPECT_FALSE(child2->renderSurface());
2535
2536 // Verify the renderSurfaceLayerList. The back-facing surface should be culled.
2537 ASSERT_EQ(2u, renderSurfaceLayerList.size());
2538 EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
2539 EXPECT_EQ(frontFacingSurface->id(), renderSurfaceLayerList[1]->id());
2540
2541 // Verify root surface's layerList.
2542 ASSERT_EQ(1u, renderSurfaceLayerList[0]->renderSurface()->layerList().size());
2543 EXPECT_EQ(frontFacingSurface->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[0]->id());
2544
2545 // Verify frontFacingSurface's layerList.
2546 ASSERT_EQ(2u, renderSurfaceLayerList[1]->renderSurface()->layerList().size());
2547 EXPECT_EQ(frontFacingSurface->id(), renderSurfaceLayerList[1]->renderSurface()->layerList()[0]->id());
2548 EXPECT_EQ(child1->id(), renderSurfaceLayerList[1]->renderSurface()->layerList()[1]->id());
2549}
2550
2551TEST(CCLayerTreeHostCommonTest, verifyHitTestingForEmptyLayerList)
2552{
2553 // Hit testing on an empty renderSurfaceLayerList should return a null pointer.
2554 DebugScopedSetImplThread thisScopeIsOnImplThread;
2555
2556 Vector<CCLayerImpl*> renderSurfaceLayerList;
2557
2558 IntPoint testPoint(0, 0);
2559 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2560 EXPECT_FALSE(resultLayer);
2561
2562 testPoint = IntPoint(10, 20);
2563 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2564 EXPECT_FALSE(resultLayer);
2565}
2566
2567TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSingleLayer)
2568{
2569 DebugScopedSetImplThread thisScopeIsOnImplThread;
2570
2571 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(12345);
2572
2573 WebTransformationMatrix identityMatrix;
2574 FloatPoint anchor(0, 0);
2575 FloatPoint position(0, 0);
2576 IntSize bounds(100, 100);
2577 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
2578 root->setDrawsContent(true);
2579
2580 Vector<CCLayerImpl*> renderSurfaceLayerList;
2581 int dummyMaxTextureSize = 512;
2582 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
2583 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
2584
2585 // Sanity check the scenario we just created.
2586 ASSERT_EQ(1u, renderSurfaceLayerList.size());
2587 ASSERT_EQ(1u, root->renderSurface()->layerList().size());
2588
2589 // Hit testing for a point outside the layer should return a null pointer.
2590 IntPoint testPoint(101, 101);
2591 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2592 EXPECT_FALSE(resultLayer);
2593
2594 testPoint = IntPoint(-1, -1);
2595 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2596 EXPECT_FALSE(resultLayer);
2597
2598 // Hit testing for a point inside should return the root layer.
2599 testPoint = IntPoint(1, 1);
2600 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2601 ASSERT_TRUE(resultLayer);
2602 EXPECT_EQ(12345, resultLayer->id());
2603
2604 testPoint = IntPoint(99, 99);
2605 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2606 ASSERT_TRUE(resultLayer);
2607 EXPECT_EQ(12345, resultLayer->id());
2608}
2609
2610TEST(CCLayerTreeHostCommonTest, verifyHitTestingForUninvertibleTransform)
2611{
2612 DebugScopedSetImplThread thisScopeIsOnImplThread;
2613
2614 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(12345);
2615
2616 WebTransformationMatrix uninvertibleTransform;
2617 uninvertibleTransform.setM11(0);
2618 uninvertibleTransform.setM22(0);
2619 uninvertibleTransform.setM33(0);
2620 uninvertibleTransform.setM44(0);
2621 ASSERT_FALSE(uninvertibleTransform.isInvertible());
2622
2623 WebTransformationMatrix identityMatrix;
2624 FloatPoint anchor(0, 0);
2625 FloatPoint position(0, 0);
2626 IntSize bounds(100, 100);
2627 setLayerPropertiesForTesting(root.get(), uninvertibleTransform, identityMatrix, anchor, position, bounds, false);
2628 root->setDrawsContent(true);
2629
2630 Vector<CCLayerImpl*> renderSurfaceLayerList;
2631 int dummyMaxTextureSize = 512;
2632 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
2633 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
2634
2635 // Sanity check the scenario we just created.
2636 ASSERT_EQ(1u, renderSurfaceLayerList.size());
2637 ASSERT_EQ(1u, root->renderSurface()->layerList().size());
2638 ASSERT_FALSE(root->screenSpaceTransform().isInvertible());
2639
2640 // Hit testing any point should not hit the layer. If the invertible matrix is
2641 // accidentally ignored and treated like an identity, then the hit testing will
2642 // incorrectly hit the layer when it shouldn't.
2643 IntPoint testPoint(1, 1);
2644 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2645 EXPECT_FALSE(resultLayer);
2646
2647 testPoint = IntPoint(10, 10);
2648 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2649 EXPECT_FALSE(resultLayer);
2650
2651 testPoint = IntPoint(10, 30);
2652 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2653 EXPECT_FALSE(resultLayer);
2654
2655 testPoint = IntPoint(50, 50);
2656 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2657 EXPECT_FALSE(resultLayer);
2658
2659 testPoint = IntPoint(67, 48);
2660 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2661 EXPECT_FALSE(resultLayer);
2662
2663 testPoint = IntPoint(99, 99);
2664 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2665 EXPECT_FALSE(resultLayer);
2666
2667 testPoint = IntPoint(-1, -1);
2668 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2669 EXPECT_FALSE(resultLayer);
2670}
2671
2672TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSinglePositionedLayer)
2673{
2674 DebugScopedSetImplThread thisScopeIsOnImplThread;
2675
2676 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(12345);
2677
2678 WebTransformationMatrix identityMatrix;
2679 FloatPoint anchor(0, 0);
2680 FloatPoint position(50, 50); // this layer is positioned, and hit testing should correctly know where the layer is located.
2681 IntSize bounds(100, 100);
2682 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
2683 root->setDrawsContent(true);
2684
2685 Vector<CCLayerImpl*> renderSurfaceLayerList;
2686 int dummyMaxTextureSize = 512;
2687 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
2688 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
2689
2690 // Sanity check the scenario we just created.
2691 ASSERT_EQ(1u, renderSurfaceLayerList.size());
2692 ASSERT_EQ(1u, root->renderSurface()->layerList().size());
2693
2694 // Hit testing for a point outside the layer should return a null pointer.
2695 IntPoint testPoint(49, 49);
2696 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2697 EXPECT_FALSE(resultLayer);
2698
2699 // Even though the layer exists at (101, 101), it should not be visible there since the root renderSurface would clamp it.
2700 testPoint = IntPoint(101, 101);
2701 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2702 EXPECT_FALSE(resultLayer);
2703
2704 // Hit testing for a point inside should return the root layer.
2705 testPoint = IntPoint(51, 51);
2706 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2707 ASSERT_TRUE(resultLayer);
2708 EXPECT_EQ(12345, resultLayer->id());
2709
2710 testPoint = IntPoint(99, 99);
2711 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2712 ASSERT_TRUE(resultLayer);
2713 EXPECT_EQ(12345, resultLayer->id());
2714}
2715
2716TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSingleRotatedLayer)
2717{
2718 DebugScopedSetImplThread thisScopeIsOnImplThread;
2719
2720 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(12345);
2721
2722 WebTransformationMatrix identityMatrix;
2723 WebTransformationMatrix rotation45DegreesAboutCenter;
2724 rotation45DegreesAboutCenter.translate(50, 50);
2725 rotation45DegreesAboutCenter.rotate3d(0, 0, 45);
2726 rotation45DegreesAboutCenter.translate(-50, -50);
2727 FloatPoint anchor(0, 0);
2728 FloatPoint position(0, 0);
2729 IntSize bounds(100, 100);
2730 setLayerPropertiesForTesting(root.get(), rotation45DegreesAboutCenter, identityMatrix, anchor, position, bounds, false);
2731 root->setDrawsContent(true);
2732
2733 Vector<CCLayerImpl*> renderSurfaceLayerList;
2734 int dummyMaxTextureSize = 512;
2735 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
2736 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
2737
2738 // Sanity check the scenario we just created.
2739 ASSERT_EQ(1u, renderSurfaceLayerList.size());
2740 ASSERT_EQ(1u, root->renderSurface()->layerList().size());
2741
2742 // Hit testing for points outside the layer.
2743 // These corners would have been inside the un-transformed layer, but they should not hit the correctly transformed layer.
2744 IntPoint testPoint(99, 99);
2745 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2746 EXPECT_FALSE(resultLayer);
2747
2748 testPoint = IntPoint(1, 1);
2749 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2750 EXPECT_FALSE(resultLayer);
2751
2752 // Hit testing for a point inside should return the root layer.
2753 testPoint = IntPoint(1, 50);
2754 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2755 ASSERT_TRUE(resultLayer);
2756 EXPECT_EQ(12345, resultLayer->id());
2757
2758 // Hit testing the corners that would overlap the unclipped layer, but are outside the clipped region.
2759 testPoint = IntPoint(50, -1);
2760 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2761 ASSERT_FALSE(resultLayer);
2762
2763 testPoint = IntPoint(-1, 50);
2764 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2765 ASSERT_FALSE(resultLayer);
2766}
2767
2768TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSinglePerspectiveLayer)
2769{
2770 DebugScopedSetImplThread thisScopeIsOnImplThread;
2771
2772 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(12345);
2773
2774 WebTransformationMatrix identityMatrix;
2775
2776 // perspectiveProjectionAboutCenter * translationByZ is designed so that the 100 x 100 layer becomes 50 x 50, and remains centered at (50, 50).
2777 WebTransformationMatrix perspectiveProjectionAboutCenter;
2778 perspectiveProjectionAboutCenter.translate(50, 50);
2779 perspectiveProjectionAboutCenter.applyPerspective(1);
2780 perspectiveProjectionAboutCenter.translate(-50, -50);
2781 WebTransformationMatrix translationByZ;
2782 translationByZ.translate3d(0, 0, -1);
2783
2784 FloatPoint anchor(0, 0);
2785 FloatPoint position(0, 0);
2786 IntSize bounds(100, 100);
2787 setLayerPropertiesForTesting(root.get(), perspectiveProjectionAboutCenter * translationByZ, identityMatrix, anchor, position, bounds, false);
2788 root->setDrawsContent(true);
2789
2790 Vector<CCLayerImpl*> renderSurfaceLayerList;
2791 int dummyMaxTextureSize = 512;
2792 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
2793 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
2794
2795 // Sanity check the scenario we just created.
2796 ASSERT_EQ(1u, renderSurfaceLayerList.size());
2797 ASSERT_EQ(1u, root->renderSurface()->layerList().size());
2798
2799 // Hit testing for points outside the layer.
2800 // These corners would have been inside the un-transformed layer, but they should not hit the correctly transformed layer.
2801 IntPoint testPoint(24, 24);
2802 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2803 EXPECT_FALSE(resultLayer);
2804
2805 testPoint = IntPoint(76, 76);
2806 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2807 EXPECT_FALSE(resultLayer);
2808
2809 // Hit testing for a point inside should return the root layer.
2810 testPoint = IntPoint(26, 26);
2811 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2812 ASSERT_TRUE(resultLayer);
2813 EXPECT_EQ(12345, resultLayer->id());
2814
2815 testPoint = IntPoint(74, 74);
2816 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2817 ASSERT_TRUE(resultLayer);
2818 EXPECT_EQ(12345, resultLayer->id());
2819}
2820
2821TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSingleLayerWithScaledContents)
2822{
2823 // A layer's visibleContentRect is actually in the layer's content space. The
2824 // screenSpaceTransform converts from the layer's origin space to screen space. This
2825 // test makes sure that hit testing works correctly accounts for the contents scale.
2826 // A contentsScale that is not 1 effectively forces a non-identity transform between
2827 // layer's content space and layer's origin space. The hit testing code must take this into account.
2828 //
2829 // To test this, the layer is positioned at (25, 25), and is size (50, 50). If
2830 // contentsScale is ignored, then hit testing will mis-interpret the visibleContentRect
2831 // as being larger than the actual bounds of the layer.
2832 //
2833 DebugScopedSetImplThread thisScopeIsOnImplThread;
2834
2835 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
2836
2837 WebTransformationMatrix identityMatrix;
2838 FloatPoint anchor(0, 0);
2839
2840 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anchor, FloatPoint(0, 0), IntSize(100, 100), false);
2841
2842 {
2843 FloatPoint position(25, 25);
2844 IntSize bounds(50, 50);
2845 OwnPtr<CCLayerImpl> testLayer = CCLayerImpl::create(12345);
2846 setLayerPropertiesForTesting(testLayer.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
2847
2848 // override contentBounds
2849 testLayer->setContentBounds(IntSize(100, 100));
2850
2851 testLayer->setDrawsContent(true);
2852 root->addChild(testLayer.release());
2853 }
2854
2855 Vector<CCLayerImpl*> renderSurfaceLayerList;
2856 int dummyMaxTextureSize = 512;
2857 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
2858 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
2859
2860 // Sanity check the scenario we just created.
2861 // The visibleContentRect for testLayer is actually 100x100, even though its layout size is 50x50, positioned at 25x25.
2862 CCLayerImpl* testLayer = root->children()[0].get();
[email protected]022cbf162012-09-01 01:15:172863 EXPECT_RECT_EQ(IntRect(IntPoint::zero(), IntSize(100, 100)), testLayer->visibleContentRect());
[email protected]94f206c12012-08-25 00:09:142864 ASSERT_EQ(1u, renderSurfaceLayerList.size());
2865 ASSERT_EQ(1u, root->renderSurface()->layerList().size());
2866
2867 // Hit testing for a point outside the layer should return a null pointer (the root layer does not draw content, so it will not be hit tested either).
2868 IntPoint testPoint(101, 101);
2869 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2870 EXPECT_FALSE(resultLayer);
2871
2872 testPoint = IntPoint(24, 24);
2873 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2874 EXPECT_FALSE(resultLayer);
2875
2876 testPoint = IntPoint(76, 76);
2877 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2878 EXPECT_FALSE(resultLayer);
2879
2880 // Hit testing for a point inside should return the test layer.
2881 testPoint = IntPoint(26, 26);
2882 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2883 ASSERT_TRUE(resultLayer);
2884 EXPECT_EQ(12345, resultLayer->id());
2885
2886 testPoint = IntPoint(74, 74);
2887 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2888 ASSERT_TRUE(resultLayer);
2889 EXPECT_EQ(12345, resultLayer->id());
2890}
2891
2892TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSimpleClippedLayer)
2893{
2894 // Test that hit-testing will only work for the visible portion of a layer, and not
2895 // the entire layer bounds. Here we just test the simple axis-aligned case.
2896 DebugScopedSetImplThread thisScopeIsOnImplThread;
2897
2898 WebTransformationMatrix identityMatrix;
2899 FloatPoint anchor(0, 0);
2900
2901 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
2902 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anchor, FloatPoint(0, 0), IntSize(100, 100), false);
2903
2904 {
2905 OwnPtr<CCLayerImpl> clippingLayer = CCLayerImpl::create(123);
2906 FloatPoint position(25, 25); // this layer is positioned, and hit testing should correctly know where the layer is located.
2907 IntSize bounds(50, 50);
2908 setLayerPropertiesForTesting(clippingLayer.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
2909 clippingLayer->setMasksToBounds(true);
2910
2911 OwnPtr<CCLayerImpl> child = CCLayerImpl::create(456);
2912 position = FloatPoint(-50, -50);
2913 bounds = IntSize(300, 300);
2914 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
2915 child->setDrawsContent(true);
2916 clippingLayer->addChild(child.release());
2917 root->addChild(clippingLayer.release());
2918 }
2919
2920 Vector<CCLayerImpl*> renderSurfaceLayerList;
2921 int dummyMaxTextureSize = 512;
2922 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
2923 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
2924
2925 // Sanity check the scenario we just created.
2926 ASSERT_EQ(1u, renderSurfaceLayerList.size());
2927 ASSERT_EQ(1u, root->renderSurface()->layerList().size());
2928 ASSERT_EQ(456, root->renderSurface()->layerList()[0]->id());
2929
2930 // Hit testing for a point outside the layer should return a null pointer.
2931 // Despite the child layer being very large, it should be clipped to the root layer's bounds.
2932 IntPoint testPoint(24, 24);
2933 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2934 EXPECT_FALSE(resultLayer);
2935
2936 // Even though the layer exists at (101, 101), it should not be visible there since the clippingLayer would clamp it.
2937 testPoint = IntPoint(76, 76);
2938 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2939 EXPECT_FALSE(resultLayer);
2940
2941 // Hit testing for a point inside should return the child layer.
2942 testPoint = IntPoint(26, 26);
2943 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2944 ASSERT_TRUE(resultLayer);
2945 EXPECT_EQ(456, resultLayer->id());
2946
2947 testPoint = IntPoint(74, 74);
2948 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
2949 ASSERT_TRUE(resultLayer);
2950 EXPECT_EQ(456, resultLayer->id());
2951}
2952
2953TEST(CCLayerTreeHostCommonTest, verifyHitTestingForMultiClippedRotatedLayer)
2954{
2955 // This test checks whether hit testing correctly avoids hit testing with multiple
2956 // ancestors that clip in non axis-aligned ways. To pass this test, the hit testing
2957 // algorithm needs to recognize that multiple parent layers may clip the layer, and
2958 // should not actually hit those clipped areas.
2959 //
2960 // The child and grandChild layers are both initialized to clip the rotatedLeaf. The
2961 // child layer is rotated about the top-left corner, so that the root + child clips
2962 // combined create a triangle. The rotatedLeaf will only be visible where it overlaps
2963 // this triangle.
2964 //
2965 DebugScopedSetImplThread thisScopeIsOnImplThread;
2966
2967 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(123);
2968
2969 WebTransformationMatrix identityMatrix;
2970 FloatPoint anchor(0, 0);
2971 FloatPoint position(0, 0);
2972 IntSize bounds(100, 100);
2973 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
2974 root->setMasksToBounds(true);
2975
2976 {
2977 OwnPtr<CCLayerImpl> child = CCLayerImpl::create(456);
2978 OwnPtr<CCLayerImpl> grandChild = CCLayerImpl::create(789);
2979 OwnPtr<CCLayerImpl> rotatedLeaf = CCLayerImpl::create(2468);
2980
2981 position = FloatPoint(10, 10);
2982 bounds = IntSize(80, 80);
2983 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
2984 child->setMasksToBounds(true);
2985
2986 WebTransformationMatrix rotation45DegreesAboutCorner;
2987 rotation45DegreesAboutCorner.rotate3d(0, 0, 45);
2988
2989 position = FloatPoint(0, 0); // remember, positioned with respect to its parent which is already at 10, 10
2990 bounds = IntSize(200, 200); // to ensure it covers at least sqrt(2) * 100.
2991 setLayerPropertiesForTesting(grandChild.get(), rotation45DegreesAboutCorner, identityMatrix, anchor, position, bounds, false);
2992 grandChild->setMasksToBounds(true);
2993
2994 // Rotates about the center of the layer
2995 WebTransformationMatrix rotatedLeafTransform;
2996 rotatedLeafTransform.translate(-10, -10); // cancel out the grandParent's position
2997 rotatedLeafTransform.rotate3d(0, 0, -45); // cancel out the corner 45-degree rotation of the parent.
2998 rotatedLeafTransform.translate(50, 50);
2999 rotatedLeafTransform.rotate3d(0, 0, 45);
3000 rotatedLeafTransform.translate(-50, -50);
3001 position = FloatPoint(0, 0);
3002 bounds = IntSize(100, 100);
3003 setLayerPropertiesForTesting(rotatedLeaf.get(), rotatedLeafTransform, identityMatrix, anchor, position, bounds, false);
3004 rotatedLeaf->setDrawsContent(true);
3005
3006 grandChild->addChild(rotatedLeaf.release());
3007 child->addChild(grandChild.release());
3008 root->addChild(child.release());
3009 }
3010
3011 Vector<CCLayerImpl*> renderSurfaceLayerList;
3012 int dummyMaxTextureSize = 512;
3013 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
3014 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
3015
3016 // Sanity check the scenario we just created.
3017 // The grandChild is expected to create a renderSurface because it masksToBounds and is not axis aligned.
3018 ASSERT_EQ(2u, renderSurfaceLayerList.size());
3019 ASSERT_EQ(1u, renderSurfaceLayerList[0]->renderSurface()->layerList().size());
3020 ASSERT_EQ(789, renderSurfaceLayerList[0]->renderSurface()->layerList()[0]->id()); // grandChild's surface.
3021 ASSERT_EQ(1u, renderSurfaceLayerList[1]->renderSurface()->layerList().size());
3022 ASSERT_EQ(2468, renderSurfaceLayerList[1]->renderSurface()->layerList()[0]->id());
3023
3024 // (11, 89) is close to the the bottom left corner within the clip, but it is not inside the layer.
3025 IntPoint testPoint(11, 89);
3026 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3027 EXPECT_FALSE(resultLayer);
3028
3029 // Closer inwards from the bottom left will overlap the layer.
3030 testPoint = IntPoint(25, 75);
3031 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3032 ASSERT_TRUE(resultLayer);
3033 EXPECT_EQ(2468, resultLayer->id());
3034
3035 // (4, 50) is inside the unclipped layer, but that corner of the layer should be
3036 // clipped away by the grandParent and should not get hit. If hit testing blindly uses
3037 // visibleContentRect without considering how parent may clip the layer, then hit
3038 // testing would accidentally think that the point successfully hits the layer.
3039 testPoint = IntPoint(4, 50);
3040 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3041 EXPECT_FALSE(resultLayer);
3042
3043 // (11, 50) is inside the layer and within the clipped area.
3044 testPoint = IntPoint(11, 50);
3045 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3046 ASSERT_TRUE(resultLayer);
3047 EXPECT_EQ(2468, resultLayer->id());
3048
3049 // Around the middle, just to the right and up, would have hit the layer except that
3050 // that area should be clipped away by the parent.
3051 testPoint = IntPoint(51, 51);
3052 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3053 EXPECT_FALSE(resultLayer);
3054
3055 // Around the middle, just to the left and down, should successfully hit the layer.
3056 testPoint = IntPoint(49, 51);
3057 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3058 ASSERT_TRUE(resultLayer);
3059 EXPECT_EQ(2468, resultLayer->id());
3060}
3061
3062TEST(CCLayerTreeHostCommonTest, verifyHitTestingForNonClippingIntermediateLayer)
3063{
3064 // This test checks that hit testing code does not accidentally clip to layer
3065 // bounds for a layer that actually does not clip.
3066 DebugScopedSetImplThread thisScopeIsOnImplThread;
3067
3068 WebTransformationMatrix identityMatrix;
3069 FloatPoint anchor(0, 0);
3070
3071 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
3072 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anchor, FloatPoint(0, 0), IntSize(100, 100), false);
3073
3074 {
3075 OwnPtr<CCLayerImpl> intermediateLayer = CCLayerImpl::create(123);
3076 FloatPoint position(10, 10); // this layer is positioned, and hit testing should correctly know where the layer is located.
3077 IntSize bounds(50, 50);
3078 setLayerPropertiesForTesting(intermediateLayer.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
3079 // Sanity check the intermediate layer should not clip.
3080 ASSERT_FALSE(intermediateLayer->masksToBounds());
3081 ASSERT_FALSE(intermediateLayer->maskLayer());
3082
3083 // The child of the intermediateLayer is translated so that it does not overlap intermediateLayer at all.
3084 // If child is incorrectly clipped, we would not be able to hit it successfully.
3085 OwnPtr<CCLayerImpl> child = CCLayerImpl::create(456);
3086 position = FloatPoint(60, 60); // 70, 70 in screen space
3087 bounds = IntSize(20, 20);
3088 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
3089 child->setDrawsContent(true);
3090 intermediateLayer->addChild(child.release());
3091 root->addChild(intermediateLayer.release());
3092 }
3093
3094 Vector<CCLayerImpl*> renderSurfaceLayerList;
3095 int dummyMaxTextureSize = 512;
3096 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
3097 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
3098
3099 // Sanity check the scenario we just created.
3100 ASSERT_EQ(1u, renderSurfaceLayerList.size());
3101 ASSERT_EQ(1u, root->renderSurface()->layerList().size());
3102 ASSERT_EQ(456, root->renderSurface()->layerList()[0]->id());
3103
3104 // Hit testing for a point outside the layer should return a null pointer.
3105 IntPoint testPoint(69, 69);
3106 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3107 EXPECT_FALSE(resultLayer);
3108
3109 testPoint = IntPoint(91, 91);
3110 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3111 EXPECT_FALSE(resultLayer);
3112
3113 // Hit testing for a point inside should return the child layer.
3114 testPoint = IntPoint(71, 71);
3115 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3116 ASSERT_TRUE(resultLayer);
3117 EXPECT_EQ(456, resultLayer->id());
3118
3119 testPoint = IntPoint(89, 89);
3120 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3121 ASSERT_TRUE(resultLayer);
3122 EXPECT_EQ(456, resultLayer->id());
3123}
3124
3125
3126TEST(CCLayerTreeHostCommonTest, verifyHitTestingForMultipleLayers)
3127{
3128 DebugScopedSetImplThread thisScopeIsOnImplThread;
3129
3130 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
3131
3132 WebTransformationMatrix identityMatrix;
3133 FloatPoint anchor(0, 0);
3134 FloatPoint position(0, 0);
3135 IntSize bounds(100, 100);
3136 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
3137 root->setDrawsContent(true);
3138
3139 {
3140 // child 1 and child2 are initialized to overlap between x=50 and x=60.
3141 // grandChild is set to overlap both child1 and child2 between y=50 and y=60.
3142 // The expected stacking order is:
3143 // (front) child2, (second) grandChild, (third) child1, and (back) the root layer behind all other layers.
3144
3145 OwnPtr<CCLayerImpl> child1 = CCLayerImpl::create(2);
3146 OwnPtr<CCLayerImpl> child2 = CCLayerImpl::create(3);
3147 OwnPtr<CCLayerImpl> grandChild1 = CCLayerImpl::create(4);
3148
3149 position = FloatPoint(10, 10);
3150 bounds = IntSize(50, 50);
3151 setLayerPropertiesForTesting(child1.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
3152 child1->setDrawsContent(true);
3153
3154 position = FloatPoint(50, 10);
3155 bounds = IntSize(50, 50);
3156 setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
3157 child2->setDrawsContent(true);
3158
3159 // Remember that grandChild is positioned with respect to its parent (i.e. child1).
3160 // In screen space, the intended position is (10, 50), with size 100 x 50.
3161 position = FloatPoint(0, 40);
3162 bounds = IntSize(100, 50);
3163 setLayerPropertiesForTesting(grandChild1.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
3164 grandChild1->setDrawsContent(true);
3165
3166 child1->addChild(grandChild1.release());
3167 root->addChild(child1.release());
3168 root->addChild(child2.release());
3169 }
3170
3171 CCLayerImpl* child1 = root->children()[0].get();
3172 CCLayerImpl* child2 = root->children()[1].get();
3173 CCLayerImpl* grandChild1 = child1->children()[0].get();
3174
3175 Vector<CCLayerImpl*> renderSurfaceLayerList;
3176 int dummyMaxTextureSize = 512;
3177 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
3178 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
3179
3180 // Sanity check the scenario we just created.
3181 ASSERT_TRUE(child1);
3182 ASSERT_TRUE(child2);
3183 ASSERT_TRUE(grandChild1);
3184 ASSERT_EQ(1u, renderSurfaceLayerList.size());
3185 ASSERT_EQ(4u, root->renderSurface()->layerList().size());
3186 ASSERT_EQ(1, root->renderSurface()->layerList()[0]->id()); // root layer
3187 ASSERT_EQ(2, root->renderSurface()->layerList()[1]->id()); // child1
3188 ASSERT_EQ(4, root->renderSurface()->layerList()[2]->id()); // grandChild1
3189 ASSERT_EQ(3, root->renderSurface()->layerList()[3]->id()); // child2
3190
3191 // Nothing overlaps the rootLayer at (1, 1), so hit testing there should find the root layer.
3192 IntPoint testPoint = IntPoint(1, 1);
3193 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3194 ASSERT_TRUE(resultLayer);
3195 EXPECT_EQ(1, resultLayer->id());
3196
3197 // At (15, 15), child1 and root are the only layers. child1 is expected to be on top.
3198 testPoint = IntPoint(15, 15);
3199 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3200 ASSERT_TRUE(resultLayer);
3201 EXPECT_EQ(2, resultLayer->id());
3202
3203 // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
3204 testPoint = IntPoint(51, 20);
3205 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3206 ASSERT_TRUE(resultLayer);
3207 EXPECT_EQ(3, resultLayer->id());
3208
3209 // At (80, 51), child2 and grandChild1 overlap. child2 is expected to be on top.
3210 testPoint = IntPoint(80, 51);
3211 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3212 ASSERT_TRUE(resultLayer);
3213 EXPECT_EQ(3, resultLayer->id());
3214
3215 // At (51, 51), all layers overlap each other. child2 is expected to be on top of all other layers.
3216 testPoint = IntPoint(51, 51);
3217 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3218 ASSERT_TRUE(resultLayer);
3219 EXPECT_EQ(3, resultLayer->id());
3220
3221 // At (20, 51), child1 and grandChild1 overlap. grandChild1 is expected to be on top.
3222 testPoint = IntPoint(20, 51);
3223 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3224 ASSERT_TRUE(resultLayer);
3225 EXPECT_EQ(4, resultLayer->id());
3226}
3227
3228TEST(CCLayerTreeHostCommonTest, verifyHitTestingForMultipleLayerLists)
3229{
3230 //
3231 // The geometry is set up similarly to the previous case, but
3232 // all layers are forced to be renderSurfaces now.
3233 //
3234 DebugScopedSetImplThread thisScopeIsOnImplThread;
3235
3236 OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
3237
3238 WebTransformationMatrix identityMatrix;
3239 FloatPoint anchor(0, 0);
3240 FloatPoint position(0, 0);
3241 IntSize bounds(100, 100);
3242 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
3243 root->setDrawsContent(true);
3244
3245 {
3246 // child 1 and child2 are initialized to overlap between x=50 and x=60.
3247 // grandChild is set to overlap both child1 and child2 between y=50 and y=60.
3248 // The expected stacking order is:
3249 // (front) child2, (second) grandChild, (third) child1, and (back) the root layer behind all other layers.
3250
3251 OwnPtr<CCLayerImpl> child1 = CCLayerImpl::create(2);
3252 OwnPtr<CCLayerImpl> child2 = CCLayerImpl::create(3);
3253 OwnPtr<CCLayerImpl> grandChild1 = CCLayerImpl::create(4);
3254
3255 position = FloatPoint(10, 10);
3256 bounds = IntSize(50, 50);
3257 setLayerPropertiesForTesting(child1.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
3258 child1->setDrawsContent(true);
3259 child1->setForceRenderSurface(true);
3260
3261 position = FloatPoint(50, 10);
3262 bounds = IntSize(50, 50);
3263 setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
3264 child2->setDrawsContent(true);
3265 child2->setForceRenderSurface(true);
3266
3267 // Remember that grandChild is positioned with respect to its parent (i.e. child1).
3268 // In screen space, the intended position is (10, 50), with size 100 x 50.
3269 position = FloatPoint(0, 40);
3270 bounds = IntSize(100, 50);
3271 setLayerPropertiesForTesting(grandChild1.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
3272 grandChild1->setDrawsContent(true);
3273 grandChild1->setForceRenderSurface(true);
3274
3275 child1->addChild(grandChild1.release());
3276 root->addChild(child1.release());
3277 root->addChild(child2.release());
3278 }
3279
3280 CCLayerImpl* child1 = root->children()[0].get();
3281 CCLayerImpl* child2 = root->children()[1].get();
3282 CCLayerImpl* grandChild1 = child1->children()[0].get();
3283
3284 Vector<CCLayerImpl*> renderSurfaceLayerList;
3285 int dummyMaxTextureSize = 512;
3286 CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
3287 CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
3288
3289 // Sanity check the scenario we just created.
3290 ASSERT_TRUE(child1);
3291 ASSERT_TRUE(child2);
3292 ASSERT_TRUE(grandChild1);
3293 ASSERT_TRUE(child1->renderSurface());
3294 ASSERT_TRUE(child2->renderSurface());
3295 ASSERT_TRUE(grandChild1->renderSurface());
3296 ASSERT_EQ(4u, renderSurfaceLayerList.size());
3297 ASSERT_EQ(3u, root->renderSurface()->layerList().size()); // The root surface has the root layer, and child1's and child2's renderSurfaces.
3298 ASSERT_EQ(2u, child1->renderSurface()->layerList().size()); // The child1 surface has the child1 layer and grandChild1's renderSurface.
3299 ASSERT_EQ(1u, child2->renderSurface()->layerList().size());
3300 ASSERT_EQ(1u, grandChild1->renderSurface()->layerList().size());
3301 ASSERT_EQ(1, renderSurfaceLayerList[0]->id()); // root layer
3302 ASSERT_EQ(2, renderSurfaceLayerList[1]->id()); // child1
3303 ASSERT_EQ(4, renderSurfaceLayerList[2]->id()); // grandChild1
3304 ASSERT_EQ(3, renderSurfaceLayerList[3]->id()); // child2
3305
3306 // Nothing overlaps the rootLayer at (1, 1), so hit testing there should find the root layer.
3307 IntPoint testPoint = IntPoint(1, 1);
3308 CCLayerImpl* resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3309 ASSERT_TRUE(resultLayer);
3310 EXPECT_EQ(1, resultLayer->id());
3311
3312 // At (15, 15), child1 and root are the only layers. child1 is expected to be on top.
3313 testPoint = IntPoint(15, 15);
3314 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3315 ASSERT_TRUE(resultLayer);
3316 EXPECT_EQ(2, resultLayer->id());
3317
3318 // At (51, 20), child1 and child2 overlap. child2 is expected to be on top.
3319 testPoint = IntPoint(51, 20);
3320 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3321 ASSERT_TRUE(resultLayer);
3322 EXPECT_EQ(3, resultLayer->id());
3323
3324 // At (80, 51), child2 and grandChild1 overlap. child2 is expected to be on top.
3325 testPoint = IntPoint(80, 51);
3326 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3327 ASSERT_TRUE(resultLayer);
3328 EXPECT_EQ(3, resultLayer->id());
3329
3330 // At (51, 51), all layers overlap each other. child2 is expected to be on top of all other layers.
3331 testPoint = IntPoint(51, 51);
3332 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3333 ASSERT_TRUE(resultLayer);
3334 EXPECT_EQ(3, resultLayer->id());
3335
3336 // At (20, 51), child1 and grandChild1 overlap. grandChild1 is expected to be on top.
3337 testPoint = IntPoint(20, 51);
3338 resultLayer = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(testPoint, renderSurfaceLayerList);
3339 ASSERT_TRUE(resultLayer);
3340 EXPECT_EQ(4, resultLayer->id());
3341}
3342
[email protected]be3aa6f2012-08-31 23:55:403343class MockContentLayerChromiumClient : public ContentLayerChromiumClient {
[email protected]94f206c12012-08-25 00:09:143344public:
[email protected]be3aa6f2012-08-31 23:55:403345 MockContentLayerChromiumClient() { }
3346 virtual ~MockContentLayerChromiumClient() { }
[email protected]94f206c12012-08-25 00:09:143347 virtual void paintContents(SkCanvas*, const IntRect& clip, FloatRect& opaque) OVERRIDE { }
3348};
3349
[email protected]be3aa6f2012-08-31 23:55:403350PassRefPtr<ContentLayerChromium> createDrawableContentLayerChromium(ContentLayerChromiumClient* delegate)
[email protected]94f206c12012-08-25 00:09:143351{
3352 RefPtr<ContentLayerChromium> toReturn = ContentLayerChromium::create(delegate);
3353 toReturn->setIsDrawable(true);
3354 return toReturn.release();
3355}
3356
3357TEST(CCLayerTreeHostCommonTest, verifyLayerTransformsInHighDPI)
3358{
3359 // Verify draw and screen space transforms of layers not in a surface.
[email protected]be3aa6f2012-08-31 23:55:403360 MockContentLayerChromiumClient delegate;
[email protected]94f206c12012-08-25 00:09:143361 WebTransformationMatrix identityMatrix;
3362
3363 RefPtr<ContentLayerChromium> parent = createDrawableContentLayerChromium(&delegate);
3364 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
3365
3366 RefPtr<ContentLayerChromium> child = createDrawableContentLayerChromium(&delegate);
3367 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(2, 2), IntSize(10, 10), true);
3368
3369 RefPtr<ContentLayerChromium> childNoScale = createDrawableContentLayerChromium(&delegate);
3370 setLayerPropertiesForTesting(childNoScale.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(2, 2), IntSize(10, 10), true);
3371
3372 parent->addChild(child);
3373 parent->addChild(childNoScale);
3374
3375 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
3376 int dummyMaxTextureSize = 512;
3377
3378 const double deviceScaleFactor = 2.5;
3379 parent->setContentsScale(deviceScaleFactor);
3380 child->setContentsScale(deviceScaleFactor);
3381 EXPECT_EQ(childNoScale->contentsScale(), 1);
3382
3383 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList);
3384
3385 EXPECT_EQ(1u, renderSurfaceLayerList.size());
3386
3387 // Verify parent transforms
3388 WebTransformationMatrix expectedParentTransform;
3389 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedParentTransform, parent->screenSpaceTransform());
3390 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedParentTransform, parent->drawTransform());
3391
3392 // Verify results of transformed parent rects
3393 FloatRect parentContentBounds(FloatPoint(), FloatSize(parent->contentBounds()));
3394
3395 FloatRect parentDrawRect = CCMathUtil::mapClippedRect(parent->drawTransform(), parentContentBounds);
3396 FloatRect parentScreenSpaceRect = CCMathUtil::mapClippedRect(parent->screenSpaceTransform(), parentContentBounds);
3397
3398 FloatRect expectedParentDrawRect(FloatPoint(), parent->bounds());
3399 expectedParentDrawRect.scale(deviceScaleFactor);
3400 EXPECT_FLOAT_RECT_EQ(expectedParentDrawRect, parentDrawRect);
3401 EXPECT_FLOAT_RECT_EQ(expectedParentDrawRect, parentScreenSpaceRect);
3402
3403 // Verify child transforms
3404 WebTransformationMatrix expectedChildTransform;
3405 expectedChildTransform.translate(deviceScaleFactor * child->position().x(), deviceScaleFactor * child->position().y());
3406 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
3407 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->screenSpaceTransform());
3408
3409 // Verify results of transformed child rects
3410 FloatRect childContentBounds(FloatPoint(), FloatSize(child->contentBounds()));
3411
3412 FloatRect childDrawRect = CCMathUtil::mapClippedRect(child->drawTransform(), childContentBounds);
3413 FloatRect childScreenSpaceRect = CCMathUtil::mapClippedRect(child->screenSpaceTransform(), childContentBounds);
3414
3415 FloatRect expectedChildDrawRect(FloatPoint(), child->bounds());
3416 expectedChildDrawRect.move(child->position().x(), child->position().y());
3417 expectedChildDrawRect.scale(deviceScaleFactor);
3418 EXPECT_FLOAT_RECT_EQ(expectedChildDrawRect, childDrawRect);
3419 EXPECT_FLOAT_RECT_EQ(expectedChildDrawRect, childScreenSpaceRect);
3420
3421 // Verify childNoScale transforms
3422 WebTransformationMatrix expectedChildNoScaleTransform = child->drawTransform();
3423 // All transforms operate on content rects. The child's content rect
3424 // incorporates device scale, but the childNoScale does not; add it here.
3425 expectedChildNoScaleTransform.scale(deviceScaleFactor);
3426 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildNoScaleTransform, childNoScale->drawTransform());
3427 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildNoScaleTransform, childNoScale->screenSpaceTransform());
3428}
3429
3430TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceTransformsInHighDPI)
3431{
[email protected]be3aa6f2012-08-31 23:55:403432 MockContentLayerChromiumClient delegate;
[email protected]94f206c12012-08-25 00:09:143433 WebTransformationMatrix identityMatrix;
3434
3435 RefPtr<ContentLayerChromium> parent = createDrawableContentLayerChromium(&delegate);
3436 setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(30, 30), true);
3437
3438 RefPtr<ContentLayerChromium> child = createDrawableContentLayerChromium(&delegate);
3439 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(2, 2), IntSize(10, 10), true);
3440
3441 WebTransformationMatrix replicaTransform;
3442 replicaTransform.scaleNonUniform(1, -1);
3443 RefPtr<ContentLayerChromium> replica = createDrawableContentLayerChromium(&delegate);
3444 setLayerPropertiesForTesting(replica.get(), replicaTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(2, 2), IntSize(10, 10), true);
3445
3446 // This layer should end up in the same surface as child, with the same draw
3447 // and screen space transforms.
3448 RefPtr<ContentLayerChromium> duplicateChildNonOwner = createDrawableContentLayerChromium(&delegate);
3449 setLayerPropertiesForTesting(duplicateChildNonOwner.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), true);
3450
3451 parent->addChild(child);
3452 child->addChild(duplicateChildNonOwner);
3453 child->setReplicaLayer(replica.get());
3454
3455 Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
3456 int dummyMaxTextureSize = 512;
3457
3458 const double deviceScaleFactor = 1.5;
3459 parent->setContentsScale(deviceScaleFactor);
3460 child->setContentsScale(deviceScaleFactor);
3461 duplicateChildNonOwner->setContentsScale(deviceScaleFactor);
3462 replica->setContentsScale(deviceScaleFactor);
3463
3464 CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList);
3465
3466 // We should have two render surfaces. The root's render surface and child's
3467 // render surface (it needs one because it has a replica layer).
3468 EXPECT_EQ(2u, renderSurfaceLayerList.size());
3469
3470 WebTransformationMatrix expectedParentTransform;
3471 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedParentTransform, parent->screenSpaceTransform());
3472 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedParentTransform, parent->drawTransform());
3473
3474 WebTransformationMatrix expectedDrawTransform;
3475 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedDrawTransform, child->drawTransform());
3476
3477 WebTransformationMatrix expectedScreenSpaceTransform;
3478 expectedScreenSpaceTransform.translate(deviceScaleFactor * child->position().x(), deviceScaleFactor * child->position().y());
3479 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedScreenSpaceTransform, child->screenSpaceTransform());
3480
3481 WebTransformationMatrix expectedDuplicateChildDrawTransform = child->drawTransform();
3482 EXPECT_TRANSFORMATION_MATRIX_EQ(child->drawTransform(), duplicateChildNonOwner->drawTransform());
3483 EXPECT_TRANSFORMATION_MATRIX_EQ(child->screenSpaceTransform(), duplicateChildNonOwner->screenSpaceTransform());
[email protected]022cbf162012-09-01 01:15:173484 EXPECT_RECT_EQ(child->drawableContentRect(), duplicateChildNonOwner->drawableContentRect());
[email protected]94f206c12012-08-25 00:09:143485 EXPECT_EQ(child->contentBounds(), duplicateChildNonOwner->contentBounds());
3486
3487 WebTransformationMatrix expectedRenderSurfaceDrawTransform;
3488 expectedRenderSurfaceDrawTransform.translate(deviceScaleFactor * child->position().x(), deviceScaleFactor * child->position().y());
3489 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedRenderSurfaceDrawTransform, child->renderSurface()->drawTransform());
3490
3491 WebTransformationMatrix expectedSurfaceDrawTransform;
3492 expectedSurfaceDrawTransform.translate(deviceScaleFactor * 2, deviceScaleFactor * 2);
3493 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedSurfaceDrawTransform, child->renderSurface()->drawTransform());
3494
3495 WebTransformationMatrix expectedSurfaceScreenSpaceTransform;
3496 expectedSurfaceScreenSpaceTransform.translate(deviceScaleFactor * 2, deviceScaleFactor * 2);
3497 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedSurfaceScreenSpaceTransform, child->renderSurface()->screenSpaceTransform());
3498
3499 WebTransformationMatrix expectedReplicaDrawTransform;
3500 expectedReplicaDrawTransform.setM22(-1);
3501 expectedReplicaDrawTransform.setM41(6);
3502 expectedReplicaDrawTransform.setM42(6);
3503 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedReplicaDrawTransform, child->renderSurface()->replicaDrawTransform());
3504
3505 WebTransformationMatrix expectedReplicaScreenSpaceTransform;
3506 expectedReplicaScreenSpaceTransform.setM22(-1);
3507 expectedReplicaScreenSpaceTransform.setM41(6);
3508 expectedReplicaScreenSpaceTransform.setM42(6);
3509 EXPECT_TRANSFORMATION_MATRIX_EQ(expectedReplicaScreenSpaceTransform, child->renderSurface()->replicaScreenSpaceTransform());
3510}
3511
3512TEST(CCLayerTreeHostCommonTest, verifySubtreeSearch)
3513{
3514 RefPtr<LayerChromium> root = LayerChromium::create();
3515 RefPtr<LayerChromium> child = LayerChromium::create();
3516 RefPtr<LayerChromium> grandChild = LayerChromium::create();
3517 RefPtr<LayerChromium> maskLayer = LayerChromium::create();
3518 RefPtr<LayerChromium> replicaLayer = LayerChromium::create();
3519
3520 grandChild->setReplicaLayer(replicaLayer.get());
3521 child->addChild(grandChild.get());
3522 child->setMaskLayer(maskLayer.get());
3523 root->addChild(child.get());
3524
3525 int nonexistentId = -1;
3526 EXPECT_EQ(root, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), root->id()));
3527 EXPECT_EQ(child, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), child->id()));
3528 EXPECT_EQ(grandChild, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), grandChild->id()));
3529 EXPECT_EQ(maskLayer, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), maskLayer->id()));
3530 EXPECT_EQ(replicaLayer, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), replicaLayer->id()));
3531 EXPECT_EQ(0, CCLayerTreeHostCommon::findLayerInSubtree(root.get(), nonexistentId));
3532}
3533
3534} // namespace