OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "compositor_state_deserializer.h" | |
6 | |
7 #include "base/memory/ptr_util.h" | |
8 #include "base/run_loop.h" | |
9 #include "cc/animation/animation_host.h" | |
10 #include "cc/blimp/client_picture_cache.h" | |
11 #include "cc/blimp/compositor_proto_state.h" | |
12 #include "cc/blimp/layer_tree_host_remote.h" | |
13 #include "cc/layers/content_layer_client.h" | |
14 #include "cc/layers/picture_layer.h" | |
15 #include "cc/layers/solid_color_scrollbar_layer.h" | |
16 #include "cc/playback/display_item_list.h" | |
17 #include "cc/playback/drawing_display_item.h" | |
18 #include "cc/proto/compositor_message.pb.h" | |
19 #include "cc/test/fake_image_serialization_processor.h" | |
20 #include "cc/test/fake_layer_tree_host.h" | |
21 #include "cc/test/fake_layer_tree_host_client.h" | |
22 #include "cc/test/fake_proxy.h" | |
23 #include "cc/test/fake_remote_compositor_bridge.h" | |
24 #include "cc/test/remote_client_layer_factory.h" | |
25 #include "cc/test/remote_compositor_test.h" | |
26 #include "cc/test/serialization_test_utils.h" | |
27 #include "cc/test/skia_common.h" | |
28 #include "cc/test/stub_layer_tree_host_client.h" | |
29 #include "cc/test/test_task_graph_runner.h" | |
30 #include "cc/trees/layer_tree_host_common.h" | |
31 #include "testing/gtest/include/gtest/gtest.h" | |
32 #include "third_party/skia/include/core/SkPictureRecorder.h" | |
33 | |
34 namespace cc { | |
35 namespace { | |
36 | |
37 class FakeContentLayerClient : public ContentLayerClient { | |
38 public: | |
39 FakeContentLayerClient(scoped_refptr<DisplayItemList> display_list, | |
40 gfx::Rect recorded_viewport) | |
41 : display_list_(std::move(display_list)), | |
42 recorded_viewport_(recorded_viewport) {} | |
43 ~FakeContentLayerClient() override {} | |
44 | |
45 // ContentLayerClient implementation. | |
46 gfx::Rect PaintableRegion() override { return recorded_viewport_; } | |
47 scoped_refptr<DisplayItemList> PaintContentsToDisplayList( | |
48 PaintingControlSetting painting_status) override { | |
49 return display_list_; | |
50 } | |
51 bool FillsBoundsCompletely() const override { return false; } | |
52 size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } | |
53 | |
54 private: | |
55 scoped_refptr<DisplayItemList> display_list_; | |
56 gfx::Rect recorded_viewport_; | |
57 }; | |
58 | |
59 class CompositorStateDeserializerTest : public RemoteCompositorTest { | |
60 public: | |
61 void VerifyTreesAreIdentical() { | |
62 VerifySerializedTreesAreIdentical( | |
63 layer_tree_host_remote_->GetLayerTree(), | |
64 layer_tree_host_in_process_->GetLayerTree(), | |
65 compositor_state_deserializer_.get()); | |
66 } | |
67 }; | |
68 | |
69 TEST_F(CompositorStateDeserializerTest, BasicSync) { | |
70 // Set up a tree with a single node. | |
71 scoped_refptr<Layer> root_layer = Layer::Create(); | |
72 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); | |
73 | |
74 // Synchronize State and verify. | |
75 base::RunLoop().RunUntilIdle(); | |
76 VerifyTreesAreIdentical(); | |
77 | |
78 // Swap the root layer. | |
79 scoped_refptr<Layer> new_root_layer = Layer::Create(); | |
80 new_root_layer->AddChild(Layer::Create()); | |
81 new_root_layer->AddChild(Layer::Create()); | |
82 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(new_root_layer); | |
83 | |
84 // Synchronize State and verify. | |
85 base::RunLoop().RunUntilIdle(); | |
86 VerifyTreesAreIdentical(); | |
87 // Verify that we are no longer tracking the destroyed layer on the client. | |
88 EXPECT_EQ( | |
89 compositor_state_deserializer_->GetLayerForEngineId(root_layer->id()), | |
90 nullptr); | |
91 | |
92 // Remove the root layer to change to a null tree. | |
93 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(nullptr); | |
94 | |
95 // Synchronize State and verify. | |
96 base::RunLoop().RunUntilIdle(); | |
97 VerifyTreesAreIdentical(); | |
98 } | |
99 | |
100 TEST_F(CompositorStateDeserializerTest, ViewportLayers) { | |
101 scoped_refptr<Layer> root_layer = Layer::Create(); | |
102 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); | |
103 | |
104 scoped_refptr<Layer> overscroll_elasticity_layer = Layer::Create(); | |
105 scoped_refptr<Layer> inner_viewport_scroll_layer = Layer::Create(); | |
106 scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create(); | |
107 scoped_refptr<Layer> page_scale_layer = Layer::Create(); | |
108 layer_tree_host_remote_->GetLayerTree()->RegisterViewportLayers( | |
109 overscroll_elasticity_layer, page_scale_layer, | |
110 inner_viewport_scroll_layer, outer_viewport_scroll_layer); | |
111 | |
112 root_layer->AddChild(overscroll_elasticity_layer); | |
113 overscroll_elasticity_layer->AddChild(page_scale_layer); | |
114 page_scale_layer->AddChild(inner_viewport_scroll_layer); | |
115 inner_viewport_scroll_layer->AddChild(outer_viewport_scroll_layer); | |
116 | |
117 // Synchronize State and verify. | |
118 base::RunLoop().RunUntilIdle(); | |
119 VerifyTreesAreIdentical(); | |
120 } | |
121 | |
122 TEST_F(CompositorStateDeserializerTest, ScrollClipAndMaskLayers) { | |
123 /* root -- A---C---D | |
124 / | \ | |
125 / | E(MaskLayer) | |
126 / ------B */ | |
127 scoped_refptr<Layer> root_layer = Layer::Create(); | |
128 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); | |
129 | |
130 scoped_refptr<Layer> layer_a = Layer::Create(); | |
131 scoped_refptr<Layer> layer_b = Layer::Create(); | |
132 scoped_refptr<Layer> layer_c = Layer::Create(); | |
133 scoped_refptr<Layer> layer_d = Layer::Create(); | |
134 scoped_refptr<Layer> layer_e = Layer::Create(); | |
135 | |
136 root_layer->AddChild(layer_a); | |
137 root_layer->AddChild(layer_b); | |
138 layer_a->AddChild(layer_c); | |
139 layer_c->AddChild(layer_d); | |
140 | |
141 layer_a->SetMaskLayer(layer_e.get()); | |
142 layer_c->SetScrollParent(layer_b.get()); | |
143 layer_c->SetScrollClipLayerId(root_layer->id()); | |
144 layer_d->SetClipParent(layer_a.get()); | |
145 | |
146 // Synchronize State and verify. | |
147 base::RunLoop().RunUntilIdle(); | |
148 VerifyTreesAreIdentical(); | |
149 } | |
150 | |
151 TEST_F(CompositorStateDeserializerTest, ReconcileScrollAndScale) { | |
152 scoped_refptr<Layer> root_layer = Layer::Create(); | |
153 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); | |
154 | |
155 // Set scroll offset. | |
156 scoped_refptr<Layer> scroll_layer = Layer::Create(); | |
157 root_layer->AddChild(scroll_layer); | |
158 gfx::ScrollOffset engine_offset(4, 3); | |
159 scroll_layer->SetScrollOffset(engine_offset); | |
160 | |
161 // Set page scale. | |
162 float engine_page_scale = 0.5f; | |
163 layer_tree_host_remote_->GetLayerTree()->SetPageScaleFactorAndLimits( | |
164 engine_page_scale, 1.0, 1.0); | |
165 | |
166 // Synchronize State and verify that the engine values are used. | |
167 base::RunLoop().RunUntilIdle(); | |
168 VerifyTreesAreIdentical(); | |
169 Layer* client_scroll_layer = | |
170 compositor_state_deserializer_->GetLayerForEngineId(scroll_layer->id()); | |
171 EXPECT_EQ(engine_page_scale, | |
172 layer_tree_host_in_process_->GetLayerTree()->page_scale_factor()); | |
173 EXPECT_EQ(engine_offset, client_scroll_layer->scroll_offset()); | |
174 | |
175 // Now send some updates from the impl thread. | |
176 ScrollAndScaleSet scroll_and_scale_set; | |
177 | |
178 gfx::ScrollOffset offset_from_impl_thread(10, 3); | |
179 gfx::ScrollOffset scroll_delta = | |
180 offset_from_impl_thread - client_scroll_layer->scroll_offset(); | |
181 LayerTreeHostCommon::ScrollUpdateInfo scroll_update; | |
182 scroll_update.layer_id = client_scroll_layer->id(); | |
183 scroll_update.scroll_delta = gfx::ScrollOffsetToFlooredVector2d(scroll_delta); | |
184 scroll_and_scale_set.scrolls.push_back(scroll_update); | |
185 | |
186 float page_scale_from_impl_side = 3.2f; | |
187 float page_scale_delta = | |
188 page_scale_from_impl_side / | |
189 layer_tree_host_in_process_->GetLayerTree()->page_scale_factor(); | |
190 scroll_and_scale_set.page_scale_delta = page_scale_delta; | |
191 | |
192 layer_tree_host_in_process_->ApplyScrollAndScale(&scroll_and_scale_set); | |
193 | |
194 // The values on the client should have been forced to retain the original | |
195 // engine value. | |
196 EXPECT_EQ(engine_page_scale, | |
197 layer_tree_host_in_process_->GetLayerTree()->page_scale_factor()); | |
198 EXPECT_EQ(engine_offset, client_scroll_layer->scroll_offset()); | |
199 | |
200 // Now pull the deltas from the client onto the engine, this should result | |
201 // in an aborted commit. | |
202 proto::ClientStateUpdate client_state_update; | |
203 compositor_state_deserializer_->PullClientStateUpdate(&client_state_update); | |
204 | |
205 // Send the reflected main frame state to the client layer tree host. | |
206 compositor_state_deserializer_->SendUnappliedDeltasToLayerTreeHost(); | |
207 const ReflectedMainFrameState* reflected_state = | |
208 layer_tree_host_in_process_->reflected_main_frame_state_for_testing(); | |
209 EXPECT_EQ(reflected_state->scrolls.size(), 1u); | |
210 EXPECT_EQ(reflected_state->scrolls[0].layer_id, client_scroll_layer->id()); | |
211 EXPECT_EQ(reflected_state->scrolls[0].scroll_delta, | |
212 gfx::ScrollOffsetToVector2dF(scroll_delta)); | |
213 EXPECT_EQ(reflected_state->page_scale_delta, page_scale_delta); | |
214 | |
215 layer_tree_host_remote_->ApplyStateUpdateFromClient(client_state_update); | |
216 | |
217 // Inform the deserializer that the updates were applied on the engine. | |
218 // This should pre-emptively apply the deltas on the client. | |
219 compositor_state_deserializer_->DidApplyStateUpdatesOnEngine(); | |
220 EXPECT_EQ(page_scale_from_impl_side, | |
221 layer_tree_host_in_process_->GetLayerTree()->page_scale_factor()); | |
222 EXPECT_EQ(offset_from_impl_thread, client_scroll_layer->scroll_offset()); | |
223 | |
224 // Now update the scroll offset on the engine, and ensure that the value is | |
225 // used on the client. | |
226 gfx::ScrollOffset new_engine_offset(10, 20); | |
227 scroll_layer->SetScrollOffset(new_engine_offset); | |
228 | |
229 base::RunLoop().RunUntilIdle(); | |
230 VerifyTreesAreIdentical(); | |
231 EXPECT_EQ(page_scale_from_impl_side, | |
232 layer_tree_host_in_process_->GetLayerTree()->page_scale_factor()); | |
233 EXPECT_EQ(new_engine_offset, client_scroll_layer->scroll_offset()); | |
234 } | |
235 | |
236 TEST_F(CompositorStateDeserializerTest, PropertyTreesAreIdentical) { | |
237 // Override the LayerFactory. This is necessary to ensure the layer ids | |
238 // tracked in PropertyTrees on the engine and client are identical. | |
239 compositor_state_deserializer_->SetLayerFactoryForTesting( | |
240 base::MakeUnique<RemoteClientLayerFactory>()); | |
241 | |
242 scoped_refptr<Layer> root_layer = Layer::Create(); | |
243 root_layer->SetBounds(gfx::Size(10, 10)); | |
244 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); | |
245 | |
246 scoped_refptr<Layer> child1 = Layer::Create(); | |
247 root_layer->AddChild(child1); | |
248 gfx::Transform transform; | |
249 transform.Translate(gfx::Vector2dF(5, 4)); | |
250 child1->SetTransform(transform); | |
251 child1->SetMasksToBounds(true); | |
252 | |
253 scoped_refptr<Layer> child2 = Layer::Create(); | |
254 root_layer->AddChild(child2); | |
255 child2->SetBounds(gfx::Size(5, 5)); | |
256 child2->SetScrollOffset(gfx::ScrollOffset(3, 4)); | |
257 child2->SetScrollParent(child1.get()); | |
258 child2->SetUserScrollable(true, true); | |
259 | |
260 scoped_refptr<Layer> grandchild11 = Layer::Create(); | |
261 child1->AddChild(grandchild11); | |
262 grandchild11->SetClipParent(root_layer.get()); | |
263 | |
264 scoped_refptr<Layer> grandchild21 = Layer::Create(); | |
265 child2->AddChild(grandchild21); | |
266 grandchild21->SetScrollClipLayerId(child1->id()); | |
267 grandchild21->SetOpacity(0.5); | |
268 | |
269 // Synchronize State and verify. | |
270 base::RunLoop().RunUntilIdle(); | |
271 VerifyTreesAreIdentical(); | |
272 EXPECT_EQ(root_layer->id(), layer_tree_host_in_process_->root_layer()->id()); | |
273 | |
274 // Sanity test to ensure that the PropertyTrees generated from the Layers on | |
275 // the client and engine are identical. | |
276 layer_tree_host_remote_->GetLayerTree()->BuildPropertyTreesForTesting(); | |
277 PropertyTrees* engine_property_trees = | |
278 layer_tree_host_remote_->GetLayerTree()->property_trees(); | |
279 | |
280 layer_tree_host_in_process_->BuildPropertyTreesForTesting(); | |
281 PropertyTrees* client_property_trees = | |
282 layer_tree_host_in_process_->property_trees(); | |
283 | |
284 EXPECT_EQ(*engine_property_trees, *client_property_trees); | |
285 } | |
286 | |
287 TEST_F(CompositorStateDeserializerTest, SolidColorScrollbarLayer) { | |
288 scoped_refptr<Layer> root_layer = Layer::Create(); | |
289 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); | |
290 | |
291 scoped_refptr<Layer> child_layer1 = Layer::Create(); | |
292 root_layer->AddChild(child_layer1); | |
293 scoped_refptr<SolidColorScrollbarLayer> scroll_layer1 = | |
294 SolidColorScrollbarLayer::Create(ScrollbarOrientation::HORIZONTAL, 20, 5, | |
295 true, 3); | |
296 scroll_layer1->SetScrollLayer(child_layer1->id()); | |
297 child_layer1->AddChild(scroll_layer1); | |
298 | |
299 scoped_refptr<SolidColorScrollbarLayer> scroll_layer2 = | |
300 SolidColorScrollbarLayer::Create(ScrollbarOrientation::VERTICAL, 2, 9, | |
301 false, 3); | |
302 root_layer->AddChild(scroll_layer2); | |
303 scoped_refptr<Layer> child_layer2 = Layer::Create(); | |
304 scroll_layer2->AddChild(child_layer2); | |
305 scroll_layer2->SetScrollLayer(child_layer2->id()); | |
306 | |
307 // Synchronize State and verify. | |
308 base::RunLoop().RunUntilIdle(); | |
309 VerifyTreesAreIdentical(); | |
310 | |
311 // Verify Scrollbar layers. | |
312 SolidColorScrollbarLayer* client_scroll_layer1 = | |
313 static_cast<SolidColorScrollbarLayer*>( | |
314 compositor_state_deserializer_->GetLayerForEngineId( | |
315 scroll_layer1->id())); | |
316 EXPECT_EQ(client_scroll_layer1->ScrollLayerId(), | |
317 compositor_state_deserializer_ | |
318 ->GetLayerForEngineId(scroll_layer1->ScrollLayerId()) | |
319 ->id()); | |
320 EXPECT_EQ(client_scroll_layer1->orientation(), scroll_layer1->orientation()); | |
321 | |
322 SolidColorScrollbarLayer* client_scroll_layer2 = | |
323 static_cast<SolidColorScrollbarLayer*>( | |
324 compositor_state_deserializer_->GetLayerForEngineId( | |
325 scroll_layer2->id())); | |
326 EXPECT_EQ(client_scroll_layer2->ScrollLayerId(), | |
327 compositor_state_deserializer_ | |
328 ->GetLayerForEngineId(scroll_layer2->ScrollLayerId()) | |
329 ->id()); | |
330 EXPECT_EQ(client_scroll_layer2->orientation(), scroll_layer2->orientation()); | |
331 } | |
332 | |
333 TEST_F(CompositorStateDeserializerTest, PictureLayer) { | |
334 scoped_refptr<Layer> root_layer = Layer::Create(); | |
335 root_layer->SetBounds(gfx::Size(10, 10)); | |
336 root_layer->SetIsDrawable(true); | |
337 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); | |
338 | |
339 gfx::Size layer_size = gfx::Size(5, 5); | |
340 | |
341 gfx::PointF offset(2.f, 3.f); | |
342 SkPictureRecorder recorder; | |
343 SkCanvas* canvas; | |
344 SkPaint red_paint; | |
345 red_paint.setColor(SK_ColorRED); | |
346 canvas = recorder.beginRecording(SkRect::MakeXYWH( | |
347 offset.x(), offset.y(), layer_size.width(), layer_size.height())); | |
348 canvas->translate(offset.x(), offset.y()); | |
349 canvas->drawRectCoords(0.f, 0.f, 4.f, 4.f, red_paint); | |
350 sk_sp<SkPicture> test_picture = recorder.finishRecordingAsPicture(); | |
351 | |
352 DisplayItemListSettings settings; | |
353 settings.use_cached_picture = false; | |
354 scoped_refptr<DisplayItemList> display_list = | |
355 DisplayItemList::Create(settings); | |
356 const gfx::Rect visual_rect(0, 0, 42, 42); | |
357 display_list->CreateAndAppendDrawingItem<DrawingDisplayItem>(visual_rect, | |
358 test_picture); | |
359 display_list->Finalize(); | |
360 FakeContentLayerClient content_client(display_list, gfx::Rect(layer_size)); | |
361 | |
362 scoped_refptr<PictureLayer> picture_layer = | |
363 PictureLayer::Create(&content_client); | |
364 picture_layer->SetBounds(layer_size); | |
365 picture_layer->SetIsDrawable(true); | |
366 root_layer->AddChild(picture_layer); | |
367 | |
368 // Synchronize State and verify. | |
369 base::RunLoop().RunUntilIdle(); | |
370 VerifyTreesAreIdentical(); | |
371 | |
372 // Verify PictureLayer. | |
373 PictureLayer* client_picture_layer = static_cast<PictureLayer*>( | |
374 compositor_state_deserializer_->GetLayerForEngineId(picture_layer->id())); | |
375 scoped_refptr<DisplayItemList> client_display_list = | |
376 client_picture_layer->client()->PaintContentsToDisplayList( | |
377 ContentLayerClient::PaintingControlSetting::PAINTING_BEHAVIOR_NORMAL); | |
378 EXPECT_TRUE(AreDisplayListDrawingResultsSame( | |
379 gfx::Rect(layer_size), display_list.get(), client_display_list.get())); | |
380 | |
381 // Now attach new layer with the same DisplayList. | |
382 scoped_refptr<PictureLayer> picture_layer2 = | |
383 PictureLayer::Create(&content_client); | |
384 picture_layer2->SetBounds(layer_size); | |
385 picture_layer2->SetIsDrawable(true); | |
386 root_layer->AddChild(picture_layer2); | |
387 | |
388 // Synchronize State and verify. | |
389 base::RunLoop().RunUntilIdle(); | |
390 VerifyTreesAreIdentical(); | |
391 | |
392 // Verify PictureLayer2. | |
393 PictureLayer* client_picture_layer2 = static_cast<PictureLayer*>( | |
394 compositor_state_deserializer_->GetLayerForEngineId( | |
395 picture_layer2->id())); | |
396 scoped_refptr<DisplayItemList> client_display_list2 = | |
397 client_picture_layer2->client()->PaintContentsToDisplayList( | |
398 ContentLayerClient::PaintingControlSetting::PAINTING_BEHAVIOR_NORMAL); | |
399 EXPECT_TRUE(AreDisplayListDrawingResultsSame( | |
400 gfx::Rect(layer_size), display_list.get(), client_display_list2.get())); | |
401 } | |
402 | |
403 } // namespace | |
404 } // namespace cc | |
OLD | NEW |