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