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