OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 "base/mac/sdk_forward_declarations.h" | |
6 #include "content/common/gpu/ca_layer_tree_mac.h" | |
7 #include "gpu/GLES2/gl2extchromium.h" | |
8 #include "testing/gtest/include/gtest/gtest.h" | |
9 #include "third_party/skia/include/core/SkColor.h" | |
10 #include "ui/gfx/geometry/dip_util.h" | |
11 #include "ui/gfx/mac/io_surface.h" | |
12 | |
13 namespace content { | |
14 | |
15 class CALayerTreeTest : public testing::Test { | |
16 protected: | |
17 void SetUp() override { | |
18 superlayer_.reset([[CALayer alloc] init]); | |
19 } | |
20 | |
21 base::scoped_nsobject<CALayer> superlayer_; | |
22 }; | |
23 | |
24 // Test updating each layer's properties. | |
25 TEST_F(CALayerTreeTest, PropertyUpdates) { | |
26 base::ScopedCFTypeRef<IOSurfaceRef> io_surface(gfx::CreateIOSurface( | |
27 gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888)); | |
28 bool is_clipped = true; | |
29 gfx::Rect clip_rect(2, 4, 8, 16); | |
30 int sorting_context_id = 0; | |
31 gfx::Transform transform; | |
32 transform.Translate(10, 20); | |
33 gfx::RectF contents_rect(0.0f, 0.25f, 0.5f, 0.75f); | |
34 gfx::Rect rect(16, 32, 64, 128); | |
35 unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0, 0); | |
36 unsigned edge_aa_mask = GL_CA_LAYER_EDGE_LEFT_CHROMIUM; | |
37 float opacity = 0.5f; | |
38 float scale_factor = 1.0f; | |
39 bool result = false; | |
40 | |
41 scoped_ptr<CALayerTree> ca_layer_tree; | |
42 CALayer* root_layer = nil; | |
43 CALayer* clip_and_sorting_layer = nil; | |
44 CALayer* transform_layer = nil; | |
45 CALayer* content_layer = nil; | |
46 | |
47 // Validate the initial values. | |
48 { | |
49 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
50 result = new_ca_layer_tree->ScheduleCALayer( | |
51 is_clipped, | |
52 clip_rect, | |
53 sorting_context_id, | |
54 transform, | |
55 io_surface, | |
56 contents_rect, | |
57 rect, | |
58 background_color, | |
59 edge_aa_mask, | |
60 opacity); | |
61 EXPECT_TRUE(result); | |
62 new_ca_layer_tree->CommitScheduledCALayers( | |
63 superlayer_, std::move(ca_layer_tree), scale_factor); | |
64 std::swap(new_ca_layer_tree, ca_layer_tree); | |
65 | |
66 // Validate the tree structure. | |
67 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
68 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | |
69 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
70 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; | |
71 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
72 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; | |
73 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
74 content_layer = [[transform_layer sublayers] objectAtIndex:0]; | |
75 | |
76 // Validate the clip and sorting context layer. | |
77 EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); | |
78 EXPECT_EQ(gfx::Rect(clip_rect.size()), | |
79 gfx::Rect([clip_and_sorting_layer bounds])); | |
80 EXPECT_EQ(clip_rect.origin(), | |
81 gfx::Point([clip_and_sorting_layer position])); | |
82 EXPECT_EQ(-clip_rect.origin().x(), | |
83 [clip_and_sorting_layer sublayerTransform].m41); | |
84 EXPECT_EQ(-clip_rect.origin().y(), | |
85 [clip_and_sorting_layer sublayerTransform].m42); | |
86 | |
87 // Validate the transform layer. | |
88 EXPECT_EQ(transform.matrix().get(3, 0), | |
89 [transform_layer sublayerTransform].m41); | |
90 EXPECT_EQ(transform.matrix().get(3, 1), | |
91 [transform_layer sublayerTransform].m42); | |
92 | |
93 // Validate the content layer. | |
94 EXPECT_EQ(static_cast<id>(io_surface.get()), [content_layer contents]); | |
95 EXPECT_EQ(contents_rect, gfx::RectF([content_layer contentsRect])); | |
96 EXPECT_EQ(rect.origin(), gfx::Point([content_layer position])); | |
97 EXPECT_EQ(gfx::Rect(rect.size()), gfx::Rect([content_layer bounds])); | |
98 EXPECT_EQ(kCALayerLeftEdge, [content_layer edgeAntialiasingMask]); | |
99 EXPECT_EQ(opacity, [content_layer opacity]); | |
100 if ([content_layer respondsToSelector:(@selector(contentsScale))]) | |
101 EXPECT_EQ(scale_factor, [content_layer contentsScale]); | |
102 } | |
103 | |
104 // Update just the clip rect and re-commit. | |
105 { | |
106 clip_rect = gfx::Rect(4, 8, 16, 32); | |
107 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
108 result = new_ca_layer_tree->ScheduleCALayer( | |
109 is_clipped, | |
110 clip_rect, | |
111 sorting_context_id, | |
112 transform, | |
113 io_surface, | |
114 contents_rect, | |
115 rect, | |
116 background_color, | |
117 edge_aa_mask, | |
118 opacity); | |
119 EXPECT_TRUE(result); | |
120 new_ca_layer_tree->CommitScheduledCALayers( | |
121 superlayer_, std::move(ca_layer_tree), scale_factor); | |
122 std::swap(new_ca_layer_tree, ca_layer_tree); | |
123 | |
124 // Validate the tree structure | |
125 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
126 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
127 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
128 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
129 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
130 EXPECT_EQ(transform_layer, | |
131 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
132 | |
133 // Validate the clip and sorting context layer. | |
134 EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); | |
135 EXPECT_EQ(gfx::Rect(clip_rect.size()), | |
136 gfx::Rect([clip_and_sorting_layer bounds])); | |
137 EXPECT_EQ(clip_rect.origin(), | |
138 gfx::Point([clip_and_sorting_layer position])); | |
139 EXPECT_EQ(-clip_rect.origin().x(), | |
140 [clip_and_sorting_layer sublayerTransform].m41); | |
141 EXPECT_EQ(-clip_rect.origin().y(), | |
142 [clip_and_sorting_layer sublayerTransform].m42); | |
143 } | |
144 | |
145 // Disable clipping and re-commit. | |
146 { | |
147 is_clipped = false; | |
148 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
149 result = new_ca_layer_tree->ScheduleCALayer( | |
150 is_clipped, | |
151 clip_rect, | |
152 sorting_context_id, | |
153 transform, | |
154 io_surface, | |
155 contents_rect, | |
156 rect, | |
157 background_color, | |
158 edge_aa_mask, | |
159 opacity); | |
160 EXPECT_TRUE(result); | |
161 new_ca_layer_tree->CommitScheduledCALayers( | |
162 superlayer_, std::move(ca_layer_tree), scale_factor); | |
163 std::swap(new_ca_layer_tree, ca_layer_tree); | |
164 | |
165 // Validate the tree structure | |
166 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
167 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
168 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
169 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
170 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
171 EXPECT_EQ(transform_layer, | |
172 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
173 | |
174 // Validate the clip and sorting context layer. | |
175 EXPECT_FALSE([clip_and_sorting_layer masksToBounds]); | |
176 EXPECT_EQ(gfx::Rect(), gfx::Rect([clip_and_sorting_layer bounds])); | |
177 EXPECT_EQ(gfx::Point(), gfx::Point([clip_and_sorting_layer position])); | |
178 EXPECT_EQ(0.0, [clip_and_sorting_layer sublayerTransform].m41); | |
179 EXPECT_EQ(0.0, [clip_and_sorting_layer sublayerTransform].m42); | |
180 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
181 } | |
182 | |
183 // Change the transform and re-commit. | |
184 { | |
185 transform.Translate(5, 5); | |
186 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
187 result = new_ca_layer_tree->ScheduleCALayer( | |
188 is_clipped, | |
189 clip_rect, | |
190 sorting_context_id, | |
191 transform, | |
192 io_surface, | |
193 contents_rect, | |
194 rect, | |
195 background_color, | |
196 edge_aa_mask, | |
197 opacity); | |
198 EXPECT_TRUE(result); | |
199 new_ca_layer_tree->CommitScheduledCALayers( | |
200 superlayer_, std::move(ca_layer_tree), scale_factor); | |
201 std::swap(new_ca_layer_tree, ca_layer_tree); | |
202 | |
203 // Validate the tree structure. | |
204 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
205 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
206 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
207 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
208 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
209 EXPECT_EQ(transform_layer, | |
210 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
211 | |
212 // Validate the transform layer. | |
213 EXPECT_EQ(transform.matrix().get(3, 0), | |
214 [transform_layer sublayerTransform].m41); | |
215 EXPECT_EQ(transform.matrix().get(3, 1), | |
216 [transform_layer sublayerTransform].m42); | |
217 } | |
218 | |
219 // Change the edge antialiasing mask and commit. | |
220 { | |
221 edge_aa_mask = GL_CA_LAYER_EDGE_TOP_CHROMIUM; | |
222 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
223 result = new_ca_layer_tree->ScheduleCALayer( | |
224 is_clipped, | |
225 clip_rect, | |
226 sorting_context_id, | |
227 transform, | |
228 io_surface, | |
229 contents_rect, | |
230 rect, | |
231 background_color, | |
232 edge_aa_mask, | |
233 opacity); | |
234 EXPECT_TRUE(result); | |
235 new_ca_layer_tree->CommitScheduledCALayers( | |
236 superlayer_, std::move(ca_layer_tree), scale_factor); | |
237 std::swap(new_ca_layer_tree, ca_layer_tree); | |
238 | |
239 // Validate the tree structure. | |
240 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
241 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
242 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
243 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
244 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
245 EXPECT_EQ(transform_layer, | |
246 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
247 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
248 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
249 | |
250 // Validate the content layer. Note that top and bottom edges flip. | |
251 EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); | |
252 } | |
253 | |
254 // Change the contents and commit. | |
255 { | |
256 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
257 result = new_ca_layer_tree->ScheduleCALayer( | |
258 is_clipped, | |
259 clip_rect, | |
260 sorting_context_id, | |
261 transform, | |
262 nullptr, | |
263 contents_rect, | |
264 rect, | |
265 background_color, | |
266 edge_aa_mask, | |
267 opacity); | |
268 EXPECT_TRUE(result); | |
269 new_ca_layer_tree->CommitScheduledCALayers( | |
270 superlayer_, std::move(ca_layer_tree), scale_factor); | |
271 std::swap(new_ca_layer_tree, ca_layer_tree); | |
272 | |
273 // Validate the tree structure. | |
274 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
275 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
276 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
277 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
278 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
279 EXPECT_EQ(transform_layer, | |
280 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
281 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
282 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
283 | |
284 // Validate the content layer. Note that edge anti-aliasing no longer flips. | |
285 EXPECT_EQ(nil, [content_layer contents]); | |
286 EXPECT_EQ(kCALayerTopEdge, [content_layer edgeAntialiasingMask]); | |
287 } | |
288 | |
289 // Change the rect size. | |
290 { | |
291 rect = gfx::Rect(rect.origin(), gfx::Size(32, 16)); | |
292 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
293 result = new_ca_layer_tree->ScheduleCALayer( | |
294 is_clipped, | |
295 clip_rect, | |
296 sorting_context_id, | |
297 transform, | |
298 nullptr, | |
299 contents_rect, | |
300 rect, | |
301 background_color, | |
302 edge_aa_mask, | |
303 opacity); | |
304 EXPECT_TRUE(result); | |
305 new_ca_layer_tree->CommitScheduledCALayers( | |
306 superlayer_, std::move(ca_layer_tree), scale_factor); | |
307 std::swap(new_ca_layer_tree, ca_layer_tree); | |
308 | |
309 // Validate the tree structure. | |
310 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
311 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
312 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
313 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
314 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
315 EXPECT_EQ(transform_layer, | |
316 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
317 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
318 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
319 | |
320 // Validate the content layer. | |
321 EXPECT_EQ(rect.origin(), gfx::Point([content_layer position])); | |
322 EXPECT_EQ(gfx::Rect(rect.size()), gfx::Rect([content_layer bounds])); | |
323 } | |
324 | |
325 // Change the rect position. | |
326 { | |
327 rect = gfx::Rect(gfx::Point(16, 4), rect.size()); | |
328 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
329 result = new_ca_layer_tree->ScheduleCALayer( | |
330 is_clipped, | |
331 clip_rect, | |
332 sorting_context_id, | |
333 transform, | |
334 nullptr, | |
335 contents_rect, | |
336 rect, | |
337 background_color, | |
338 edge_aa_mask, | |
339 opacity); | |
340 EXPECT_TRUE(result); | |
341 new_ca_layer_tree->CommitScheduledCALayers( | |
342 superlayer_, std::move(ca_layer_tree), scale_factor); | |
343 std::swap(new_ca_layer_tree, ca_layer_tree); | |
344 | |
345 // Validate the tree structure. | |
346 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
347 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
348 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
349 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
350 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
351 EXPECT_EQ(transform_layer, | |
352 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
353 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
354 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
355 | |
356 // Validate the content layer. | |
357 EXPECT_EQ(rect.origin(), gfx::Point([content_layer position])); | |
358 EXPECT_EQ(gfx::Rect(rect.size()), gfx::Rect([content_layer bounds])); | |
359 } | |
360 | |
361 // Change the opacity. | |
362 { | |
363 opacity = 1.0f; | |
364 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
365 result = new_ca_layer_tree->ScheduleCALayer( | |
366 is_clipped, | |
367 clip_rect, | |
368 sorting_context_id, | |
369 transform, | |
370 nullptr, | |
371 contents_rect, | |
372 rect, | |
373 background_color, | |
374 edge_aa_mask, | |
375 opacity); | |
376 EXPECT_TRUE(result); | |
377 new_ca_layer_tree->CommitScheduledCALayers( | |
378 superlayer_, std::move(ca_layer_tree), scale_factor); | |
379 std::swap(new_ca_layer_tree, ca_layer_tree); | |
380 | |
381 // Validate the tree structure. | |
382 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
383 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
384 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
385 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
386 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
387 EXPECT_EQ(transform_layer, | |
388 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
389 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
390 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
391 | |
392 // Validate the content layer. | |
393 EXPECT_EQ(opacity, [content_layer opacity]); | |
394 } | |
395 | |
396 // Add the clipping and IOSurface contents back. | |
397 { | |
398 is_clipped = true; | |
399 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
400 result = new_ca_layer_tree->ScheduleCALayer( | |
401 is_clipped, | |
402 clip_rect, | |
403 sorting_context_id, | |
404 transform, | |
405 io_surface, | |
406 contents_rect, | |
407 rect, | |
408 background_color, | |
409 edge_aa_mask, | |
410 opacity); | |
411 EXPECT_TRUE(result); | |
412 new_ca_layer_tree->CommitScheduledCALayers( | |
413 superlayer_, std::move(ca_layer_tree), scale_factor); | |
414 std::swap(new_ca_layer_tree, ca_layer_tree); | |
415 | |
416 // Validate the tree structure. | |
417 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
418 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
419 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
420 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
421 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
422 EXPECT_EQ(transform_layer, | |
423 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
424 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
425 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
426 | |
427 // Validate the content layer. | |
428 EXPECT_EQ(static_cast<id>(io_surface.get()), [content_layer contents]); | |
429 EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); | |
430 } | |
431 | |
432 // Change the scale factor. This should result in a new tree being created. | |
433 { | |
434 scale_factor = 2.0f; | |
435 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
436 result = new_ca_layer_tree->ScheduleCALayer( | |
437 is_clipped, | |
438 clip_rect, | |
439 sorting_context_id, | |
440 transform, | |
441 io_surface, | |
442 contents_rect, | |
443 rect, | |
444 background_color, | |
445 edge_aa_mask, | |
446 opacity); | |
447 EXPECT_TRUE(result); | |
448 new_ca_layer_tree->CommitScheduledCALayers( | |
449 superlayer_, std::move(ca_layer_tree), scale_factor); | |
450 std::swap(new_ca_layer_tree, ca_layer_tree); | |
451 | |
452 // Validate the tree structure. | |
453 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
454 EXPECT_NE(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
455 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | |
456 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
457 EXPECT_NE(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
458 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; | |
459 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
460 EXPECT_NE(transform_layer, | |
461 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
462 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; | |
463 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
464 EXPECT_NE(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
465 content_layer = [[transform_layer sublayers] objectAtIndex:0]; | |
466 | |
467 // Validate the clip and sorting context layer. | |
468 EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); | |
469 EXPECT_EQ(gfx::ConvertRectToDIP(scale_factor, gfx::Rect(clip_rect.size())), | |
470 gfx::Rect([clip_and_sorting_layer bounds])); | |
471 EXPECT_EQ(gfx::ConvertPointToDIP(scale_factor, clip_rect.origin()), | |
472 gfx::Point([clip_and_sorting_layer position])); | |
473 EXPECT_EQ(-clip_rect.origin().x() / scale_factor, | |
474 [clip_and_sorting_layer sublayerTransform].m41); | |
475 EXPECT_EQ(-clip_rect.origin().y() / scale_factor, | |
476 [clip_and_sorting_layer sublayerTransform].m42); | |
477 | |
478 // Validate the transform layer. | |
479 EXPECT_EQ(transform.matrix().get(3, 0) / scale_factor, | |
480 [transform_layer sublayerTransform].m41); | |
481 EXPECT_EQ(transform.matrix().get(3, 1) / scale_factor, | |
482 [transform_layer sublayerTransform].m42); | |
483 | |
484 // Validate the content layer. | |
485 EXPECT_EQ(static_cast<id>(io_surface.get()), [content_layer contents]); | |
486 EXPECT_EQ(contents_rect, gfx::RectF([content_layer contentsRect])); | |
487 EXPECT_EQ(gfx::ConvertPointToDIP(scale_factor, rect.origin()), | |
488 gfx::Point([content_layer position])); | |
489 EXPECT_EQ(gfx::ConvertRectToDIP(scale_factor, gfx::Rect(rect.size())), | |
490 gfx::Rect([content_layer bounds])); | |
491 EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); | |
492 EXPECT_EQ(opacity, [content_layer opacity]); | |
493 if ([content_layer respondsToSelector:(@selector(contentsScale))]) | |
494 EXPECT_EQ(scale_factor, [content_layer contentsScale]); | |
495 } | |
496 } | |
497 | |
498 // Verify that sorting context zero is split at non-flat transforms. | |
499 TEST_F(CALayerTreeTest, SplitSortingContextZero) { | |
500 bool is_clipped = false; | |
501 gfx::Rect clip_rect; | |
502 int sorting_context_id = 0; | |
503 gfx::RectF contents_rect(0, 0, 1, 1); | |
504 gfx::Rect rect(0, 0, 256, 256); | |
505 unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF); | |
506 unsigned edge_aa_mask = 0; | |
507 float opacity = 1.0f; | |
508 float scale_factor = 1.0f; | |
509 | |
510 // We'll use the IOSurface contents to identify the content layers. | |
511 base::ScopedCFTypeRef<IOSurfaceRef> io_surfaces[5]; | |
512 for (size_t i = 0; i < 5; ++i) { | |
513 io_surfaces[i].reset(gfx::CreateIOSurface( | |
514 gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888)); | |
515 } | |
516 | |
517 // Have 5 transforms: | |
518 // * 2 flat but different (1 sorting context layer, 2 transform layers) | |
519 // * 1 non-flat (new sorting context layer) | |
520 // * 2 flat and the same (new sorting context layer, 1 transform layer) | |
521 gfx::Transform transforms[5]; | |
522 transforms[0].Translate(10, 10); | |
523 transforms[1].RotateAboutZAxis(45.0f); | |
524 transforms[2].RotateAboutYAxis(45.0f); | |
525 transforms[3].Translate(10, 10); | |
526 transforms[4].Translate(10, 10); | |
527 | |
528 // Schedule and commit the layers. | |
529 scoped_ptr<CALayerTree> ca_layer_tree(new CALayerTree); | |
530 for (size_t i = 0; i < 5; ++i) { | |
531 bool result = ca_layer_tree->ScheduleCALayer( | |
532 is_clipped, | |
533 clip_rect, | |
534 sorting_context_id, | |
535 transforms[i], | |
536 io_surfaces[i], | |
537 contents_rect, | |
538 rect, | |
539 background_color, | |
540 edge_aa_mask, | |
541 opacity); | |
542 EXPECT_TRUE(result); | |
543 } | |
544 ca_layer_tree->CommitScheduledCALayers(superlayer_, nullptr, scale_factor); | |
545 | |
546 // Validate the root layer. | |
547 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
548 CALayer* root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | |
549 | |
550 // Validate that we have 3 sorting context layers. | |
551 EXPECT_EQ(3u, [[root_layer sublayers] count]); | |
552 CALayer* clip_and_sorting_layer_0 = [[root_layer sublayers] objectAtIndex:0]; | |
553 CALayer* clip_and_sorting_layer_1 = [[root_layer sublayers] objectAtIndex:1]; | |
554 CALayer* clip_and_sorting_layer_2 = [[root_layer sublayers] objectAtIndex:2]; | |
555 | |
556 // Validate that the first sorting context has 2 transform layers each with | |
557 // one content layer. | |
558 EXPECT_EQ(2u, [[clip_and_sorting_layer_0 sublayers] count]); | |
559 CALayer* transform_layer_0_0 = | |
560 [[clip_and_sorting_layer_0 sublayers] objectAtIndex:0]; | |
561 CALayer* transform_layer_0_1 = | |
562 [[clip_and_sorting_layer_0 sublayers] objectAtIndex:1]; | |
563 EXPECT_EQ(1u, [[transform_layer_0_0 sublayers] count]); | |
564 CALayer* content_layer_0 = [[transform_layer_0_0 sublayers] objectAtIndex:0]; | |
565 EXPECT_EQ(1u, [[transform_layer_0_1 sublayers] count]); | |
566 CALayer* content_layer_1 = [[transform_layer_0_1 sublayers] objectAtIndex:0]; | |
567 | |
568 // Validate that the second sorting context has 1 transform layer with one | |
569 // content layer. | |
570 EXPECT_EQ(1u, [[clip_and_sorting_layer_1 sublayers] count]); | |
571 CALayer* transform_layer_1_0 = | |
572 [[clip_and_sorting_layer_1 sublayers] objectAtIndex:0]; | |
573 EXPECT_EQ(1u, [[transform_layer_1_0 sublayers] count]); | |
574 CALayer* content_layer_2 = [[transform_layer_1_0 sublayers] objectAtIndex:0]; | |
575 | |
576 // Validate that the third sorting context has 1 transform layer with two | |
577 // content layers. | |
578 EXPECT_EQ(1u, [[clip_and_sorting_layer_2 sublayers] count]); | |
579 CALayer* transform_layer_2_0 = | |
580 [[clip_and_sorting_layer_2 sublayers] objectAtIndex:0]; | |
581 EXPECT_EQ(2u, [[transform_layer_2_0 sublayers] count]); | |
582 CALayer* content_layer_3 = [[transform_layer_2_0 sublayers] objectAtIndex:0]; | |
583 CALayer* content_layer_4 = [[transform_layer_2_0 sublayers] objectAtIndex:1]; | |
584 | |
585 // Validate that the layers come out in order. | |
586 EXPECT_EQ(static_cast<id>(io_surfaces[0].get()), [content_layer_0 contents]); | |
587 EXPECT_EQ(static_cast<id>(io_surfaces[1].get()), [content_layer_1 contents]); | |
588 EXPECT_EQ(static_cast<id>(io_surfaces[2].get()), [content_layer_2 contents]); | |
589 EXPECT_EQ(static_cast<id>(io_surfaces[3].get()), [content_layer_3 contents]); | |
590 EXPECT_EQ(static_cast<id>(io_surfaces[4].get()), [content_layer_4 contents]); | |
591 } | |
592 | |
593 // Verify that sorting contexts are allocated appropriately. | |
594 TEST_F(CALayerTreeTest, SortingContexts) { | |
595 bool is_clipped = false; | |
596 gfx::Rect clip_rect; | |
597 int sorting_context_ids[3] = {3, -1, 0}; | |
598 gfx::RectF contents_rect(0, 0, 1, 1); | |
599 gfx::Rect rect(0, 0, 256, 256); | |
600 gfx::Transform transform; | |
601 unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF); | |
602 unsigned edge_aa_mask = 0; | |
603 float opacity = 1.0f; | |
604 float scale_factor = 1.0f; | |
605 | |
606 // We'll use the IOSurface contents to identify the content layers. | |
607 base::ScopedCFTypeRef<IOSurfaceRef> io_surfaces[3]; | |
608 for (size_t i = 0; i < 3; ++i) { | |
609 io_surfaces[i].reset(gfx::CreateIOSurface( | |
610 gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888)); | |
611 } | |
612 | |
613 // Schedule and commit the layers. | |
614 scoped_ptr<CALayerTree> ca_layer_tree(new CALayerTree); | |
615 for (size_t i = 0; i < 3; ++i) { | |
616 bool result = ca_layer_tree->ScheduleCALayer( | |
617 is_clipped, | |
618 clip_rect, | |
619 sorting_context_ids[i], | |
620 transform, | |
621 io_surfaces[i], | |
622 contents_rect, | |
623 rect, | |
624 background_color, | |
625 edge_aa_mask, | |
626 opacity); | |
627 EXPECT_TRUE(result); | |
628 } | |
629 ca_layer_tree->CommitScheduledCALayers(superlayer_, nullptr, scale_factor); | |
630 | |
631 // Validate the root layer. | |
632 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
633 CALayer* root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | |
634 | |
635 // Validate that we have 3 sorting context layers. | |
636 EXPECT_EQ(3u, [[root_layer sublayers] count]); | |
637 CALayer* clip_and_sorting_layer_0 = [[root_layer sublayers] objectAtIndex:0]; | |
638 CALayer* clip_and_sorting_layer_1 = [[root_layer sublayers] objectAtIndex:1]; | |
639 CALayer* clip_and_sorting_layer_2 = [[root_layer sublayers] objectAtIndex:2]; | |
640 | |
641 // Validate that each sorting context has 1 transform layer. | |
642 EXPECT_EQ(1u, [[clip_and_sorting_layer_0 sublayers] count]); | |
643 CALayer* transform_layer_0 = | |
644 [[clip_and_sorting_layer_0 sublayers] objectAtIndex:0]; | |
645 EXPECT_EQ(1u, [[clip_and_sorting_layer_1 sublayers] count]); | |
646 CALayer* transform_layer_1 = | |
647 [[clip_and_sorting_layer_1 sublayers] objectAtIndex:0]; | |
648 EXPECT_EQ(1u, [[clip_and_sorting_layer_2 sublayers] count]); | |
649 CALayer* transform_layer_2 = | |
650 [[clip_and_sorting_layer_2 sublayers] objectAtIndex:0]; | |
651 | |
652 // Validate that each transform has 1 content layer. | |
653 EXPECT_EQ(1u, [[transform_layer_0 sublayers] count]); | |
654 CALayer* content_layer_0 = [[transform_layer_0 sublayers] objectAtIndex:0]; | |
655 EXPECT_EQ(1u, [[transform_layer_1 sublayers] count]); | |
656 CALayer* content_layer_1 = [[transform_layer_1 sublayers] objectAtIndex:0]; | |
657 EXPECT_EQ(1u, [[transform_layer_2 sublayers] count]); | |
658 CALayer* content_layer_2 = [[transform_layer_2 sublayers] objectAtIndex:0]; | |
659 | |
660 // Validate that the layers come out in order. | |
661 EXPECT_EQ(static_cast<id>(io_surfaces[0].get()), [content_layer_0 contents]); | |
662 EXPECT_EQ(static_cast<id>(io_surfaces[1].get()), [content_layer_1 contents]); | |
663 EXPECT_EQ(static_cast<id>(io_surfaces[2].get()), [content_layer_2 contents]); | |
664 } | |
665 | |
666 // Verify that sorting contexts must all have the same clipping properties. | |
667 TEST_F(CALayerTreeTest, SortingContextMustHaveConsistentClip) { | |
668 base::ScopedCFTypeRef<IOSurfaceRef> io_surface; | |
669 gfx::RectF contents_rect(0, 0, 1, 1); | |
670 gfx::Rect rect(0, 0, 256, 256); | |
671 gfx::Transform transform; | |
672 unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF); | |
673 unsigned edge_aa_mask = 0; | |
674 float opacity = 1.0f; | |
675 | |
676 // Vary the clipping parameters within sorting contexts. | |
677 bool is_clippeds[3] = { true, true, false}; | |
678 gfx::Rect clip_rects[3] = { | |
679 gfx::Rect(0, 0, 16, 16), | |
680 gfx::Rect(4, 8, 16, 32), | |
681 gfx::Rect(0, 0, 16, 16) | |
682 }; | |
683 | |
684 scoped_ptr<CALayerTree> ca_layer_tree(new CALayerTree); | |
685 // First send the various clip parameters to sorting context zero. This is | |
686 // legitimate. | |
687 for (size_t i = 0; i < 3; ++i) { | |
688 int sorting_context_id = 0; | |
689 bool result = ca_layer_tree->ScheduleCALayer( | |
690 is_clippeds[i], | |
691 clip_rects[i], | |
692 sorting_context_id, | |
693 transform, | |
694 io_surface, | |
695 contents_rect, | |
696 rect, | |
697 background_color, | |
698 edge_aa_mask, | |
699 opacity); | |
700 EXPECT_TRUE(result); | |
701 } | |
702 // Next send the various clip parameters to a non-zero sorting context. This | |
703 // will fail when we try to change the clip within the sorting context. | |
704 for (size_t i = 0; i < 3; ++i) { | |
705 int sorting_context_id = 3; | |
706 bool result = ca_layer_tree->ScheduleCALayer( | |
707 is_clippeds[i], | |
708 clip_rects[i], | |
709 sorting_context_id, | |
710 transform, | |
711 io_surface, | |
712 contents_rect, | |
713 rect, | |
714 background_color, | |
715 edge_aa_mask, | |
716 opacity); | |
717 if (i == 0) | |
718 EXPECT_TRUE(result); | |
719 else | |
720 EXPECT_FALSE(result); | |
721 } | |
722 // Try once more with the original clip and verify it works. | |
723 { | |
724 int sorting_context_id = 3; | |
725 bool result = ca_layer_tree->ScheduleCALayer( | |
726 is_clippeds[0], | |
727 clip_rects[0], | |
728 sorting_context_id, | |
729 transform, | |
730 io_surface, | |
731 contents_rect, | |
732 rect, | |
733 background_color, | |
734 edge_aa_mask, | |
735 opacity); | |
736 EXPECT_TRUE(result); | |
737 } | |
738 } | |
739 | |
740 // Test updating each layer's properties. | |
741 TEST_F(CALayerTreeTest, AVLayer) { | |
742 base::ScopedCFTypeRef<IOSurfaceRef> io_surface(gfx::CreateIOSurface( | |
743 gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR)); | |
744 bool is_clipped = true; | |
745 gfx::Rect clip_rect(2, 4, 8, 16); | |
746 int sorting_context_id = 0; | |
747 gfx::Transform transform; | |
748 gfx::RectF contents_rect(0.0f, 0.0f, 1.0f, 1.0f); | |
749 gfx::Rect rect(16, 32, 64, 128); | |
750 unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0, 0); | |
751 unsigned edge_aa_mask = GL_CA_LAYER_EDGE_LEFT_CHROMIUM; | |
752 float opacity = 0.5f; | |
753 float scale_factor = 1.0f; | |
754 bool result = false; | |
755 | |
756 scoped_ptr<CALayerTree> ca_layer_tree; | |
757 CALayer* root_layer = nil; | |
758 CALayer* clip_and_sorting_layer = nil; | |
759 CALayer* transform_layer = nil; | |
760 CALayer* content_layer1 = nil; | |
761 CALayer* content_layer2 = nil; | |
762 CALayer* content_layer3 = nil; | |
763 | |
764 // Validate the initial values. | |
765 { | |
766 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
767 result = new_ca_layer_tree->ScheduleCALayer( | |
768 is_clipped, clip_rect, sorting_context_id, transform, io_surface, | |
769 contents_rect, rect, background_color, edge_aa_mask, opacity); | |
770 EXPECT_TRUE(result); | |
771 new_ca_layer_tree->CommitScheduledCALayers( | |
772 superlayer_, std::move(ca_layer_tree), scale_factor); | |
773 std::swap(new_ca_layer_tree, ca_layer_tree); | |
774 | |
775 // Validate the tree structure. | |
776 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
777 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | |
778 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
779 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; | |
780 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
781 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; | |
782 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
783 content_layer1 = [[transform_layer sublayers] objectAtIndex:0]; | |
784 | |
785 // Validate the content layer. | |
786 EXPECT_FALSE([content_layer1 | |
787 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); | |
788 } | |
789 | |
790 io_surface.reset(gfx::CreateIOSurface(gfx::Size(256, 256), | |
791 gfx::BufferFormat::YUV_420_BIPLANAR)); | |
792 | |
793 // Pass another frame. | |
794 { | |
795 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
796 result = new_ca_layer_tree->ScheduleCALayer( | |
797 is_clipped, clip_rect, sorting_context_id, transform, io_surface, | |
798 contents_rect, rect, background_color, edge_aa_mask, opacity); | |
799 EXPECT_TRUE(result); | |
800 new_ca_layer_tree->CommitScheduledCALayers( | |
801 superlayer_, std::move(ca_layer_tree), scale_factor); | |
802 std::swap(new_ca_layer_tree, ca_layer_tree); | |
803 | |
804 // Validate the tree structure. | |
805 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
806 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | |
807 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
808 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; | |
809 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
810 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; | |
811 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
812 content_layer2 = [[transform_layer sublayers] objectAtIndex:0]; | |
813 | |
814 // Validate the content layer. | |
815 EXPECT_FALSE([content_layer2 | |
816 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); | |
817 EXPECT_EQ(content_layer2, content_layer1); | |
818 } | |
819 | |
820 io_surface.reset(gfx::CreateIOSurface(gfx::Size(256, 256), | |
821 gfx::BufferFormat::YUV_420_BIPLANAR)); | |
822 | |
823 // Pass a frame that is clipped. | |
824 contents_rect = gfx::RectF(0, 0, 1, 0.9); | |
825 { | |
826 scoped_ptr<CALayerTree> new_ca_layer_tree(new CALayerTree); | |
827 result = new_ca_layer_tree->ScheduleCALayer( | |
828 is_clipped, clip_rect, sorting_context_id, transform, io_surface, | |
829 contents_rect, rect, background_color, edge_aa_mask, opacity); | |
830 EXPECT_TRUE(result); | |
831 new_ca_layer_tree->CommitScheduledCALayers( | |
832 superlayer_, std::move(ca_layer_tree), scale_factor); | |
833 std::swap(new_ca_layer_tree, ca_layer_tree); | |
834 | |
835 // Validate the tree structure. | |
836 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
837 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | |
838 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
839 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; | |
840 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
841 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; | |
842 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
843 content_layer3 = [[transform_layer sublayers] objectAtIndex:0]; | |
844 | |
845 // Validate the content layer. | |
846 EXPECT_FALSE([content_layer3 | |
847 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); | |
848 EXPECT_EQ(content_layer3, content_layer2); | |
849 } | |
850 } | |
851 | |
852 } // namespace content | |
OLD | NEW |