| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "cc/layers/layer_position_constraint.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "cc/layers/layer_impl.h" | |
| 10 #include "cc/test/fake_impl_proxy.h" | |
| 11 #include "cc/test/fake_layer_tree_host_impl.h" | |
| 12 #include "cc/test/geometry_test_utils.h" | |
| 13 #include "cc/test/test_shared_bitmap_manager.h" | |
| 14 #include "cc/test/test_task_graph_runner.h" | |
| 15 #include "cc/trees/layer_tree_host_common.h" | |
| 16 #include "testing/gtest/include/gtest/gtest.h" | |
| 17 | |
| 18 namespace cc { | |
| 19 namespace { | |
| 20 | |
| 21 void SetLayerPropertiesForTesting(LayerImpl* layer, | |
| 22 const gfx::Transform& transform, | |
| 23 const gfx::Point3F& transform_origin, | |
| 24 const gfx::PointF& position, | |
| 25 const gfx::Size& bounds, | |
| 26 bool flatten_transform) { | |
| 27 layer->SetTransform(transform); | |
| 28 layer->SetTransformOrigin(transform_origin); | |
| 29 layer->SetPosition(position); | |
| 30 layer->SetBounds(bounds); | |
| 31 layer->SetShouldFlattenTransform(flatten_transform); | |
| 32 layer->SetContentBounds(bounds); | |
| 33 } | |
| 34 | |
| 35 void ExecuteCalculateDrawProperties(LayerImpl* root_layer, | |
| 36 float device_scale_factor, | |
| 37 float page_scale_factor, | |
| 38 LayerImpl* page_scale_application_layer, | |
| 39 bool can_use_lcd_text) { | |
| 40 gfx::Transform identity_matrix; | |
| 41 std::vector<LayerImpl*> dummy_render_surface_layer_list; | |
| 42 LayerImpl* scroll_layer = root_layer->children()[0]; | |
| 43 gfx::Size device_viewport_size = | |
| 44 gfx::Size(root_layer->bounds().width() * device_scale_factor, | |
| 45 root_layer->bounds().height() * device_scale_factor); | |
| 46 | |
| 47 // We are probably not testing what is intended if the scroll_layer bounds are | |
| 48 // empty. | |
| 49 DCHECK(!scroll_layer->bounds().IsEmpty()); | |
| 50 LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( | |
| 51 root_layer, device_viewport_size, &dummy_render_surface_layer_list); | |
| 52 inputs.device_scale_factor = device_scale_factor; | |
| 53 inputs.page_scale_factor = page_scale_factor; | |
| 54 inputs.page_scale_application_layer = page_scale_application_layer; | |
| 55 inputs.can_use_lcd_text = can_use_lcd_text; | |
| 56 LayerTreeHostCommon::CalculateDrawProperties(&inputs); | |
| 57 } | |
| 58 | |
| 59 void ExecuteCalculateDrawProperties(LayerImpl* root_layer) { | |
| 60 LayerImpl* page_scale_application_layer = nullptr; | |
| 61 ExecuteCalculateDrawProperties( | |
| 62 root_layer, 1.f, 1.f, page_scale_application_layer, false); | |
| 63 } | |
| 64 | |
| 65 class LayerPositionConstraintTest : public testing::Test { | |
| 66 public: | |
| 67 LayerPositionConstraintTest() | |
| 68 : host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_) { | |
| 69 root_ = CreateTreeForTest(); | |
| 70 scroll_ = root_->children()[0]; | |
| 71 fixed_to_top_left_.set_is_fixed_position(true); | |
| 72 fixed_to_bottom_right_.set_is_fixed_position(true); | |
| 73 fixed_to_bottom_right_.set_is_fixed_to_right_edge(true); | |
| 74 fixed_to_bottom_right_.set_is_fixed_to_bottom_edge(true); | |
| 75 } | |
| 76 | |
| 77 scoped_ptr<LayerImpl> CreateTreeForTest() { | |
| 78 scoped_ptr<LayerImpl> root = | |
| 79 LayerImpl::Create(host_impl_.active_tree(), 42); | |
| 80 scoped_ptr<LayerImpl> scroll_layer = | |
| 81 LayerImpl::Create(host_impl_.active_tree(), 1); | |
| 82 scoped_ptr<LayerImpl> child = | |
| 83 LayerImpl::Create(host_impl_.active_tree(), 2); | |
| 84 scoped_ptr<LayerImpl> grand_child = | |
| 85 LayerImpl::Create(host_impl_.active_tree(), 3); | |
| 86 scoped_ptr<LayerImpl> great_grand_child = | |
| 87 LayerImpl::Create(host_impl_.active_tree(), 4); | |
| 88 | |
| 89 root->SetHasRenderSurface(true); | |
| 90 gfx::Transform IdentityMatrix; | |
| 91 gfx::Point3F transform_origin; | |
| 92 gfx::PointF position; | |
| 93 gfx::Size bounds(200, 200); | |
| 94 gfx::Size clip_bounds(100, 100); | |
| 95 SetLayerPropertiesForTesting(scroll_layer.get(), | |
| 96 IdentityMatrix, | |
| 97 transform_origin, | |
| 98 position, | |
| 99 bounds, | |
| 100 true); | |
| 101 SetLayerPropertiesForTesting( | |
| 102 child.get(), IdentityMatrix, transform_origin, position, bounds, true); | |
| 103 SetLayerPropertiesForTesting(grand_child.get(), | |
| 104 IdentityMatrix, | |
| 105 transform_origin, | |
| 106 position, | |
| 107 bounds, | |
| 108 true); | |
| 109 SetLayerPropertiesForTesting(great_grand_child.get(), | |
| 110 IdentityMatrix, | |
| 111 transform_origin, | |
| 112 position, | |
| 113 bounds, | |
| 114 true); | |
| 115 | |
| 116 root->SetBounds(clip_bounds); | |
| 117 scroll_layer->SetScrollClipLayer(root->id()); | |
| 118 child->SetScrollClipLayer(root->id()); | |
| 119 grand_child->SetScrollClipLayer(root->id()); | |
| 120 | |
| 121 grand_child->AddChild(great_grand_child.Pass()); | |
| 122 child->AddChild(grand_child.Pass()); | |
| 123 scroll_layer->AddChild(child.Pass()); | |
| 124 root->AddChild(scroll_layer.Pass()); | |
| 125 | |
| 126 return root.Pass(); | |
| 127 } | |
| 128 | |
| 129 protected: | |
| 130 FakeImplProxy proxy_; | |
| 131 TestSharedBitmapManager shared_bitmap_manager_; | |
| 132 TestTaskGraphRunner task_graph_runner_; | |
| 133 FakeLayerTreeHostImpl host_impl_; | |
| 134 scoped_ptr<LayerImpl> root_; | |
| 135 LayerImpl* scroll_; | |
| 136 | |
| 137 LayerPositionConstraint fixed_to_top_left_; | |
| 138 LayerPositionConstraint fixed_to_bottom_right_; | |
| 139 }; | |
| 140 | |
| 141 namespace { | |
| 142 | |
| 143 void SetFixedContainerSizeDelta(LayerImpl* scroll_layer, | |
| 144 const gfx::Vector2d& delta) { | |
| 145 DCHECK(scroll_layer); | |
| 146 DCHECK(scroll_layer->scrollable()); | |
| 147 | |
| 148 LayerImpl* container_layer = scroll_layer->scroll_clip_layer(); | |
| 149 container_layer->SetBoundsDelta(delta); | |
| 150 } | |
| 151 } // namespace | |
| 152 | |
| 153 TEST_F(LayerPositionConstraintTest, | |
| 154 ScrollCompensationForFixedPositionLayerWithDirectContainer) { | |
| 155 // This test checks for correct scroll compensation when the fixed-position | |
| 156 // container is the direct parent of the fixed-position layer. | |
| 157 LayerImpl* child = scroll_->children()[0]; | |
| 158 LayerImpl* grand_child = child->children()[0]; | |
| 159 | |
| 160 child->SetIsContainerForFixedPositionLayers(true); | |
| 161 grand_child->SetPositionConstraint(fixed_to_top_left_); | |
| 162 | |
| 163 // Case 1: scroll delta of 0, 0 | |
| 164 child->SetScrollDelta(gfx::Vector2d(0, 0)); | |
| 165 ExecuteCalculateDrawProperties(root_.get()); | |
| 166 | |
| 167 gfx::Transform expected_child_transform; | |
| 168 gfx::Transform expected_grand_child_transform = expected_child_transform; | |
| 169 | |
| 170 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 171 child->draw_transform()); | |
| 172 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 173 grand_child->draw_transform()); | |
| 174 | |
| 175 // Case 2: scroll delta of 10, 10 | |
| 176 child->SetScrollDelta(gfx::Vector2d(10, 10)); | |
| 177 ExecuteCalculateDrawProperties(root_.get()); | |
| 178 | |
| 179 // Here the child is affected by scroll delta, but the fixed position | |
| 180 // grand_child should not be affected. | |
| 181 expected_child_transform.MakeIdentity(); | |
| 182 expected_child_transform.Translate(-10.0, -10.0); | |
| 183 | |
| 184 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 185 child->draw_transform()); | |
| 186 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 187 grand_child->draw_transform()); | |
| 188 | |
| 189 // Case 3: fixed-container size delta of 20, 20 | |
| 190 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); | |
| 191 ExecuteCalculateDrawProperties(root_.get()); | |
| 192 | |
| 193 // Top-left fixed-position layer should not be affected by container size. | |
| 194 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 195 child->draw_transform()); | |
| 196 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 197 grand_child->draw_transform()); | |
| 198 | |
| 199 // Case 4: Bottom-right fixed-position layer. | |
| 200 grand_child->SetPositionConstraint(fixed_to_bottom_right_); | |
| 201 ExecuteCalculateDrawProperties(root_.get()); | |
| 202 | |
| 203 // Bottom-right fixed-position layer moves as container resizes. | |
| 204 expected_grand_child_transform.MakeIdentity(); | |
| 205 // Apply size delta from the child(container) layer. | |
| 206 expected_grand_child_transform.Translate(20.0, 20.0); | |
| 207 | |
| 208 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 209 child->draw_transform()); | |
| 210 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 211 grand_child->draw_transform()); | |
| 212 } | |
| 213 | |
| 214 TEST_F(LayerPositionConstraintTest, | |
| 215 ScrollCompensationForFixedPositionLayerWithTransformedDirectContainer) { | |
| 216 // This test checks for correct scroll compensation when the fixed-position | |
| 217 // container is the direct parent of the fixed-position layer, but that | |
| 218 // container is transformed. In this case, the fixed position element | |
| 219 // inherits the container's transform, but the scroll delta that has to be | |
| 220 // undone should not be affected by that transform. | |
| 221 // | |
| 222 // Transforms are in general non-commutative; using something like a | |
| 223 // non-uniform scale helps to verify that translations and non-uniform scales | |
| 224 // are applied in the correct order. | |
| 225 LayerImpl* child = scroll_->children()[0]; | |
| 226 LayerImpl* grand_child = child->children()[0]; | |
| 227 | |
| 228 // This scale will cause child and grand_child to be effectively 200 x 800 | |
| 229 // with respect to the render target. | |
| 230 gfx::Transform non_uniform_scale; | |
| 231 non_uniform_scale.Scale(2.0, 8.0); | |
| 232 child->SetTransform(non_uniform_scale); | |
| 233 | |
| 234 child->SetIsContainerForFixedPositionLayers(true); | |
| 235 grand_child->SetPositionConstraint(fixed_to_top_left_); | |
| 236 | |
| 237 // Case 1: scroll delta of 0, 0 | |
| 238 child->SetScrollDelta(gfx::Vector2d(0, 0)); | |
| 239 ExecuteCalculateDrawProperties(root_.get()); | |
| 240 | |
| 241 gfx::Transform expected_child_transform; | |
| 242 expected_child_transform.PreconcatTransform(non_uniform_scale); | |
| 243 | |
| 244 gfx::Transform expected_grand_child_transform = expected_child_transform; | |
| 245 | |
| 246 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 247 child->draw_transform()); | |
| 248 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 249 grand_child->draw_transform()); | |
| 250 | |
| 251 // Case 2: scroll delta of 10, 20 | |
| 252 child->SetScrollDelta(gfx::Vector2d(10, 20)); | |
| 253 ExecuteCalculateDrawProperties(root_.get()); | |
| 254 | |
| 255 // The child should be affected by scroll delta, but the fixed position | |
| 256 // grand_child should not be affected. | |
| 257 expected_child_transform.MakeIdentity(); | |
| 258 expected_child_transform.Translate(-10.0, -20.0); // scroll delta | |
| 259 expected_child_transform.PreconcatTransform(non_uniform_scale); | |
| 260 | |
| 261 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 262 child->draw_transform()); | |
| 263 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 264 grand_child->draw_transform()); | |
| 265 | |
| 266 // Case 3: fixed-container size delta of 20, 20 | |
| 267 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); | |
| 268 ExecuteCalculateDrawProperties(root_.get()); | |
| 269 | |
| 270 // Top-left fixed-position layer should not be affected by container size. | |
| 271 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 272 child->draw_transform()); | |
| 273 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 274 grand_child->draw_transform()); | |
| 275 | |
| 276 // Case 4: Bottom-right fixed-position layer. | |
| 277 grand_child->SetPositionConstraint(fixed_to_bottom_right_); | |
| 278 ExecuteCalculateDrawProperties(root_.get()); | |
| 279 | |
| 280 // Bottom-right fixed-position layer moves as container resizes. | |
| 281 expected_grand_child_transform.MakeIdentity(); | |
| 282 // Apply child layer transform. | |
| 283 expected_grand_child_transform.PreconcatTransform(non_uniform_scale); | |
| 284 // Apply size delta from the child(container) layer. | |
| 285 expected_grand_child_transform.Translate(20.0, 20.0); | |
| 286 | |
| 287 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 288 child->draw_transform()); | |
| 289 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 290 grand_child->draw_transform()); | |
| 291 } | |
| 292 | |
| 293 TEST_F(LayerPositionConstraintTest, | |
| 294 ScrollCompensationForFixedPositionLayerWithDistantContainer) { | |
| 295 // This test checks for correct scroll compensation when the fixed-position | |
| 296 // container is NOT the direct parent of the fixed-position layer. | |
| 297 LayerImpl* child = scroll_->children()[0]; | |
| 298 LayerImpl* grand_child = child->children()[0]; | |
| 299 LayerImpl* great_grand_child = grand_child->children()[0]; | |
| 300 | |
| 301 child->SetIsContainerForFixedPositionLayers(true); | |
| 302 grand_child->SetPosition(gfx::PointF(8.f, 6.f)); | |
| 303 great_grand_child->SetPositionConstraint(fixed_to_top_left_); | |
| 304 | |
| 305 // Case 1: scroll delta of 0, 0 | |
| 306 child->SetScrollDelta(gfx::Vector2d(0, 0)); | |
| 307 ExecuteCalculateDrawProperties(root_.get()); | |
| 308 | |
| 309 gfx::Transform expected_child_transform; | |
| 310 gfx::Transform expected_grand_child_transform; | |
| 311 expected_grand_child_transform.Translate(8.0, 6.0); | |
| 312 | |
| 313 gfx::Transform expected_great_grand_child_transform = | |
| 314 expected_grand_child_transform; | |
| 315 | |
| 316 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 317 child->draw_transform()); | |
| 318 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 319 grand_child->draw_transform()); | |
| 320 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 321 great_grand_child->draw_transform()); | |
| 322 | |
| 323 // Case 2: scroll delta of 10, 10 | |
| 324 child->SetScrollDelta(gfx::Vector2d(10, 10)); | |
| 325 ExecuteCalculateDrawProperties(root_.get()); | |
| 326 | |
| 327 // Here the child and grand_child are affected by scroll delta, but the fixed | |
| 328 // position great_grand_child should not be affected. | |
| 329 expected_child_transform.MakeIdentity(); | |
| 330 expected_child_transform.Translate(-10.0, -10.0); | |
| 331 expected_grand_child_transform.MakeIdentity(); | |
| 332 expected_grand_child_transform.Translate(-2.0, -4.0); | |
| 333 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 334 child->draw_transform()); | |
| 335 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 336 grand_child->draw_transform()); | |
| 337 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 338 great_grand_child->draw_transform()); | |
| 339 | |
| 340 // Case 3: fixed-container size delta of 20, 20 | |
| 341 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); | |
| 342 ExecuteCalculateDrawProperties(root_.get()); | |
| 343 | |
| 344 // Top-left fixed-position layer should not be affected by container size. | |
| 345 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 346 child->draw_transform()); | |
| 347 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 348 grand_child->draw_transform()); | |
| 349 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 350 great_grand_child->draw_transform()); | |
| 351 | |
| 352 // Case 4: Bottom-right fixed-position layer. | |
| 353 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_); | |
| 354 ExecuteCalculateDrawProperties(root_.get()); | |
| 355 | |
| 356 // Bottom-right fixed-position layer moves as container resizes. | |
| 357 expected_great_grand_child_transform.MakeIdentity(); | |
| 358 // Apply size delta from the child(container) layer. | |
| 359 expected_great_grand_child_transform.Translate(20.0, 20.0); | |
| 360 // Apply layer position from the grand child layer. | |
| 361 expected_great_grand_child_transform.Translate(8.0, 6.0); | |
| 362 | |
| 363 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 364 child->draw_transform()); | |
| 365 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 366 grand_child->draw_transform()); | |
| 367 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 368 great_grand_child->draw_transform()); | |
| 369 } | |
| 370 | |
| 371 TEST_F(LayerPositionConstraintTest, | |
| 372 ScrollCompensationForFixedPositionLayerWithDistantContainerAndTransforms) { | |
| 373 // This test checks for correct scroll compensation when the fixed-position | |
| 374 // container is NOT the direct parent of the fixed-position layer, and the | |
| 375 // hierarchy has various transforms that have to be processed in the correct | |
| 376 // order. | |
| 377 LayerImpl* child = scroll_->children()[0]; | |
| 378 LayerImpl* grand_child = child->children()[0]; | |
| 379 LayerImpl* great_grand_child = grand_child->children()[0]; | |
| 380 | |
| 381 gfx::Transform rotation_about_z; | |
| 382 rotation_about_z.RotateAboutZAxis(90.0); | |
| 383 | |
| 384 child->SetIsContainerForFixedPositionLayers(true); | |
| 385 child->SetTransform(rotation_about_z); | |
| 386 grand_child->SetPosition(gfx::PointF(8.f, 6.f)); | |
| 387 grand_child->SetTransform(rotation_about_z); | |
| 388 // great_grand_child is positioned upside-down with respect to the render | |
| 389 // target. | |
| 390 great_grand_child->SetPositionConstraint(fixed_to_top_left_); | |
| 391 | |
| 392 // Case 1: scroll delta of 0, 0 | |
| 393 child->SetScrollDelta(gfx::Vector2d(0, 0)); | |
| 394 ExecuteCalculateDrawProperties(root_.get()); | |
| 395 | |
| 396 gfx::Transform expected_child_transform; | |
| 397 expected_child_transform.PreconcatTransform(rotation_about_z); | |
| 398 | |
| 399 gfx::Transform expected_grand_child_transform; | |
| 400 expected_grand_child_transform.PreconcatTransform( | |
| 401 rotation_about_z); // child's local transform is inherited | |
| 402 // translation because of position occurs before layer's local transform. | |
| 403 expected_grand_child_transform.Translate(8.0, 6.0); | |
| 404 expected_grand_child_transform.PreconcatTransform( | |
| 405 rotation_about_z); // grand_child's local transform | |
| 406 | |
| 407 gfx::Transform expected_great_grand_child_transform = | |
| 408 expected_grand_child_transform; | |
| 409 | |
| 410 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 411 child->draw_transform()); | |
| 412 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 413 grand_child->draw_transform()); | |
| 414 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 415 great_grand_child->draw_transform()); | |
| 416 | |
| 417 // Case 2: scroll delta of 10, 20 | |
| 418 child->SetScrollDelta(gfx::Vector2d(10, 20)); | |
| 419 ExecuteCalculateDrawProperties(root_.get()); | |
| 420 | |
| 421 // Here the child and grand_child are affected by scroll delta, but the fixed | |
| 422 // position great_grand_child should not be affected. | |
| 423 expected_child_transform.MakeIdentity(); | |
| 424 expected_child_transform.Translate(-10.0, -20.0); // scroll delta | |
| 425 expected_child_transform.PreconcatTransform(rotation_about_z); | |
| 426 | |
| 427 expected_grand_child_transform.MakeIdentity(); | |
| 428 expected_grand_child_transform.Translate( | |
| 429 -10.0, -20.0); // child's scroll delta is inherited | |
| 430 expected_grand_child_transform.PreconcatTransform( | |
| 431 rotation_about_z); // child's local transform is inherited | |
| 432 // translation because of position occurs before layer's local transform. | |
| 433 expected_grand_child_transform.Translate(8.0, 6.0); | |
| 434 expected_grand_child_transform.PreconcatTransform( | |
| 435 rotation_about_z); // grand_child's local transform | |
| 436 | |
| 437 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 438 child->draw_transform()); | |
| 439 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 440 grand_child->draw_transform()); | |
| 441 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 442 great_grand_child->draw_transform()); | |
| 443 | |
| 444 // Case 3: fixed-container size delta of 20, 20 | |
| 445 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); | |
| 446 ExecuteCalculateDrawProperties(root_.get()); | |
| 447 | |
| 448 // Top-left fixed-position layer should not be affected by container size. | |
| 449 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 450 child->draw_transform()); | |
| 451 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 452 grand_child->draw_transform()); | |
| 453 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 454 great_grand_child->draw_transform()); | |
| 455 | |
| 456 // Case 4: Bottom-right fixed-position layer. | |
| 457 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_); | |
| 458 ExecuteCalculateDrawProperties(root_.get()); | |
| 459 | |
| 460 // Bottom-right fixed-position layer moves as container resizes. | |
| 461 expected_great_grand_child_transform.MakeIdentity(); | |
| 462 // Apply child layer transform. | |
| 463 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); | |
| 464 // Apply size delta from the child(container) layer. | |
| 465 expected_great_grand_child_transform.Translate(20.0, 20.0); | |
| 466 // Apply layer position from the grand child layer. | |
| 467 expected_great_grand_child_transform.Translate(8.0, 6.0); | |
| 468 // Apply grand child layer transform. | |
| 469 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); | |
| 470 | |
| 471 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 472 child->draw_transform()); | |
| 473 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 474 grand_child->draw_transform()); | |
| 475 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 476 great_grand_child->draw_transform()); | |
| 477 } | |
| 478 | |
| 479 TEST_F(LayerPositionConstraintTest, | |
| 480 ScrollCompensationForFixedPositionLayerWithMultipleScrollDeltas) { | |
| 481 // This test checks for correct scroll compensation when the fixed-position | |
| 482 // container has multiple ancestors that have nonzero scroll delta before | |
| 483 // reaching the space where the layer is fixed. In this test, each scroll | |
| 484 // delta occurs in a different space because of each layer's local transform. | |
| 485 // This test checks for correct scroll compensation when the fixed-position | |
| 486 // container is NOT the direct parent of the fixed-position layer, and the | |
| 487 // hierarchy has various transforms that have to be processed in the correct | |
| 488 // order. | |
| 489 LayerImpl* child = scroll_->children()[0]; | |
| 490 LayerImpl* grand_child = child->children()[0]; | |
| 491 LayerImpl* great_grand_child = grand_child->children()[0]; | |
| 492 | |
| 493 gfx::Transform rotation_about_z; | |
| 494 rotation_about_z.RotateAboutZAxis(90.0); | |
| 495 | |
| 496 child->SetIsContainerForFixedPositionLayers(true); | |
| 497 child->SetTransform(rotation_about_z); | |
| 498 grand_child->SetPosition(gfx::PointF(8.f, 6.f)); | |
| 499 grand_child->SetTransform(rotation_about_z); | |
| 500 // great_grand_child is positioned upside-down with respect to the render | |
| 501 // target. | |
| 502 great_grand_child->SetPositionConstraint(fixed_to_top_left_); | |
| 503 | |
| 504 // Case 1: scroll delta of 0, 0 | |
| 505 child->SetScrollDelta(gfx::Vector2d(0, 0)); | |
| 506 ExecuteCalculateDrawProperties(root_.get()); | |
| 507 | |
| 508 gfx::Transform expected_child_transform; | |
| 509 expected_child_transform.PreconcatTransform(rotation_about_z); | |
| 510 | |
| 511 gfx::Transform expected_grand_child_transform; | |
| 512 expected_grand_child_transform.PreconcatTransform( | |
| 513 rotation_about_z); // child's local transform is inherited | |
| 514 // translation because of position occurs before layer's local transform. | |
| 515 expected_grand_child_transform.Translate(8.0, 6.0); | |
| 516 expected_grand_child_transform.PreconcatTransform( | |
| 517 rotation_about_z); // grand_child's local transform | |
| 518 | |
| 519 gfx::Transform expected_great_grand_child_transform = | |
| 520 expected_grand_child_transform; | |
| 521 | |
| 522 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 523 child->draw_transform()); | |
| 524 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 525 grand_child->draw_transform()); | |
| 526 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 527 great_grand_child->draw_transform()); | |
| 528 | |
| 529 // Case 2: scroll delta of 10, 20 | |
| 530 child->SetScrollDelta(gfx::Vector2d(10, 0)); | |
| 531 grand_child->SetScrollDelta(gfx::Vector2d(5, 0)); | |
| 532 ExecuteCalculateDrawProperties(root_.get()); | |
| 533 | |
| 534 // Here the child and grand_child are affected by scroll delta, but the fixed | |
| 535 // position great_grand_child should not be affected. | |
| 536 expected_child_transform.MakeIdentity(); | |
| 537 expected_child_transform.Translate(-10.0, 0.0); // scroll delta | |
| 538 expected_child_transform.PreconcatTransform(rotation_about_z); | |
| 539 | |
| 540 expected_grand_child_transform.MakeIdentity(); | |
| 541 expected_grand_child_transform.Translate( | |
| 542 -10.0, 0.0); // child's scroll delta is inherited | |
| 543 expected_grand_child_transform.PreconcatTransform( | |
| 544 rotation_about_z); // child's local transform is inherited | |
| 545 expected_grand_child_transform.Translate(-5.0, | |
| 546 0.0); // grand_child's scroll delta | |
| 547 // translation because of position occurs before layer's local transform. | |
| 548 expected_grand_child_transform.Translate(8.0, 6.0); | |
| 549 expected_grand_child_transform.PreconcatTransform( | |
| 550 rotation_about_z); // grand_child's local transform | |
| 551 | |
| 552 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 553 child->draw_transform()); | |
| 554 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 555 grand_child->draw_transform()); | |
| 556 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 557 great_grand_child->draw_transform()); | |
| 558 | |
| 559 // Case 3: fixed-container size delta of 20, 20 | |
| 560 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); | |
| 561 ExecuteCalculateDrawProperties(root_.get()); | |
| 562 | |
| 563 // Top-left fixed-position layer should not be affected by container size. | |
| 564 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 565 child->draw_transform()); | |
| 566 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 567 grand_child->draw_transform()); | |
| 568 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 569 great_grand_child->draw_transform()); | |
| 570 | |
| 571 // Case 4: Bottom-right fixed-position layer. | |
| 572 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_); | |
| 573 ExecuteCalculateDrawProperties(root_.get()); | |
| 574 | |
| 575 // Bottom-right fixed-position layer moves as container resizes. | |
| 576 expected_great_grand_child_transform.MakeIdentity(); | |
| 577 // Apply child layer transform. | |
| 578 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); | |
| 579 // Apply size delta from the child(container) layer. | |
| 580 expected_great_grand_child_transform.Translate(20.0, 20.0); | |
| 581 // Apply layer position from the grand child layer. | |
| 582 expected_great_grand_child_transform.Translate(8.0, 6.0); | |
| 583 // Apply grand child layer transform. | |
| 584 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); | |
| 585 | |
| 586 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 587 child->draw_transform()); | |
| 588 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 589 grand_child->draw_transform()); | |
| 590 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 591 great_grand_child->draw_transform()); | |
| 592 } | |
| 593 | |
| 594 TEST_F(LayerPositionConstraintTest, | |
| 595 ScrollCompensationForFixedPositionWithIntermediateSurfaceAndTransforms) { | |
| 596 // This test checks for correct scroll compensation when the fixed-position | |
| 597 // container contributes to a different render surface than the fixed-position | |
| 598 // layer. In this case, the surface draw transforms also have to be accounted | |
| 599 // for when checking the scroll delta. | |
| 600 LayerImpl* child = scroll_->children()[0]; | |
| 601 LayerImpl* grand_child = child->children()[0]; | |
| 602 LayerImpl* great_grand_child = grand_child->children()[0]; | |
| 603 | |
| 604 child->SetIsContainerForFixedPositionLayers(true); | |
| 605 grand_child->SetPosition(gfx::PointF(8.f, 6.f)); | |
| 606 grand_child->SetHasRenderSurface(true); | |
| 607 great_grand_child->SetPositionConstraint(fixed_to_top_left_); | |
| 608 great_grand_child->SetDrawsContent(true); | |
| 609 | |
| 610 gfx::Transform rotation_about_z; | |
| 611 rotation_about_z.RotateAboutZAxis(90.0); | |
| 612 grand_child->SetTransform(rotation_about_z); | |
| 613 | |
| 614 // Case 1: scroll delta of 0, 0 | |
| 615 child->SetScrollDelta(gfx::Vector2d(0, 0)); | |
| 616 ExecuteCalculateDrawProperties(root_.get()); | |
| 617 | |
| 618 gfx::Transform expected_child_transform; | |
| 619 gfx::Transform expected_surface_draw_transform; | |
| 620 expected_surface_draw_transform.Translate(8.0, 6.0); | |
| 621 expected_surface_draw_transform.PreconcatTransform(rotation_about_z); | |
| 622 gfx::Transform expected_grand_child_transform; | |
| 623 gfx::Transform expected_great_grand_child_transform; | |
| 624 ASSERT_TRUE(grand_child->render_surface()); | |
| 625 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 626 child->draw_transform()); | |
| 627 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
| 628 expected_surface_draw_transform, | |
| 629 grand_child->render_surface()->draw_transform()); | |
| 630 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 631 grand_child->draw_transform()); | |
| 632 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 633 great_grand_child->draw_transform()); | |
| 634 | |
| 635 // Case 2: scroll delta of 10, 30 | |
| 636 child->SetScrollDelta(gfx::Vector2d(10, 30)); | |
| 637 ExecuteCalculateDrawProperties(root_.get()); | |
| 638 | |
| 639 // Here the grand_child remains unchanged, because it scrolls along with the | |
| 640 // render surface, and the translation is actually in the render surface. But, | |
| 641 // the fixed position great_grand_child is more awkward: its actually being | |
| 642 // drawn with respect to the render surface, but it needs to remain fixed with | |
| 643 // resepct to a container beyond that surface. So, the net result is that, | |
| 644 // unlike previous tests where the fixed position layer's transform remains | |
| 645 // unchanged, here the fixed position layer's transform explicitly contains | |
| 646 // the translation that cancels out the scroll. | |
| 647 expected_child_transform.MakeIdentity(); | |
| 648 expected_child_transform.Translate(-10.0, -30.0); // scroll delta | |
| 649 | |
| 650 expected_surface_draw_transform.MakeIdentity(); | |
| 651 expected_surface_draw_transform.Translate(-10.0, -30.0); // scroll delta | |
| 652 expected_surface_draw_transform.Translate(8.0, 6.0); | |
| 653 expected_surface_draw_transform.PreconcatTransform(rotation_about_z); | |
| 654 | |
| 655 // The rotation and its inverse are needed to place the scroll delta | |
| 656 // compensation in the correct space. This test will fail if the | |
| 657 // rotation/inverse are backwards, too, so it requires perfect order of | |
| 658 // operations. | |
| 659 expected_great_grand_child_transform.MakeIdentity(); | |
| 660 expected_great_grand_child_transform.PreconcatTransform( | |
| 661 Inverse(rotation_about_z)); | |
| 662 // explicit canceling out the scroll delta that gets embedded in the fixed | |
| 663 // position layer's surface. | |
| 664 expected_great_grand_child_transform.Translate(10.0, 30.0); | |
| 665 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); | |
| 666 | |
| 667 ASSERT_TRUE(grand_child->render_surface()); | |
| 668 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 669 child->draw_transform()); | |
| 670 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
| 671 expected_surface_draw_transform, | |
| 672 grand_child->render_surface()->draw_transform()); | |
| 673 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 674 grand_child->draw_transform()); | |
| 675 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 676 great_grand_child->draw_transform()); | |
| 677 | |
| 678 // Case 3: fixed-container size delta of 20, 20 | |
| 679 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); | |
| 680 ExecuteCalculateDrawProperties(root_.get()); | |
| 681 | |
| 682 // Top-left fixed-position layer should not be affected by container size. | |
| 683 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 684 child->draw_transform()); | |
| 685 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 686 grand_child->draw_transform()); | |
| 687 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 688 great_grand_child->draw_transform()); | |
| 689 | |
| 690 // Case 4: Bottom-right fixed-position layer. | |
| 691 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_); | |
| 692 ExecuteCalculateDrawProperties(root_.get()); | |
| 693 | |
| 694 // Bottom-right fixed-position layer moves as container resizes. | |
| 695 expected_great_grand_child_transform.MakeIdentity(); | |
| 696 // The rotation and its inverse are needed to place the scroll delta | |
| 697 // compensation in the correct space. This test will fail if the | |
| 698 // rotation/inverse are backwards, too, so it requires perfect order of | |
| 699 // operations. | |
| 700 expected_great_grand_child_transform.PreconcatTransform( | |
| 701 Inverse(rotation_about_z)); | |
| 702 // explicit canceling out the scroll delta that gets embedded in the fixed | |
| 703 // position layer's surface. | |
| 704 expected_great_grand_child_transform.Translate(10.0, 30.0); | |
| 705 // Also apply size delta in the child(container) layer space. | |
| 706 expected_great_grand_child_transform.Translate(20.0, 20.0); | |
| 707 expected_great_grand_child_transform.PreconcatTransform(rotation_about_z); | |
| 708 | |
| 709 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 710 child->draw_transform()); | |
| 711 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 712 grand_child->draw_transform()); | |
| 713 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 714 great_grand_child->draw_transform()); | |
| 715 } | |
| 716 | |
| 717 TEST_F(LayerPositionConstraintTest, | |
| 718 ScrollCompensationForFixedPositionLayerWithMultipleIntermediateSurfaces) { | |
| 719 // This test checks for correct scroll compensation when the fixed-position | |
| 720 // container contributes to a different render surface than the fixed-position | |
| 721 // layer, with additional render surfaces in-between. This checks that the | |
| 722 // conversion to ancestor surfaces is accumulated properly in the final matrix | |
| 723 // transform. | |
| 724 LayerImpl* child = scroll_->children()[0]; | |
| 725 LayerImpl* grand_child = child->children()[0]; | |
| 726 LayerImpl* great_grand_child = grand_child->children()[0]; | |
| 727 | |
| 728 // Add one more layer to the test tree for this scenario. | |
| 729 { | |
| 730 gfx::Transform identity; | |
| 731 scoped_ptr<LayerImpl> fixed_position_child = | |
| 732 LayerImpl::Create(host_impl_.active_tree(), 5); | |
| 733 SetLayerPropertiesForTesting(fixed_position_child.get(), | |
| 734 identity, | |
| 735 gfx::Point3F(), | |
| 736 gfx::PointF(), | |
| 737 gfx::Size(100, 100), | |
| 738 true); | |
| 739 great_grand_child->AddChild(fixed_position_child.Pass()); | |
| 740 } | |
| 741 LayerImpl* fixed_position_child = great_grand_child->children()[0]; | |
| 742 | |
| 743 // Actually set up the scenario here. | |
| 744 child->SetIsContainerForFixedPositionLayers(true); | |
| 745 grand_child->SetPosition(gfx::PointF(8.f, 6.f)); | |
| 746 grand_child->SetHasRenderSurface(true); | |
| 747 great_grand_child->SetPosition(gfx::PointF(40.f, 60.f)); | |
| 748 great_grand_child->SetHasRenderSurface(true); | |
| 749 fixed_position_child->SetPositionConstraint(fixed_to_top_left_); | |
| 750 fixed_position_child->SetDrawsContent(true); | |
| 751 | |
| 752 // The additional rotations, which are non-commutative with translations, help | |
| 753 // to verify that we have correct order-of-operations in the final scroll | |
| 754 // compensation. Note that rotating about the center of the layer ensures we | |
| 755 // do not accidentally clip away layers that we want to test. | |
| 756 gfx::Transform rotation_about_z; | |
| 757 rotation_about_z.Translate(50.0, 50.0); | |
| 758 rotation_about_z.RotateAboutZAxis(90.0); | |
| 759 rotation_about_z.Translate(-50.0, -50.0); | |
| 760 grand_child->SetTransform(rotation_about_z); | |
| 761 great_grand_child->SetTransform(rotation_about_z); | |
| 762 | |
| 763 // Case 1: scroll delta of 0, 0 | |
| 764 child->SetScrollDelta(gfx::Vector2d(0, 0)); | |
| 765 ExecuteCalculateDrawProperties(root_.get()); | |
| 766 | |
| 767 gfx::Transform expected_child_transform; | |
| 768 | |
| 769 gfx::Transform expected_grand_child_surface_draw_transform; | |
| 770 expected_grand_child_surface_draw_transform.Translate(8.0, 6.0); | |
| 771 expected_grand_child_surface_draw_transform.PreconcatTransform( | |
| 772 rotation_about_z); | |
| 773 | |
| 774 gfx::Transform expected_grand_child_transform; | |
| 775 | |
| 776 gfx::Transform expected_great_grand_child_surface_draw_transform; | |
| 777 expected_great_grand_child_surface_draw_transform.Translate(40.0, 60.0); | |
| 778 expected_great_grand_child_surface_draw_transform.PreconcatTransform( | |
| 779 rotation_about_z); | |
| 780 | |
| 781 gfx::Transform expected_great_grand_child_transform; | |
| 782 | |
| 783 gfx::Transform expected_fixed_position_child_transform; | |
| 784 | |
| 785 ASSERT_TRUE(grand_child->render_surface()); | |
| 786 ASSERT_TRUE(great_grand_child->render_surface()); | |
| 787 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 788 child->draw_transform()); | |
| 789 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
| 790 expected_grand_child_surface_draw_transform, | |
| 791 grand_child->render_surface()->draw_transform()); | |
| 792 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 793 grand_child->draw_transform()); | |
| 794 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
| 795 expected_great_grand_child_surface_draw_transform, | |
| 796 great_grand_child->render_surface()->draw_transform()); | |
| 797 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 798 great_grand_child->draw_transform()); | |
| 799 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform, | |
| 800 fixed_position_child->draw_transform()); | |
| 801 | |
| 802 // Case 2: scroll delta of 10, 30 | |
| 803 child->SetScrollDelta(gfx::Vector2d(10, 30)); | |
| 804 ExecuteCalculateDrawProperties(root_.get()); | |
| 805 | |
| 806 expected_child_transform.MakeIdentity(); | |
| 807 expected_child_transform.Translate(-10.0, -30.0); // scroll delta | |
| 808 | |
| 809 expected_grand_child_surface_draw_transform.MakeIdentity(); | |
| 810 expected_grand_child_surface_draw_transform.Translate(-10.0, | |
| 811 -30.0); // scroll delta | |
| 812 expected_grand_child_surface_draw_transform.Translate(8.0, 6.0); | |
| 813 expected_grand_child_surface_draw_transform.PreconcatTransform( | |
| 814 rotation_about_z); | |
| 815 | |
| 816 // grand_child, great_grand_child, and great_grand_child's surface are not | |
| 817 // expected to change, since they are all not fixed, and they are all drawn | |
| 818 // with respect to grand_child's surface that already has the scroll delta | |
| 819 // accounted for. | |
| 820 | |
| 821 // But the great-great grandchild, "fixed_position_child", should have a | |
| 822 // transform that explicitly cancels out the scroll delta. The expected | |
| 823 // transform is: compound_draw_transform.Inverse() * translate(positive scroll | |
| 824 // delta) * compound_origin_transform from great_grand_childSurface's origin | |
| 825 // to the root surface. | |
| 826 gfx::Transform compound_draw_transform; | |
| 827 compound_draw_transform.Translate(8.0, | |
| 828 6.0); // origin translation of grand_child | |
| 829 compound_draw_transform.PreconcatTransform( | |
| 830 rotation_about_z); // rotation of grand_child | |
| 831 compound_draw_transform.Translate( | |
| 832 40.0, 60.0); // origin translation of great_grand_child | |
| 833 compound_draw_transform.PreconcatTransform( | |
| 834 rotation_about_z); // rotation of great_grand_child | |
| 835 | |
| 836 expected_fixed_position_child_transform.MakeIdentity(); | |
| 837 expected_fixed_position_child_transform.PreconcatTransform( | |
| 838 Inverse(compound_draw_transform)); | |
| 839 // explicit canceling out the scroll delta that gets embedded in the fixed | |
| 840 // position layer's surface. | |
| 841 expected_fixed_position_child_transform.Translate(10.0, 30.0); | |
| 842 expected_fixed_position_child_transform.PreconcatTransform( | |
| 843 compound_draw_transform); | |
| 844 | |
| 845 ASSERT_TRUE(grand_child->render_surface()); | |
| 846 ASSERT_TRUE(great_grand_child->render_surface()); | |
| 847 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 848 child->draw_transform()); | |
| 849 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
| 850 expected_grand_child_surface_draw_transform, | |
| 851 grand_child->render_surface()->draw_transform()); | |
| 852 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 853 grand_child->draw_transform()); | |
| 854 EXPECT_TRANSFORMATION_MATRIX_EQ( | |
| 855 expected_great_grand_child_surface_draw_transform, | |
| 856 great_grand_child->render_surface()->draw_transform()); | |
| 857 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 858 great_grand_child->draw_transform()); | |
| 859 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform, | |
| 860 fixed_position_child->draw_transform()); | |
| 861 | |
| 862 | |
| 863 // Case 3: fixed-container size delta of 20, 20 | |
| 864 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); | |
| 865 ExecuteCalculateDrawProperties(root_.get()); | |
| 866 | |
| 867 // Top-left fixed-position layer should not be affected by container size. | |
| 868 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 869 child->draw_transform()); | |
| 870 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 871 grand_child->draw_transform()); | |
| 872 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 873 great_grand_child->draw_transform()); | |
| 874 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform, | |
| 875 fixed_position_child->draw_transform()); | |
| 876 | |
| 877 // Case 4: Bottom-right fixed-position layer. | |
| 878 fixed_position_child->SetPositionConstraint(fixed_to_bottom_right_); | |
| 879 ExecuteCalculateDrawProperties(root_.get()); | |
| 880 | |
| 881 // Bottom-right fixed-position layer moves as container resizes. | |
| 882 expected_fixed_position_child_transform.MakeIdentity(); | |
| 883 expected_fixed_position_child_transform.PreconcatTransform( | |
| 884 Inverse(compound_draw_transform)); | |
| 885 // explicit canceling out the scroll delta that gets embedded in the fixed | |
| 886 // position layer's surface. | |
| 887 expected_fixed_position_child_transform.Translate(10.0, 30.0); | |
| 888 // Also apply size delta in the child(container) layer space. | |
| 889 expected_fixed_position_child_transform.Translate(20.0, 20.0); | |
| 890 expected_fixed_position_child_transform.PreconcatTransform( | |
| 891 compound_draw_transform); | |
| 892 | |
| 893 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 894 child->draw_transform()); | |
| 895 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 896 grand_child->draw_transform()); | |
| 897 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 898 great_grand_child->draw_transform()); | |
| 899 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform, | |
| 900 fixed_position_child->draw_transform()); | |
| 901 } | |
| 902 | |
| 903 TEST_F(LayerPositionConstraintTest, | |
| 904 ScrollCompensationForFixedPositionLayerWithContainerLayerThatHasSurface) { | |
| 905 // This test checks for correct scroll compensation when the fixed-position | |
| 906 // container itself has a render surface. In this case, the container layer | |
| 907 // should be treated like a layer that contributes to a render target, and | |
| 908 // that render target is completely irrelevant; it should not affect the | |
| 909 // scroll compensation. | |
| 910 LayerImpl* child = scroll_->children()[0]; | |
| 911 LayerImpl* grand_child = child->children()[0]; | |
| 912 | |
| 913 child->SetIsContainerForFixedPositionLayers(true); | |
| 914 child->SetHasRenderSurface(true); | |
| 915 grand_child->SetPositionConstraint(fixed_to_top_left_); | |
| 916 grand_child->SetDrawsContent(true); | |
| 917 | |
| 918 // Case 1: scroll delta of 0, 0 | |
| 919 child->SetScrollDelta(gfx::Vector2d(0, 0)); | |
| 920 ExecuteCalculateDrawProperties(root_.get()); | |
| 921 | |
| 922 gfx::Transform expected_surface_draw_transform; | |
| 923 expected_surface_draw_transform.Translate(0.0, 0.0); | |
| 924 gfx::Transform expected_child_transform; | |
| 925 gfx::Transform expected_grand_child_transform; | |
| 926 ASSERT_TRUE(child->render_surface()); | |
| 927 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform, | |
| 928 child->render_surface()->draw_transform()); | |
| 929 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 930 child->draw_transform()); | |
| 931 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 932 grand_child->draw_transform()); | |
| 933 | |
| 934 // Case 2: scroll delta of 10, 10 | |
| 935 child->SetScrollDelta(gfx::Vector2d(10, 10)); | |
| 936 ExecuteCalculateDrawProperties(root_.get()); | |
| 937 | |
| 938 // The surface is translated by scroll delta, the child transform doesn't | |
| 939 // change because it scrolls along with the surface, but the fixed position | |
| 940 // grand_child needs to compensate for the scroll translation. | |
| 941 expected_surface_draw_transform.MakeIdentity(); | |
| 942 expected_surface_draw_transform.Translate(-10.0, -10.0); | |
| 943 expected_grand_child_transform.MakeIdentity(); | |
| 944 expected_grand_child_transform.Translate(10.0, 10.0); | |
| 945 | |
| 946 ASSERT_TRUE(child->render_surface()); | |
| 947 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform, | |
| 948 child->render_surface()->draw_transform()); | |
| 949 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 950 child->draw_transform()); | |
| 951 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 952 grand_child->draw_transform()); | |
| 953 | |
| 954 // Case 3: fixed-container size delta of 20, 20 | |
| 955 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); | |
| 956 ExecuteCalculateDrawProperties(root_.get()); | |
| 957 | |
| 958 // Top-left fixed-position layer should not be affected by container size. | |
| 959 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 960 child->draw_transform()); | |
| 961 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 962 grand_child->draw_transform()); | |
| 963 | |
| 964 // Case 4: Bottom-right fixed-position layer. | |
| 965 grand_child->SetPositionConstraint(fixed_to_bottom_right_); | |
| 966 ExecuteCalculateDrawProperties(root_.get()); | |
| 967 | |
| 968 // Bottom-right fixed-position layer moves as container resizes. | |
| 969 expected_grand_child_transform.MakeIdentity(); | |
| 970 // The surface is translated by scroll delta, the child transform doesn't | |
| 971 // change because it scrolls along with the surface, but the fixed position | |
| 972 // grand_child needs to compensate for the scroll translation. | |
| 973 expected_grand_child_transform.Translate(10.0, 10.0); | |
| 974 // Apply size delta from the child(container) layer. | |
| 975 expected_grand_child_transform.Translate(20.0, 20.0); | |
| 976 | |
| 977 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 978 child->draw_transform()); | |
| 979 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 980 grand_child->draw_transform()); | |
| 981 } | |
| 982 | |
| 983 TEST_F(LayerPositionConstraintTest, | |
| 984 ScrollCompensationForFixedPositionLayerThatIsAlsoFixedPositionContainer) { | |
| 985 // This test checks the scenario where a fixed-position layer also happens to | |
| 986 // be a container itself for a descendant fixed position layer. In particular, | |
| 987 // the layer should not accidentally be fixed to itself. | |
| 988 LayerImpl* child = scroll_->children()[0]; | |
| 989 LayerImpl* grand_child = child->children()[0]; | |
| 990 | |
| 991 child->SetIsContainerForFixedPositionLayers(true); | |
| 992 grand_child->SetPositionConstraint(fixed_to_top_left_); | |
| 993 | |
| 994 // This should not confuse the grand_child. If correct, the grand_child would | |
| 995 // still be considered fixed to its container (i.e. "child"). | |
| 996 grand_child->SetIsContainerForFixedPositionLayers(true); | |
| 997 | |
| 998 // Case 1: scroll delta of 0, 0 | |
| 999 child->SetScrollDelta(gfx::Vector2d(0, 0)); | |
| 1000 ExecuteCalculateDrawProperties(root_.get()); | |
| 1001 | |
| 1002 gfx::Transform expected_child_transform; | |
| 1003 gfx::Transform expected_grand_child_transform; | |
| 1004 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 1005 child->draw_transform()); | |
| 1006 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 1007 grand_child->draw_transform()); | |
| 1008 | |
| 1009 // Case 2: scroll delta of 10, 10 | |
| 1010 child->SetScrollDelta(gfx::Vector2d(10, 10)); | |
| 1011 ExecuteCalculateDrawProperties(root_.get()); | |
| 1012 | |
| 1013 // Here the child is affected by scroll delta, but the fixed position | |
| 1014 // grand_child should not be affected. | |
| 1015 expected_child_transform.MakeIdentity(); | |
| 1016 expected_child_transform.Translate(-10.0, -10.0); | |
| 1017 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 1018 child->draw_transform()); | |
| 1019 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 1020 grand_child->draw_transform()); | |
| 1021 | |
| 1022 // Case 3: fixed-container size delta of 20, 20 | |
| 1023 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); | |
| 1024 ExecuteCalculateDrawProperties(root_.get()); | |
| 1025 | |
| 1026 // Top-left fixed-position layer should not be affected by container size. | |
| 1027 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 1028 child->draw_transform()); | |
| 1029 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 1030 grand_child->draw_transform()); | |
| 1031 | |
| 1032 // Case 4: Bottom-right fixed-position layer. | |
| 1033 grand_child->SetPositionConstraint(fixed_to_bottom_right_); | |
| 1034 ExecuteCalculateDrawProperties(root_.get()); | |
| 1035 | |
| 1036 // Bottom-right fixed-position layer moves as container resizes. | |
| 1037 expected_grand_child_transform.MakeIdentity(); | |
| 1038 // Apply size delta from the child(container) layer. | |
| 1039 expected_grand_child_transform.Translate(20.0, 20.0); | |
| 1040 | |
| 1041 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 1042 child->draw_transform()); | |
| 1043 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 1044 grand_child->draw_transform()); | |
| 1045 } | |
| 1046 | |
| 1047 TEST_F(LayerPositionConstraintTest, | |
| 1048 ScrollCompensationForFixedWithinFixedWithSameContainer) { | |
| 1049 // This test checks scroll compensation for a fixed-position layer that is | |
| 1050 // inside of another fixed-position layer and both share the same container. | |
| 1051 // In this situation, the parent fixed-position layer will receive | |
| 1052 // the scroll compensation, and the child fixed-position layer does not | |
| 1053 // need to compensate further. | |
| 1054 | |
| 1055 LayerImpl* child = scroll_->children()[0]; | |
| 1056 LayerImpl* grand_child = child->children()[0]; | |
| 1057 LayerImpl* great_grand_child = grand_child->children()[0]; | |
| 1058 | |
| 1059 child->SetIsContainerForFixedPositionLayers(true); | |
| 1060 grand_child->SetPositionConstraint(fixed_to_top_left_); | |
| 1061 | |
| 1062 // Note carefully - great_grand_child is fixed to bottom right, to test | |
| 1063 // sizeDelta being applied correctly; the compensation skips the grand_child | |
| 1064 // because it is fixed to top left. | |
| 1065 great_grand_child->SetPositionConstraint(fixed_to_bottom_right_); | |
| 1066 | |
| 1067 // Case 1: scrollDelta | |
| 1068 child->SetScrollDelta(gfx::Vector2d(10, 10)); | |
| 1069 ExecuteCalculateDrawProperties(root_.get()); | |
| 1070 | |
| 1071 // Here the child is affected by scroll delta, but the fixed position | |
| 1072 // grand_child should not be affected. | |
| 1073 gfx::Transform expected_child_transform; | |
| 1074 expected_child_transform.Translate(-10.0, -10.0); | |
| 1075 | |
| 1076 gfx::Transform expected_grand_child_transform; | |
| 1077 gfx::Transform expected_great_grand_child_transform; | |
| 1078 | |
| 1079 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 1080 child->draw_transform()); | |
| 1081 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 1082 grand_child->draw_transform()); | |
| 1083 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 1084 great_grand_child->draw_transform()); | |
| 1085 | |
| 1086 // Case 2: sizeDelta | |
| 1087 child->SetScrollDelta(gfx::Vector2d(0, 0)); | |
| 1088 SetFixedContainerSizeDelta(child, gfx::Vector2d(20, 20)); | |
| 1089 ExecuteCalculateDrawProperties(root_.get()); | |
| 1090 | |
| 1091 expected_child_transform.MakeIdentity(); | |
| 1092 | |
| 1093 expected_grand_child_transform.MakeIdentity(); | |
| 1094 | |
| 1095 // Fixed to bottom-right, size-delta compensation is applied. | |
| 1096 expected_great_grand_child_transform.MakeIdentity(); | |
| 1097 expected_great_grand_child_transform.Translate(20.0, 20.0); | |
| 1098 | |
| 1099 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, | |
| 1100 child->draw_transform()); | |
| 1101 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform, | |
| 1102 grand_child->draw_transform()); | |
| 1103 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform, | |
| 1104 great_grand_child->draw_transform()); | |
| 1105 } | |
| 1106 | |
| 1107 TEST_F(LayerPositionConstraintTest, | |
| 1108 ScrollCompensationForFixedWithinFixedWithInterveningContainer) { | |
| 1109 // This test checks scroll compensation for a fixed-position layer that is | |
| 1110 // inside of another fixed-position layer, but they have different fixed | |
| 1111 // position containers. In this situation, the child fixed-position element | |
| 1112 // would still have to compensate with respect to its container. | |
| 1113 | |
| 1114 LayerImpl* container1 = scroll_->children()[0]; | |
| 1115 LayerImpl* fixed_to_container1 = container1->children()[0]; | |
| 1116 LayerImpl* container2 = fixed_to_container1->children()[0]; | |
| 1117 | |
| 1118 { | |
| 1119 // Add one more layer to the hierarchy for this test. | |
| 1120 scoped_ptr<LayerImpl> fixed_to_container2_ptr = | |
| 1121 LayerImpl::Create(host_impl_.active_tree(), 5); | |
| 1122 container2->AddChild(fixed_to_container2_ptr.Pass()); | |
| 1123 } | |
| 1124 | |
| 1125 LayerImpl* fixed_to_container2 = container2->children()[0]; | |
| 1126 | |
| 1127 container1->SetIsContainerForFixedPositionLayers(true); | |
| 1128 fixed_to_container1->SetPositionConstraint(fixed_to_top_left_); | |
| 1129 container2->SetIsContainerForFixedPositionLayers(true); | |
| 1130 fixed_to_container2->SetPositionConstraint(fixed_to_top_left_); | |
| 1131 | |
| 1132 container1->SetScrollDelta(gfx::Vector2d(0, 15)); | |
| 1133 container2->SetScrollDelta(gfx::Vector2d(30, 0)); | |
| 1134 ExecuteCalculateDrawProperties(root_.get()); | |
| 1135 | |
| 1136 gfx::Transform expected_container1_transform; | |
| 1137 expected_container1_transform.Translate(0.0, -15.0); | |
| 1138 | |
| 1139 gfx::Transform expected_fixed_to_container1_transform; | |
| 1140 | |
| 1141 // Since the container is a descendant of the fixed layer above, | |
| 1142 // the expected draw transform for container2 would not | |
| 1143 // include the scrollDelta that was applied to container1. | |
| 1144 gfx::Transform expected_container2_transform; | |
| 1145 expected_container2_transform.Translate(-30.0, 0.0); | |
| 1146 | |
| 1147 gfx::Transform expected_fixed_to_container2_transform; | |
| 1148 | |
| 1149 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_container1_transform, | |
| 1150 container1->draw_transform()); | |
| 1151 | |
| 1152 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container1_transform, | |
| 1153 fixed_to_container1->draw_transform()); | |
| 1154 | |
| 1155 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_container2_transform, | |
| 1156 container2->draw_transform()); | |
| 1157 | |
| 1158 EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_to_container2_transform, | |
| 1159 fixed_to_container2->draw_transform()); | |
| 1160 } | |
| 1161 } // namespace | |
| 1162 } // namespace cc | |
| OLD | NEW |