OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <AVFoundation/AVFoundation.h> | 5 #include <AVFoundation/AVFoundation.h> |
6 #include <memory> | 6 #include <memory> |
7 | 7 |
8 #include "base/mac/sdk_forward_declarations.h" | 8 #include "base/mac/sdk_forward_declarations.h" |
9 #include "gpu/GLES2/gl2extchromium.h" | 9 #include "gpu/GLES2/gl2extchromium.h" |
10 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
(...skipping 21 matching lines...) Expand all Loading... |
32 int sorting_context_id = 0; | 32 int sorting_context_id = 0; |
33 gfx::Transform transform; | 33 gfx::Transform transform; |
34 gfx::RectF contents_rect = gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f); | 34 gfx::RectF contents_rect = gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f); |
35 gfx::Rect rect = gfx::Rect(0, 0, 256, 256); | 35 gfx::Rect rect = gfx::Rect(0, 0, 256, 256); |
36 unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF); | 36 unsigned background_color = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF); |
37 unsigned edge_aa_mask = 0; | 37 unsigned edge_aa_mask = 0; |
38 float opacity = 1.0f; | 38 float opacity = 1.0f; |
39 float scale_factor = 1.0f; | 39 float scale_factor = 1.0f; |
40 unsigned filter = GL_LINEAR; | 40 unsigned filter = GL_LINEAR; |
41 scoped_refptr<gl::GLImageIOSurface> gl_image; | 41 scoped_refptr<gl::GLImageIOSurface> gl_image; |
| 42 |
| 43 bool allow_av_layers = true; |
| 44 bool allow_solid_color_layers = true; |
42 }; | 45 }; |
43 | 46 |
44 scoped_refptr<gl::GLImageIOSurface> CreateGLImage(const gfx::Size& size, | 47 scoped_refptr<gl::GLImageIOSurface> CreateGLImage(const gfx::Size& size, |
45 gfx::BufferFormat format, | 48 gfx::BufferFormat format, |
46 bool video) { | 49 bool video) { |
47 scoped_refptr<gl::GLImageIOSurface> gl_image( | 50 scoped_refptr<gl::GLImageIOSurface> gl_image( |
48 new gl::GLImageIOSurface(size, GL_RGBA)); | 51 new gl::GLImageIOSurface(size, GL_RGBA)); |
49 base::ScopedCFTypeRef<IOSurfaceRef> io_surface( | 52 base::ScopedCFTypeRef<IOSurfaceRef> io_surface( |
50 gfx::CreateIOSurface(size, format)); | 53 gfx::CreateIOSurface(size, format)); |
51 if (video) { | 54 if (video) { |
(...skipping 15 matching lines...) Expand all Loading... |
67 properties->sorting_context_id, properties->transform, | 70 properties->sorting_context_id, properties->transform, |
68 properties->gl_image.get(), properties->contents_rect, properties->rect, | 71 properties->gl_image.get(), properties->contents_rect, properties->rect, |
69 properties->background_color, properties->edge_aa_mask, | 72 properties->background_color, properties->edge_aa_mask, |
70 properties->opacity, properties->filter)); | 73 properties->opacity, properties->filter)); |
71 } | 74 } |
72 | 75 |
73 void UpdateCALayerTree(std::unique_ptr<ui::CARendererLayerTree>& ca_layer_tree, | 76 void UpdateCALayerTree(std::unique_ptr<ui::CARendererLayerTree>& ca_layer_tree, |
74 CALayerProperties* properties, | 77 CALayerProperties* properties, |
75 CALayer* superlayer) { | 78 CALayer* superlayer) { |
76 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( | 79 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( |
77 new ui::CARendererLayerTree(true)); | 80 new ui::CARendererLayerTree(properties->allow_av_layers, |
| 81 properties->allow_solid_color_layers)); |
78 bool result = ScheduleCALayer(new_ca_layer_tree.get(), properties); | 82 bool result = ScheduleCALayer(new_ca_layer_tree.get(), properties); |
79 EXPECT_TRUE(result); | 83 EXPECT_TRUE(result); |
80 new_ca_layer_tree->CommitScheduledCALayers( | 84 new_ca_layer_tree->CommitScheduledCALayers( |
81 superlayer, std::move(ca_layer_tree), properties->scale_factor); | |
82 std::swap(new_ca_layer_tree, ca_layer_tree); | |
83 } | |
84 | |
85 void UpdateCALayerTreeWithAVDisabled( | |
86 std::unique_ptr<ui::CARendererLayerTree>& ca_layer_tree, | |
87 CALayerProperties* properties, | |
88 CALayer* superlayer) { | |
89 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( | |
90 new ui::CARendererLayerTree(false)); | |
91 bool result = ScheduleCALayer(new_ca_layer_tree.get(), properties); | |
92 EXPECT_TRUE(result); | |
93 new_ca_layer_tree->CommitScheduledCALayers( | |
94 superlayer, std::move(ca_layer_tree), properties->scale_factor); | 85 superlayer, std::move(ca_layer_tree), properties->scale_factor); |
95 std::swap(new_ca_layer_tree, ca_layer_tree); | 86 std::swap(new_ca_layer_tree, ca_layer_tree); |
96 } | 87 } |
97 | 88 |
98 } // namespace | 89 } // namespace |
99 | 90 |
100 class CALayerTreeTest : public testing::Test { | 91 class CALayerTreeTest : public testing::Test { |
101 protected: | 92 protected: |
102 void SetUp() override { | 93 void SetUp() override { |
103 superlayer_.reset([[CALayer alloc] init]); | 94 superlayer_.reset([[CALayer alloc] init]); |
104 fullscreen_low_power_layer_.reset( | 95 fullscreen_low_power_layer_.reset( |
105 [[AVSampleBufferDisplayLayer alloc] init]); | 96 [[AVSampleBufferDisplayLayer alloc] init]); |
106 } | 97 } |
107 | 98 |
108 base::scoped_nsobject<CALayer> superlayer_; | 99 base::scoped_nsobject<CALayer> superlayer_; |
109 base::scoped_nsobject<AVSampleBufferDisplayLayer> fullscreen_low_power_layer_; | 100 base::scoped_nsobject<AVSampleBufferDisplayLayer> fullscreen_low_power_layer_; |
110 }; | 101 }; |
111 | 102 |
112 // Test updating each layer's properties. | 103 // Test updating each layer's properties. |
113 TEST_F(CALayerTreeTest, PropertyUpdates) { | 104 class CALayerTreePropertyUpdatesTest : public CALayerTreeTest { |
114 CALayerProperties properties; | 105 public: |
115 properties.clip_rect = gfx::Rect(2, 4, 8, 16); | 106 void RunTest(bool allow_solid_color_layers) { |
116 properties.transform.Translate(10, 20); | 107 CALayerProperties properties; |
117 properties.contents_rect = gfx::RectF(0.0f, 0.25f, 0.5f, 0.75f); | 108 properties.allow_solid_color_layers = allow_solid_color_layers; |
118 properties.rect = gfx::Rect(16, 32, 64, 128); | 109 properties.clip_rect = gfx::Rect(2, 4, 8, 16); |
119 properties.background_color = SkColorSetARGB(0xFF, 0xFF, 0, 0); | 110 properties.transform.Translate(10, 20); |
120 properties.edge_aa_mask = GL_CA_LAYER_EDGE_LEFT_CHROMIUM; | 111 properties.contents_rect = gfx::RectF(0.0f, 0.25f, 0.5f, 0.75f); |
121 properties.opacity = 0.5f; | 112 properties.rect = gfx::Rect(16, 32, 64, 128); |
122 properties.gl_image = | 113 properties.background_color = SkColorSetARGB(0xFF, 0xFF, 0, 0); |
123 CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); | 114 properties.edge_aa_mask = GL_CA_LAYER_EDGE_LEFT_CHROMIUM; |
124 | 115 properties.opacity = 0.5f; |
125 std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree; | |
126 CALayer* root_layer = nil; | |
127 CALayer* clip_and_sorting_layer = nil; | |
128 CALayer* transform_layer = nil; | |
129 CALayer* content_layer = nil; | |
130 | |
131 // Validate the initial values. | |
132 { | |
133 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( | |
134 new ui::CARendererLayerTree(true)); | |
135 | |
136 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
137 | |
138 // Validate the tree structure. | |
139 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
140 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | |
141 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
142 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; | |
143 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
144 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; | |
145 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
146 content_layer = [[transform_layer sublayers] objectAtIndex:0]; | |
147 | |
148 // Validate the clip and sorting context layer. | |
149 EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); | |
150 EXPECT_EQ(gfx::Rect(properties.clip_rect.size()), | |
151 gfx::Rect([clip_and_sorting_layer bounds])); | |
152 EXPECT_EQ(properties.clip_rect.origin(), | |
153 gfx::Point([clip_and_sorting_layer position])); | |
154 EXPECT_EQ(-properties.clip_rect.origin().x(), | |
155 [clip_and_sorting_layer sublayerTransform].m41); | |
156 EXPECT_EQ(-properties.clip_rect.origin().y(), | |
157 [clip_and_sorting_layer sublayerTransform].m42); | |
158 | |
159 // Validate the transform layer. | |
160 EXPECT_EQ(properties.transform.matrix().get(3, 0), | |
161 [transform_layer sublayerTransform].m41); | |
162 EXPECT_EQ(properties.transform.matrix().get(3, 1), | |
163 [transform_layer sublayerTransform].m42); | |
164 | |
165 // Validate the content layer. | |
166 EXPECT_EQ(static_cast<id>(properties.gl_image->io_surface().get()), | |
167 [content_layer contents]); | |
168 EXPECT_EQ(properties.contents_rect, | |
169 gfx::RectF([content_layer contentsRect])); | |
170 EXPECT_EQ(properties.rect.origin(), gfx::Point([content_layer position])); | |
171 EXPECT_EQ(gfx::Rect(properties.rect.size()), | |
172 gfx::Rect([content_layer bounds])); | |
173 EXPECT_EQ(kCALayerLeftEdge, [content_layer edgeAntialiasingMask]); | |
174 EXPECT_EQ(properties.opacity, [content_layer opacity]); | |
175 EXPECT_NSEQ(kCAFilterLinear, [content_layer minificationFilter]); | |
176 EXPECT_NSEQ(kCAFilterLinear, [content_layer magnificationFilter]); | |
177 if ([content_layer respondsToSelector:(@selector(contentsScale))]) | |
178 EXPECT_EQ(properties.scale_factor, [content_layer contentsScale]); | |
179 } | |
180 | |
181 // Update just the clip rect and re-commit. | |
182 { | |
183 properties.clip_rect = gfx::Rect(4, 8, 16, 32); | |
184 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
185 | |
186 // Validate the tree structure | |
187 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
188 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
189 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
190 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
191 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
192 EXPECT_EQ(transform_layer, | |
193 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
194 | |
195 // Validate the clip and sorting context layer. | |
196 EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); | |
197 EXPECT_EQ(gfx::Rect(properties.clip_rect.size()), | |
198 gfx::Rect([clip_and_sorting_layer bounds])); | |
199 EXPECT_EQ(properties.clip_rect.origin(), | |
200 gfx::Point([clip_and_sorting_layer position])); | |
201 EXPECT_EQ(-properties.clip_rect.origin().x(), | |
202 [clip_and_sorting_layer sublayerTransform].m41); | |
203 EXPECT_EQ(-properties.clip_rect.origin().y(), | |
204 [clip_and_sorting_layer sublayerTransform].m42); | |
205 } | |
206 | |
207 // Disable clipping and re-commit. | |
208 { | |
209 properties.is_clipped = false; | |
210 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
211 | |
212 // Validate the tree structure | |
213 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
214 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
215 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
216 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
217 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
218 EXPECT_EQ(transform_layer, | |
219 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
220 | |
221 // Validate the clip and sorting context layer. | |
222 EXPECT_FALSE([clip_and_sorting_layer masksToBounds]); | |
223 EXPECT_EQ(gfx::Rect(), gfx::Rect([clip_and_sorting_layer bounds])); | |
224 EXPECT_EQ(gfx::Point(), gfx::Point([clip_and_sorting_layer position])); | |
225 EXPECT_EQ(0.0, [clip_and_sorting_layer sublayerTransform].m41); | |
226 EXPECT_EQ(0.0, [clip_and_sorting_layer sublayerTransform].m42); | |
227 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
228 } | |
229 | |
230 // Change the transform and re-commit. | |
231 { | |
232 properties.transform.Translate(5, 5); | |
233 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
234 | |
235 // Validate the tree structure. | |
236 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
237 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
238 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
239 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
240 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
241 EXPECT_EQ(transform_layer, | |
242 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
243 | |
244 // Validate the transform layer. | |
245 EXPECT_EQ(properties.transform.matrix().get(3, 0), | |
246 [transform_layer sublayerTransform].m41); | |
247 EXPECT_EQ(properties.transform.matrix().get(3, 1), | |
248 [transform_layer sublayerTransform].m42); | |
249 } | |
250 | |
251 // Change the edge antialiasing mask and commit. | |
252 { | |
253 properties.edge_aa_mask = GL_CA_LAYER_EDGE_TOP_CHROMIUM; | |
254 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
255 | |
256 // Validate the tree structure. | |
257 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
258 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
259 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
260 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
261 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
262 EXPECT_EQ(transform_layer, | |
263 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
264 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
265 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
266 | |
267 // Validate the content layer. Note that top and bottom edges flip. | |
268 EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); | |
269 } | |
270 | |
271 // Change the contents and commit. | |
272 { | |
273 properties.gl_image->Destroy(true); | |
274 properties.gl_image = nullptr; | |
275 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
276 | |
277 // Validate the tree structure. | |
278 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
279 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
280 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
281 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
282 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
283 EXPECT_EQ(transform_layer, | |
284 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
285 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
286 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
287 | |
288 // Validate the content layer. Note that edge anti-aliasing no longer flips. | |
289 EXPECT_EQ(nil, [content_layer contents]); | |
290 EXPECT_EQ(kCALayerTopEdge, [content_layer edgeAntialiasingMask]); | |
291 } | |
292 | |
293 // Change the rect size. | |
294 { | |
295 properties.rect = gfx::Rect(properties.rect.origin(), gfx::Size(32, 16)); | |
296 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
297 | |
298 // Validate the tree structure. | |
299 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
300 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
301 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
302 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
303 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
304 EXPECT_EQ(transform_layer, | |
305 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
306 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
307 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
308 | |
309 // Validate the content layer. | |
310 EXPECT_EQ(properties.rect.origin(), gfx::Point([content_layer position])); | |
311 EXPECT_EQ(gfx::Rect(properties.rect.size()), | |
312 gfx::Rect([content_layer bounds])); | |
313 } | |
314 | |
315 // Change the rect position. | |
316 { | |
317 properties.rect = gfx::Rect(gfx::Point(16, 4), properties.rect.size()); | |
318 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
319 | |
320 // Validate the tree structure. | |
321 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
322 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
323 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
324 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
325 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
326 EXPECT_EQ(transform_layer, | |
327 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
328 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
329 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
330 | |
331 // Validate the content layer. | |
332 EXPECT_EQ(properties.rect.origin(), gfx::Point([content_layer position])); | |
333 EXPECT_EQ(gfx::Rect(properties.rect.size()), | |
334 gfx::Rect([content_layer bounds])); | |
335 } | |
336 | |
337 // Change the opacity. | |
338 { | |
339 properties.opacity = 1.0f; | |
340 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
341 | |
342 // Validate the tree structure. | |
343 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
344 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
345 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
346 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
347 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
348 EXPECT_EQ(transform_layer, | |
349 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
350 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
351 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
352 | |
353 // Validate the content layer. | |
354 EXPECT_EQ(properties.opacity, [content_layer opacity]); | |
355 } | |
356 | |
357 // Change the filter. | |
358 { | |
359 properties.filter = GL_NEAREST; | |
360 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
361 | |
362 // Validate the tree structure. | |
363 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
364 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
365 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
366 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
367 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
368 EXPECT_EQ(transform_layer, | |
369 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
370 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
371 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
372 | |
373 // Validate the content layer. | |
374 EXPECT_NSEQ(kCAFilterNearest, [content_layer minificationFilter]); | |
375 EXPECT_NSEQ(kCAFilterNearest, [content_layer magnificationFilter]); | |
376 } | |
377 | |
378 // Add the clipping and IOSurface contents back. | |
379 { | |
380 properties.is_clipped = true; | |
381 properties.gl_image = | 116 properties.gl_image = |
382 CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); | 117 CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); |
383 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | 118 |
384 | 119 std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree; |
385 // Validate the tree structure. | 120 CALayer* root_layer = nil; |
386 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | 121 CALayer* clip_and_sorting_layer = nil; |
387 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | 122 CALayer* transform_layer = nil; |
388 EXPECT_EQ(1u, [[root_layer sublayers] count]); | 123 CALayer* content_layer = nil; |
389 EXPECT_EQ(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | 124 |
390 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | 125 // Validate the initial values. |
391 EXPECT_EQ(transform_layer, | 126 { |
392 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | 127 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( |
393 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | 128 new ui::CARendererLayerTree(true, allow_solid_color_layers)); |
394 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | 129 |
395 | 130 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
396 // Validate the content layer. | 131 |
397 EXPECT_EQ(static_cast<id>(properties.gl_image->io_surface().get()), | 132 // Validate the tree structure. |
398 [content_layer contents]); | 133 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
399 EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); | 134 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; |
| 135 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 136 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; |
| 137 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 138 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; |
| 139 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
| 140 content_layer = [[transform_layer sublayers] objectAtIndex:0]; |
| 141 |
| 142 // Validate the clip and sorting context layer. |
| 143 EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); |
| 144 EXPECT_EQ(gfx::Rect(properties.clip_rect.size()), |
| 145 gfx::Rect([clip_and_sorting_layer bounds])); |
| 146 EXPECT_EQ(properties.clip_rect.origin(), |
| 147 gfx::Point([clip_and_sorting_layer position])); |
| 148 EXPECT_EQ(-properties.clip_rect.origin().x(), |
| 149 [clip_and_sorting_layer sublayerTransform].m41); |
| 150 EXPECT_EQ(-properties.clip_rect.origin().y(), |
| 151 [clip_and_sorting_layer sublayerTransform].m42); |
| 152 |
| 153 // Validate the transform layer. |
| 154 EXPECT_EQ(properties.transform.matrix().get(3, 0), |
| 155 [transform_layer sublayerTransform].m41); |
| 156 EXPECT_EQ(properties.transform.matrix().get(3, 1), |
| 157 [transform_layer sublayerTransform].m42); |
| 158 |
| 159 // Validate the content layer. |
| 160 EXPECT_EQ(static_cast<id>(properties.gl_image->io_surface().get()), |
| 161 [content_layer contents]); |
| 162 EXPECT_EQ(properties.contents_rect, |
| 163 gfx::RectF([content_layer contentsRect])); |
| 164 EXPECT_EQ(properties.rect.origin(), gfx::Point([content_layer position])); |
| 165 EXPECT_EQ(gfx::Rect(properties.rect.size()), |
| 166 gfx::Rect([content_layer bounds])); |
| 167 EXPECT_EQ(kCALayerLeftEdge, [content_layer edgeAntialiasingMask]); |
| 168 EXPECT_EQ(properties.opacity, [content_layer opacity]); |
| 169 EXPECT_NSEQ(kCAFilterLinear, [content_layer minificationFilter]); |
| 170 EXPECT_NSEQ(kCAFilterLinear, [content_layer magnificationFilter]); |
| 171 if ([content_layer respondsToSelector:(@selector(contentsScale))]) |
| 172 EXPECT_EQ(properties.scale_factor, [content_layer contentsScale]); |
| 173 } |
| 174 |
| 175 // Update just the clip rect and re-commit. |
| 176 { |
| 177 properties.clip_rect = gfx::Rect(4, 8, 16, 32); |
| 178 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 179 |
| 180 // Validate the tree structure |
| 181 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
| 182 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); |
| 183 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 184 EXPECT_EQ(clip_and_sorting_layer, |
| 185 [[root_layer sublayers] objectAtIndex:0]); |
| 186 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 187 EXPECT_EQ(transform_layer, |
| 188 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 189 |
| 190 // Validate the clip and sorting context layer. |
| 191 EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); |
| 192 EXPECT_EQ(gfx::Rect(properties.clip_rect.size()), |
| 193 gfx::Rect([clip_and_sorting_layer bounds])); |
| 194 EXPECT_EQ(properties.clip_rect.origin(), |
| 195 gfx::Point([clip_and_sorting_layer position])); |
| 196 EXPECT_EQ(-properties.clip_rect.origin().x(), |
| 197 [clip_and_sorting_layer sublayerTransform].m41); |
| 198 EXPECT_EQ(-properties.clip_rect.origin().y(), |
| 199 [clip_and_sorting_layer sublayerTransform].m42); |
| 200 } |
| 201 |
| 202 // Disable clipping and re-commit. |
| 203 { |
| 204 properties.is_clipped = false; |
| 205 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 206 |
| 207 // Validate the tree structure |
| 208 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
| 209 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); |
| 210 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 211 EXPECT_EQ(clip_and_sorting_layer, |
| 212 [[root_layer sublayers] objectAtIndex:0]); |
| 213 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 214 EXPECT_EQ(transform_layer, |
| 215 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 216 |
| 217 // Validate the clip and sorting context layer. |
| 218 EXPECT_FALSE([clip_and_sorting_layer masksToBounds]); |
| 219 EXPECT_EQ(gfx::Rect(), gfx::Rect([clip_and_sorting_layer bounds])); |
| 220 EXPECT_EQ(gfx::Point(), gfx::Point([clip_and_sorting_layer position])); |
| 221 EXPECT_EQ(0.0, [clip_and_sorting_layer sublayerTransform].m41); |
| 222 EXPECT_EQ(0.0, [clip_and_sorting_layer sublayerTransform].m42); |
| 223 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 224 } |
| 225 |
| 226 // Change the transform and re-commit. |
| 227 { |
| 228 properties.transform.Translate(5, 5); |
| 229 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 230 |
| 231 // Validate the tree structure. |
| 232 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
| 233 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); |
| 234 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 235 EXPECT_EQ(clip_and_sorting_layer, |
| 236 [[root_layer sublayers] objectAtIndex:0]); |
| 237 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 238 EXPECT_EQ(transform_layer, |
| 239 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 240 |
| 241 // Validate the transform layer. |
| 242 EXPECT_EQ(properties.transform.matrix().get(3, 0), |
| 243 [transform_layer sublayerTransform].m41); |
| 244 EXPECT_EQ(properties.transform.matrix().get(3, 1), |
| 245 [transform_layer sublayerTransform].m42); |
| 246 } |
| 247 |
| 248 // Change the edge antialiasing mask and commit. |
| 249 { |
| 250 properties.edge_aa_mask = GL_CA_LAYER_EDGE_TOP_CHROMIUM; |
| 251 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 252 |
| 253 // Validate the tree structure. |
| 254 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
| 255 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); |
| 256 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 257 EXPECT_EQ(clip_and_sorting_layer, |
| 258 [[root_layer sublayers] objectAtIndex:0]); |
| 259 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 260 EXPECT_EQ(transform_layer, |
| 261 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 262 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
| 263 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); |
| 264 |
| 265 // Validate the content layer. Note that top and bottom edges flip. |
| 266 EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); |
| 267 } |
| 268 |
| 269 // Change the contents and commit. |
| 270 { |
| 271 properties.gl_image->Destroy(true); |
| 272 properties.gl_image = nullptr; |
| 273 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 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, |
| 280 [[root_layer sublayers] objectAtIndex:0]); |
| 281 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 282 EXPECT_EQ(transform_layer, |
| 283 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 284 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
| 285 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); |
| 286 |
| 287 // Validate the content layer. Note that edge anti-aliasing does not flip |
| 288 // for solid colors. |
| 289 if (allow_solid_color_layers) { |
| 290 EXPECT_EQ(nil, [content_layer contents]); |
| 291 EXPECT_EQ(kCALayerTopEdge, [content_layer edgeAntialiasingMask]); |
| 292 } else { |
| 293 EXPECT_EQ(ca_layer_tree->ContentsForSolidColorForTesting( |
| 294 properties.background_color), |
| 295 [content_layer contents]); |
| 296 EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); |
| 297 } |
| 298 } |
| 299 |
| 300 // Change the rect size. |
| 301 { |
| 302 properties.rect = gfx::Rect(properties.rect.origin(), gfx::Size(32, 16)); |
| 303 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 304 |
| 305 // Validate the tree structure. |
| 306 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
| 307 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); |
| 308 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 309 EXPECT_EQ(clip_and_sorting_layer, |
| 310 [[root_layer sublayers] objectAtIndex:0]); |
| 311 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 312 EXPECT_EQ(transform_layer, |
| 313 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 314 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
| 315 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); |
| 316 |
| 317 // Validate the content layer. |
| 318 EXPECT_EQ(properties.rect.origin(), gfx::Point([content_layer position])); |
| 319 EXPECT_EQ(gfx::Rect(properties.rect.size()), |
| 320 gfx::Rect([content_layer bounds])); |
| 321 } |
| 322 |
| 323 // Change the rect position. |
| 324 { |
| 325 properties.rect = gfx::Rect(gfx::Point(16, 4), properties.rect.size()); |
| 326 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 327 |
| 328 // Validate the tree structure. |
| 329 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
| 330 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); |
| 331 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 332 EXPECT_EQ(clip_and_sorting_layer, |
| 333 [[root_layer sublayers] objectAtIndex:0]); |
| 334 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 335 EXPECT_EQ(transform_layer, |
| 336 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 337 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
| 338 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); |
| 339 |
| 340 // Validate the content layer. |
| 341 EXPECT_EQ(properties.rect.origin(), gfx::Point([content_layer position])); |
| 342 EXPECT_EQ(gfx::Rect(properties.rect.size()), |
| 343 gfx::Rect([content_layer bounds])); |
| 344 } |
| 345 |
| 346 // Change the opacity. |
| 347 { |
| 348 properties.opacity = 1.0f; |
| 349 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 350 |
| 351 // Validate the tree structure. |
| 352 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
| 353 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); |
| 354 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 355 EXPECT_EQ(clip_and_sorting_layer, |
| 356 [[root_layer sublayers] objectAtIndex:0]); |
| 357 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 358 EXPECT_EQ(transform_layer, |
| 359 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 360 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
| 361 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); |
| 362 |
| 363 // Validate the content layer. |
| 364 EXPECT_EQ(properties.opacity, [content_layer opacity]); |
| 365 } |
| 366 |
| 367 // Change the filter. |
| 368 { |
| 369 properties.filter = GL_NEAREST; |
| 370 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 371 |
| 372 // Validate the tree structure. |
| 373 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
| 374 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); |
| 375 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 376 EXPECT_EQ(clip_and_sorting_layer, |
| 377 [[root_layer sublayers] objectAtIndex:0]); |
| 378 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 379 EXPECT_EQ(transform_layer, |
| 380 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 381 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
| 382 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); |
| 383 |
| 384 // Validate the content layer. |
| 385 EXPECT_NSEQ(kCAFilterNearest, [content_layer minificationFilter]); |
| 386 EXPECT_NSEQ(kCAFilterNearest, [content_layer magnificationFilter]); |
| 387 } |
| 388 |
| 389 // Add the clipping and IOSurface contents back. |
| 390 { |
| 391 properties.is_clipped = true; |
| 392 properties.gl_image = CreateGLImage(gfx::Size(256, 256), |
| 393 gfx::BufferFormat::BGRA_8888, false); |
| 394 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 395 |
| 396 // Validate the tree structure. |
| 397 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
| 398 EXPECT_EQ(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); |
| 399 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 400 EXPECT_EQ(clip_and_sorting_layer, |
| 401 [[root_layer sublayers] objectAtIndex:0]); |
| 402 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 403 EXPECT_EQ(transform_layer, |
| 404 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 405 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
| 406 EXPECT_EQ(content_layer, [[transform_layer sublayers] objectAtIndex:0]); |
| 407 |
| 408 // Validate the content layer. |
| 409 EXPECT_EQ(static_cast<id>(properties.gl_image->io_surface().get()), |
| 410 [content_layer contents]); |
| 411 EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); |
| 412 } |
| 413 |
| 414 // Change the scale factor. This should result in a new tree being created. |
| 415 { |
| 416 properties.scale_factor = 2.0f; |
| 417 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
| 418 |
| 419 // Validate the tree structure. |
| 420 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
| 421 EXPECT_NE(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); |
| 422 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; |
| 423 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
| 424 EXPECT_NE(clip_and_sorting_layer, |
| 425 [[root_layer sublayers] objectAtIndex:0]); |
| 426 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; |
| 427 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
| 428 EXPECT_NE(transform_layer, |
| 429 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); |
| 430 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; |
| 431 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
| 432 EXPECT_NE(content_layer, [[transform_layer sublayers] objectAtIndex:0]); |
| 433 content_layer = [[transform_layer sublayers] objectAtIndex:0]; |
| 434 |
| 435 // Validate the clip and sorting context layer. |
| 436 EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); |
| 437 EXPECT_EQ(gfx::ConvertRectToDIP(properties.scale_factor, |
| 438 gfx::Rect(properties.clip_rect.size())), |
| 439 gfx::Rect([clip_and_sorting_layer bounds])); |
| 440 EXPECT_EQ(gfx::ConvertPointToDIP(properties.scale_factor, |
| 441 properties.clip_rect.origin()), |
| 442 gfx::Point([clip_and_sorting_layer position])); |
| 443 EXPECT_EQ(-properties.clip_rect.origin().x() / properties.scale_factor, |
| 444 [clip_and_sorting_layer sublayerTransform].m41); |
| 445 EXPECT_EQ(-properties.clip_rect.origin().y() / properties.scale_factor, |
| 446 [clip_and_sorting_layer sublayerTransform].m42); |
| 447 |
| 448 // Validate the transform layer. |
| 449 EXPECT_EQ( |
| 450 properties.transform.matrix().get(3, 0) / properties.scale_factor, |
| 451 [transform_layer sublayerTransform].m41); |
| 452 EXPECT_EQ( |
| 453 properties.transform.matrix().get(3, 1) / properties.scale_factor, |
| 454 [transform_layer sublayerTransform].m42); |
| 455 |
| 456 // Validate the content layer. |
| 457 EXPECT_EQ(static_cast<id>(properties.gl_image->io_surface().get()), |
| 458 [content_layer contents]); |
| 459 EXPECT_EQ(properties.contents_rect, |
| 460 gfx::RectF([content_layer contentsRect])); |
| 461 EXPECT_EQ(gfx::ConvertPointToDIP(properties.scale_factor, |
| 462 properties.rect.origin()), |
| 463 gfx::Point([content_layer position])); |
| 464 EXPECT_EQ(gfx::ConvertRectToDIP(properties.scale_factor, |
| 465 gfx::Rect(properties.rect.size())), |
| 466 gfx::Rect([content_layer bounds])); |
| 467 EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); |
| 468 EXPECT_EQ(properties.opacity, [content_layer opacity]); |
| 469 if ([content_layer respondsToSelector:(@selector(contentsScale))]) |
| 470 EXPECT_EQ(properties.scale_factor, [content_layer contentsScale]); |
| 471 } |
| 472 |
| 473 properties.gl_image->Destroy(true); |
400 } | 474 } |
401 | 475 }; |
402 // Change the scale factor. This should result in a new tree being created. | 476 |
403 { | 477 TEST_F(CALayerTreePropertyUpdatesTest, AllowSolidColors) { |
404 properties.scale_factor = 2.0f; | 478 RunTest(true); |
405 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); | |
406 | |
407 // Validate the tree structure. | |
408 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | |
409 EXPECT_NE(root_layer, [[superlayer_ sublayers] objectAtIndex:0]); | |
410 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | |
411 EXPECT_EQ(1u, [[root_layer sublayers] count]); | |
412 EXPECT_NE(clip_and_sorting_layer, [[root_layer sublayers] objectAtIndex:0]); | |
413 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; | |
414 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | |
415 EXPECT_NE(transform_layer, | |
416 [[clip_and_sorting_layer sublayers] objectAtIndex:0]); | |
417 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; | |
418 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | |
419 EXPECT_NE(content_layer, [[transform_layer sublayers] objectAtIndex:0]); | |
420 content_layer = [[transform_layer sublayers] objectAtIndex:0]; | |
421 | |
422 // Validate the clip and sorting context layer. | |
423 EXPECT_TRUE([clip_and_sorting_layer masksToBounds]); | |
424 EXPECT_EQ(gfx::ConvertRectToDIP(properties.scale_factor, | |
425 gfx::Rect(properties.clip_rect.size())), | |
426 gfx::Rect([clip_and_sorting_layer bounds])); | |
427 EXPECT_EQ(gfx::ConvertPointToDIP(properties.scale_factor, | |
428 properties.clip_rect.origin()), | |
429 gfx::Point([clip_and_sorting_layer position])); | |
430 EXPECT_EQ(-properties.clip_rect.origin().x() / properties.scale_factor, | |
431 [clip_and_sorting_layer sublayerTransform].m41); | |
432 EXPECT_EQ(-properties.clip_rect.origin().y() / properties.scale_factor, | |
433 [clip_and_sorting_layer sublayerTransform].m42); | |
434 | |
435 // Validate the transform layer. | |
436 EXPECT_EQ(properties.transform.matrix().get(3, 0) / properties.scale_factor, | |
437 [transform_layer sublayerTransform].m41); | |
438 EXPECT_EQ(properties.transform.matrix().get(3, 1) / properties.scale_factor, | |
439 [transform_layer sublayerTransform].m42); | |
440 | |
441 // Validate the content layer. | |
442 EXPECT_EQ(static_cast<id>(properties.gl_image->io_surface().get()), | |
443 [content_layer contents]); | |
444 EXPECT_EQ(properties.contents_rect, | |
445 gfx::RectF([content_layer contentsRect])); | |
446 EXPECT_EQ(gfx::ConvertPointToDIP(properties.scale_factor, | |
447 properties.rect.origin()), | |
448 gfx::Point([content_layer position])); | |
449 EXPECT_EQ(gfx::ConvertRectToDIP(properties.scale_factor, | |
450 gfx::Rect(properties.rect.size())), | |
451 gfx::Rect([content_layer bounds])); | |
452 EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); | |
453 EXPECT_EQ(properties.opacity, [content_layer opacity]); | |
454 if ([content_layer respondsToSelector:(@selector(contentsScale))]) | |
455 EXPECT_EQ(properties.scale_factor, [content_layer contentsScale]); | |
456 } | |
457 | |
458 properties.gl_image->Destroy(true); | |
459 } | 479 } |
460 | 480 |
| 481 TEST_F(CALayerTreePropertyUpdatesTest, DisallowSolidColors) { |
| 482 RunTest(false); |
| 483 } |
| 484 |
461 // Verify that sorting context zero is split at non-flat transforms. | 485 // Verify that sorting context zero is split at non-flat transforms. |
462 TEST_F(CALayerTreeTest, SplitSortingContextZero) { | 486 TEST_F(CALayerTreeTest, SplitSortingContextZero) { |
463 CALayerProperties properties; | 487 CALayerProperties properties; |
464 properties.is_clipped = false; | 488 properties.is_clipped = false; |
465 properties.clip_rect = gfx::Rect(); | 489 properties.clip_rect = gfx::Rect(); |
466 properties.rect = gfx::Rect(0, 0, 256, 256); | 490 properties.rect = gfx::Rect(0, 0, 256, 256); |
467 | 491 |
468 // We'll use the IOSurface contents to identify the content layers. | 492 // We'll use the IOSurface contents to identify the content layers. |
469 scoped_refptr<gl::GLImageIOSurface> gl_images[5]; | 493 scoped_refptr<gl::GLImageIOSurface> gl_images[5]; |
470 for (size_t i = 0; i < 5; ++i) { | 494 for (size_t i = 0; i < 5; ++i) { |
471 gl_images[i] = | 495 gl_images[i] = |
472 CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); | 496 CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); |
473 } | 497 } |
474 | 498 |
475 // Have 5 transforms: | 499 // Have 5 transforms: |
476 // * 2 flat but different (1 sorting context layer, 2 transform layers) | 500 // * 2 flat but different (1 sorting context layer, 2 transform layers) |
477 // * 1 non-flat (new sorting context layer) | 501 // * 1 non-flat (new sorting context layer) |
478 // * 2 flat and the same (new sorting context layer, 1 transform layer) | 502 // * 2 flat and the same (new sorting context layer, 1 transform layer) |
479 gfx::Transform transforms[5]; | 503 gfx::Transform transforms[5]; |
480 transforms[0].Translate(10, 10); | 504 transforms[0].Translate(10, 10); |
481 transforms[1].RotateAboutZAxis(45.0f); | 505 transforms[1].RotateAboutZAxis(45.0f); |
482 transforms[2].RotateAboutYAxis(45.0f); | 506 transforms[2].RotateAboutYAxis(45.0f); |
483 transforms[3].Translate(10, 10); | 507 transforms[3].Translate(10, 10); |
484 transforms[4].Translate(10, 10); | 508 transforms[4].Translate(10, 10); |
485 | 509 |
486 // Schedule and commit the layers. | 510 // Schedule and commit the layers. |
487 std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree( | 511 std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree( |
488 new ui::CARendererLayerTree(true)); | 512 new ui::CARendererLayerTree(true, true)); |
489 for (size_t i = 0; i < 5; ++i) { | 513 for (size_t i = 0; i < 5; ++i) { |
490 properties.gl_image = gl_images[i]; | 514 properties.gl_image = gl_images[i]; |
491 properties.transform = transforms[i]; | 515 properties.transform = transforms[i]; |
492 bool result = ScheduleCALayer(ca_layer_tree.get(), &properties); | 516 bool result = ScheduleCALayer(ca_layer_tree.get(), &properties); |
493 EXPECT_TRUE(result); | 517 EXPECT_TRUE(result); |
494 } | 518 } |
495 ca_layer_tree->CommitScheduledCALayers(superlayer_, nullptr, | 519 ca_layer_tree->CommitScheduledCALayers(superlayer_, nullptr, |
496 properties.scale_factor); | 520 properties.scale_factor); |
497 | 521 |
498 // Validate the root layer. | 522 // Validate the root layer. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 scoped_refptr<gl::GLImageIOSurface> gl_images[3]; | 585 scoped_refptr<gl::GLImageIOSurface> gl_images[3]; |
562 for (size_t i = 0; i < 3; ++i) { | 586 for (size_t i = 0; i < 3; ++i) { |
563 gl_images[i] = | 587 gl_images[i] = |
564 CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); | 588 CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); |
565 } | 589 } |
566 | 590 |
567 int sorting_context_ids[3] = {3, -1, 0}; | 591 int sorting_context_ids[3] = {3, -1, 0}; |
568 | 592 |
569 // Schedule and commit the layers. | 593 // Schedule and commit the layers. |
570 std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree( | 594 std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree( |
571 new ui::CARendererLayerTree(true)); | 595 new ui::CARendererLayerTree(true, true)); |
572 for (size_t i = 0; i < 3; ++i) { | 596 for (size_t i = 0; i < 3; ++i) { |
573 properties.sorting_context_id = sorting_context_ids[i]; | 597 properties.sorting_context_id = sorting_context_ids[i]; |
574 properties.gl_image = gl_images[i]; | 598 properties.gl_image = gl_images[i]; |
575 bool result = ScheduleCALayer(ca_layer_tree.get(), &properties); | 599 bool result = ScheduleCALayer(ca_layer_tree.get(), &properties); |
576 EXPECT_TRUE(result); | 600 EXPECT_TRUE(result); |
577 } | 601 } |
578 ca_layer_tree->CommitScheduledCALayers(superlayer_, nullptr, | 602 ca_layer_tree->CommitScheduledCALayers(superlayer_, nullptr, |
579 properties.scale_factor); | 603 properties.scale_factor); |
580 | 604 |
581 // Validate the root layer. | 605 // Validate the root layer. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 | 649 |
626 // Vary the clipping parameters within sorting contexts. | 650 // Vary the clipping parameters within sorting contexts. |
627 bool is_clippeds[3] = { true, true, false}; | 651 bool is_clippeds[3] = { true, true, false}; |
628 gfx::Rect clip_rects[3] = { | 652 gfx::Rect clip_rects[3] = { |
629 gfx::Rect(0, 0, 16, 16), | 653 gfx::Rect(0, 0, 16, 16), |
630 gfx::Rect(4, 8, 16, 32), | 654 gfx::Rect(4, 8, 16, 32), |
631 gfx::Rect(0, 0, 16, 16) | 655 gfx::Rect(0, 0, 16, 16) |
632 }; | 656 }; |
633 | 657 |
634 std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree( | 658 std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree( |
635 new ui::CARendererLayerTree(true)); | 659 new ui::CARendererLayerTree(true, true)); |
636 // First send the various clip parameters to sorting context zero. This is | 660 // First send the various clip parameters to sorting context zero. This is |
637 // legitimate. | 661 // legitimate. |
638 for (size_t i = 0; i < 3; ++i) { | 662 for (size_t i = 0; i < 3; ++i) { |
639 properties.is_clipped = is_clippeds[i]; | 663 properties.is_clipped = is_clippeds[i]; |
640 properties.clip_rect = clip_rects[i]; | 664 properties.clip_rect = clip_rects[i]; |
641 | 665 |
642 bool result = ScheduleCALayer(ca_layer_tree.get(), &properties); | 666 bool result = ScheduleCALayer(ca_layer_tree.get(), &properties); |
643 EXPECT_TRUE(result); | 667 EXPECT_TRUE(result); |
644 } | 668 } |
645 | 669 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; | 824 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; |
801 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | 825 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
802 content_layer1 = [[transform_layer sublayers] objectAtIndex:0]; | 826 content_layer1 = [[transform_layer sublayers] objectAtIndex:0]; |
803 | 827 |
804 // Validate the content layer. | 828 // Validate the content layer. |
805 EXPECT_TRUE([content_layer1 | 829 EXPECT_TRUE([content_layer1 |
806 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); | 830 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); |
807 } | 831 } |
808 | 832 |
809 { | 833 { |
810 UpdateCALayerTreeWithAVDisabled(ca_layer_tree, &properties, superlayer_); | 834 properties.allow_av_layers = false; |
| 835 UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); |
811 | 836 |
812 // Validate the tree structure. | 837 // Validate the tree structure. |
813 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | 838 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
814 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | 839 root_layer = [[superlayer_ sublayers] objectAtIndex:0]; |
815 EXPECT_EQ(1u, [[root_layer sublayers] count]); | 840 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
816 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; | 841 clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; |
817 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | 842 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
818 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; | 843 transform_layer = [[clip_and_sorting_layer sublayers] objectAtIndex:0]; |
819 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | 844 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
820 content_layer2 = [[transform_layer sublayers] objectAtIndex:0]; | 845 content_layer2 = [[transform_layer sublayers] objectAtIndex:0]; |
(...skipping 17 matching lines...) Expand all Loading... |
838 properties_black.background_color = SK_ColorBLACK; | 863 properties_black.background_color = SK_ColorBLACK; |
839 CALayerProperties properties_white; | 864 CALayerProperties properties_white; |
840 properties_white.is_clipped = false; | 865 properties_white.is_clipped = false; |
841 properties_white.background_color = SK_ColorWHITE; | 866 properties_white.background_color = SK_ColorWHITE; |
842 | 867 |
843 std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree; | 868 std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree; |
844 | 869 |
845 // Test a configuration with no background. | 870 // Test a configuration with no background. |
846 { | 871 { |
847 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( | 872 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( |
848 new ui::CARendererLayerTree(true)); | 873 new ui::CARendererLayerTree(true, true)); |
849 bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties); | 874 bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties); |
850 EXPECT_TRUE(result); | 875 EXPECT_TRUE(result); |
851 new_ca_layer_tree->CommitScheduledCALayers( | 876 new_ca_layer_tree->CommitScheduledCALayers( |
852 superlayer_, std::move(ca_layer_tree), properties.scale_factor); | 877 superlayer_, std::move(ca_layer_tree), properties.scale_factor); |
853 bool fullscreen_low_power_valid = | 878 bool fullscreen_low_power_valid = |
854 new_ca_layer_tree->CommitFullscreenLowPowerLayer( | 879 new_ca_layer_tree->CommitFullscreenLowPowerLayer( |
855 fullscreen_low_power_layer_); | 880 fullscreen_low_power_layer_); |
856 std::swap(new_ca_layer_tree, ca_layer_tree); | 881 std::swap(new_ca_layer_tree, ca_layer_tree); |
857 | 882 |
858 // Validate the tree structure. | 883 // Validate the tree structure. |
859 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); | 884 EXPECT_EQ(1u, [[superlayer_ sublayers] count]); |
860 CALayer* root_layer = [[superlayer_ sublayers] objectAtIndex:0]; | 885 CALayer* root_layer = [[superlayer_ sublayers] objectAtIndex:0]; |
861 EXPECT_EQ(1u, [[root_layer sublayers] count]); | 886 EXPECT_EQ(1u, [[root_layer sublayers] count]); |
862 CALayer* clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; | 887 CALayer* clip_and_sorting_layer = [[root_layer sublayers] objectAtIndex:0]; |
863 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); | 888 EXPECT_EQ(1u, [[clip_and_sorting_layer sublayers] count]); |
864 CALayer* transform_layer = | 889 CALayer* transform_layer = |
865 [[clip_and_sorting_layer sublayers] objectAtIndex:0]; | 890 [[clip_and_sorting_layer sublayers] objectAtIndex:0]; |
866 EXPECT_EQ(1u, [[transform_layer sublayers] count]); | 891 EXPECT_EQ(1u, [[transform_layer sublayers] count]); |
867 CALayer* content_layer = [[transform_layer sublayers] objectAtIndex:0]; | 892 CALayer* content_layer = [[transform_layer sublayers] objectAtIndex:0]; |
868 | 893 |
869 // Validate the content layer and fullscreen low power mode. | 894 // Validate the content layer and fullscreen low power mode. |
870 EXPECT_TRUE([content_layer | 895 EXPECT_TRUE([content_layer |
871 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); | 896 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); |
872 EXPECT_TRUE(fullscreen_low_power_valid); | 897 EXPECT_TRUE(fullscreen_low_power_valid); |
873 } | 898 } |
874 | 899 |
875 // Test a configuration with a black background. | 900 // Test a configuration with a black background. |
876 { | 901 { |
877 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( | 902 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( |
878 new ui::CARendererLayerTree(true)); | 903 new ui::CARendererLayerTree(true, true)); |
879 bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties_black); | 904 bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties_black); |
880 EXPECT_TRUE(result); | 905 EXPECT_TRUE(result); |
881 result = ScheduleCALayer(new_ca_layer_tree.get(), &properties); | 906 result = ScheduleCALayer(new_ca_layer_tree.get(), &properties); |
882 EXPECT_TRUE(result); | 907 EXPECT_TRUE(result); |
883 new_ca_layer_tree->CommitScheduledCALayers( | 908 new_ca_layer_tree->CommitScheduledCALayers( |
884 superlayer_, std::move(ca_layer_tree), properties.scale_factor); | 909 superlayer_, std::move(ca_layer_tree), properties.scale_factor); |
885 bool fullscreen_low_power_valid = | 910 bool fullscreen_low_power_valid = |
886 new_ca_layer_tree->CommitFullscreenLowPowerLayer( | 911 new_ca_layer_tree->CommitFullscreenLowPowerLayer( |
887 fullscreen_low_power_layer_); | 912 fullscreen_low_power_layer_); |
888 std::swap(new_ca_layer_tree, ca_layer_tree); | 913 std::swap(new_ca_layer_tree, ca_layer_tree); |
(...skipping 11 matching lines...) Expand all Loading... |
900 | 925 |
901 // Validate the content layer and fullscreen low power mode. | 926 // Validate the content layer and fullscreen low power mode. |
902 EXPECT_TRUE([content_layer | 927 EXPECT_TRUE([content_layer |
903 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); | 928 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); |
904 EXPECT_TRUE(fullscreen_low_power_valid); | 929 EXPECT_TRUE(fullscreen_low_power_valid); |
905 } | 930 } |
906 | 931 |
907 // Test a configuration with a white background. It will fail. | 932 // Test a configuration with a white background. It will fail. |
908 { | 933 { |
909 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( | 934 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( |
910 new ui::CARendererLayerTree(true)); | 935 new ui::CARendererLayerTree(true, true)); |
911 bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties_white); | 936 bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties_white); |
912 EXPECT_TRUE(result); | 937 EXPECT_TRUE(result); |
913 result = ScheduleCALayer(new_ca_layer_tree.get(), &properties); | 938 result = ScheduleCALayer(new_ca_layer_tree.get(), &properties); |
914 EXPECT_TRUE(result); | 939 EXPECT_TRUE(result); |
915 new_ca_layer_tree->CommitScheduledCALayers( | 940 new_ca_layer_tree->CommitScheduledCALayers( |
916 superlayer_, std::move(ca_layer_tree), properties.scale_factor); | 941 superlayer_, std::move(ca_layer_tree), properties.scale_factor); |
917 bool fullscreen_low_power_valid = | 942 bool fullscreen_low_power_valid = |
918 new_ca_layer_tree->CommitFullscreenLowPowerLayer( | 943 new_ca_layer_tree->CommitFullscreenLowPowerLayer( |
919 fullscreen_low_power_layer_); | 944 fullscreen_low_power_layer_); |
920 std::swap(new_ca_layer_tree, ca_layer_tree); | 945 std::swap(new_ca_layer_tree, ca_layer_tree); |
(...skipping 11 matching lines...) Expand all Loading... |
932 | 957 |
933 // Validate the content layer and fullscreen low power mode. | 958 // Validate the content layer and fullscreen low power mode. |
934 EXPECT_TRUE([content_layer | 959 EXPECT_TRUE([content_layer |
935 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); | 960 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); |
936 EXPECT_FALSE(fullscreen_low_power_valid); | 961 EXPECT_FALSE(fullscreen_low_power_valid); |
937 } | 962 } |
938 | 963 |
939 // Test a configuration with a black foreground. It too will fail. | 964 // Test a configuration with a black foreground. It too will fail. |
940 { | 965 { |
941 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( | 966 std::unique_ptr<ui::CARendererLayerTree> new_ca_layer_tree( |
942 new ui::CARendererLayerTree(true)); | 967 new ui::CARendererLayerTree(true, true)); |
943 bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties); | 968 bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties); |
944 EXPECT_TRUE(result); | 969 EXPECT_TRUE(result); |
945 result = ScheduleCALayer(new_ca_layer_tree.get(), &properties_black); | 970 result = ScheduleCALayer(new_ca_layer_tree.get(), &properties_black); |
946 EXPECT_TRUE(result); | 971 EXPECT_TRUE(result); |
947 new_ca_layer_tree->CommitScheduledCALayers( | 972 new_ca_layer_tree->CommitScheduledCALayers( |
948 superlayer_, std::move(ca_layer_tree), properties.scale_factor); | 973 superlayer_, std::move(ca_layer_tree), properties.scale_factor); |
949 bool fullscreen_low_power_valid = | 974 bool fullscreen_low_power_valid = |
950 new_ca_layer_tree->CommitFullscreenLowPowerLayer( | 975 new_ca_layer_tree->CommitFullscreenLowPowerLayer( |
951 fullscreen_low_power_layer_); | 976 fullscreen_low_power_layer_); |
952 std::swap(new_ca_layer_tree, ca_layer_tree); | 977 std::swap(new_ca_layer_tree, ca_layer_tree); |
(...skipping 10 matching lines...) Expand all Loading... |
963 CALayer* content_layer = [[transform_layer sublayers] objectAtIndex:0]; | 988 CALayer* content_layer = [[transform_layer sublayers] objectAtIndex:0]; |
964 | 989 |
965 // Validate the content layer and fullscreen low power mode. | 990 // Validate the content layer and fullscreen low power mode. |
966 EXPECT_TRUE([content_layer | 991 EXPECT_TRUE([content_layer |
967 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); | 992 isKindOfClass:NSClassFromString(@"AVSampleBufferDisplayLayer")]); |
968 EXPECT_FALSE(fullscreen_low_power_valid); | 993 EXPECT_FALSE(fullscreen_low_power_valid); |
969 } | 994 } |
970 } | 995 } |
971 | 996 |
972 } // namespace gpu | 997 } // namespace gpu |
OLD | NEW |