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