OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2012 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 "cc/layer_tree_host.h" | |
6 | |
7 #include "cc/layer.h" | |
8 #include "cc/test/layer_tree_test_common.h" | |
9 #include "cc/test/occlusion_tracker_test_common.h" | |
10 | |
11 namespace cc { | |
12 namespace { | |
13 | |
14 class TestLayer : public Layer { | |
15 public: | |
16 static scoped_refptr<TestLayer> Create() { | |
17 return make_scoped_refptr(new TestLayer()); | |
18 } | |
19 | |
20 virtual void update( | |
21 ResourceUpdateQueue& update_queue, | |
22 const OcclusionTracker* occlusion, | |
23 RenderingStats& stats) OVERRIDE { | |
24 if (!occlusion) | |
25 return; | |
26 | |
27 // Gain access to internals of the OcclusionTracker. | |
28 const TestOcclusionTracker* test_occlusion = | |
29 static_cast<const TestOcclusionTracker*>(occlusion); | |
30 occlusion_ = UnionRegions( | |
31 test_occlusion->occlusionFromInsideTarget(), | |
32 test_occlusion->occlusionFromOutsideTarget()); | |
33 } | |
34 | |
35 const Region& occlusion() const { return occlusion_; } | |
36 const Region& expected_occlusion() const { return expected_occlusion_; } | |
37 void set_expected_occlusion(const Region& occlusion) { | |
38 expected_occlusion_ = occlusion; | |
39 } | |
40 | |
41 private: | |
42 TestLayer() : Layer() { | |
43 setIsDrawable(true); | |
44 } | |
45 virtual ~TestLayer() { } | |
46 | |
47 Region occlusion_; | |
48 Region expected_occlusion_; | |
49 }; | |
50 | |
51 class LayerTreeHostOcclusionTest : public ThreadedTest { | |
52 public: | |
53 | |
54 LayerTreeHostOcclusionTest() | |
55 : root_(TestLayer::Create()), | |
56 child_(TestLayer::Create()), | |
57 child2_(TestLayer::Create()), | |
58 grand_child_(TestLayer::Create()), | |
59 mask_(TestLayer::Create()) { | |
60 } | |
61 | |
62 virtual void beginTest() OVERRIDE { | |
63 postSetNeedsCommitToMainThread(); | |
64 } | |
65 | |
66 virtual void didCommit() OVERRIDE { | |
67 TestLayer* root = static_cast<TestLayer*>(m_layerTreeHost->rootLayer()); | |
68 VerifyOcclusion(root); | |
69 | |
70 endTest(); | |
71 } | |
72 | |
73 virtual void afterTest() OVERRIDE {} | |
74 | |
75 void VerifyOcclusion(TestLayer* layer) const { | |
76 EXPECT_EQ(layer->expected_occlusion().ToString(), | |
77 layer->occlusion().ToString()); | |
78 | |
79 for (size_t i = 0; i < layer->children().size(); ++i) { | |
80 TestLayer* child = static_cast<TestLayer*>(layer->children()[i].get()); | |
81 VerifyOcclusion(child); | |
82 } | |
83 } | |
84 | |
85 void SetLayerPropertiesForTesting( | |
86 TestLayer* layer, TestLayer* parent, const gfx::Transform& transform, | |
87 const gfx::PointF& position, const gfx::Size& bounds, bool opaque) const { | |
88 layer->removeAllChildren(); | |
89 if (parent) | |
90 parent->addChild(layer); | |
91 layer->setTransform(transform); | |
92 layer->setPosition(position); | |
93 layer->setBounds(bounds); | |
94 layer->setContentsOpaque(opaque); | |
95 | |
96 layer->setAnchorPoint(gfx::PointF(0, 0)); | |
jamesr
2012/12/19 22:41:01
gfx::PointF() or gfx::PointF(0.0f, 0.0f) please
danakj
2012/12/19 23:29:17
Done.
| |
97 } | |
98 | |
99 protected: | |
100 scoped_refptr<TestLayer> root_; | |
101 scoped_refptr<TestLayer> child_; | |
102 scoped_refptr<TestLayer> child2_; | |
103 scoped_refptr<TestLayer> grand_child_; | |
104 scoped_refptr<TestLayer> mask_; | |
105 | |
106 gfx::Transform identity_matrix_; | |
107 }; | |
108 | |
109 | |
110 class LayerTreeHostOcclusionTestOcclusionSurfaceClipping : | |
111 public LayerTreeHostOcclusionTest { | |
112 public: | |
113 virtual void setupTree() OVERRIDE { | |
114 // The child layer is a surface and the grandChild is opaque, but clipped to | |
115 // the child and root | |
116 SetLayerPropertiesForTesting( | |
117 root_.get(), NULL, identity_matrix_, | |
118 gfx::PointF(0, 0), gfx::Size(200, 200), true); | |
119 SetLayerPropertiesForTesting( | |
120 child_.get(), root_.get(), identity_matrix_, | |
121 gfx::PointF(10, 10), gfx::Size(500, 500), false); | |
122 SetLayerPropertiesForTesting( | |
123 grand_child_.get(), child_.get(), identity_matrix_, | |
124 gfx::PointF(-10, -10), gfx::Size(20, 500), true); | |
125 | |
126 child_->setMasksToBounds(true); | |
127 child_->setForceRenderSurface(true); | |
128 | |
129 child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190)); | |
130 root_->set_expected_occlusion(gfx::Rect(10, 10, 10, 190)); | |
131 | |
132 m_layerTreeHost->setRootLayer(root_); | |
133 ThreadedTest::setupTree(); | |
134 } | |
135 }; | |
136 | |
137 SINGLE_AND_MULTI_THREAD_TEST_F( | |
138 LayerTreeHostOcclusionTestOcclusionSurfaceClipping) | |
139 | |
140 class LayerTreeHostOcclusionTestOcclusionSurfaceClippingOpaque : | |
141 public LayerTreeHostOcclusionTest { | |
142 public: | |
143 virtual void setupTree() OVERRIDE { | |
144 // If the child layer is opaque, then it adds to the occlusion seen by the | |
145 // root_. | |
146 SetLayerPropertiesForTesting( | |
147 root_.get(), NULL, identity_matrix_, | |
148 gfx::PointF(0, 0), gfx::Size(200, 200), true); | |
jamesr
2012/12/19 22:41:01
use 0.0f, etc, for float literals
danakj
2012/12/19 23:29:17
Done.
| |
149 SetLayerPropertiesForTesting( | |
150 child_.get(), root_.get(), identity_matrix_, | |
151 gfx::PointF(10, 10), gfx::Size(500, 500), true); | |
152 SetLayerPropertiesForTesting( | |
153 grand_child_.get(), child_.get(), identity_matrix_, | |
154 gfx::PointF(-10, -10), gfx::Size(20, 500), true); | |
155 | |
156 child_->setMasksToBounds(true); | |
157 child_->setForceRenderSurface(true); | |
158 | |
159 child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190)); | |
160 root_->set_expected_occlusion(gfx::Rect(10, 10, 190, 190)); | |
161 | |
162 m_layerTreeHost->setRootLayer(root_); | |
163 ThreadedTest::setupTree(); | |
164 } | |
165 }; | |
166 | |
167 SINGLE_AND_MULTI_THREAD_TEST_F( | |
168 LayerTreeHostOcclusionTestOcclusionSurfaceClippingOpaque); | |
169 | |
170 class LayerTreeHostOcclusionTestOcclusionTwoChildren : | |
171 public LayerTreeHostOcclusionTest { | |
172 public: | |
173 virtual void setupTree() OVERRIDE { | |
174 // Add a second child to the root layer and the regions should merge | |
175 SetLayerPropertiesForTesting( | |
176 root_.get(), NULL, identity_matrix_, | |
177 gfx::PointF(0, 0), gfx::Size(200, 200), true); | |
178 SetLayerPropertiesForTesting( | |
179 child_.get(), root_.get(), identity_matrix_, | |
180 gfx::PointF(10, 10), gfx::Size(500, 500), false); | |
181 SetLayerPropertiesForTesting( | |
182 grand_child_.get(), child_.get(), identity_matrix_, | |
183 gfx::PointF(-10, -10), gfx::Size(20, 500), true); | |
184 SetLayerPropertiesForTesting( | |
185 child2_.get(), root_.get(), identity_matrix_, | |
186 gfx::PointF(20, 10), gfx::Size(10, 500), true); | |
187 | |
188 child_->setMasksToBounds(true); | |
189 child_->setForceRenderSurface(true); | |
190 | |
191 grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190)); | |
192 child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190)); | |
193 root_->set_expected_occlusion(gfx::Rect(10, 10, 20, 190)); | |
194 | |
195 m_layerTreeHost->setRootLayer(root_); | |
196 ThreadedTest::setupTree(); | |
197 } | |
198 }; | |
199 | |
200 SINGLE_AND_MULTI_THREAD_TEST_F( | |
201 LayerTreeHostOcclusionTestOcclusionTwoChildren) | |
202 | |
203 class LayerTreeHostOcclusionTestOcclusionMask : | |
204 public LayerTreeHostOcclusionTest { | |
205 public: | |
206 virtual void setupTree() OVERRIDE { | |
207 // If the child layer has a mask on it, then it shouldn't contribute to | |
208 // occlusion on stuff below it. | |
209 SetLayerPropertiesForTesting( | |
210 root_.get(), NULL, identity_matrix_, | |
211 gfx::PointF(0, 0), gfx::Size(200, 200), true); | |
212 SetLayerPropertiesForTesting( | |
213 child2_.get(), root_.get(), identity_matrix_, | |
214 gfx::PointF(10, 10), gfx::Size(500, 500), true); | |
215 SetLayerPropertiesForTesting( | |
216 child_.get(), root_.get(), identity_matrix_, | |
217 gfx::PointF(20, 20), gfx::Size(500, 500), true); | |
218 SetLayerPropertiesForTesting( | |
219 grand_child_.get(), child_.get(), identity_matrix_, | |
220 gfx::PointF(-10, -10), gfx::Size(500, 500), true); | |
221 | |
222 child_->setMasksToBounds(true); | |
223 child_->setForceRenderSurface(true); | |
224 child_->setMaskLayer(mask_.get()); | |
225 | |
226 child_->set_expected_occlusion(gfx::Rect(0, 0, 180, 180)); | |
227 root_->set_expected_occlusion(gfx::Rect(10, 10, 190, 190)); | |
228 | |
229 m_layerTreeHost->setRootLayer(root_); | |
230 ThreadedTest::setupTree(); | |
231 } | |
232 }; | |
233 | |
234 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionMask) | |
235 | |
236 class LayerTreeHostOcclusionTestOcclusionMaskBelowOcclusion : | |
237 public LayerTreeHostOcclusionTest { | |
238 public: | |
239 virtual void setupTree() OVERRIDE { | |
240 // If the child layer with a mask is below child2, then child2 should | |
241 // contribute to occlusion on everything, and child shouldn't contribute | |
242 // to the root_. | |
243 SetLayerPropertiesForTesting( | |
244 root_.get(), NULL, identity_matrix_, | |
245 gfx::PointF(0, 0), gfx::Size(200, 200), true); | |
246 SetLayerPropertiesForTesting( | |
247 child_.get(), root_.get(), identity_matrix_, | |
248 gfx::PointF(10, 10), gfx::Size(500, 500), true); | |
249 SetLayerPropertiesForTesting( | |
250 grand_child_.get(), child_.get(), identity_matrix_, | |
251 gfx::PointF(-10, -10), gfx::Size(20, 500), true); | |
252 SetLayerPropertiesForTesting( | |
253 child2_.get(), root_.get(), identity_matrix_, | |
254 gfx::PointF(20, 10), gfx::Size(10, 500), true); | |
255 | |
256 child_->setMasksToBounds(true); | |
257 child_->setForceRenderSurface(true); | |
258 child_->setMaskLayer(mask_.get()); | |
259 | |
260 grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190)); | |
261 child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190)); | |
262 root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190)); | |
263 | |
264 m_layerTreeHost->setRootLayer(root_); | |
265 ThreadedTest::setupTree(); | |
266 } | |
267 }; | |
268 | |
269 SINGLE_AND_MULTI_THREAD_TEST_F( | |
270 LayerTreeHostOcclusionTestOcclusionMaskBelowOcclusion) | |
271 | |
272 class LayerTreeHostOcclusionTestOcclusionOpacity : | |
273 public LayerTreeHostOcclusionTest { | |
274 public: | |
275 virtual void setupTree() OVERRIDE { | |
276 // If the child layer has a non-opaque opacity, then it shouldn't | |
277 // contribute to occlusion on stuff below it | |
278 SetLayerPropertiesForTesting( | |
279 root_.get(), NULL, identity_matrix_, | |
280 gfx::PointF(0, 0), gfx::Size(200, 200), true); | |
281 SetLayerPropertiesForTesting( | |
282 child2_.get(), root_.get(), identity_matrix_, | |
283 gfx::PointF(20, 10), gfx::Size(10, 500), true); | |
284 SetLayerPropertiesForTesting( | |
285 child_.get(), root_.get(), identity_matrix_, | |
286 gfx::PointF(10, 10), gfx::Size(500, 500), true); | |
287 SetLayerPropertiesForTesting( | |
288 grand_child_.get(), child_.get(), identity_matrix_, | |
289 gfx::PointF(-10, -10), gfx::Size(20, 500), true); | |
290 | |
291 child_->setMasksToBounds(true); | |
292 child_->setForceRenderSurface(true); | |
293 child_->setOpacity(0.5); | |
294 | |
295 child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190)); | |
296 root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190)); | |
297 | |
298 m_layerTreeHost->setRootLayer(root_); | |
299 ThreadedTest::setupTree(); | |
300 } | |
301 }; | |
302 | |
303 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionOpacity) | |
304 | |
305 class LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion : | |
306 public LayerTreeHostOcclusionTest { | |
307 public: | |
308 virtual void setupTree() OVERRIDE { | |
309 // If the child layer with non-opaque opacity is below child2, then | |
310 // child2 should contribute to occlusion on everything, and child shouldn't | |
311 // contribute to the root_. | |
312 SetLayerPropertiesForTesting( | |
313 root_.get(), NULL, identity_matrix_, | |
314 gfx::PointF(0, 0), gfx::Size(200, 200), true); | |
315 SetLayerPropertiesForTesting( | |
316 child_.get(), root_.get(), identity_matrix_, | |
317 gfx::PointF(10, 10), gfx::Size(500, 500), true); | |
318 SetLayerPropertiesForTesting( | |
319 grand_child_.get(), child_.get(), identity_matrix_, | |
320 gfx::PointF(-10, -10), gfx::Size(20, 500), true); | |
321 SetLayerPropertiesForTesting( | |
322 child2_.get(), root_.get(), identity_matrix_, | |
323 gfx::PointF(20, 10), gfx::Size(10, 500), true); | |
324 | |
325 child_->setMasksToBounds(true); | |
326 child_->setForceRenderSurface(true); | |
327 child_->setOpacity(0.5); | |
328 | |
329 grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190)); | |
330 child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190)); | |
331 root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190)); | |
332 | |
333 m_layerTreeHost->setRootLayer(root_); | |
334 ThreadedTest::setupTree(); | |
335 } | |
336 }; | |
337 | |
338 SINGLE_AND_MULTI_THREAD_TEST_F( | |
339 LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion) | |
340 | |
341 class LayerTreeHostOcclusionTestOcclusionOpacityFilter : | |
342 public LayerTreeHostOcclusionTest { | |
343 public: | |
344 virtual void setupTree() OVERRIDE { | |
345 gfx::Transform childTransform; | |
346 childTransform.Translate(250, 250); | |
347 childTransform.Rotate(90); | |
348 childTransform.Translate(-250, -250); | |
349 | |
350 WebKit::WebFilterOperations filters; | |
351 filters.append(WebKit::WebFilterOperation::createOpacityFilter(0.5)); | |
352 | |
353 // If the child layer has a filter that changes alpha values, and is below | |
354 // child2, then child2 should contribute to occlusion on everything, | |
355 // and child shouldn't contribute to the root | |
356 SetLayerPropertiesForTesting( | |
357 root_.get(), NULL, identity_matrix_, | |
358 gfx::PointF(0, 0), gfx::Size(200, 200), true); | |
359 SetLayerPropertiesForTesting( | |
360 child_.get(), root_.get(), childTransform, | |
361 gfx::PointF(30, 30), gfx::Size(500, 500), true); | |
362 SetLayerPropertiesForTesting( | |
363 grand_child_.get(), child_.get(), identity_matrix_, | |
364 gfx::PointF(10, 10), gfx::Size(500, 500), true); | |
365 SetLayerPropertiesForTesting( | |
366 child2_.get(), root_.get(), identity_matrix_, | |
367 gfx::PointF(10, 70), gfx::Size(500, 500), true); | |
368 | |
369 child_->setMasksToBounds(true); | |
370 child_->setFilters(filters); | |
371 | |
372 grand_child_->set_expected_occlusion(gfx::Rect(40, 330, 130, 190)); | |
373 child_->set_expected_occlusion(UnionRegions( | |
374 gfx::Rect(10, 330, 160, 170), gfx::Rect(40, 500, 130, 20))); | |
375 root_->set_expected_occlusion(gfx::Rect(10, 70, 190, 130)); | |
376 | |
377 m_layerTreeHost->setRootLayer(root_); | |
378 ThreadedTest::setupTree(); | |
379 } | |
380 }; | |
381 | |
382 SINGLE_AND_MULTI_THREAD_TEST_F( | |
383 LayerTreeHostOcclusionTestOcclusionOpacityFilter) | |
384 | |
385 class LayerTreeHostOcclusionTestOcclusionBlurFilter : | |
386 public LayerTreeHostOcclusionTest { | |
387 public: | |
388 virtual void setupTree() OVERRIDE { | |
389 gfx::Transform childTransform; | |
390 childTransform.Translate(250, 250); | |
391 childTransform.Rotate(90); | |
392 childTransform.Translate(-250, -250); | |
393 | |
394 WebKit::WebFilterOperations filters; | |
395 filters.append(WebKit::WebFilterOperation::createBlurFilter(10)); | |
396 | |
397 // If the child layer has a filter that moves pixels/changes alpha, and is | |
398 // below child2, then child should not inherit occlusion from outside its | |
399 // subtree, and should not contribute to the root | |
400 SetLayerPropertiesForTesting( | |
401 root_.get(), NULL, identity_matrix_, | |
402 gfx::PointF(0, 0), gfx::Size(200, 200), true); | |
403 SetLayerPropertiesForTesting( | |
404 child_.get(), root_.get(), childTransform, | |
405 gfx::PointF(30, 30), gfx::Size(500, 500), true); | |
406 SetLayerPropertiesForTesting( | |
407 grand_child_.get(), child_.get(), identity_matrix_, | |
408 gfx::PointF(10, 10), gfx::Size(500, 500), true); | |
409 SetLayerPropertiesForTesting( | |
410 child2_.get(), root_.get(), identity_matrix_, | |
411 gfx::PointF(10, 70), gfx::Size(500, 500), true); | |
412 | |
413 child_->setMasksToBounds(true); | |
414 child_->setFilters(filters); | |
415 | |
416 child_->set_expected_occlusion(gfx::Rect(10, 330, 160, 170)); | |
417 root_->set_expected_occlusion(gfx::Rect(10, 70, 190, 130)); | |
418 | |
419 m_layerTreeHost->setRootLayer(root_); | |
420 ThreadedTest::setupTree(); | |
421 } | |
422 }; | |
423 | |
424 SINGLE_AND_MULTI_THREAD_TEST_F( | |
425 LayerTreeHostOcclusionTestOcclusionBlurFilter) | |
426 | |
427 class LayerTreeHostOcclusionTestManySurfaces : | |
428 public LayerTreeHostOcclusionTest { | |
429 public: | |
430 virtual void setupTree() OVERRIDE { | |
431 // We create enough RenderSurfaces that it will trigger Vector reallocation | |
432 // while computing occlusion. | |
433 std::vector<scoped_refptr<TestLayer> > layers; | |
434 int num_surfaces = 200; | |
435 int root_width = 400; | |
436 int root_height = 400; | |
437 | |
438 for (int i = 0; i < num_surfaces; ++i) { | |
439 layers.push_back(TestLayer::Create()); | |
440 if (!i) { | |
441 SetLayerPropertiesForTesting( | |
442 layers.back().get(), NULL, identity_matrix_, | |
443 gfx::PointF(0, 0), gfx::Size(root_width, root_height), true); | |
444 layers.back()->createRenderSurface(); | |
445 } else { | |
446 SetLayerPropertiesForTesting( | |
447 layers.back().get(), layers[layers.size()-2].get(), | |
448 identity_matrix_, | |
449 gfx::PointF(1, 1), gfx::Size(root_width-i, root_height-i), true); | |
450 layers.back()->setForceRenderSurface(true); | |
451 } | |
452 } | |
453 | |
454 for (int i = 1; i < num_surfaces; ++i) { | |
455 scoped_refptr<TestLayer> child = TestLayer::Create(); | |
456 SetLayerPropertiesForTesting( | |
457 child.get(), layers[i].get(), identity_matrix_, | |
458 gfx::PointF(0, 0), gfx::Size(root_width, root_height), false); | |
459 } | |
460 | |
461 for (int i = 0; i < num_surfaces-1; ++i) { | |
462 gfx::Rect expected_occlusion(1, 1, root_width-i-1, root_height-i-1); | |
463 layers[i]->set_expected_occlusion(expected_occlusion); | |
464 } | |
465 | |
466 m_layerTreeHost->setRootLayer(layers[0].get()); | |
467 ThreadedTest::setupTree(); | |
468 } | |
469 }; | |
470 | |
471 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestManySurfaces) | |
472 | |
473 } // namespace | |
474 } // namespace cc | |
OLD | NEW |