
Since LayerTreeHost is threaded, callbacks tied to a frame submitted by the main thread are posted asynchronously. This means when the compositor is swapped between widgets (for RenderDocument), the new widget could receive callbacks tied to content submitted by the previous widget resulting in errors. This change avoids this by adding a source_frame_number to such callbacks. The source_frame_number is 1:1 with main frames and as such can be used to tie callbacks to a particular frame. The LayerTreeView can then safely ignore callbacks for main frames submitted by a previous widget. Bug: 1464791 Change-Id: I343b75474c7c2bf7a7c050ab949d2ccf328bbe80 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4993439 Reviewed-by: Vladimir Levin <vmpstr@chromium.org> Reviewed-by: Rakina Zata Amni <rakina@chromium.org> Auto-Submit: Khushal Sagar <khushalsagar@chromium.org> Commit-Queue: Khushal Sagar <khushalsagar@chromium.org> Reviewed-by: Ian Vollick <vollick@chromium.org> Cr-Commit-Position: refs/heads/main@{#1218442}
149 lines
5.6 KiB
C++
149 lines
5.6 KiB
C++
// 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());
|
|
|
|
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
|