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