Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3300)

Unified Diff: cc/blimp/compositor_state_deserializer_unittest.cc

Issue 2375363002: cc/blimp: Set up the framework for state serialization. (Closed)
Patch Set: test update Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/blimp/compositor_state_deserializer_client.h ('k') | cc/blimp/layer_factory.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/blimp/compositor_state_deserializer_unittest.cc
diff --git a/cc/blimp/compositor_state_deserializer_unittest.cc b/cc/blimp/compositor_state_deserializer_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3d86f3193b07b9f8da06046b56fee4863587afa7
--- /dev/null
+++ b/cc/blimp/compositor_state_deserializer_unittest.cc
@@ -0,0 +1,421 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "compositor_state_deserializer.h"
+
+#include "base/run_loop.h"
+#include "cc/animation/animation_host.h"
+#include "cc/blimp/compositor_proto_state.h"
+#include "cc/blimp/compositor_state_deserializer_client.h"
+#include "cc/blimp/layer_tree_host_remote.h"
+#include "cc/proto/compositor_message.pb.h"
+#include "cc/test/fake_layer_tree_host.h"
+#include "cc/test/fake_layer_tree_host_client.h"
+#include "cc/test/fake_remote_compositor_bridge.h"
+#include "cc/test/remote_client_layer_factory.h"
+#include "cc/test/stub_layer_tree_host_client.h"
+#include "cc/test/test_task_graph_runner.h"
+#include "cc/trees/layer_tree_host_common.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+#define EXPECT_LAYERS_EQ(engine_layer_id, client_layer) \
+ EXPECT_EQ( \
+ compositor_state_deserializer_->GetLayerForEngineId(engine_layer_id), \
+ client_layer);
+
+class RemoteCompositorBridgeForTest : public FakeRemoteCompositorBridge {
+ public:
+ using ProtoFrameCallback = base::Callback<void(
+ std::unique_ptr<CompositorProtoState> compositor_proto_state)>;
+
+ RemoteCompositorBridgeForTest(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ ProtoFrameCallback proto_frame_callback)
+ : FakeRemoteCompositorBridge(main_task_runner),
+ proto_frame_callback_(proto_frame_callback) {}
+
+ ~RemoteCompositorBridgeForTest() override = default;
+
+ void ProcessCompositorStateUpdate(
+ std::unique_ptr<CompositorProtoState> compositor_proto_state) override {
+ proto_frame_callback_.Run(std::move(compositor_proto_state));
+ }
+
+ private:
+ ProtoFrameCallback proto_frame_callback_;
+};
+
+class CompositorStateDeserializerTest
+ : public testing::Test,
+ public CompositorStateDeserializerClient {
+ public:
+ void SetUp() override {
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner =
+ base::ThreadTaskRunnerHandle::Get();
+
+ // Engine side setup.
+ LayerTreeHostRemote::InitParams params;
+ params.client = &layer_tree_host_client_remote_;
+ params.main_task_runner = main_task_runner;
+ params.animation_host = AnimationHost::CreateMainInstance();
+ params.remote_compositor_bridge =
+ base::MakeUnique<RemoteCompositorBridgeForTest>(
+ main_task_runner,
+ base::Bind(
+ &CompositorStateDeserializerTest::ProcessCompositorStateUpdate,
+ base::Unretained(this)));
+ LayerTreeSettings settings;
+ params.settings = &settings;
+
+ layer_tree_host_remote_ = base::MakeUnique<LayerTreeHostRemote>(&params);
+
+ // Client side setup.
+ layer_tree_host_in_process_ = FakeLayerTreeHost::Create(
+ &layer_tree_host_client_client_, &task_graph_runner_);
+ compositor_state_deserializer_ =
+ base::MakeUnique<CompositorStateDeserializer>(
+ layer_tree_host_in_process_.get(),
+ base::Bind(&CompositorStateDeserializerTest::LayerScrolled,
+ base::Unretained(this)),
+ this);
+ }
+
+ void TearDown() override {
+ layer_tree_host_remote_ = nullptr;
+ compositor_state_deserializer_ = nullptr;
+ layer_tree_host_in_process_ = nullptr;
+ }
+
+ void ProcessCompositorStateUpdate(
+ std::unique_ptr<CompositorProtoState> compositor_proto_state) {
+ // Immediately deserialize the state update.
+ compositor_state_deserializer_->DeserializeCompositorUpdate(
+ compositor_proto_state->compositor_message->layer_tree_host());
+ }
+
+ // CompositorStateDeserializer implementation.
+ bool ShouldRetainClientScroll(int engine_layer_id,
+ const gfx::ScrollOffset& new_offset) override {
+ return should_retain_client_scroll_;
+ }
+ bool ShouldRetainClientPageScale(float new_page_scale) override {
+ return should_retain_client_scale_;
+ }
+
+ void LayerScrolled(int engine_layer_id) {}
+
+ void VerifyTreesAreIdentical() {
+ LayerTree* engine_layer_tree = layer_tree_host_remote_->GetLayerTree();
+ LayerTree* client_layer_tree = layer_tree_host_in_process_->GetLayerTree();
+
+ if (engine_layer_tree->root_layer()) {
+ LayerTreeHostCommon::CallFunctionForEveryLayer(
+ engine_layer_tree, [this](Layer* engine_layer) {
+ VerifyLayersAreIdentical(
+ engine_layer,
+ compositor_state_deserializer_->GetLayerForEngineId(
+ engine_layer->id()));
+ });
+ } else {
+ EXPECT_EQ(layer_tree_host_in_process_->GetLayerTree()->root_layer(),
+ nullptr);
+ }
+
+ // Viewport layers.
+ // Overscroll Elasticty Layer.
+ Layer* client_overscroll_elasticity_layer =
+ client_layer_tree->overscroll_elasticity_layer();
+ if (engine_layer_tree->overscroll_elasticity_layer()) {
+ int engine_overscroll_elasticity_layer_id =
+ engine_layer_tree->overscroll_elasticity_layer()->id();
+
+ EXPECT_LAYERS_EQ(engine_overscroll_elasticity_layer_id,
+ client_overscroll_elasticity_layer);
+ } else {
+ EXPECT_EQ(client_overscroll_elasticity_layer, nullptr);
+ }
+
+ // PageScale Layer.
+ Layer* client_page_scale_layer = client_layer_tree->page_scale_layer();
+ if (engine_layer_tree->page_scale_layer()) {
+ int engine_page_scale_layer_id =
+ engine_layer_tree->page_scale_layer()->id();
+
+ EXPECT_LAYERS_EQ(engine_page_scale_layer_id, client_page_scale_layer);
+ } else {
+ EXPECT_EQ(client_page_scale_layer, nullptr);
+ }
+
+ // InnerViewportScroll Layer.
+ Layer* client_inner_viewport_layer =
+ client_layer_tree->inner_viewport_scroll_layer();
+ if (engine_layer_tree->inner_viewport_scroll_layer()) {
+ int engine_inner_viewport_layer_id =
+ engine_layer_tree->inner_viewport_scroll_layer()->id();
+
+ EXPECT_LAYERS_EQ(engine_inner_viewport_layer_id,
+ client_inner_viewport_layer);
+ } else {
+ EXPECT_EQ(client_inner_viewport_layer, nullptr);
+ }
+
+ // OuterViewportScroll Layer.
+ Layer* client_outer_viewport_layer =
+ client_layer_tree->outer_viewport_scroll_layer();
+ if (engine_layer_tree->outer_viewport_scroll_layer()) {
+ int engine_outer_viewport_layer_id =
+ engine_layer_tree->outer_viewport_scroll_layer()->id();
+
+ EXPECT_LAYERS_EQ(engine_outer_viewport_layer_id,
+ client_outer_viewport_layer);
+ } else {
+ EXPECT_EQ(client_outer_viewport_layer, nullptr);
+ }
+ }
+
+ void VerifyLayersAreIdentical(Layer* engine_layer, Layer* client_layer) {
+ ASSERT_NE(client_layer, nullptr);
+
+ LayerTree* client_layer_tree = layer_tree_host_in_process_->GetLayerTree();
+ EXPECT_EQ(client_layer_tree, client_layer->GetLayerTree());
+
+ // Parent.
+ if (engine_layer->parent()) {
+ int engine_parent_id = engine_layer->parent()->id();
+ EXPECT_LAYERS_EQ(engine_parent_id, client_layer->parent());
+ } else {
+ EXPECT_EQ(client_layer->parent(), nullptr);
+ }
+
+ // Mask Layers.
+ if (engine_layer->mask_layer()) {
+ int engine_mask_layer_id = engine_layer->mask_layer()->id();
+ EXPECT_LAYERS_EQ(engine_mask_layer_id, client_layer->mask_layer());
+ } else {
+ EXPECT_EQ(client_layer->mask_layer(), nullptr);
+ }
+
+ // Scroll parent.
+ if (engine_layer->scroll_parent()) {
+ int engine_scroll_parent_id = engine_layer->scroll_parent()->id();
+ EXPECT_LAYERS_EQ(engine_scroll_parent_id, client_layer->scroll_parent());
+ } else {
+ EXPECT_EQ(client_layer->scroll_parent(), nullptr);
+ }
+
+ // Clip parent.
+ if (engine_layer->clip_parent()) {
+ int engine_clip_parent_id = engine_layer->clip_parent()->id();
+ EXPECT_LAYERS_EQ(engine_clip_parent_id, client_layer->clip_parent());
+ } else {
+ EXPECT_EQ(client_layer->clip_parent(), nullptr);
+ }
+
+ // Scroll-clip layer.
+ if (engine_layer->scroll_clip_layer()) {
+ int scroll_clip_id = engine_layer->scroll_clip_layer()->id();
+ EXPECT_LAYERS_EQ(scroll_clip_id, client_layer->scroll_clip_layer());
+ } else {
+ EXPECT_EQ(client_layer->scroll_clip_layer(), nullptr);
+ }
+ }
+
+ // Engine setup.
+ std::unique_ptr<LayerTreeHostRemote> layer_tree_host_remote_;
+ StubLayerTreeHostClient layer_tree_host_client_remote_;
+
+ // Client setup.
+ std::unique_ptr<FakeLayerTreeHost> layer_tree_host_in_process_;
+ std::unique_ptr<CompositorStateDeserializer> compositor_state_deserializer_;
+ FakeLayerTreeHostClient layer_tree_host_client_client_;
+ TestTaskGraphRunner task_graph_runner_;
+
+ bool should_retain_client_scroll_ = false;
+ bool should_retain_client_scale_ = false;
+};
+
+TEST_F(CompositorStateDeserializerTest, BasicSync) {
+ // Set up a tree with a single node.
+ scoped_refptr<Layer> root_layer = Layer::Create();
+ layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer);
+
+ // Synchronize State and verify.
+ base::RunLoop().RunUntilIdle();
+ VerifyTreesAreIdentical();
+
+ // Swap the root layer.
+ scoped_refptr<Layer> new_root_layer = Layer::Create();
+ new_root_layer->AddChild(Layer::Create());
+ new_root_layer->AddChild(Layer::Create());
+ layer_tree_host_remote_->GetLayerTree()->SetRootLayer(new_root_layer);
+
+ // Synchronize State and verify.
+ base::RunLoop().RunUntilIdle();
+ VerifyTreesAreIdentical();
+ // Verify that we are no longer tracking the destroyed layer on the client.
+ EXPECT_EQ(
+ compositor_state_deserializer_->GetLayerForEngineId(root_layer->id()),
+ nullptr);
+
+ // Remove the root layer to change to a null tree.
+ layer_tree_host_remote_->GetLayerTree()->SetRootLayer(nullptr);
+
+ // Synchronize State and verify.
+ base::RunLoop().RunUntilIdle();
+ VerifyTreesAreIdentical();
+}
+
+TEST_F(CompositorStateDeserializerTest, ViewportLayers) {
+ scoped_refptr<Layer> root_layer = Layer::Create();
+ layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer);
+
+ scoped_refptr<Layer> overscroll_elasticity_layer = Layer::Create();
+ scoped_refptr<Layer> inner_viewport_scroll_layer = Layer::Create();
+ scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create();
+ scoped_refptr<Layer> page_scale_layer = Layer::Create();
+ layer_tree_host_remote_->GetLayerTree()->RegisterViewportLayers(
+ overscroll_elasticity_layer, page_scale_layer,
+ inner_viewport_scroll_layer, outer_viewport_scroll_layer);
+
+ root_layer->AddChild(overscroll_elasticity_layer);
+ overscroll_elasticity_layer->AddChild(page_scale_layer);
+ page_scale_layer->AddChild(inner_viewport_scroll_layer);
+ inner_viewport_scroll_layer->AddChild(outer_viewport_scroll_layer);
+
+ // Synchronize State and verify.
+ base::RunLoop().RunUntilIdle();
+ VerifyTreesAreIdentical();
+}
+
+TEST_F(CompositorStateDeserializerTest, ScrollClipAndMaskLayers) {
+ /* root -- A---C---D
+ / | \
+ / | E(MaskLayer)
+ / ------B */
+ scoped_refptr<Layer> root_layer = Layer::Create();
+ layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer);
+
+ scoped_refptr<Layer> layer_a = Layer::Create();
+ scoped_refptr<Layer> layer_b = Layer::Create();
+ scoped_refptr<Layer> layer_c = Layer::Create();
+ scoped_refptr<Layer> layer_d = Layer::Create();
+ scoped_refptr<Layer> layer_e = Layer::Create();
+
+ root_layer->AddChild(layer_a);
+ root_layer->AddChild(layer_b);
+ layer_a->AddChild(layer_c);
+ layer_c->AddChild(layer_d);
+
+ layer_a->SetMaskLayer(layer_e.get());
+ layer_c->SetScrollParent(layer_b.get());
+ layer_c->SetScrollClipLayerId(root_layer->id());
+ layer_d->SetClipParent(layer_a.get());
+
+ // Synchronize State and verify.
+ base::RunLoop().RunUntilIdle();
+ VerifyTreesAreIdentical();
+}
+
+TEST_F(CompositorStateDeserializerTest, ReconcileScrollAndScale) {
+ scoped_refptr<Layer> root_layer = Layer::Create();
+ layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer);
+
+ // Set scroll offset.
+ scoped_refptr<Layer> scroll_layer = Layer::Create();
+ root_layer->AddChild(scroll_layer);
+ gfx::ScrollOffset engine_offset(4, 3);
+ scroll_layer->SetScrollOffset(engine_offset);
+
+ // Set page scale.
+ float engine_page_scale = 0.5f;
+ layer_tree_host_remote_->GetLayerTree()->SetPageScaleFactorAndLimits(
+ engine_page_scale, 1.0, 1.0);
+
+ // Synchronize State and verify that the engine values are used.
+ base::RunLoop().RunUntilIdle();
+ VerifyTreesAreIdentical();
+
+ EXPECT_EQ(engine_page_scale,
+ layer_tree_host_in_process_->GetLayerTree()->page_scale_factor());
+ EXPECT_EQ(engine_offset, compositor_state_deserializer_
+ ->GetLayerForEngineId(scroll_layer->id())
+ ->scroll_offset());
+
+ // Now reset the scroll offset and page scale and force-retain the client
+ // values.
+ gfx::ScrollOffset new_engine_offset(2, 2);
+ scroll_layer->SetScrollOffset(new_engine_offset);
+ float new_engine_page_scale = 0.8f;
+ layer_tree_host_remote_->GetLayerTree()->SetPageScaleFactorAndLimits(
+ new_engine_page_scale, 1.0, 1.0);
+ should_retain_client_scroll_ = true;
+ should_retain_client_scale_ = true;
+
+ // Synchronize State and verify that the client values are retained.
+ base::RunLoop().RunUntilIdle();
+ VerifyTreesAreIdentical();
+
+ EXPECT_EQ(engine_page_scale,
+ layer_tree_host_in_process_->GetLayerTree()->page_scale_factor());
+ EXPECT_EQ(engine_offset, compositor_state_deserializer_
+ ->GetLayerForEngineId(scroll_layer->id())
+ ->scroll_offset());
+}
+
+TEST_F(CompositorStateDeserializerTest, PropertyTreesAreIdentical) {
+ // Override the LayerFactory. This is necessary to ensure the layer ids
+ // tracked in PropertyTrees on the engine and client are identical.
+ compositor_state_deserializer_->SetLayerFactoryForTesting(
+ base::MakeUnique<RemoteClientLayerFactory>());
+
+ scoped_refptr<Layer> root_layer = Layer::Create();
+ root_layer->SetBounds(gfx::Size(10, 10));
+ layer_tree_host_remote_->GetLayerTree()->SetRootLayer(root_layer);
+
+ scoped_refptr<Layer> child1 = Layer::Create();
+ root_layer->AddChild(child1);
+ gfx::Transform transform;
+ transform.Translate(gfx::Vector2dF(5, 4));
+ child1->SetTransform(transform);
+ child1->SetMasksToBounds(true);
+
+ scoped_refptr<Layer> child2 = Layer::Create();
+ root_layer->AddChild(child2);
+ child2->SetBounds(gfx::Size(5, 5));
+ child2->SetScrollOffset(gfx::ScrollOffset(3, 4));
+ child2->SetScrollParent(child1.get());
+ child2->SetUserScrollable(true, true);
+
+ scoped_refptr<Layer> grandchild11 = Layer::Create();
+ child1->AddChild(grandchild11);
+ grandchild11->SetClipParent(root_layer.get());
+
+ scoped_refptr<Layer> grandchild21 = Layer::Create();
+ child2->AddChild(grandchild21);
+ grandchild21->SetScrollClipLayerId(child1->id());
+ grandchild21->SetOpacity(0.5);
+
+ // Synchronize State and verify.
+ base::RunLoop().RunUntilIdle();
+ VerifyTreesAreIdentical();
+ EXPECT_EQ(root_layer->id(), layer_tree_host_in_process_->root_layer()->id());
+
+ // Sanity test to ensure that the PropertyTrees generated from the Layers on
+ // the client and engine are identical.
+ layer_tree_host_remote_->GetLayerTree()->BuildPropertyTreesForTesting();
+ PropertyTrees* engine_property_trees =
+ layer_tree_host_remote_->GetLayerTree()->property_trees();
+
+ layer_tree_host_in_process_->BuildPropertyTreesForTesting();
+ PropertyTrees* client_property_trees =
+ layer_tree_host_in_process_->property_trees();
+
+ EXPECT_EQ(*engine_property_trees, *client_property_trees);
+}
+
+} // namespace
+} // namespace cc
« no previous file with comments | « cc/blimp/compositor_state_deserializer_client.h ('k') | cc/blimp/layer_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698