Add signalSyncPoint to the WebGraphicsContext3D command buffer impls.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_occlusion.cc
blobea32a9e338b75d44f18510ab159f3d4c50f0d767
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.
5 #include "cc/trees/layer_tree_host.h"
7 #include "cc/layers/layer.h"
8 #include "cc/test/layer_tree_test.h"
9 #include "cc/test/occlusion_tracker_test_common.h"
11 namespace cc {
12 namespace {
14 class TestLayer : public Layer {
15 public:
16 static scoped_refptr<TestLayer> Create() {
17 return make_scoped_refptr(new TestLayer());
20 virtual void Update(
21 ResourceUpdateQueue* update_queue,
22 const OcclusionTracker* occlusion,
23 RenderingStats* stats) OVERRIDE {
24 if (!occlusion)
25 return;
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->occlusion_from_inside_target(),
32 test_occlusion->occlusion_from_outside_target());
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;
41 private:
42 TestLayer() : Layer() {
43 SetIsDrawable(true);
45 virtual ~TestLayer() {}
47 Region occlusion_;
48 Region expected_occlusion_;
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()) {
61 virtual void BeginTest() OVERRIDE {
62 PostSetNeedsCommitToMainThread();
65 virtual void DidCommit() OVERRIDE {
66 TestLayer* root = static_cast<TestLayer*>(layer_tree_host()->root_layer());
67 VerifyOcclusion(root);
69 EndTest();
72 virtual void AfterTest() OVERRIDE {}
74 void VerifyOcclusion(TestLayer* layer) const {
75 EXPECT_EQ(layer->expected_occlusion().ToString(),
76 layer->occlusion().ToString());
78 for (size_t i = 0; i < layer->children().size(); ++i) {
79 TestLayer* child = static_cast<TestLayer*>(layer->children()[i].get());
80 VerifyOcclusion(child);
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);
98 layer->SetAnchorPoint(gfx::PointF());
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_;
108 gfx::Transform identity_matrix_;
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);
128 child_->SetMasksToBounds(true);
129 child_->SetForceRenderSurface(true);
131 child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
132 root_->set_expected_occlusion(gfx::Rect(10, 10, 10, 190));
134 layer_tree_host()->SetRootLayer(root_);
135 LayerTreeTest::SetupTree();
139 SINGLE_AND_MULTI_THREAD_TEST_F(
140 LayerTreeHostOcclusionTestOcclusionSurfaceClipping);
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);
158 child_->SetMasksToBounds(true);
159 child_->SetForceRenderSurface(true);
161 child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
162 root_->set_expected_occlusion(gfx::Rect(10, 10, 190, 190));
164 layer_tree_host()->SetRootLayer(root_);
165 LayerTreeTest::SetupTree();
169 SINGLE_AND_MULTI_THREAD_TEST_F(
170 LayerTreeHostOcclusionTestOcclusionSurfaceClippingOpaque);
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);
190 child_->SetMasksToBounds(true);
191 child_->SetForceRenderSurface(true);
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));
197 layer_tree_host()->SetRootLayer(root_);
198 LayerTreeTest::SetupTree();
202 SINGLE_AND_MULTI_THREAD_TEST_F(
203 LayerTreeHostOcclusionTestOcclusionTwoChildren);
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);
224 child_->SetMasksToBounds(true);
225 child_->SetForceRenderSurface(true);
226 child_->SetMaskLayer(mask_.get());
228 child_->set_expected_occlusion(gfx::Rect(0, 0, 180, 180));
229 root_->set_expected_occlusion(gfx::Rect(10, 10, 190, 190));
231 layer_tree_host()->SetRootLayer(root_);
232 LayerTreeTest::SetupTree();
236 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionMask);
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);
258 child_->SetMasksToBounds(true);
259 child_->SetForceRenderSurface(true);
260 child_->SetMaskLayer(mask_.get());
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));
266 layer_tree_host()->SetRootLayer(root_);
267 LayerTreeTest::SetupTree();
271 SINGLE_AND_MULTI_THREAD_TEST_F(
272 LayerTreeHostOcclusionTestOcclusionMaskBelowOcclusion);
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);
293 child_->SetMasksToBounds(true);
294 child_->SetForceRenderSurface(true);
295 child_->SetOpacity(0.5f);
297 child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
298 root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
300 layer_tree_host()->SetRootLayer(root_);
301 LayerTreeTest::SetupTree();
305 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionOpacity);
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);
327 child_->SetMasksToBounds(true);
328 child_->SetForceRenderSurface(true);
329 child_->SetOpacity(0.5f);
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));
335 layer_tree_host()->SetRootLayer(root_);
336 LayerTreeTest::SetupTree();
340 SINGLE_AND_MULTI_THREAD_TEST_F(
341 LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion);
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);
352 WebKit::WebFilterOperations filters;
353 filters.append(WebKit::WebFilterOperation::createOpacityFilter(0.5));
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);
371 child_->SetMasksToBounds(true);
372 child_->SetFilters(filters);
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));
379 layer_tree_host()->SetRootLayer(root_);
380 LayerTreeTest::SetupTree();
384 SINGLE_AND_MULTI_THREAD_TEST_F(
385 LayerTreeHostOcclusionTestOcclusionOpacityFilter);
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);
396 WebKit::WebFilterOperations filters;
397 filters.append(WebKit::WebFilterOperation::createBlurFilter(10));
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);
415 child_->SetMasksToBounds(true);
416 child_->SetFilters(filters);
418 child_->set_expected_occlusion(gfx::Rect(10, 330, 160, 170));
419 root_->set_expected_occlusion(gfx::Rect(10, 70, 190, 130));
421 layer_tree_host()->SetRootLayer(root_);
422 LayerTreeTest::SetupTree();
426 SINGLE_AND_MULTI_THREAD_TEST_F(
427 LayerTreeHostOcclusionTestOcclusionBlurFilter);
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;
440 for (int i = 0; i < num_surfaces; ++i) {
441 layers.push_back(TestLayer::Create());
442 if (!i) {
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 layers.back()->CreateRenderSurface();
448 } else {
449 SetLayerPropertiesForTesting(
450 layers.back().get(), layers[layers.size() - 2].get(),
451 identity_matrix_,
452 gfx::PointF(1.f, 1.f),
453 gfx::Size(root_width-i, root_height-i), true);
454 layers.back()->SetForceRenderSurface(true);
458 for (int i = 1; i < num_surfaces; ++i) {
459 scoped_refptr<TestLayer> child = TestLayer::Create();
460 SetLayerPropertiesForTesting(
461 child.get(), layers[i].get(), identity_matrix_,
462 gfx::PointF(0.f, 0.f), gfx::Size(root_width, root_height), false);
465 for (int i = 0; i < num_surfaces-1; ++i) {
466 gfx::Rect expected_occlusion(1, 1, root_width-i-1, root_height-i-1);
467 layers[i]->set_expected_occlusion(expected_occlusion);
470 layer_tree_host()->SetRootLayer(layers[0]);
471 LayerTreeTest::SetupTree();
475 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestManySurfaces);
477 } // namespace
478 } // namespace cc