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/run_loop.h" |
| 8 #include "cc/animation/animation_host.h" |
| 9 #include "cc/blimp/compositor_proto_state.h" |
| 10 #include "cc/blimp/compositor_state_deserializer_client.h" |
| 11 #include "cc/blimp/layer_tree_host_remote.h" |
| 12 #include "cc/proto/compositor_message.pb.h" |
| 13 #include "cc/test/fake_layer_tree_host.h" |
| 14 #include "cc/test/fake_layer_tree_host_client.h" |
| 15 #include "cc/test/fake_remote_compositor_bridge.h" |
| 16 #include "cc/test/remote_client_layer_factory.h" |
| 17 #include "cc/test/stub_layer_tree_host_client.h" |
| 18 #include "cc/test/test_task_graph_runner.h" |
| 19 #include "cc/trees/layer_tree_host_common.h" |
| 20 #include "testing/gtest/include/gtest/gtest.h" |
| 21 |
| 22 namespace cc { |
| 23 namespace { |
| 24 |
| 25 #define EXPECT_LAYERS_EQ(engine_layer_id, client_layer) \ |
| 26 EXPECT_EQ( \ |
| 27 compositor_state_deserializer_->GetLayerForEngineId(engine_layer_id), \ |
| 28 client_layer); |
| 29 |
| 30 class RemoteCompositorBridgeForTest : public FakeRemoteCompositorBridge { |
| 31 public: |
| 32 using ProtoFrameCallback = base::Callback<void( |
| 33 std::unique_ptr<CompositorProtoState> compositor_proto_state)>; |
| 34 |
| 35 RemoteCompositorBridgeForTest( |
| 36 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| 37 ProtoFrameCallback proto_frame_callback) |
| 38 : FakeRemoteCompositorBridge(main_task_runner), |
| 39 proto_frame_callback_(proto_frame_callback) {} |
| 40 |
| 41 ~RemoteCompositorBridgeForTest() override = default; |
| 42 |
| 43 void ProcessCompositorStateUpdate( |
| 44 std::unique_ptr<CompositorProtoState> compositor_proto_state) override { |
| 45 proto_frame_callback_.Run(std::move(compositor_proto_state)); |
| 46 } |
| 47 |
| 48 private: |
| 49 ProtoFrameCallback proto_frame_callback_; |
| 50 }; |
| 51 |
| 52 class CompositorStateDeserializerTest |
| 53 : public testing::Test, |
| 54 public CompositorStateDeserializerClient { |
| 55 public: |
| 56 void SetUp() override { |
| 57 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner = |
| 58 base::ThreadTaskRunnerHandle::Get(); |
| 59 |
| 60 // Engine side setup. |
| 61 LayerTreeHostRemote::InitParams params; |
| 62 params.client = &layer_tree_host_client_remote_; |
| 63 params.main_task_runner = main_task_runner; |
| 64 params.animation_host = AnimationHost::CreateMainInstance(); |
| 65 params.remote_compositor_bridge = |
| 66 base::MakeUnique<RemoteCompositorBridgeForTest>( |
| 67 main_task_runner, |
| 68 base::Bind( |
| 69 &CompositorStateDeserializerTest::ProcessCompositorStateUpdate, |
| 70 base::Unretained(this))); |
| 71 LayerTreeSettings settings; |
| 72 params.settings = &settings; |
| 73 |
| 74 layer_tree_host_remote_ = base::MakeUnique<LayerTreeHostRemote>(¶ms); |
| 75 |
| 76 // Client side setup. |
| 77 layer_tree_host_in_process_ = FakeLayerTreeHost::Create( |
| 78 &layer_tree_host_client_client_, &task_graph_runner_); |
| 79 compositor_state_deserializer_ = |
| 80 base::MakeUnique<CompositorStateDeserializer>( |
| 81 layer_tree_host_in_process_.get(), |
| 82 base::Bind(&CompositorStateDeserializerTest::LayerScrolled, |
| 83 base::Unretained(this)), |
| 84 this); |
| 85 } |
| 86 |
| 87 void TearDown() override { |
| 88 layer_tree_host_remote_ = nullptr; |
| 89 compositor_state_deserializer_ = nullptr; |
| 90 layer_tree_host_in_process_ = nullptr; |
| 91 } |
| 92 |
| 93 void ProcessCompositorStateUpdate( |
| 94 std::unique_ptr<CompositorProtoState> compositor_proto_state) { |
| 95 // Immediately deserialize the state update. |
| 96 compositor_state_deserializer_->DeserializeCompositorUpdate( |
| 97 compositor_proto_state->compositor_message->layer_tree_host()); |
| 98 } |
| 99 |
| 100 // CompositorStateDeserializer implementation. |
| 101 bool ShouldRetainClientScroll(int engine_layer_id, |
| 102 const gfx::ScrollOffset& new_offset) override { |
| 103 return should_retain_client_scroll_; |
| 104 } |
| 105 bool ShouldRetainClientPageScale(float new_page_scale) override { |
| 106 return should_retain_client_scale_; |
| 107 } |
| 108 |
| 109 void LayerScrolled(int engine_layer_id) {} |
| 110 |
| 111 void VerifyTreesAreIdentical() { |
| 112 LayerTree* engine_layer_tree = layer_tree_host_remote_->GetLayerTree(); |
| 113 LayerTree* client_layer_tree = layer_tree_host_in_process_->GetLayerTree(); |
| 114 |
| 115 if (engine_layer_tree->root_layer()) { |
| 116 LayerTreeHostCommon::CallFunctionForEveryLayer( |
| 117 engine_layer_tree, [this](Layer* engine_layer) { |
| 118 VerifyLayersAreIdentical( |
| 119 engine_layer, |
| 120 compositor_state_deserializer_->GetLayerForEngineId( |
| 121 engine_layer->id())); |
| 122 }); |
| 123 } else { |
| 124 EXPECT_EQ(layer_tree_host_in_process_->GetLayerTree()->root_layer(), |
| 125 nullptr); |
| 126 } |
| 127 |
| 128 // Viewport layers. |
| 129 // Overscroll Elasticty Layer. |
| 130 Layer* client_overscroll_elasticity_layer = |
| 131 client_layer_tree->overscroll_elasticity_layer(); |
| 132 if (engine_layer_tree->overscroll_elasticity_layer()) { |
| 133 int engine_overscroll_elasticity_layer_id = |
| 134 engine_layer_tree->overscroll_elasticity_layer()->id(); |
| 135 |
| 136 EXPECT_LAYERS_EQ(engine_overscroll_elasticity_layer_id, |
| 137 client_overscroll_elasticity_layer); |
| 138 } else { |
| 139 EXPECT_EQ(client_overscroll_elasticity_layer, nullptr); |
| 140 } |
| 141 |
| 142 // PageScale Layer. |
| 143 Layer* client_page_scale_layer = client_layer_tree->page_scale_layer(); |
| 144 if (engine_layer_tree->page_scale_layer()) { |
| 145 int engine_page_scale_layer_id = |
| 146 engine_layer_tree->page_scale_layer()->id(); |
| 147 |
| 148 EXPECT_LAYERS_EQ(engine_page_scale_layer_id, client_page_scale_layer); |
| 149 } else { |
| 150 EXPECT_EQ(client_page_scale_layer, nullptr); |
| 151 } |
| 152 |
| 153 // InnerViewportScroll Layer. |
| 154 Layer* client_inner_viewport_layer = |
| 155 client_layer_tree->inner_viewport_scroll_layer(); |
| 156 if (engine_layer_tree->inner_viewport_scroll_layer()) { |
| 157 int engine_inner_viewport_layer_id = |
| 158 engine_layer_tree->inner_viewport_scroll_layer()->id(); |
| 159 |
| 160 EXPECT_LAYERS_EQ(engine_inner_viewport_layer_id, |
| 161 client_inner_viewport_layer); |
| 162 } else { |
| 163 EXPECT_EQ(client_inner_viewport_layer, nullptr); |
| 164 } |
| 165 |
| 166 // OuterViewportScroll Layer. |
| 167 Layer* client_outer_viewport_layer = |
| 168 client_layer_tree->outer_viewport_scroll_layer(); |
| 169 if (engine_layer_tree->outer_viewport_scroll_layer()) { |
| 170 int engine_outer_viewport_layer_id = |
| 171 engine_layer_tree->outer_viewport_scroll_layer()->id(); |
| 172 |
| 173 EXPECT_LAYERS_EQ(engine_outer_viewport_layer_id, |
| 174 client_outer_viewport_layer); |
| 175 } else { |
| 176 EXPECT_EQ(client_outer_viewport_layer, nullptr); |
| 177 } |
| 178 } |
| 179 |
| 180 void VerifyLayersAreIdentical(Layer* engine_layer, Layer* client_layer) { |
| 181 ASSERT_NE(client_layer, nullptr); |
| 182 |
| 183 LayerTree* client_layer_tree = layer_tree_host_in_process_->GetLayerTree(); |
| 184 EXPECT_EQ(client_layer_tree, client_layer->GetLayerTree()); |
| 185 |
| 186 // Parent. |
| 187 if (engine_layer->parent()) { |
| 188 int engine_parent_id = engine_layer->parent()->id(); |
| 189 EXPECT_LAYERS_EQ(engine_parent_id, client_layer->parent()); |
| 190 } else { |
| 191 EXPECT_EQ(client_layer->parent(), nullptr); |
| 192 } |
| 193 |
| 194 // Mask Layers. |
| 195 if (engine_layer->mask_layer()) { |
| 196 int engine_mask_layer_id = engine_layer->mask_layer()->id(); |
| 197 EXPECT_LAYERS_EQ(engine_mask_layer_id, client_layer->mask_layer()); |
| 198 } else { |
| 199 EXPECT_EQ(client_layer->mask_layer(), nullptr); |
| 200 } |
| 201 |
| 202 // Scroll parent. |
| 203 if (engine_layer->scroll_parent()) { |
| 204 int engine_scroll_parent_id = engine_layer->scroll_parent()->id(); |
| 205 EXPECT_LAYERS_EQ(engine_scroll_parent_id, client_layer->scroll_parent()); |
| 206 } else { |
| 207 EXPECT_EQ(client_layer->scroll_parent(), nullptr); |
| 208 } |
| 209 |
| 210 // Clip parent. |
| 211 if (engine_layer->clip_parent()) { |
| 212 int engine_clip_parent_id = engine_layer->clip_parent()->id(); |
| 213 EXPECT_LAYERS_EQ(engine_clip_parent_id, client_layer->clip_parent()); |
| 214 } else { |
| 215 EXPECT_EQ(client_layer->clip_parent(), nullptr); |
| 216 } |
| 217 |
| 218 // Scroll-clip layer. |
| 219 if (engine_layer->scroll_clip_layer()) { |
| 220 int scroll_clip_id = engine_layer->scroll_clip_layer()->id(); |
| 221 EXPECT_LAYERS_EQ(scroll_clip_id, client_layer->scroll_clip_layer()); |
| 222 } else { |
| 223 EXPECT_EQ(client_layer->scroll_clip_layer(), nullptr); |
| 224 } |
| 225 } |
| 226 |
| 227 // Engine setup. |
| 228 std::unique_ptr<LayerTreeHostRemote> layer_tree_host_remote_; |
| 229 StubLayerTreeHostClient layer_tree_host_client_remote_; |
| 230 |
| 231 // Client setup. |
| 232 std::unique_ptr<FakeLayerTreeHost> layer_tree_host_in_process_; |
| 233 std::unique_ptr<CompositorStateDeserializer> compositor_state_deserializer_; |
| 234 FakeLayerTreeHostClient layer_tree_host_client_client_; |
| 235 TestTaskGraphRunner task_graph_runner_; |
| 236 |
| 237 bool should_retain_client_scroll_ = false; |
| 238 bool should_retain_client_scale_ = false; |
| 239 }; |
| 240 |
| 241 TEST_F(CompositorStateDeserializerTest, BasicSync) { |
| 242 // Set up a tree with a single node. |
| 243 scoped_refptr<Layer> root_layer = Layer::Create(); |
| 244 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); |
| 245 |
| 246 // Synchronize State and verify. |
| 247 base::RunLoop().RunUntilIdle(); |
| 248 VerifyTreesAreIdentical(); |
| 249 |
| 250 // Swap the root layer. |
| 251 scoped_refptr<Layer> new_root_layer = Layer::Create(); |
| 252 new_root_layer->AddChild(Layer::Create()); |
| 253 new_root_layer->AddChild(Layer::Create()); |
| 254 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(new_root_layer); |
| 255 |
| 256 // Synchronize State and verify. |
| 257 base::RunLoop().RunUntilIdle(); |
| 258 VerifyTreesAreIdentical(); |
| 259 // Verify that we are no longer tracking the destroyed layer on the client. |
| 260 EXPECT_EQ( |
| 261 compositor_state_deserializer_->GetLayerForEngineId(root_layer->id()), |
| 262 nullptr); |
| 263 |
| 264 // Remove the root layer to change to a null tree. |
| 265 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(nullptr); |
| 266 |
| 267 // Synchronize State and verify. |
| 268 base::RunLoop().RunUntilIdle(); |
| 269 VerifyTreesAreIdentical(); |
| 270 } |
| 271 |
| 272 TEST_F(CompositorStateDeserializerTest, ViewportLayers) { |
| 273 scoped_refptr<Layer> root_layer = Layer::Create(); |
| 274 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); |
| 275 |
| 276 scoped_refptr<Layer> overscroll_elasticity_layer = Layer::Create(); |
| 277 scoped_refptr<Layer> inner_viewport_scroll_layer = Layer::Create(); |
| 278 scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create(); |
| 279 scoped_refptr<Layer> page_scale_layer = Layer::Create(); |
| 280 layer_tree_host_remote_->GetLayerTree()->RegisterViewportLayers( |
| 281 overscroll_elasticity_layer, page_scale_layer, |
| 282 inner_viewport_scroll_layer, outer_viewport_scroll_layer); |
| 283 |
| 284 root_layer->AddChild(overscroll_elasticity_layer); |
| 285 overscroll_elasticity_layer->AddChild(page_scale_layer); |
| 286 page_scale_layer->AddChild(inner_viewport_scroll_layer); |
| 287 inner_viewport_scroll_layer->AddChild(outer_viewport_scroll_layer); |
| 288 |
| 289 // Synchronize State and verify. |
| 290 base::RunLoop().RunUntilIdle(); |
| 291 VerifyTreesAreIdentical(); |
| 292 } |
| 293 |
| 294 TEST_F(CompositorStateDeserializerTest, ScrollClipAndMaskLayers) { |
| 295 /* root -- A---C---D |
| 296 / | \ |
| 297 / | E(MaskLayer) |
| 298 / ------B */ |
| 299 scoped_refptr<Layer> root_layer = Layer::Create(); |
| 300 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); |
| 301 |
| 302 scoped_refptr<Layer> layer_a = Layer::Create(); |
| 303 scoped_refptr<Layer> layer_b = Layer::Create(); |
| 304 scoped_refptr<Layer> layer_c = Layer::Create(); |
| 305 scoped_refptr<Layer> layer_d = Layer::Create(); |
| 306 scoped_refptr<Layer> layer_e = Layer::Create(); |
| 307 |
| 308 root_layer->AddChild(layer_a); |
| 309 root_layer->AddChild(layer_b); |
| 310 layer_a->AddChild(layer_c); |
| 311 layer_c->AddChild(layer_d); |
| 312 |
| 313 layer_a->SetMaskLayer(layer_e.get()); |
| 314 layer_c->SetScrollParent(layer_b.get()); |
| 315 layer_c->SetScrollClipLayerId(root_layer->id()); |
| 316 layer_d->SetClipParent(layer_a.get()); |
| 317 |
| 318 // Synchronize State and verify. |
| 319 base::RunLoop().RunUntilIdle(); |
| 320 VerifyTreesAreIdentical(); |
| 321 } |
| 322 |
| 323 TEST_F(CompositorStateDeserializerTest, ReconcileScrollAndScale) { |
| 324 scoped_refptr<Layer> root_layer = Layer::Create(); |
| 325 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); |
| 326 |
| 327 // Set scroll offset. |
| 328 scoped_refptr<Layer> scroll_layer = Layer::Create(); |
| 329 root_layer->AddChild(scroll_layer); |
| 330 gfx::ScrollOffset engine_offset(4, 3); |
| 331 scroll_layer->SetScrollOffset(engine_offset); |
| 332 |
| 333 // Set page scale. |
| 334 float engine_page_scale = 0.5f; |
| 335 layer_tree_host_remote_->GetLayerTree()->SetPageScaleFactorAndLimits( |
| 336 engine_page_scale, 1.0, 1.0); |
| 337 |
| 338 // Synchronize State and verify that the engine values are used. |
| 339 base::RunLoop().RunUntilIdle(); |
| 340 VerifyTreesAreIdentical(); |
| 341 |
| 342 EXPECT_EQ(engine_page_scale, |
| 343 layer_tree_host_in_process_->GetLayerTree()->page_scale_factor()); |
| 344 EXPECT_EQ(engine_offset, compositor_state_deserializer_ |
| 345 ->GetLayerForEngineId(scroll_layer->id()) |
| 346 ->scroll_offset()); |
| 347 |
| 348 // Now reset the scroll offset and page scale and force-retain the client |
| 349 // values. |
| 350 gfx::ScrollOffset new_engine_offset(2, 2); |
| 351 scroll_layer->SetScrollOffset(new_engine_offset); |
| 352 float new_engine_page_scale = 0.8f; |
| 353 layer_tree_host_remote_->GetLayerTree()->SetPageScaleFactorAndLimits( |
| 354 new_engine_page_scale, 1.0, 1.0); |
| 355 should_retain_client_scroll_ = true; |
| 356 should_retain_client_scale_ = true; |
| 357 |
| 358 // Synchronize State and verify that the client values are retained. |
| 359 base::RunLoop().RunUntilIdle(); |
| 360 VerifyTreesAreIdentical(); |
| 361 |
| 362 EXPECT_EQ(engine_page_scale, |
| 363 layer_tree_host_in_process_->GetLayerTree()->page_scale_factor()); |
| 364 EXPECT_EQ(engine_offset, compositor_state_deserializer_ |
| 365 ->GetLayerForEngineId(scroll_layer->id()) |
| 366 ->scroll_offset()); |
| 367 } |
| 368 |
| 369 TEST_F(CompositorStateDeserializerTest, PropertyTreesAreIdentical) { |
| 370 // Override the LayerFactory. This is necessary to ensure the layer ids |
| 371 // tracked in PropertyTrees on the engine and client are identical. |
| 372 compositor_state_deserializer_->SetLayerFactoryForTesting( |
| 373 base::MakeUnique<RemoteClientLayerFactory>()); |
| 374 |
| 375 scoped_refptr<Layer> root_layer = Layer::Create(); |
| 376 root_layer->SetBounds(gfx::Size(10, 10)); |
| 377 layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer); |
| 378 |
| 379 scoped_refptr<Layer> child1 = Layer::Create(); |
| 380 root_layer->AddChild(child1); |
| 381 gfx::Transform transform; |
| 382 transform.Translate(gfx::Vector2dF(5, 4)); |
| 383 child1->SetTransform(transform); |
| 384 child1->SetMasksToBounds(true); |
| 385 |
| 386 scoped_refptr<Layer> child2 = Layer::Create(); |
| 387 root_layer->AddChild(child2); |
| 388 child2->SetBounds(gfx::Size(5, 5)); |
| 389 child2->SetScrollOffset(gfx::ScrollOffset(3, 4)); |
| 390 child2->SetScrollParent(child1.get()); |
| 391 child2->SetUserScrollable(true, true); |
| 392 |
| 393 scoped_refptr<Layer> grandchild11 = Layer::Create(); |
| 394 child1->AddChild(grandchild11); |
| 395 grandchild11->SetClipParent(root_layer.get()); |
| 396 |
| 397 scoped_refptr<Layer> grandchild21 = Layer::Create(); |
| 398 child2->AddChild(grandchild21); |
| 399 grandchild21->SetScrollClipLayerId(child1->id()); |
| 400 grandchild21->SetOpacity(0.5); |
| 401 |
| 402 // Synchronize State and verify. |
| 403 base::RunLoop().RunUntilIdle(); |
| 404 VerifyTreesAreIdentical(); |
| 405 EXPECT_EQ(root_layer->id(), layer_tree_host_in_process_->root_layer()->id()); |
| 406 |
| 407 // Sanity test to ensure that the PropertyTrees generated from the Layers on |
| 408 // the client and engine are identical. |
| 409 layer_tree_host_remote_->GetLayerTree()->BuildPropertyTreesForTesting(); |
| 410 PropertyTrees* engine_property_trees = |
| 411 layer_tree_host_remote_->GetLayerTree()->property_trees(); |
| 412 |
| 413 layer_tree_host_in_process_->BuildPropertyTreesForTesting(); |
| 414 PropertyTrees* client_property_trees = |
| 415 layer_tree_host_in_process_->property_trees(); |
| 416 |
| 417 EXPECT_EQ(*engine_property_trees, *client_property_trees); |
| 418 } |
| 419 |
| 420 } // namespace |
| 421 } // namespace cc |
OLD | NEW |