OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 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 "cc/trees/layer_tree_host.h" | 5 #include "cc/trees/layer_tree_host.h" |
6 | 6 |
7 #include "cc/layers/layer.h" | 7 #include "cc/layers/layer.h" |
8 #include "cc/output/copy_output_request.h" | 8 #include "cc/layers/picture_layer.h" |
9 #include "cc/output/copy_output_result.h" | 9 #include "cc/test/fake_content_layer_client.h" |
10 #include "cc/test/layer_tree_test.h" | 10 #include "cc/test/layer_tree_test.h" |
11 #include "cc/test/test_occlusion_tracker.h" | 11 #include "cc/trees/layer_tree_impl.h" |
12 | 12 |
13 namespace cc { | 13 namespace cc { |
14 namespace { | 14 namespace { |
15 | 15 |
16 class TestLayer : public Layer { | 16 #define EXPECT_OCCLUSION_EQ(expected, actual) \ |
17 public: | 17 EXPECT_TRUE(expected.IsEqual(actual)) \ |
18 static scoped_refptr<TestLayer> Create() { | 18 << " Expected: " << expected.ToString() << std::endl \ |
19 return make_scoped_refptr(new TestLayer()); | 19 << " Actual: " << actual.ToString(); |
20 } | |
21 | |
22 bool Update(ResourceUpdateQueue* update_queue, | |
23 const OcclusionTracker<Layer>* occlusion) override { | |
24 if (!occlusion) | |
25 return false; | |
26 | |
27 const TestOcclusionTracker<Layer>* test_occlusion = | |
28 static_cast<const TestOcclusionTracker<Layer>*>(occlusion); | |
29 occlusion_ = UnionSimpleEnclosedRegions( | |
30 test_occlusion->occlusion_from_inside_target(), | |
31 test_occlusion->occlusion_from_outside_target()); | |
32 return false; | |
33 } | |
34 | |
35 const SimpleEnclosedRegion& occlusion() const { return occlusion_; } | |
36 const SimpleEnclosedRegion& expected_occlusion() const { | |
37 return expected_occlusion_; | |
38 } | |
39 void set_expected_occlusion(const gfx::Rect& occlusion) { | |
40 expected_occlusion_ = SimpleEnclosedRegion(occlusion); | |
41 } | |
42 | |
43 private: | |
44 TestLayer() : Layer() { | |
45 SetIsDrawable(true); | |
46 } | |
47 ~TestLayer() override {} | |
48 | |
49 SimpleEnclosedRegion occlusion_; | |
50 SimpleEnclosedRegion expected_occlusion_; | |
51 }; | |
52 | 20 |
53 class LayerTreeHostOcclusionTest : public LayerTreeTest { | 21 class LayerTreeHostOcclusionTest : public LayerTreeTest { |
54 public: | |
55 LayerTreeHostOcclusionTest() | |
56 : root_(TestLayer::Create()), | |
57 child_(TestLayer::Create()), | |
58 child2_(TestLayer::Create()), | |
59 grand_child_(TestLayer::Create()), | |
60 mask_(TestLayer::Create()) { | |
61 } | |
62 | |
63 void BeginTest() override { PostSetNeedsCommitToMainThread(); } | |
64 | |
65 void DidCommit() override { | |
66 TestLayer* root = static_cast<TestLayer*>(layer_tree_host()->root_layer()); | |
67 VerifyOcclusion(root); | |
68 | |
69 EndTest(); | |
70 } | |
71 | |
72 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 const gfx::PointF& position, | |
88 const 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 | |
99 protected: | 22 protected: |
100 void InitializeSettings(LayerTreeSettings* settings) override { | 23 void InitializeSettings(LayerTreeSettings* settings) override { |
101 settings->minimum_occlusion_tracking_size = gfx::Size(); | 24 settings->minimum_occlusion_tracking_size = gfx::Size(); |
102 } | 25 } |
103 | 26 }; |
104 scoped_refptr<TestLayer> root_; | 27 |
105 scoped_refptr<TestLayer> child_; | 28 // Verify occlusion is set on the layer draw properties. |
106 scoped_refptr<TestLayer> child2_; | 29 class LayerTreeHostOcclusionTestDrawPropertiesOnLayer |
107 scoped_refptr<TestLayer> grand_child_; | 30 : public LayerTreeHostOcclusionTest { |
108 scoped_refptr<TestLayer> mask_; | 31 public: |
109 | 32 void SetupTree() override { |
110 gfx::Transform identity_matrix_; | 33 scoped_refptr<Layer> root = Layer::Create(); |
111 }; | 34 root->SetBounds(gfx::Size(100, 100)); |
112 | 35 root->SetIsDrawable(true); |
113 | 36 |
114 class LayerTreeHostOcclusionTestOcclusionSurfaceClipping | 37 scoped_refptr<Layer> child = Layer::Create(); |
115 : public LayerTreeHostOcclusionTest { | 38 child->SetBounds(gfx::Size(50, 60)); |
116 public: | 39 child->SetPosition(gfx::PointF(10.f, 5.5f)); |
117 void SetupTree() override { | 40 child->SetContentsOpaque(true); |
118 // The child layer is a surface and the grand_child is opaque, but clipped | 41 child->SetIsDrawable(true); |
119 // to the child and root | 42 root->AddChild(child); |
120 SetLayerPropertiesForTesting( | 43 |
121 root_.get(), NULL, identity_matrix_, | 44 layer_tree_host()->SetRootLayer(root); |
122 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | 45 LayerTreeTest::SetupTree(); |
123 SetLayerPropertiesForTesting( | 46 } |
124 child_.get(), root_.get(), identity_matrix_, | 47 |
125 gfx::PointF(10.f, 10.f), gfx::Size(500, 500), false); | 48 void BeginTest() override { PostSetNeedsCommitToMainThread(); } |
126 SetLayerPropertiesForTesting( | 49 |
127 grand_child_.get(), child_.get(), identity_matrix_, | 50 void DrawLayersOnThread(LayerTreeHostImpl* impl) override { |
128 gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true); | 51 LayerImpl* root = impl->active_tree()->root_layer(); |
129 | 52 LayerImpl* child = root->children()[0]; |
130 child_->SetMasksToBounds(true); | 53 |
131 child_->SetForceRenderSurface(true); | 54 // Verify the draw properties are valid. |
132 | 55 EXPECT_TRUE(root->IsDrawnRenderSurfaceLayerListMember()); |
133 child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190)); | 56 EXPECT_TRUE(child->IsDrawnRenderSurfaceLayerListMember()); |
134 root_->set_expected_occlusion(gfx::Rect(10, 10, 10, 190)); | 57 |
135 | 58 EXPECT_OCCLUSION_EQ( |
136 layer_tree_host()->SetRootLayer(root_); | 59 Occlusion(child->draw_transform(), SimpleEnclosedRegion(), |
137 LayerTreeTest::SetupTree(); | 60 SimpleEnclosedRegion()), |
138 } | 61 child->draw_properties().occlusion_in_content_space); |
| 62 EXPECT_OCCLUSION_EQ( |
| 63 Occlusion(root->draw_transform(), SimpleEnclosedRegion(), |
| 64 SimpleEnclosedRegion(gfx::Rect(10, 6, 50, 59))), |
| 65 root->draw_properties().occlusion_in_content_space); |
| 66 EndTest(); |
| 67 } |
| 68 |
| 69 void AfterTest() override {} |
| 70 }; |
| 71 |
| 72 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestDrawPropertiesOnLayer); |
| 73 |
| 74 // Verify occlusion is set on the render surfaces. |
| 75 class LayerTreeHostOcclusionTestDrawPropertiesOnSurface |
| 76 : public LayerTreeHostOcclusionTest { |
| 77 public: |
| 78 void SetupTree() override { |
| 79 scoped_refptr<Layer> root = Layer::Create(); |
| 80 root->SetBounds(gfx::Size(100, 100)); |
| 81 root->SetIsDrawable(true); |
| 82 |
| 83 scoped_refptr<Layer> child = Layer::Create(); |
| 84 child->SetBounds(gfx::Size(1, 1)); |
| 85 child->SetPosition(gfx::PointF(10.f, 5.5f)); |
| 86 child->SetIsDrawable(true); |
| 87 child->SetForceRenderSurface(true); |
| 88 root->AddChild(child); |
| 89 |
| 90 scoped_refptr<Layer> child2 = Layer::Create(); |
| 91 child2->SetBounds(gfx::Size(10, 12)); |
| 92 child2->SetPosition(gfx::PointF(13.f, 8.5f)); |
| 93 child2->SetContentsOpaque(true); |
| 94 child2->SetIsDrawable(true); |
| 95 root->AddChild(child2); |
| 96 |
| 97 layer_tree_host()->SetRootLayer(root); |
| 98 LayerTreeTest::SetupTree(); |
| 99 } |
| 100 |
| 101 void BeginTest() override { PostSetNeedsCommitToMainThread(); } |
| 102 |
| 103 void DrawLayersOnThread(LayerTreeHostImpl* impl) override { |
| 104 LayerImpl* root = impl->active_tree()->root_layer(); |
| 105 LayerImpl* child = root->children()[0]; |
| 106 RenderSurfaceImpl* surface = child->render_surface(); |
| 107 |
| 108 // Verify the draw properties are valid. |
| 109 EXPECT_TRUE(root->IsDrawnRenderSurfaceLayerListMember()); |
| 110 EXPECT_TRUE(child->IsDrawnRenderSurfaceLayerListMember()); |
| 111 EXPECT_EQ(child, child->render_target()); |
| 112 |
| 113 EXPECT_OCCLUSION_EQ( |
| 114 Occlusion(surface->draw_transform(), SimpleEnclosedRegion(), |
| 115 SimpleEnclosedRegion(gfx::Rect(13, 9, 10, 11))), |
| 116 surface->occlusion_in_content_space()); |
| 117 EndTest(); |
| 118 } |
| 119 |
| 120 void AfterTest() override {} |
139 }; | 121 }; |
140 | 122 |
141 SINGLE_AND_MULTI_THREAD_TEST_F( | 123 SINGLE_AND_MULTI_THREAD_TEST_F( |
142 LayerTreeHostOcclusionTestOcclusionSurfaceClipping); | 124 LayerTreeHostOcclusionTestDrawPropertiesOnSurface); |
143 | 125 |
144 class LayerTreeHostOcclusionTestOcclusionSurfaceClippingOpaque | 126 // Verify occlusion is set on mask layers. |
145 : public LayerTreeHostOcclusionTest { | 127 class LayerTreeHostOcclusionTestDrawPropertiesOnMask |
146 public: | 128 : public LayerTreeHostOcclusionTest { |
147 void SetupTree() override { | 129 public: |
148 // If the child layer is opaque, then it adds to the occlusion seen by the | 130 void SetupTree() override { |
149 // root_. | 131 scoped_refptr<Layer> root = Layer::Create(); |
150 SetLayerPropertiesForTesting( | 132 root->SetBounds(gfx::Size(100, 100)); |
151 root_.get(), NULL, identity_matrix_, | 133 root->SetIsDrawable(true); |
152 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | 134 |
153 SetLayerPropertiesForTesting( | 135 scoped_refptr<Layer> child = Layer::Create(); |
154 child_.get(), root_.get(), identity_matrix_, | 136 child->SetBounds(gfx::Size(30, 40)); |
155 gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true); | 137 child->SetPosition(gfx::PointF(10.f, 5.5f)); |
156 SetLayerPropertiesForTesting( | 138 child->SetIsDrawable(true); |
157 grand_child_.get(), child_.get(), identity_matrix_, | 139 root->AddChild(child); |
158 gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true); | 140 |
159 | 141 scoped_refptr<Layer> make_surface_bigger = Layer::Create(); |
160 child_->SetMasksToBounds(true); | 142 make_surface_bigger->SetBounds(gfx::Size(100, 100)); |
161 child_->SetForceRenderSurface(true); | 143 make_surface_bigger->SetPosition(gfx::PointF(-10.f, -15.f)); |
162 | 144 make_surface_bigger->SetIsDrawable(true); |
163 child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190)); | 145 child->AddChild(make_surface_bigger); |
164 root_->set_expected_occlusion(gfx::Rect(10, 10, 190, 190)); | 146 |
165 | 147 scoped_refptr<Layer> mask = PictureLayer::Create(&client_); |
166 layer_tree_host()->SetRootLayer(root_); | 148 mask->SetBounds(gfx::Size(30, 40)); |
167 LayerTreeTest::SetupTree(); | 149 mask->SetIsDrawable(true); |
168 } | 150 child->SetMaskLayer(mask.get()); |
| 151 |
| 152 scoped_refptr<Layer> child2 = Layer::Create(); |
| 153 child2->SetBounds(gfx::Size(10, 12)); |
| 154 child2->SetPosition(gfx::PointF(13.f, 8.5f)); |
| 155 child2->SetContentsOpaque(true); |
| 156 child2->SetIsDrawable(true); |
| 157 root->AddChild(child2); |
| 158 |
| 159 layer_tree_host()->SetRootLayer(root); |
| 160 LayerTreeTest::SetupTree(); |
| 161 } |
| 162 |
| 163 void BeginTest() override { PostSetNeedsCommitToMainThread(); } |
| 164 |
| 165 void DrawLayersOnThread(LayerTreeHostImpl* impl) override { |
| 166 LayerImpl* root = impl->active_tree()->root_layer(); |
| 167 LayerImpl* child = root->children()[0]; |
| 168 RenderSurfaceImpl* surface = child->render_surface(); |
| 169 LayerImpl* mask = child->mask_layer(); |
| 170 |
| 171 // Verify the draw properties are valid. |
| 172 EXPECT_TRUE(root->IsDrawnRenderSurfaceLayerListMember()); |
| 173 EXPECT_TRUE(child->IsDrawnRenderSurfaceLayerListMember()); |
| 174 EXPECT_EQ(child, child->render_target()); |
| 175 |
| 176 gfx::Transform transform = surface->draw_transform(); |
| 177 transform.PreconcatTransform(child->draw_transform()); |
| 178 |
| 179 EXPECT_OCCLUSION_EQ( |
| 180 Occlusion(transform, SimpleEnclosedRegion(), |
| 181 SimpleEnclosedRegion(gfx::Rect(13, 9, 10, 11))), |
| 182 mask->draw_properties().occlusion_in_content_space); |
| 183 EndTest(); |
| 184 } |
| 185 |
| 186 void AfterTest() override {} |
| 187 |
| 188 FakeContentLayerClient client_; |
| 189 }; |
| 190 |
| 191 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestDrawPropertiesOnMask); |
| 192 |
| 193 // Verify occlusion is set to empty inside the subtree of a replica. This is |
| 194 // done because the tile system does not know about replicas, and so would not |
| 195 // know that something is unoccluded on the replica even though it's occluded on |
| 196 // the original. |
| 197 class LayerTreeHostOcclusionTestDrawPropertiesInsideReplica |
| 198 : public LayerTreeHostOcclusionTest { |
| 199 public: |
| 200 void SetupTree() override { |
| 201 scoped_refptr<Layer> root = Layer::Create(); |
| 202 root->SetBounds(gfx::Size(100, 100)); |
| 203 root->SetIsDrawable(true); |
| 204 |
| 205 scoped_refptr<Layer> child = Layer::Create(); |
| 206 child->SetBounds(gfx::Size(1, 1)); |
| 207 child->SetPosition(gfx::PointF(10.f, 5.5f)); |
| 208 child->SetIsDrawable(true); |
| 209 child->SetForceRenderSurface(true); |
| 210 root->AddChild(child); |
| 211 |
| 212 scoped_refptr<Layer> replica = Layer::Create(); |
| 213 gfx::Transform translate; |
| 214 translate.Translate(20.f, 4.f); |
| 215 replica->SetTransform(translate); |
| 216 child->SetReplicaLayer(replica.get()); |
| 217 |
| 218 scoped_refptr<Layer> mask = PictureLayer::Create(&client_); |
| 219 mask->SetBounds(gfx::Size(30, 40)); |
| 220 mask->SetIsDrawable(true); |
| 221 child->SetMaskLayer(mask.get()); |
| 222 |
| 223 scoped_refptr<Layer> child2 = Layer::Create(); |
| 224 child2->SetBounds(gfx::Size(10, 12)); |
| 225 child2->SetPosition(gfx::PointF(13.f, 8.5f)); |
| 226 child2->SetContentsOpaque(true); |
| 227 child2->SetIsDrawable(true); |
| 228 root->AddChild(child2); |
| 229 |
| 230 layer_tree_host()->SetRootLayer(root); |
| 231 LayerTreeTest::SetupTree(); |
| 232 } |
| 233 |
| 234 void BeginTest() override { PostSetNeedsCommitToMainThread(); } |
| 235 |
| 236 void DrawLayersOnThread(LayerTreeHostImpl* impl) override { |
| 237 LayerImpl* root = impl->active_tree()->root_layer(); |
| 238 LayerImpl* child = root->children()[0]; |
| 239 RenderSurfaceImpl* surface = child->render_surface(); |
| 240 LayerImpl* mask = child->mask_layer(); |
| 241 |
| 242 // Verify the draw properties are valid. |
| 243 EXPECT_TRUE(root->IsDrawnRenderSurfaceLayerListMember()); |
| 244 EXPECT_TRUE(child->IsDrawnRenderSurfaceLayerListMember()); |
| 245 EXPECT_EQ(child, child->render_target()); |
| 246 |
| 247 // No occlusion from on child, which is part of the replica. |
| 248 EXPECT_OCCLUSION_EQ(Occlusion(), |
| 249 child->draw_properties().occlusion_in_content_space); |
| 250 // Occlusion on the surface is okay. |
| 251 EXPECT_OCCLUSION_EQ( |
| 252 Occlusion(surface->draw_transform(), SimpleEnclosedRegion(), |
| 253 SimpleEnclosedRegion(gfx::Rect(13, 9, 10, 11))), |
| 254 surface->occlusion_in_content_space()); |
| 255 // No occlusion on the replica'd mask. |
| 256 EXPECT_OCCLUSION_EQ(Occlusion(), |
| 257 mask->draw_properties().occlusion_in_content_space); |
| 258 EndTest(); |
| 259 } |
| 260 |
| 261 void AfterTest() override {} |
| 262 |
| 263 FakeContentLayerClient client_; |
169 }; | 264 }; |
170 | 265 |
171 SINGLE_AND_MULTI_THREAD_TEST_F( | 266 SINGLE_AND_MULTI_THREAD_TEST_F( |
172 LayerTreeHostOcclusionTestOcclusionSurfaceClippingOpaque); | 267 LayerTreeHostOcclusionTestDrawPropertiesInsideReplica); |
173 | |
174 class LayerTreeHostOcclusionTestOcclusionTwoChildren | |
175 : public LayerTreeHostOcclusionTest { | |
176 public: | |
177 void SetupTree() override { | |
178 // Add a second child to the root layer and the regions should merge | |
179 SetLayerPropertiesForTesting( | |
180 root_.get(), NULL, identity_matrix_, | |
181 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | |
182 SetLayerPropertiesForTesting( | |
183 child_.get(), root_.get(), identity_matrix_, | |
184 gfx::PointF(10.f, 10.f), gfx::Size(500, 500), false); | |
185 SetLayerPropertiesForTesting( | |
186 grand_child_.get(), child_.get(), identity_matrix_, | |
187 gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true); | |
188 SetLayerPropertiesForTesting( | |
189 child2_.get(), root_.get(), identity_matrix_, | |
190 gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true); | |
191 | |
192 child_->SetMasksToBounds(true); | |
193 child_->SetForceRenderSurface(true); | |
194 | |
195 grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190)); | |
196 child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190)); | |
197 root_->set_expected_occlusion(gfx::Rect(10, 10, 20, 190)); | |
198 | |
199 layer_tree_host()->SetRootLayer(root_); | |
200 LayerTreeTest::SetupTree(); | |
201 } | |
202 }; | |
203 | |
204 SINGLE_AND_MULTI_THREAD_TEST_F( | |
205 LayerTreeHostOcclusionTestOcclusionTwoChildren); | |
206 | |
207 class LayerTreeHostOcclusionTestOcclusionMask | |
208 : public LayerTreeHostOcclusionTest { | |
209 public: | |
210 void SetupTree() override { | |
211 // If the child layer has a mask on it, then it shouldn't contribute to | |
212 // occlusion on stuff below it. | |
213 SetLayerPropertiesForTesting( | |
214 root_.get(), NULL, identity_matrix_, | |
215 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | |
216 SetLayerPropertiesForTesting( | |
217 child2_.get(), root_.get(), identity_matrix_, | |
218 gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true); | |
219 SetLayerPropertiesForTesting( | |
220 child_.get(), root_.get(), identity_matrix_, | |
221 gfx::PointF(20.f, 20.f), gfx::Size(500, 500), true); | |
222 SetLayerPropertiesForTesting( | |
223 grand_child_.get(), child_.get(), identity_matrix_, | |
224 gfx::PointF(-10.f, -10.f), gfx::Size(500, 500), true); | |
225 | |
226 child_->SetMasksToBounds(true); | |
227 child_->SetForceRenderSurface(true); | |
228 child_->SetMaskLayer(mask_.get()); | |
229 | |
230 child_->set_expected_occlusion(gfx::Rect(0, 0, 180, 180)); | |
231 root_->set_expected_occlusion(gfx::Rect(10, 10, 190, 190)); | |
232 | |
233 layer_tree_host()->SetRootLayer(root_); | |
234 LayerTreeTest::SetupTree(); | |
235 } | |
236 }; | |
237 | |
238 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionMask); | |
239 | |
240 class LayerTreeHostOcclusionTestOcclusionMaskBelowOcclusion | |
241 : public LayerTreeHostOcclusionTest { | |
242 public: | |
243 void SetupTree() override { | |
244 // If the child layer with a mask is below child2, then child2 should | |
245 // contribute to occlusion on everything, and child shouldn't contribute | |
246 // to the root_. | |
247 SetLayerPropertiesForTesting( | |
248 root_.get(), NULL, identity_matrix_, | |
249 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | |
250 SetLayerPropertiesForTesting( | |
251 child_.get(), root_.get(), identity_matrix_, | |
252 gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true); | |
253 SetLayerPropertiesForTesting( | |
254 grand_child_.get(), child_.get(), identity_matrix_, | |
255 gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true); | |
256 SetLayerPropertiesForTesting( | |
257 child2_.get(), root_.get(), identity_matrix_, | |
258 gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true); | |
259 | |
260 child_->SetMasksToBounds(true); | |
261 child_->SetForceRenderSurface(true); | |
262 child_->SetMaskLayer(mask_.get()); | |
263 | |
264 grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190)); | |
265 child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190)); | |
266 root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190)); | |
267 | |
268 layer_tree_host()->SetRootLayer(root_); | |
269 LayerTreeTest::SetupTree(); | |
270 } | |
271 }; | |
272 | |
273 SINGLE_AND_MULTI_THREAD_TEST_F( | |
274 LayerTreeHostOcclusionTestOcclusionMaskBelowOcclusion); | |
275 | |
276 class LayerTreeHostOcclusionTestOcclusionOpacity | |
277 : public LayerTreeHostOcclusionTest { | |
278 public: | |
279 void SetupTree() override { | |
280 // If the child layer has a non-opaque opacity, then it shouldn't | |
281 // contribute to occlusion on stuff below it | |
282 SetLayerPropertiesForTesting( | |
283 root_.get(), NULL, identity_matrix_, | |
284 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | |
285 SetLayerPropertiesForTesting( | |
286 child2_.get(), root_.get(), identity_matrix_, | |
287 gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true); | |
288 SetLayerPropertiesForTesting( | |
289 child_.get(), root_.get(), identity_matrix_, | |
290 gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true); | |
291 SetLayerPropertiesForTesting( | |
292 grand_child_.get(), child_.get(), identity_matrix_, | |
293 gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true); | |
294 | |
295 child_->SetMasksToBounds(true); | |
296 child_->SetForceRenderSurface(true); | |
297 child_->SetOpacity(0.5f); | |
298 | |
299 child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190)); | |
300 root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190)); | |
301 | |
302 layer_tree_host()->SetRootLayer(root_); | |
303 LayerTreeTest::SetupTree(); | |
304 } | |
305 }; | |
306 | |
307 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionOpacity); | |
308 | |
309 class LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion | |
310 : public LayerTreeHostOcclusionTest { | |
311 public: | |
312 void SetupTree() override { | |
313 // If the child layer with non-opaque opacity is below child2, then | |
314 // child2 should contribute to occlusion on everything, and child shouldn't | |
315 // contribute to the root_. | |
316 SetLayerPropertiesForTesting( | |
317 root_.get(), NULL, identity_matrix_, | |
318 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | |
319 SetLayerPropertiesForTesting( | |
320 child_.get(), root_.get(), identity_matrix_, | |
321 gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true); | |
322 SetLayerPropertiesForTesting( | |
323 grand_child_.get(), child_.get(), identity_matrix_, | |
324 gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true); | |
325 SetLayerPropertiesForTesting( | |
326 child2_.get(), root_.get(), identity_matrix_, | |
327 gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true); | |
328 | |
329 child_->SetMasksToBounds(true); | |
330 child_->SetForceRenderSurface(true); | |
331 child_->SetOpacity(0.5f); | |
332 | |
333 grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190)); | |
334 child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190)); | |
335 root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190)); | |
336 | |
337 layer_tree_host()->SetRootLayer(root_); | |
338 LayerTreeTest::SetupTree(); | |
339 } | |
340 }; | |
341 | |
342 SINGLE_AND_MULTI_THREAD_TEST_F( | |
343 LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion); | |
344 | |
345 class LayerTreeHostOcclusionTestOcclusionBlending | |
346 : public LayerTreeHostOcclusionTest { | |
347 public: | |
348 void SetupTree() override { | |
349 // If the child layer has a blend mode, then it shouldn't | |
350 // contribute to occlusion on stuff below it | |
351 SetLayerPropertiesForTesting( | |
352 root_.get(), NULL, identity_matrix_, | |
353 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | |
354 SetLayerPropertiesForTesting( | |
355 child2_.get(), root_.get(), identity_matrix_, | |
356 gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true); | |
357 SetLayerPropertiesForTesting( | |
358 child_.get(), root_.get(), identity_matrix_, | |
359 gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true); | |
360 SetLayerPropertiesForTesting( | |
361 grand_child_.get(), child_.get(), identity_matrix_, | |
362 gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true); | |
363 | |
364 child_->SetMasksToBounds(true); | |
365 child_->SetBlendMode(SkXfermode::kMultiply_Mode); | |
366 child_->SetForceRenderSurface(true); | |
367 | |
368 child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190)); | |
369 root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190)); | |
370 | |
371 layer_tree_host()->SetRootLayer(root_); | |
372 LayerTreeTest::SetupTree(); | |
373 } | |
374 }; | |
375 | |
376 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionBlending); | |
377 | |
378 class LayerTreeHostOcclusionTestOcclusionBlendingBelowOcclusion | |
379 : public LayerTreeHostOcclusionTest { | |
380 public: | |
381 void SetupTree() override { | |
382 // If the child layer with a blend mode is below child2, then | |
383 // child2 should contribute to occlusion on everything, and child shouldn't | |
384 // contribute to the root_. | |
385 SetLayerPropertiesForTesting( | |
386 root_.get(), NULL, identity_matrix_, | |
387 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | |
388 SetLayerPropertiesForTesting( | |
389 child_.get(), root_.get(), identity_matrix_, | |
390 gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true); | |
391 SetLayerPropertiesForTesting( | |
392 grand_child_.get(), child_.get(), identity_matrix_, | |
393 gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true); | |
394 SetLayerPropertiesForTesting( | |
395 child2_.get(), root_.get(), identity_matrix_, | |
396 gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true); | |
397 | |
398 child_->SetMasksToBounds(true); | |
399 child_->SetBlendMode(SkXfermode::kMultiply_Mode); | |
400 | |
401 grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190)); | |
402 child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190)); | |
403 root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190)); | |
404 | |
405 layer_tree_host()->SetRootLayer(root_); | |
406 LayerTreeTest::SetupTree(); | |
407 } | |
408 }; | |
409 | |
410 SINGLE_AND_MULTI_THREAD_TEST_F( | |
411 LayerTreeHostOcclusionTestOcclusionBlendingBelowOcclusion); | |
412 | |
413 class LayerTreeHostOcclusionTestOcclusionOpacityFilter | |
414 : public LayerTreeHostOcclusionTest { | |
415 public: | |
416 void SetupTree() override { | |
417 FilterOperations filters; | |
418 filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); | |
419 | |
420 // If the child layer has a filter that changes alpha values, and is below | |
421 // child2, then child2 should contribute to occlusion on everything, | |
422 // and child shouldn't contribute to the root | |
423 SetLayerPropertiesForTesting( | |
424 root_.get(), NULL, identity_matrix_, | |
425 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | |
426 SetLayerPropertiesForTesting(child_.get(), | |
427 root_.get(), | |
428 identity_matrix_, | |
429 gfx::PointF(0.f, 0.f), | |
430 gfx::Size(500, 500), | |
431 true); | |
432 SetLayerPropertiesForTesting(grand_child_.get(), | |
433 child_.get(), | |
434 identity_matrix_, | |
435 gfx::PointF(0.f, 0.f), | |
436 gfx::Size(500, 500), | |
437 true); | |
438 SetLayerPropertiesForTesting(child2_.get(), | |
439 root_.get(), | |
440 identity_matrix_, | |
441 gfx::PointF(10.f, 10.f), | |
442 gfx::Size(30, 30), | |
443 true); | |
444 | |
445 child_->SetMasksToBounds(true); | |
446 child_->SetFilters(filters); | |
447 | |
448 // child2_ occludes grand_child_, showing it does occlude inside child_'s | |
449 // subtree. | |
450 grand_child_->set_expected_occlusion(gfx::Rect(10, 10, 30, 30)); | |
451 // grand_child_ occludes child_, showing there is more occlusion in | |
452 // child_'s subtree. | |
453 child_->set_expected_occlusion(gfx::Rect(0, 0, 200, 200)); | |
454 // child2_'s occlusion reaches the root, but child_'s subtree does not. | |
455 root_->set_expected_occlusion(gfx::Rect(10, 10, 30, 30)); | |
456 | |
457 layer_tree_host()->SetRootLayer(root_); | |
458 LayerTreeTest::SetupTree(); | |
459 } | |
460 }; | |
461 | |
462 SINGLE_AND_MULTI_THREAD_TEST_F( | |
463 LayerTreeHostOcclusionTestOcclusionOpacityFilter); | |
464 | |
465 class LayerTreeHostOcclusionTestOcclusionBlurFilter | |
466 : public LayerTreeHostOcclusionTest { | |
467 public: | |
468 void SetupTree() override { | |
469 gfx::Transform child_transform; | |
470 child_transform.Translate(250.0, 250.0); | |
471 child_transform.Rotate(90.0); | |
472 child_transform.Translate(-250.0, -250.0); | |
473 | |
474 FilterOperations filters; | |
475 filters.Append(FilterOperation::CreateBlurFilter(10.f)); | |
476 | |
477 // If the child layer has a filter that moves pixels/changes alpha, and is | |
478 // below child2, then child should not inherit occlusion from outside its | |
479 // subtree, and should not contribute to the root | |
480 SetLayerPropertiesForTesting( | |
481 root_.get(), NULL, identity_matrix_, | |
482 gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); | |
483 SetLayerPropertiesForTesting( | |
484 child_.get(), root_.get(), child_transform, | |
485 gfx::PointF(30.f, 30.f), gfx::Size(500, 500), true); | |
486 SetLayerPropertiesForTesting( | |
487 grand_child_.get(), child_.get(), identity_matrix_, | |
488 gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true); | |
489 SetLayerPropertiesForTesting( | |
490 child2_.get(), root_.get(), identity_matrix_, | |
491 gfx::PointF(10.f, 70.f), gfx::Size(500, 500), true); | |
492 | |
493 child_->SetMasksToBounds(true); | |
494 child_->SetFilters(filters); | |
495 | |
496 child_->set_expected_occlusion(gfx::Rect(10, 330, 160, 170)); | |
497 root_->set_expected_occlusion(gfx::Rect(10, 70, 190, 130)); | |
498 | |
499 layer_tree_host()->SetRootLayer(root_); | |
500 LayerTreeTest::SetupTree(); | |
501 } | |
502 }; | |
503 | |
504 SINGLE_AND_MULTI_THREAD_TEST_F( | |
505 LayerTreeHostOcclusionTestOcclusionBlurFilter); | |
506 | |
507 class LayerTreeHostOcclusionTestOcclusionCopyRequest | |
508 : public LayerTreeHostOcclusionTest { | |
509 public: | |
510 static void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {} | |
511 | |
512 void SetupTree() override { | |
513 // If the child layer has copy request, and is below child2, | |
514 // then child should not inherit occlusion from outside its subtree. | |
515 // The child layer will still receive occlusion from inside, and | |
516 // the root layer will recive occlusion from child. | |
517 SetLayerPropertiesForTesting( | |
518 root_.get(), NULL, identity_matrix_, | |
519 gfx::PointF(), gfx::Size(100, 100), true); | |
520 SetLayerPropertiesForTesting( | |
521 child_.get(), root_.get(), identity_matrix_, | |
522 gfx::PointF(), gfx::Size(75, 75), true); | |
523 SetLayerPropertiesForTesting( | |
524 grand_child_.get(), child_.get(), identity_matrix_, | |
525 gfx::PointF(), gfx::Size(75, 50), true); | |
526 SetLayerPropertiesForTesting( | |
527 child2_.get(), root_.get(), identity_matrix_, | |
528 gfx::PointF(0.f, 25.f), gfx::Size(75, 75), true); | |
529 | |
530 child_->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest( | |
531 base::Bind(&CopyOutputCallback))); | |
532 EXPECT_TRUE(child_->HasCopyRequest()); | |
533 | |
534 child_->set_expected_occlusion(gfx::Rect(0, 0, 75, 50)); | |
535 root_->set_expected_occlusion(gfx::Rect(0, 0, 75, 100)); | |
536 | |
537 layer_tree_host()->SetRootLayer(root_); | |
538 LayerTreeTest::SetupTree(); | |
539 } | |
540 }; | |
541 | |
542 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionCopyRequest); | |
543 | |
544 class LayerTreeHostOcclusionTestOcclusionReplica | |
545 : public LayerTreeHostOcclusionTest { | |
546 public: | |
547 void SetupTree() override { | |
548 // If the child layer has copy request, and is below child2, | |
549 // then child should not inherit occlusion from outside its subtree. | |
550 // The child layer will still receive occlusion from inside, and | |
551 // the root layer will recive occlusion from child. | |
552 SetLayerPropertiesForTesting( | |
553 root_.get(), NULL, identity_matrix_, | |
554 gfx::PointF(), gfx::Size(100, 100), true); | |
555 SetLayerPropertiesForTesting( | |
556 child_.get(), root_.get(), identity_matrix_, | |
557 gfx::PointF(), gfx::Size(75, 75), true); | |
558 SetLayerPropertiesForTesting( | |
559 grand_child_.get(), child_.get(), identity_matrix_, | |
560 gfx::PointF(), gfx::Size(75, 50), true); | |
561 SetLayerPropertiesForTesting( | |
562 child2_.get(), root_.get(), identity_matrix_, | |
563 gfx::PointF(0.f, 25.f), gfx::Size(75, 75), true); | |
564 | |
565 scoped_refptr<Layer> replica_layer(Layer::Create()); | |
566 child_->SetReplicaLayer(replica_layer.get()); | |
567 EXPECT_TRUE(child_->has_replica()); | |
568 | |
569 child_->set_expected_occlusion(gfx::Rect(0, 0, 75, 50)); | |
570 root_->set_expected_occlusion(gfx::Rect(0, 0, 75, 100)); | |
571 | |
572 layer_tree_host()->SetRootLayer(root_); | |
573 LayerTreeTest::SetupTree(); | |
574 } | |
575 }; | |
576 | |
577 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionReplica); | |
578 | |
579 class LayerTreeHostOcclusionTestManySurfaces | |
580 : public LayerTreeHostOcclusionTest { | |
581 public: | |
582 void SetupTree() override { | |
583 // We create enough RenderSurfaces that it will trigger Vector reallocation | |
584 // while computing occlusion. | |
585 std::vector<scoped_refptr<TestLayer>> layers; | |
586 int num_surfaces = 200; | |
587 int root_width = 400; | |
588 int root_height = 400; | |
589 | |
590 for (int i = 0; i < num_surfaces; ++i) { | |
591 layers.push_back(TestLayer::Create()); | |
592 if (i == 0) { | |
593 SetLayerPropertiesForTesting( | |
594 layers.back().get(), NULL, identity_matrix_, | |
595 gfx::PointF(0.f, 0.f), | |
596 gfx::Size(root_width, root_height), true); | |
597 } else { | |
598 SetLayerPropertiesForTesting( | |
599 layers.back().get(), layers[layers.size() - 2].get(), | |
600 identity_matrix_, | |
601 gfx::PointF(1.f, 1.f), | |
602 gfx::Size(root_width-i, root_height-i), true); | |
603 layers.back()->SetForceRenderSurface(true); | |
604 } | |
605 } | |
606 | |
607 for (int i = 1; i < num_surfaces; ++i) { | |
608 scoped_refptr<TestLayer> child = TestLayer::Create(); | |
609 SetLayerPropertiesForTesting( | |
610 child.get(), layers[i].get(), identity_matrix_, | |
611 gfx::PointF(0.f, 0.f), gfx::Size(root_width, root_height), false); | |
612 } | |
613 | |
614 for (int i = 0; i < num_surfaces-1; ++i) { | |
615 gfx::Rect expected_occlusion(1, 1, root_width-i-1, root_height-i-1); | |
616 layers[i]->set_expected_occlusion(expected_occlusion); | |
617 } | |
618 | |
619 layer_tree_host()->SetRootLayer(layers[0]); | |
620 LayerTreeTest::SetupTree(); | |
621 } | |
622 }; | |
623 | |
624 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestManySurfaces); | |
625 | 268 |
626 } // namespace | 269 } // namespace |
627 } // namespace cc | 270 } // namespace cc |
OLD | NEW |