| 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 |