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