OLD | NEW |
1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 | 6 |
7 #include "CCLayerSorter.h" | 7 #include "CCLayerSorter.h" |
8 | 8 |
9 #include "CCLayerImpl.h" | 9 #include "CCLayerImpl.h" |
10 #include "CCMathUtil.h" | 10 #include "CCMathUtil.h" |
11 #include "CCSingleThreadProxy.h" | 11 #include "CCSingleThreadProxy.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
13 #include <public/WebTransformationMatrix.h> | 13 #include <public/WebTransformationMatrix.h> |
14 | 14 |
15 using namespace cc; | 15 using namespace cc; |
16 using WebKit::WebTransformationMatrix; | 16 using WebKit::WebTransformationMatrix; |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 // Note: In the following overlap tests, the "camera" is looking down the negati
ve Z axis, | 20 // Note: In the following overlap tests, the "camera" is looking down the negati
ve Z axis, |
21 // meaning that layers with smaller z values (more negative) are further from th
e camera | 21 // meaning that layers with smaller z values (more negative) are further from th
e camera |
22 // and therefore must be drawn before layers with higher z values. | 22 // and therefore must be drawn before layers with higher z values. |
23 | 23 |
24 TEST(CCLayerSorterTest, BasicOverlap) | 24 TEST(LayerSorterTest, BasicOverlap) |
25 { | 25 { |
26 CCLayerSorter::ABCompareResult overlapResult; | 26 LayerSorter::ABCompareResult overlapResult; |
27 const float zThreshold = 0.1f; | 27 const float zThreshold = 0.1f; |
28 float weight = 0; | 28 float weight = 0; |
29 | 29 |
30 // Trivial test, with one layer directly obscuring the other. | 30 // Trivial test, with one layer directly obscuring the other. |
31 WebTransformationMatrix neg4Translate; | 31 WebTransformationMatrix neg4Translate; |
32 neg4Translate.translate3d(0, 0, -4); | 32 neg4Translate.translate3d(0, 0, -4); |
33 LayerShape front(2, 2, neg4Translate); | 33 LayerShape front(2, 2, neg4Translate); |
34 | 34 |
35 WebTransformationMatrix neg5Translate; | 35 WebTransformationMatrix neg5Translate; |
36 neg5Translate.translate3d(0, 0, -5); | 36 neg5Translate.translate3d(0, 0, -5); |
37 LayerShape back(2, 2, neg5Translate); | 37 LayerShape back(2, 2, neg5Translate); |
38 | 38 |
39 overlapResult = CCLayerSorter::checkOverlap(&front, &back, zThreshold, weigh
t); | 39 overlapResult = LayerSorter::checkOverlap(&front, &back, zThreshold, weight)
; |
40 EXPECT_EQ(CCLayerSorter::BBeforeA, overlapResult); | 40 EXPECT_EQ(LayerSorter::BBeforeA, overlapResult); |
41 EXPECT_EQ(1, weight); | 41 EXPECT_EQ(1, weight); |
42 | 42 |
43 overlapResult = CCLayerSorter::checkOverlap(&back, &front, zThreshold, weigh
t); | 43 overlapResult = LayerSorter::checkOverlap(&back, &front, zThreshold, weight)
; |
44 EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult); | 44 EXPECT_EQ(LayerSorter::ABeforeB, overlapResult); |
45 EXPECT_EQ(1, weight); | 45 EXPECT_EQ(1, weight); |
46 | 46 |
47 // One layer translated off to the right. No overlap should be detected. | 47 // One layer translated off to the right. No overlap should be detected. |
48 WebTransformationMatrix rightTranslate; | 48 WebTransformationMatrix rightTranslate; |
49 rightTranslate.translate3d(10, 0, -5); | 49 rightTranslate.translate3d(10, 0, -5); |
50 LayerShape backRight(2, 2, rightTranslate); | 50 LayerShape backRight(2, 2, rightTranslate); |
51 overlapResult = CCLayerSorter::checkOverlap(&front, &backRight, zThreshold,
weight); | 51 overlapResult = LayerSorter::checkOverlap(&front, &backRight, zThreshold, we
ight); |
52 EXPECT_EQ(CCLayerSorter::None, overlapResult); | 52 EXPECT_EQ(LayerSorter::None, overlapResult); |
53 | 53 |
54 // When comparing a layer with itself, z difference is always 0. | 54 // When comparing a layer with itself, z difference is always 0. |
55 overlapResult = CCLayerSorter::checkOverlap(&front, &front, zThreshold, weig
ht); | 55 overlapResult = LayerSorter::checkOverlap(&front, &front, zThreshold, weight
); |
56 EXPECT_EQ(0, weight); | 56 EXPECT_EQ(0, weight); |
57 } | 57 } |
58 | 58 |
59 TEST(CCLayerSorterTest, RightAngleOverlap) | 59 TEST(LayerSorterTest, RightAngleOverlap) |
60 { | 60 { |
61 CCLayerSorter::ABCompareResult overlapResult; | 61 LayerSorter::ABCompareResult overlapResult; |
62 const float zThreshold = 0.1f; | 62 const float zThreshold = 0.1f; |
63 float weight = 0; | 63 float weight = 0; |
64 | 64 |
65 WebTransformationMatrix perspectiveMatrix; | 65 WebTransformationMatrix perspectiveMatrix; |
66 perspectiveMatrix.applyPerspective(1000); | 66 perspectiveMatrix.applyPerspective(1000); |
67 | 67 |
68 // Two layers forming a right angle with a perspective viewing transform. | 68 // Two layers forming a right angle with a perspective viewing transform. |
69 WebTransformationMatrix leftFaceMatrix; | 69 WebTransformationMatrix leftFaceMatrix; |
70 leftFaceMatrix.rotate3d(0, 1, 0, -90); | 70 leftFaceMatrix.rotate3d(0, 1, 0, -90); |
71 leftFaceMatrix.translateRight3d(-1, 0, -5); | 71 leftFaceMatrix.translateRight3d(-1, 0, -5); |
72 leftFaceMatrix.translate(-1, -1); | 72 leftFaceMatrix.translate(-1, -1); |
73 LayerShape leftFace(2, 2, perspectiveMatrix * leftFaceMatrix); | 73 LayerShape leftFace(2, 2, perspectiveMatrix * leftFaceMatrix); |
74 WebTransformationMatrix frontFaceMatrix; | 74 WebTransformationMatrix frontFaceMatrix; |
75 frontFaceMatrix.translate3d(0, 0, -4); | 75 frontFaceMatrix.translate3d(0, 0, -4); |
76 frontFaceMatrix.translate(-1, -1); | 76 frontFaceMatrix.translate(-1, -1); |
77 LayerShape frontFace(2, 2, perspectiveMatrix * frontFaceMatrix); | 77 LayerShape frontFace(2, 2, perspectiveMatrix * frontFaceMatrix); |
78 | 78 |
79 overlapResult = CCLayerSorter::checkOverlap(&frontFace, &leftFace, zThreshol
d, weight); | 79 overlapResult = LayerSorter::checkOverlap(&frontFace, &leftFace, zThreshold,
weight); |
80 EXPECT_EQ(CCLayerSorter::BBeforeA, overlapResult); | 80 EXPECT_EQ(LayerSorter::BBeforeA, overlapResult); |
81 } | 81 } |
82 | 82 |
83 TEST(CCLayerSorterTest, IntersectingLayerOverlap) | 83 TEST(LayerSorterTest, IntersectingLayerOverlap) |
84 { | 84 { |
85 CCLayerSorter::ABCompareResult overlapResult; | 85 LayerSorter::ABCompareResult overlapResult; |
86 const float zThreshold = 0.1f; | 86 const float zThreshold = 0.1f; |
87 float weight = 0; | 87 float weight = 0; |
88 | 88 |
89 WebTransformationMatrix perspectiveMatrix; | 89 WebTransformationMatrix perspectiveMatrix; |
90 perspectiveMatrix.applyPerspective(1000); | 90 perspectiveMatrix.applyPerspective(1000); |
91 | 91 |
92 // Intersecting layers. An explicit order will be returned based on relative
z | 92 // Intersecting layers. An explicit order will be returned based on relative
z |
93 // values at the overlapping features but the weight returned should be zero
. | 93 // values at the overlapping features but the weight returned should be zero
. |
94 WebTransformationMatrix frontFaceMatrix; | 94 WebTransformationMatrix frontFaceMatrix; |
95 frontFaceMatrix.translate3d(0, 0, -4); | 95 frontFaceMatrix.translate3d(0, 0, -4); |
96 frontFaceMatrix.translate(-1, -1); | 96 frontFaceMatrix.translate(-1, -1); |
97 LayerShape frontFace(2, 2, perspectiveMatrix * frontFaceMatrix); | 97 LayerShape frontFace(2, 2, perspectiveMatrix * frontFaceMatrix); |
98 | 98 |
99 WebTransformationMatrix throughMatrix; | 99 WebTransformationMatrix throughMatrix; |
100 throughMatrix.rotate3d(0, 1, 0, 45); | 100 throughMatrix.rotate3d(0, 1, 0, 45); |
101 throughMatrix.translateRight3d(0, 0, -4); | 101 throughMatrix.translateRight3d(0, 0, -4); |
102 throughMatrix.translate(-1, -1); | 102 throughMatrix.translate(-1, -1); |
103 LayerShape rotatedFace(2, 2, perspectiveMatrix * throughMatrix); | 103 LayerShape rotatedFace(2, 2, perspectiveMatrix * throughMatrix); |
104 overlapResult = CCLayerSorter::checkOverlap(&frontFace, &rotatedFace, zThres
hold, weight); | 104 overlapResult = LayerSorter::checkOverlap(&frontFace, &rotatedFace, zThresho
ld, weight); |
105 EXPECT_NE(CCLayerSorter::None, overlapResult); | 105 EXPECT_NE(LayerSorter::None, overlapResult); |
106 EXPECT_EQ(0, weight); | 106 EXPECT_EQ(0, weight); |
107 } | 107 } |
108 | 108 |
109 TEST(CCLayerSorterTest, LayersAtAngleOverlap) | 109 TEST(LayerSorterTest, LayersAtAngleOverlap) |
110 { | 110 { |
111 CCLayerSorter::ABCompareResult overlapResult; | 111 LayerSorter::ABCompareResult overlapResult; |
112 const float zThreshold = 0.1f; | 112 const float zThreshold = 0.1f; |
113 float weight = 0; | 113 float weight = 0; |
114 | 114 |
115 // Trickier test with layers at an angle. | 115 // Trickier test with layers at an angle. |
116 // | 116 // |
117 // -x . . . . 0 . . . . +x | 117 // -x . . . . 0 . . . . +x |
118 // -z / | 118 // -z / |
119 // : /----B---- | 119 // : /----B---- |
120 // 0 C | 120 // 0 C |
121 // : ----A----/ | 121 // : ----A----/ |
(...skipping 10 matching lines...) Expand all Loading... |
132 WebTransformationMatrix transformB; | 132 WebTransformationMatrix transformB; |
133 transformB.translate3d(6, 0, -1); | 133 transformB.translate3d(6, 0, -1); |
134 transformB.translate(-4, -10); | 134 transformB.translate(-4, -10); |
135 LayerShape layerB(8, 20, transformB); | 135 LayerShape layerB(8, 20, transformB); |
136 | 136 |
137 WebTransformationMatrix transformC; | 137 WebTransformationMatrix transformC; |
138 transformC.rotate3d(0, 1, 0, 40); | 138 transformC.rotate3d(0, 1, 0, 40); |
139 transformC.translate(-4, -10); | 139 transformC.translate(-4, -10); |
140 LayerShape layerC(8, 20, transformC); | 140 LayerShape layerC(8, 20, transformC); |
141 | 141 |
142 overlapResult = CCLayerSorter::checkOverlap(&layerA, &layerC, zThreshold, we
ight); | 142 overlapResult = LayerSorter::checkOverlap(&layerA, &layerC, zThreshold, weig
ht); |
143 EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult); | 143 EXPECT_EQ(LayerSorter::ABeforeB, overlapResult); |
144 overlapResult = CCLayerSorter::checkOverlap(&layerC, &layerB, zThreshold, we
ight); | 144 overlapResult = LayerSorter::checkOverlap(&layerC, &layerB, zThreshold, weig
ht); |
145 EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult); | 145 EXPECT_EQ(LayerSorter::ABeforeB, overlapResult); |
146 overlapResult = CCLayerSorter::checkOverlap(&layerA, &layerB, zThreshold, we
ight); | 146 overlapResult = LayerSorter::checkOverlap(&layerA, &layerB, zThreshold, weig
ht); |
147 EXPECT_EQ(CCLayerSorter::None, overlapResult); | 147 EXPECT_EQ(LayerSorter::None, overlapResult); |
148 } | 148 } |
149 | 149 |
150 TEST(CCLayerSorterTest, LayersUnderPathologicalPerspectiveTransform) | 150 TEST(LayerSorterTest, LayersUnderPathologicalPerspectiveTransform) |
151 { | 151 { |
152 CCLayerSorter::ABCompareResult overlapResult; | 152 LayerSorter::ABCompareResult overlapResult; |
153 const float zThreshold = 0.1f; | 153 const float zThreshold = 0.1f; |
154 float weight = 0; | 154 float weight = 0; |
155 | 155 |
156 // On perspective projection, if w becomes negative, the re-projected point
will be | 156 // On perspective projection, if w becomes negative, the re-projected point
will be |
157 // invalid and un-usable. Correct code needs to clip away portions of the ge
ometry | 157 // invalid and un-usable. Correct code needs to clip away portions of the ge
ometry |
158 // where w < 0. If the code uses the invalid value, it will think that a lay
er has | 158 // where w < 0. If the code uses the invalid value, it will think that a lay
er has |
159 // different bounds than it really does, which can cause things to sort inco
rrectly. | 159 // different bounds than it really does, which can cause things to sort inco
rrectly. |
160 | 160 |
161 WebTransformationMatrix perspectiveMatrix; | 161 WebTransformationMatrix perspectiveMatrix; |
162 perspectiveMatrix.applyPerspective(1); | 162 perspectiveMatrix.applyPerspective(1); |
(...skipping 10 matching lines...) Expand all Loading... |
173 WebTransformationMatrix transformB; | 173 WebTransformationMatrix transformB; |
174 transformB.translate3d(0, 0, 0.7); | 174 transformB.translate3d(0, 0, 0.7); |
175 transformB.rotate3d(0, 45, 0); | 175 transformB.rotate3d(0, 45, 0); |
176 transformB.translate(-5, -5); | 176 transformB.translate(-5, -5); |
177 LayerShape layerB(10, 10, perspectiveMatrix * transformB); | 177 LayerShape layerB(10, 10, perspectiveMatrix * transformB); |
178 | 178 |
179 // Sanity check that the test case actually covers the intended scenario, wh
ere part | 179 // Sanity check that the test case actually covers the intended scenario, wh
ere part |
180 // of layer B go behind the w = 0 plane. | 180 // of layer B go behind the w = 0 plane. |
181 FloatQuad testQuad = FloatQuad(FloatRect(FloatPoint(-0.5, -0.5), FloatSize(1
, 1))); | 181 FloatQuad testQuad = FloatQuad(FloatRect(FloatPoint(-0.5, -0.5), FloatSize(1
, 1))); |
182 bool clipped = false; | 182 bool clipped = false; |
183 CCMathUtil::mapQuad(perspectiveMatrix * transformB, testQuad, clipped); | 183 MathUtil::mapQuad(perspectiveMatrix * transformB, testQuad, clipped); |
184 ASSERT_TRUE(clipped); | 184 ASSERT_TRUE(clipped); |
185 | 185 |
186 overlapResult = CCLayerSorter::checkOverlap(&layerA, &layerB, zThreshold, we
ight); | 186 overlapResult = LayerSorter::checkOverlap(&layerA, &layerB, zThreshold, weig
ht); |
187 EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult); | 187 EXPECT_EQ(LayerSorter::ABeforeB, overlapResult); |
188 } | 188 } |
189 | 189 |
190 TEST(CCLayerSorterTest, verifyExistingOrderingPreservedWhenNoZDiff) | 190 TEST(LayerSorterTest, verifyExistingOrderingPreservedWhenNoZDiff) |
191 { | 191 { |
192 DebugScopedSetImplThread thisScopeIsOnImplThread; | 192 DebugScopedSetImplThread thisScopeIsOnImplThread; |
193 | 193 |
194 // If there is no reason to re-sort the layers (i.e. no 3d z difference), th
en the | 194 // If there is no reason to re-sort the layers (i.e. no 3d z difference), th
en the |
195 // existing ordering provided on input should be retained. This test covers
the fix in | 195 // existing ordering provided on input should be retained. This test covers
the fix in |
196 // https://bugs.webkit.org/show_bug.cgi?id=75046. Before this fix, ordering
was | 196 // https://bugs.webkit.org/show_bug.cgi?id=75046. Before this fix, ordering
was |
197 // accidentally reversed, causing bugs in z-index ordering on websites when | 197 // accidentally reversed, causing bugs in z-index ordering on websites when |
198 // preserves3D triggered the CCLayerSorter. | 198 // preserves3D triggered the LayerSorter. |
199 | 199 |
200 // Input list of layers: [1, 2, 3, 4, 5]. | 200 // Input list of layers: [1, 2, 3, 4, 5]. |
201 // Expected output: [3, 4, 1, 2, 5]. | 201 // Expected output: [3, 4, 1, 2, 5]. |
202 // - 1, 2, and 5 do not have a 3d z difference, and therefore their relat
ive ordering should be retained. | 202 // - 1, 2, and 5 do not have a 3d z difference, and therefore their relat
ive ordering should be retained. |
203 // - 3 and 4 do not have a 3d z difference, and therefore their relative
ordering should be retained. | 203 // - 3 and 4 do not have a 3d z difference, and therefore their relative
ordering should be retained. |
204 // - 3 and 4 should be re-sorted so they are in front of 1, 2, and 5. | 204 // - 3 and 4 should be re-sorted so they are in front of 1, 2, and 5. |
205 | 205 |
206 scoped_ptr<CCLayerImpl> layer1 = CCLayerImpl::create(1); | 206 scoped_ptr<LayerImpl> layer1 = LayerImpl::create(1); |
207 scoped_ptr<CCLayerImpl> layer2 = CCLayerImpl::create(2); | 207 scoped_ptr<LayerImpl> layer2 = LayerImpl::create(2); |
208 scoped_ptr<CCLayerImpl> layer3 = CCLayerImpl::create(3); | 208 scoped_ptr<LayerImpl> layer3 = LayerImpl::create(3); |
209 scoped_ptr<CCLayerImpl> layer4 = CCLayerImpl::create(4); | 209 scoped_ptr<LayerImpl> layer4 = LayerImpl::create(4); |
210 scoped_ptr<CCLayerImpl> layer5 = CCLayerImpl::create(5); | 210 scoped_ptr<LayerImpl> layer5 = LayerImpl::create(5); |
211 | 211 |
212 WebTransformationMatrix BehindMatrix; | 212 WebTransformationMatrix BehindMatrix; |
213 BehindMatrix.translate3d(0, 0, 2); | 213 BehindMatrix.translate3d(0, 0, 2); |
214 WebTransformationMatrix FrontMatrix; | 214 WebTransformationMatrix FrontMatrix; |
215 FrontMatrix.translate3d(0, 0, 1); | 215 FrontMatrix.translate3d(0, 0, 1); |
216 | 216 |
217 layer1->setBounds(IntSize(10, 10)); | 217 layer1->setBounds(IntSize(10, 10)); |
218 layer1->setContentBounds(IntSize(10, 10)); | 218 layer1->setContentBounds(IntSize(10, 10)); |
219 layer1->setDrawTransform(BehindMatrix); | 219 layer1->setDrawTransform(BehindMatrix); |
220 layer1->setDrawsContent(true); | 220 layer1->setDrawsContent(true); |
(...skipping 11 matching lines...) Expand all Loading... |
232 layer4->setBounds(IntSize(40, 40)); | 232 layer4->setBounds(IntSize(40, 40)); |
233 layer4->setContentBounds(IntSize(40, 40)); | 233 layer4->setContentBounds(IntSize(40, 40)); |
234 layer4->setDrawTransform(FrontMatrix); | 234 layer4->setDrawTransform(FrontMatrix); |
235 layer4->setDrawsContent(true); | 235 layer4->setDrawsContent(true); |
236 | 236 |
237 layer5->setBounds(IntSize(50, 50)); | 237 layer5->setBounds(IntSize(50, 50)); |
238 layer5->setContentBounds(IntSize(50, 50)); | 238 layer5->setContentBounds(IntSize(50, 50)); |
239 layer5->setDrawTransform(BehindMatrix); | 239 layer5->setDrawTransform(BehindMatrix); |
240 layer5->setDrawsContent(true); | 240 layer5->setDrawsContent(true); |
241 | 241 |
242 std::vector<CCLayerImpl*> layerList; | 242 std::vector<LayerImpl*> layerList; |
243 layerList.push_back(layer1.get()); | 243 layerList.push_back(layer1.get()); |
244 layerList.push_back(layer2.get()); | 244 layerList.push_back(layer2.get()); |
245 layerList.push_back(layer3.get()); | 245 layerList.push_back(layer3.get()); |
246 layerList.push_back(layer4.get()); | 246 layerList.push_back(layer4.get()); |
247 layerList.push_back(layer5.get()); | 247 layerList.push_back(layer5.get()); |
248 | 248 |
249 ASSERT_EQ(static_cast<size_t>(5), layerList.size()); | 249 ASSERT_EQ(static_cast<size_t>(5), layerList.size()); |
250 EXPECT_EQ(1, layerList[0]->id()); | 250 EXPECT_EQ(1, layerList[0]->id()); |
251 EXPECT_EQ(2, layerList[1]->id()); | 251 EXPECT_EQ(2, layerList[1]->id()); |
252 EXPECT_EQ(3, layerList[2]->id()); | 252 EXPECT_EQ(3, layerList[2]->id()); |
253 EXPECT_EQ(4, layerList[3]->id()); | 253 EXPECT_EQ(4, layerList[3]->id()); |
254 EXPECT_EQ(5, layerList[4]->id()); | 254 EXPECT_EQ(5, layerList[4]->id()); |
255 | 255 |
256 CCLayerSorter layerSorter; | 256 LayerSorter layerSorter; |
257 layerSorter.sort(layerList.begin(), layerList.end()); | 257 layerSorter.sort(layerList.begin(), layerList.end()); |
258 | 258 |
259 ASSERT_EQ(static_cast<size_t>(5), layerList.size()); | 259 ASSERT_EQ(static_cast<size_t>(5), layerList.size()); |
260 EXPECT_EQ(3, layerList[0]->id()); | 260 EXPECT_EQ(3, layerList[0]->id()); |
261 EXPECT_EQ(4, layerList[1]->id()); | 261 EXPECT_EQ(4, layerList[1]->id()); |
262 EXPECT_EQ(1, layerList[2]->id()); | 262 EXPECT_EQ(1, layerList[2]->id()); |
263 EXPECT_EQ(2, layerList[3]->id()); | 263 EXPECT_EQ(2, layerList[3]->id()); |
264 EXPECT_EQ(5, layerList[4]->id()); | 264 EXPECT_EQ(5, layerList[4]->id()); |
265 } | 265 } |
266 | 266 |
267 } // namespace | 267 } // namespace |
OLD | NEW |