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