/src/mozilla-central/gfx/tests/gtest/TestLayers.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* vim:set ts=2 sw=2 sts=2 et: */ |
2 | | /* Any copyright is dedicated to the Public Domain. |
3 | | * http://creativecommons.org/publicdomain/zero/1.0/ |
4 | | */ |
5 | | |
6 | | #include "TestLayers.h" |
7 | | #include "gtest/gtest.h" |
8 | | #include "gmock/gmock.h" |
9 | | #include "LayerUserData.h" |
10 | | #include "mozilla/layers/LayerMetricsWrapper.h" |
11 | | #include "mozilla/layers/CompositorBridgeParent.h" |
12 | | |
13 | | using namespace mozilla; |
14 | | using namespace mozilla::gfx; |
15 | | using namespace mozilla::layers; |
16 | | |
17 | | class TestContainerLayer: public ContainerLayer { |
18 | | public: |
19 | | explicit TestContainerLayer(LayerManager* aManager) |
20 | | : ContainerLayer(aManager, nullptr) |
21 | 0 | {} |
22 | | |
23 | 0 | virtual const char* Name() const { |
24 | 0 | return "TestContainerLayer"; |
25 | 0 | } |
26 | | |
27 | 0 | virtual LayerType GetType() const { |
28 | 0 | return TYPE_CONTAINER; |
29 | 0 | } |
30 | | |
31 | 0 | virtual void ComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface) { |
32 | 0 | DefaultComputeEffectiveTransforms(aTransformToSurface); |
33 | 0 | } |
34 | | }; |
35 | | |
36 | | class TestPaintedLayer: public PaintedLayer { |
37 | | public: |
38 | | explicit TestPaintedLayer(LayerManager* aManager) |
39 | | : PaintedLayer(aManager, nullptr) |
40 | 0 | {} |
41 | | |
42 | 0 | virtual const char* Name() const { |
43 | 0 | return "TestPaintedLayer"; |
44 | 0 | } |
45 | | |
46 | 0 | virtual LayerType GetType() const { |
47 | 0 | return TYPE_PAINTED; |
48 | 0 | } |
49 | | |
50 | 0 | virtual void InvalidateRegion(const nsIntRegion& aRegion) { |
51 | 0 | MOZ_CRASH(); |
52 | 0 | } |
53 | | }; |
54 | | |
55 | | class TestLayerManager: public LayerManager { |
56 | | public: |
57 | | TestLayerManager() |
58 | | : LayerManager() |
59 | 0 | {} |
60 | | |
61 | 0 | virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) { return false; } |
62 | 0 | virtual already_AddRefed<ContainerLayer> CreateContainerLayer() { |
63 | 0 | RefPtr<ContainerLayer> layer = new TestContainerLayer(this); |
64 | 0 | return layer.forget(); |
65 | 0 | } |
66 | 0 | virtual void GetBackendName(nsAString& aName) {} |
67 | 0 | virtual LayersBackend GetBackendType() { return LayersBackend::LAYERS_BASIC; } |
68 | 0 | virtual bool BeginTransaction() { return true; } |
69 | 0 | virtual already_AddRefed<ImageLayer> CreateImageLayer() { |
70 | 0 | MOZ_CRASH("Not implemented."); |
71 | 0 | } |
72 | 0 | virtual already_AddRefed<PaintedLayer> CreatePaintedLayer() { |
73 | 0 | RefPtr<PaintedLayer> layer = new TestPaintedLayer(this); |
74 | 0 | return layer.forget(); |
75 | 0 | } |
76 | 0 | virtual already_AddRefed<ColorLayer> CreateColorLayer() { |
77 | 0 | MOZ_CRASH("Not implemented."); |
78 | 0 | } |
79 | 0 | virtual void SetRoot(Layer* aLayer) {} |
80 | 0 | virtual bool BeginTransactionWithTarget(gfxContext* aTarget) { return true; } |
81 | 0 | virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() { |
82 | 0 | MOZ_CRASH("Not implemented."); |
83 | 0 | } |
84 | | virtual void EndTransaction(DrawPaintedLayerCallback aCallback, |
85 | | void* aCallbackData, |
86 | 0 | EndTransactionFlags aFlags = END_DEFAULT) {} |
87 | 0 | virtual int32_t GetMaxTextureSize() const { return 0; } |
88 | | }; |
89 | | |
90 | | class TestUserData: public LayerUserData { |
91 | | public: |
92 | | MOCK_METHOD0(Die, void()); |
93 | 0 | virtual ~TestUserData() { Die(); } |
94 | | }; |
95 | | |
96 | | |
97 | 0 | TEST(Layers, LayerConstructor) { |
98 | 0 | TestContainerLayer layer(nullptr); |
99 | 0 | } |
100 | | |
101 | 0 | TEST(Layers, Defaults) { |
102 | 0 | TestContainerLayer layer(nullptr); |
103 | 0 | ASSERT_EQ(1.0, layer.GetOpacity()); |
104 | 0 | ASSERT_EQ(1.0f, layer.GetPostXScale()); |
105 | 0 | ASSERT_EQ(1.0f, layer.GetPostYScale()); |
106 | 0 |
|
107 | 0 | ASSERT_EQ(nullptr, layer.GetNextSibling()); |
108 | 0 | ASSERT_EQ(nullptr, layer.GetPrevSibling()); |
109 | 0 | ASSERT_EQ(nullptr, layer.GetFirstChild()); |
110 | 0 | ASSERT_EQ(nullptr, layer.GetLastChild()); |
111 | 0 | } |
112 | | |
113 | 0 | TEST(Layers, Transform) { |
114 | 0 | TestContainerLayer layer(nullptr); |
115 | 0 |
|
116 | 0 | Matrix4x4 identity; |
117 | 0 | ASSERT_EQ(true, identity.IsIdentity()); |
118 | 0 |
|
119 | 0 | ASSERT_EQ(identity, layer.GetTransform()); |
120 | 0 | } |
121 | | |
122 | 0 | TEST(Layers, Type) { |
123 | 0 | TestContainerLayer layer(nullptr); |
124 | 0 | ASSERT_EQ(nullptr, layer.AsPaintedLayer()); |
125 | 0 | ASSERT_EQ(nullptr, layer.AsRefLayer()); |
126 | 0 | ASSERT_EQ(nullptr, layer.AsColorLayer()); |
127 | 0 | } |
128 | | |
129 | 0 | TEST(Layers, UserData) { |
130 | 0 | UniquePtr<TestContainerLayer> layerPtr(new TestContainerLayer(nullptr)); |
131 | 0 | TestContainerLayer& layer = *layerPtr; |
132 | 0 |
|
133 | 0 | void* key1 = (void*)1; |
134 | 0 | void* key2 = (void*)2; |
135 | 0 | void* key3 = (void*)3; |
136 | 0 |
|
137 | 0 | ASSERT_EQ(nullptr, layer.GetUserData(key1)); |
138 | 0 | ASSERT_EQ(nullptr, layer.GetUserData(key2)); |
139 | 0 | ASSERT_EQ(nullptr, layer.GetUserData(key3)); |
140 | 0 |
|
141 | 0 | TestUserData* data1 = new TestUserData; |
142 | 0 | TestUserData* data2 = new TestUserData; |
143 | 0 | TestUserData* data3 = new TestUserData; |
144 | 0 |
|
145 | 0 | layer.SetUserData(key1, data1); |
146 | 0 | layer.SetUserData(key2, data2); |
147 | 0 | layer.SetUserData(key3, data3); |
148 | 0 |
|
149 | 0 | // Also checking that the user data is returned but not free'd |
150 | 0 | UniquePtr<LayerUserData> d1(layer.RemoveUserData(key1)); |
151 | 0 | UniquePtr<LayerUserData> d2(layer.RemoveUserData(key2)); |
152 | 0 | UniquePtr<LayerUserData> d3(layer.RemoveUserData(key3)); |
153 | 0 | ASSERT_EQ(data1, d1.get()); |
154 | 0 | ASSERT_EQ(data2, d2.get()); |
155 | 0 | ASSERT_EQ(data3, d3.get()); |
156 | 0 |
|
157 | 0 | layer.SetUserData(key1, d1.release()); |
158 | 0 | layer.SetUserData(key2, d2.release()); |
159 | 0 | layer.SetUserData(key3, d3.release()); |
160 | 0 |
|
161 | 0 | // Layer has ownership of data1-3, check that they are destroyed |
162 | 0 | EXPECT_CALL(*data1, Die()); |
163 | 0 | EXPECT_CALL(*data2, Die()); |
164 | 0 | EXPECT_CALL(*data3, Die()); |
165 | 0 | } |
166 | | |
167 | | static |
168 | 0 | already_AddRefed<Layer> CreateLayer(char aLayerType, LayerManager* aManager) { |
169 | 0 | RefPtr<Layer> layer = nullptr; |
170 | 0 | if (aLayerType == 'c') { |
171 | 0 | layer = aManager->CreateContainerLayer(); |
172 | 0 | } else if (aLayerType == 't') { |
173 | 0 | layer = aManager->CreatePaintedLayer(); |
174 | 0 | } else if (aLayerType == 'o') { |
175 | 0 | layer = aManager->CreateColorLayer(); |
176 | 0 | } |
177 | 0 | return layer.forget(); |
178 | 0 | } |
179 | | |
180 | | already_AddRefed<Layer> CreateLayerTree( |
181 | | const char* aLayerTreeDescription, |
182 | | nsIntRegion* aVisibleRegions, |
183 | | const Matrix4x4* aTransforms, |
184 | | RefPtr<LayerManager>& manager, |
185 | 0 | nsTArray<RefPtr<Layer> >& aLayersOut) { |
186 | 0 |
|
187 | 0 | aLayersOut.Clear(); |
188 | 0 |
|
189 | 0 | if (!manager) { |
190 | 0 | manager = new TestLayerManager(); |
191 | 0 | } |
192 | 0 |
|
193 | 0 | RefPtr<Layer> rootLayer = nullptr; |
194 | 0 | RefPtr<ContainerLayer> parentContainerLayer = nullptr; |
195 | 0 | RefPtr<Layer> lastLayer = nullptr; |
196 | 0 | int layerNumber = 0; |
197 | 0 | for (size_t i = 0; i < strlen(aLayerTreeDescription); i++) { |
198 | 0 | if (aLayerTreeDescription[i] == '(') { |
199 | 0 | if (!lastLayer) { |
200 | 0 | printf("Syntax error, likely '(' character isn't preceded by a container.\n"); |
201 | 0 | MOZ_CRASH(); |
202 | 0 | } |
203 | 0 | parentContainerLayer = lastLayer->AsContainerLayer(); |
204 | 0 | if (!parentContainerLayer) { |
205 | 0 | printf("Layer before '(' must be a container.\n"); |
206 | 0 | MOZ_CRASH(); |
207 | 0 | } |
208 | 0 | } else if (aLayerTreeDescription[i] == ')') { |
209 | 0 | parentContainerLayer = parentContainerLayer->GetParent(); |
210 | 0 | lastLayer = nullptr; |
211 | 0 | } else { |
212 | 0 | RefPtr<Layer> layer = CreateLayer(aLayerTreeDescription[i], manager.get()); |
213 | 0 | if (aVisibleRegions) { |
214 | 0 | layer->SetVisibleRegion(LayerIntRegion::FromUnknownRegion(aVisibleRegions[layerNumber])); |
215 | 0 | layer->SetEventRegions(EventRegions(aVisibleRegions[layerNumber])); |
216 | 0 | } |
217 | 0 | if (aTransforms) { |
218 | 0 | layer->SetBaseTransform(aTransforms[layerNumber]); |
219 | 0 | } |
220 | 0 | aLayersOut.AppendElement(layer); |
221 | 0 | layerNumber++; |
222 | 0 | if (rootLayer && !parentContainerLayer) { |
223 | 0 | MOZ_CRASH(); |
224 | 0 | } |
225 | 0 | if (!rootLayer) { |
226 | 0 | rootLayer = layer; |
227 | 0 | } |
228 | 0 | if (parentContainerLayer) { |
229 | 0 | parentContainerLayer->InsertAfter(layer, parentContainerLayer->GetLastChild()); |
230 | 0 | layer->SetParent(parentContainerLayer); |
231 | 0 | } |
232 | 0 | lastLayer = layer; |
233 | 0 | } |
234 | 0 | } |
235 | 0 | if (rootLayer) { |
236 | 0 | rootLayer->ComputeEffectiveTransforms(Matrix4x4()); |
237 | 0 | manager->SetRoot(rootLayer); |
238 | 0 | if (rootLayer->AsHostLayer()) { |
239 | 0 | // Only perform this for LayerManagerComposite |
240 | 0 | CompositorBridgeParent::SetShadowProperties(rootLayer); |
241 | 0 | } |
242 | 0 | } |
243 | 0 | return rootLayer.forget(); |
244 | 0 | } |
245 | | |
246 | 0 | TEST(Layers, LayerTree) { |
247 | 0 | const char* layerTreeSyntax = "c(c(tt))"; |
248 | 0 | nsIntRegion layerVisibleRegion[] = { |
249 | 0 | nsIntRegion(IntRect(0,0,100,100)), |
250 | 0 | nsIntRegion(IntRect(0,0,100,100)), |
251 | 0 | nsIntRegion(IntRect(0,0,100,100)), |
252 | 0 | nsIntRegion(IntRect(10,10,20,20)), |
253 | 0 | }; |
254 | 0 | Matrix4x4 transforms[] = { |
255 | 0 | Matrix4x4(), |
256 | 0 | Matrix4x4(), |
257 | 0 | Matrix4x4(), |
258 | 0 | Matrix4x4(), |
259 | 0 | }; |
260 | 0 | nsTArray<RefPtr<Layer> > layers; |
261 | 0 |
|
262 | 0 | RefPtr<LayerManager> lm; |
263 | 0 | RefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, lm, layers); |
264 | 0 |
|
265 | 0 | // B2G g++ doesn't like ASSERT_NE with nullptr directly. It thinks it's |
266 | 0 | // an int. |
267 | 0 | Layer* nullLayer = nullptr; |
268 | 0 | ASSERT_NE(nullLayer, layers[0]->AsContainerLayer()); |
269 | 0 | ASSERT_NE(nullLayer, layers[1]->AsContainerLayer()); |
270 | 0 | ASSERT_NE(nullLayer, layers[2]->AsPaintedLayer()); |
271 | 0 | ASSERT_NE(nullLayer, layers[3]->AsPaintedLayer()); |
272 | 0 | } |
273 | | |
274 | 0 | static void ValidateTreePointers(Layer* aLayer) { |
275 | 0 | if (aLayer->GetNextSibling()) { |
276 | 0 | ASSERT_EQ(aLayer, aLayer->GetNextSibling()->GetPrevSibling()); |
277 | 0 | } else if (aLayer->GetParent()) { |
278 | 0 | ASSERT_EQ(aLayer, aLayer->GetParent()->GetLastChild()); |
279 | 0 | } |
280 | 0 | if (aLayer->GetPrevSibling()) { |
281 | 0 | ASSERT_EQ(aLayer, aLayer->GetPrevSibling()->GetNextSibling()); |
282 | 0 | } else if (aLayer->GetParent()) { |
283 | 0 | ASSERT_EQ(aLayer, aLayer->GetParent()->GetFirstChild()); |
284 | 0 | } |
285 | 0 | if (aLayer->GetFirstChild()) { |
286 | 0 | ASSERT_EQ(aLayer, aLayer->GetFirstChild()->GetParent()); |
287 | 0 | } |
288 | 0 | if (aLayer->GetLastChild()) { |
289 | 0 | ASSERT_EQ(aLayer, aLayer->GetLastChild()->GetParent()); |
290 | 0 | } |
291 | 0 | } |
292 | | |
293 | 0 | static void ValidateTreePointers(nsTArray<RefPtr<Layer> >& aLayers) { |
294 | 0 | for (uint32_t i = 0; i < aLayers.Length(); i++) { |
295 | 0 | ValidateTreePointers(aLayers[i]); |
296 | 0 | } |
297 | 0 | } |
298 | | |
299 | 0 | TEST(Layers, RepositionChild) { |
300 | 0 | const char* layerTreeSyntax = "c(ttt)"; |
301 | 0 |
|
302 | 0 | nsTArray<RefPtr<Layer> > layers; |
303 | 0 | RefPtr<LayerManager> lm; |
304 | 0 | RefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, nullptr, nullptr, lm, layers); |
305 | 0 | ContainerLayer* parent = root->AsContainerLayer(); |
306 | 0 | ValidateTreePointers(layers); |
307 | 0 |
|
308 | 0 | // tree is currently like this (using indexes into layers): |
309 | 0 | // 0 |
310 | 0 | // 1 2 3 |
311 | 0 | ASSERT_EQ(layers[2], layers[1]->GetNextSibling()); |
312 | 0 | ASSERT_EQ(layers[3], layers[2]->GetNextSibling()); |
313 | 0 | ASSERT_EQ(nullptr, layers[3]->GetNextSibling()); |
314 | 0 |
|
315 | 0 | parent->RepositionChild(layers[1], layers[3]); |
316 | 0 | ValidateTreePointers(layers); |
317 | 0 |
|
318 | 0 | // now the tree is like this: |
319 | 0 | // 0 |
320 | 0 | // 2 3 1 |
321 | 0 | ASSERT_EQ(layers[3], layers[2]->GetNextSibling()); |
322 | 0 | ASSERT_EQ(layers[1], layers[3]->GetNextSibling()); |
323 | 0 | ASSERT_EQ(nullptr, layers[1]->GetNextSibling()); |
324 | 0 |
|
325 | 0 | parent->RepositionChild(layers[3], layers[2]); |
326 | 0 | ValidateTreePointers(layers); |
327 | 0 |
|
328 | 0 | // no change |
329 | 0 | ASSERT_EQ(layers[3], layers[2]->GetNextSibling()); |
330 | 0 | ASSERT_EQ(layers[1], layers[3]->GetNextSibling()); |
331 | 0 | ASSERT_EQ(nullptr, layers[1]->GetNextSibling()); |
332 | 0 |
|
333 | 0 | parent->RepositionChild(layers[3], layers[1]); |
334 | 0 | ValidateTreePointers(layers); |
335 | 0 |
|
336 | 0 | // 0 |
337 | 0 | // 2 1 3 |
338 | 0 | ASSERT_EQ(layers[1], layers[2]->GetNextSibling()); |
339 | 0 | ASSERT_EQ(layers[3], layers[1]->GetNextSibling()); |
340 | 0 | ASSERT_EQ(nullptr, layers[3]->GetNextSibling()); |
341 | 0 |
|
342 | 0 | parent->RepositionChild(layers[3], nullptr); |
343 | 0 | ValidateTreePointers(layers); |
344 | 0 |
|
345 | 0 | // 0 |
346 | 0 | // 3 2 1 |
347 | 0 | ASSERT_EQ(layers[2], layers[3]->GetNextSibling()); |
348 | 0 | ASSERT_EQ(layers[1], layers[2]->GetNextSibling()); |
349 | 0 | ASSERT_EQ(nullptr, layers[1]->GetNextSibling()); |
350 | 0 | } |
351 | | |
352 | | class LayerMetricsWrapperTester : public ::testing::Test { |
353 | | protected: |
354 | 0 | virtual void SetUp() { |
355 | 0 | // This ensures ScrollMetadata::sNullMetadata is initialized. |
356 | 0 | gfxPlatform::GetPlatform(); |
357 | 0 | } |
358 | | }; |
359 | | |
360 | 0 | TEST_F(LayerMetricsWrapperTester, SimpleTree) { |
361 | 0 | nsTArray<RefPtr<Layer> > layers; |
362 | 0 | RefPtr<LayerManager> lm; |
363 | 0 | RefPtr<Layer> root = CreateLayerTree("c(c(c(tt)c(t)))", nullptr, nullptr, lm, layers); |
364 | 0 | LayerMetricsWrapper wrapper(root); |
365 | 0 |
|
366 | 0 | ASSERT_EQ(root.get(), wrapper.GetLayer()); |
367 | 0 | wrapper = wrapper.GetFirstChild(); |
368 | 0 | ASSERT_EQ(layers[1].get(), wrapper.GetLayer()); |
369 | 0 | ASSERT_FALSE(wrapper.GetNextSibling().IsValid()); |
370 | 0 | wrapper = wrapper.GetFirstChild(); |
371 | 0 | ASSERT_EQ(layers[2].get(), wrapper.GetLayer()); |
372 | 0 | wrapper = wrapper.GetFirstChild(); |
373 | 0 | ASSERT_EQ(layers[3].get(), wrapper.GetLayer()); |
374 | 0 | ASSERT_FALSE(wrapper.GetFirstChild().IsValid()); |
375 | 0 | wrapper = wrapper.GetNextSibling(); |
376 | 0 | ASSERT_EQ(layers[4].get(), wrapper.GetLayer()); |
377 | 0 | ASSERT_FALSE(wrapper.GetNextSibling().IsValid()); |
378 | 0 | wrapper = wrapper.GetParent(); |
379 | 0 | ASSERT_EQ(layers[2].get(), wrapper.GetLayer()); |
380 | 0 | wrapper = wrapper.GetNextSibling(); |
381 | 0 | ASSERT_EQ(layers[5].get(), wrapper.GetLayer()); |
382 | 0 | ASSERT_FALSE(wrapper.GetNextSibling().IsValid()); |
383 | 0 | wrapper = wrapper.GetLastChild(); |
384 | 0 | ASSERT_EQ(layers[6].get(), wrapper.GetLayer()); |
385 | 0 | wrapper = wrapper.GetParent(); |
386 | 0 | ASSERT_EQ(layers[5].get(), wrapper.GetLayer()); |
387 | 0 | LayerMetricsWrapper layer5 = wrapper; |
388 | 0 | wrapper = wrapper.GetPrevSibling(); |
389 | 0 | ASSERT_EQ(layers[2].get(), wrapper.GetLayer()); |
390 | 0 | wrapper = wrapper.GetParent(); |
391 | 0 | ASSERT_EQ(layers[1].get(), wrapper.GetLayer()); |
392 | 0 | ASSERT_TRUE(layer5 == wrapper.GetLastChild()); |
393 | 0 | LayerMetricsWrapper rootWrapper(root); |
394 | 0 | ASSERT_TRUE(rootWrapper == wrapper.GetParent()); |
395 | 0 | } |
396 | | |
397 | | static ScrollMetadata |
398 | 0 | MakeMetadata(FrameMetrics::ViewID aId) { |
399 | 0 | ScrollMetadata metadata; |
400 | 0 | metadata.GetMetrics().SetScrollId(aId); |
401 | 0 | return metadata; |
402 | 0 | } |
403 | | |
404 | 0 | TEST_F(LayerMetricsWrapperTester, MultiFramemetricsTree) { |
405 | 0 | nsTArray<RefPtr<Layer> > layers; |
406 | 0 | RefPtr<LayerManager> lm; |
407 | 0 | RefPtr<Layer> root = CreateLayerTree("c(c(c(tt)c(t)))", nullptr, nullptr, lm, layers); |
408 | 0 |
|
409 | 0 | nsTArray<ScrollMetadata> metadata; |
410 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::START_SCROLL_ID + 0)); // topmost of root layer |
411 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::NULL_SCROLL_ID)); |
412 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::START_SCROLL_ID + 1)); |
413 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::START_SCROLL_ID + 2)); |
414 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::NULL_SCROLL_ID)); |
415 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::NULL_SCROLL_ID)); // bottom of root layer |
416 | 0 | root->SetScrollMetadata(metadata); |
417 | 0 |
|
418 | 0 | metadata.Clear(); |
419 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::START_SCROLL_ID + 3)); |
420 | 0 | layers[1]->SetScrollMetadata(metadata); |
421 | 0 |
|
422 | 0 | metadata.Clear(); |
423 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::NULL_SCROLL_ID)); |
424 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::START_SCROLL_ID + 4)); |
425 | 0 | layers[2]->SetScrollMetadata(metadata); |
426 | 0 |
|
427 | 0 | metadata.Clear(); |
428 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::START_SCROLL_ID + 5)); |
429 | 0 | layers[4]->SetScrollMetadata(metadata); |
430 | 0 |
|
431 | 0 | metadata.Clear(); |
432 | 0 | metadata.InsertElementAt(0, MakeMetadata(FrameMetrics::START_SCROLL_ID + 6)); |
433 | 0 | layers[5]->SetScrollMetadata(metadata); |
434 | 0 |
|
435 | 0 | LayerMetricsWrapper wrapper(root, LayerMetricsWrapper::StartAt::TOP); |
436 | 0 | nsTArray<Layer*> expectedLayers; |
437 | 0 | expectedLayers.AppendElement(layers[0].get()); |
438 | 0 | expectedLayers.AppendElement(layers[0].get()); |
439 | 0 | expectedLayers.AppendElement(layers[0].get()); |
440 | 0 | expectedLayers.AppendElement(layers[0].get()); |
441 | 0 | expectedLayers.AppendElement(layers[0].get()); |
442 | 0 | expectedLayers.AppendElement(layers[0].get()); |
443 | 0 | expectedLayers.AppendElement(layers[1].get()); |
444 | 0 | expectedLayers.AppendElement(layers[2].get()); |
445 | 0 | expectedLayers.AppendElement(layers[2].get()); |
446 | 0 | expectedLayers.AppendElement(layers[3].get()); |
447 | 0 | nsTArray<FrameMetrics::ViewID> expectedIds; |
448 | 0 | expectedIds.AppendElement(FrameMetrics::START_SCROLL_ID + 0); |
449 | 0 | expectedIds.AppendElement(FrameMetrics::NULL_SCROLL_ID); |
450 | 0 | expectedIds.AppendElement(FrameMetrics::START_SCROLL_ID + 1); |
451 | 0 | expectedIds.AppendElement(FrameMetrics::START_SCROLL_ID + 2); |
452 | 0 | expectedIds.AppendElement(FrameMetrics::NULL_SCROLL_ID); |
453 | 0 | expectedIds.AppendElement(FrameMetrics::NULL_SCROLL_ID); |
454 | 0 | expectedIds.AppendElement(FrameMetrics::START_SCROLL_ID + 3); |
455 | 0 | expectedIds.AppendElement(FrameMetrics::NULL_SCROLL_ID); |
456 | 0 | expectedIds.AppendElement(FrameMetrics::START_SCROLL_ID + 4); |
457 | 0 | expectedIds.AppendElement(FrameMetrics::NULL_SCROLL_ID); |
458 | 0 | for (int i = 0; i < 10; i++) { |
459 | 0 | ASSERT_EQ(expectedLayers[i], wrapper.GetLayer()); |
460 | 0 | ASSERT_EQ(expectedIds[i], wrapper.Metrics().GetScrollId()); |
461 | 0 | wrapper = wrapper.GetFirstChild(); |
462 | 0 | } |
463 | 0 | ASSERT_FALSE(wrapper.IsValid()); |
464 | 0 |
|
465 | 0 | wrapper = LayerMetricsWrapper(root, LayerMetricsWrapper::StartAt::BOTTOM); |
466 | 0 | for (int i = 5; i < 10; i++) { |
467 | 0 | ASSERT_EQ(expectedLayers[i], wrapper.GetLayer()); |
468 | 0 | ASSERT_EQ(expectedIds[i], wrapper.Metrics().GetScrollId()); |
469 | 0 | wrapper = wrapper.GetFirstChild(); |
470 | 0 | } |
471 | 0 | ASSERT_FALSE(wrapper.IsValid()); |
472 | 0 |
|
473 | 0 | wrapper = LayerMetricsWrapper(layers[4], LayerMetricsWrapper::StartAt::BOTTOM); |
474 | 0 | ASSERT_EQ(FrameMetrics::START_SCROLL_ID + 5, wrapper.Metrics().GetScrollId()); |
475 | 0 | wrapper = wrapper.GetParent(); |
476 | 0 | ASSERT_EQ(FrameMetrics::START_SCROLL_ID + 4, wrapper.Metrics().GetScrollId()); |
477 | 0 | ASSERT_EQ(layers[2].get(), wrapper.GetLayer()); |
478 | 0 | ASSERT_FALSE(wrapper.GetNextSibling().IsValid()); |
479 | 0 | wrapper = wrapper.GetParent(); |
480 | 0 | ASSERT_EQ(FrameMetrics::NULL_SCROLL_ID, wrapper.Metrics().GetScrollId()); |
481 | 0 | ASSERT_EQ(layers[2].get(), wrapper.GetLayer()); |
482 | 0 | wrapper = wrapper.GetNextSibling(); |
483 | 0 | ASSERT_EQ(FrameMetrics::START_SCROLL_ID + 6, wrapper.Metrics().GetScrollId()); |
484 | 0 | ASSERT_EQ(layers[5].get(), wrapper.GetLayer()); |
485 | 0 | } |