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