1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149

cc / layers / mirror_layer_unittest.cc [blame]

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>
#include <utility>

#include "cc/animation/animation_host.h"
#include "cc/layers/mirror_layer.h"
#include "cc/layers/mirror_layer_impl.h"
#include "cc/test/fake_impl_task_runner_provider.h"
#include "cc/test/fake_layer_tree_host.h"
#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/test_task_graph_runner.h"
#include "cc/trees/tree_synchronizer.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cc {
namespace {

class MirrorLayerTest : public testing::Test {
 public:
  MirrorLayerTest() : host_impl_(&task_runner_provider_, &task_graph_runner_) {}

  // Synchronizes |layer_tree_host_| and |host_impl_| and pushes surface ids.
  void SynchronizeTrees() {
    TreeSynchronizer::PushLayerProperties(
        *layer_tree_host_->GetPendingCommitState(),
        layer_tree_host_->GetThreadUnsafeCommitState(),
        host_impl_.pending_tree());
  }

 protected:
  void SetUp() override {
    animation_host_ = AnimationHost::CreateForTesting(ThreadInstance::kMain);
    layer_tree_host_ = FakeLayerTreeHost::Create(
        &fake_client_, &task_graph_runner_, animation_host_.get());
    layer_tree_host_->SetViewportRectAndScale(gfx::Rect(10, 10), 1.f,
                                              viz::LocalSurfaceId());
    host_impl_.CreatePendingTree();
  }

  void TearDown() override {
    layer_tree_host_->SetRootLayer(nullptr);
    layer_tree_host_ = nullptr;
  }

  FakeLayerTreeHostClient fake_client_;
  FakeImplTaskRunnerProvider task_runner_provider_;
  TestTaskGraphRunner task_graph_runner_;
  std::unique_ptr<AnimationHost> animation_host_;
  std::unique_ptr<FakeLayerTreeHost> layer_tree_host_;
  FakeLayerTreeHostImpl host_impl_;
};

// This test verifies that MirrorLayer properties are pushed across to
// MirrorLayerImpl.
TEST_F(MirrorLayerTest, PushProperties) {
  auto root = Layer::Create();
  layer_tree_host_->SetRootLayer(root);

  auto mirrored = Layer::Create();
  root->AddChild(mirrored);
  auto mirror = MirrorLayer::Create(mirrored);
  root->AddChild(mirror);

  EXPECT_EQ(1, mirrored->mirror_count());
  EXPECT_EQ(mirrored.get(), mirror->mirrored_layer());

  auto root_impl = LayerImpl::Create(host_impl_.pending_tree(), root->id());
  auto mirrored_impl =
      LayerImpl::Create(host_impl_.pending_tree(), mirrored->id());
  auto mirror_impl =
      MirrorLayerImpl::Create(host_impl_.pending_tree(), mirror->id());

  // Verify that impl layers have default property values.
  EXPECT_EQ(0, mirror_impl->mirrored_layer_id());

  SynchronizeTrees();

  // Verify that property values are pushed to impl layers.
  EXPECT_EQ(mirrored_impl->id(), mirror_impl->mirrored_layer_id());
}

// This test verifies adding/removing mirror layers updates mirror count
// properly and sets appropriate bits on the layer tree host.
TEST_F(MirrorLayerTest, MirrorCount) {
  auto mirrored = Layer::Create();
  mirrored->SetLayerTreeHost(layer_tree_host_.get());

  layer_tree_host_->ClearPendingLayerCommitStates();
  auto commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
                                                   /*has_updates=*/true);
  layer_tree_host_->CommitComplete(commit_state->source_frame_number,
                                   {base::TimeTicks(), base::TimeTicks::Now()});
  layer_tree_host_->property_trees()->set_needs_rebuild(false);
  EXPECT_EQ(0, mirrored->mirror_count());

  // Creating the first mirror layer should trigger property trees rebuild.
  auto mirror1 = MirrorLayer::Create(mirrored);
  EXPECT_EQ(1, mirrored->mirror_count());
  EXPECT_EQ(mirrored.get(), mirror1->mirrored_layer());
  EXPECT_TRUE(layer_tree_host_->property_trees()->needs_rebuild());
  EXPECT_TRUE(
      const_cast<const FakeLayerTreeHost*>(layer_tree_host_.get())
          ->pending_commit_state()
          ->layers_that_should_push_properties.contains(mirrored.get()));
  layer_tree_host_->property_trees()->set_needs_rebuild(false);

  // Creating a second mirror layer should not trigger property trees rebuild.
  auto mirror2 = MirrorLayer::Create(mirrored);
  EXPECT_EQ(2, mirrored->mirror_count());
  EXPECT_EQ(mirrored.get(), mirror2->mirrored_layer());
  EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild());
  EXPECT_TRUE(
      const_cast<const FakeLayerTreeHost*>(layer_tree_host_.get())
          ->pending_commit_state()
          ->layers_that_should_push_properties.contains(mirrored.get()));
  layer_tree_host_->property_trees()->set_needs_rebuild(false);

  // Destroying one of the mirror layers should not trigger property trees
  // rebuild.
  mirror1->RemoveFromParent();
  mirror1 = nullptr;
  EXPECT_EQ(1, mirrored->mirror_count());
  EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild());
  EXPECT_EQ(1u, const_cast<const FakeLayerTreeHost*>(layer_tree_host_.get())
                    ->pending_commit_state()
                    ->layers_that_should_push_properties.size());
  layer_tree_host_->property_trees()->set_needs_rebuild(false);

  // Destroying the only remaining mirror layer should trigger property trees
  // rebuild.
  mirror2->RemoveFromParent();
  mirror2 = nullptr;
  EXPECT_EQ(0, mirrored->mirror_count());
  EXPECT_TRUE(layer_tree_host_->property_trees()->needs_rebuild());
  EXPECT_TRUE(
      const_cast<const FakeLayerTreeHost*>(layer_tree_host_.get())
          ->pending_commit_state()
          ->layers_that_should_push_properties.contains(mirrored.get()));
  layer_tree_host_->property_trees()->set_needs_rebuild(false);

  mirrored->SetLayerTreeHost(nullptr);
}

}  // namespace
}  // namespace cc