Commit 1e6e3aec authored by Yi Gu's avatar Yi Gu Committed by Commit Bot

[Animation Worklet] Update the animator name sync logic to serve multiple global scopes

Prior to crrev.com/c/1409844 we have one global scope per animator and
the animator's name gets synced to main thread upon registration. With
the support of multiple global scopes, the sync should be done only when
the name is registered on both global scopes.

Change-Id: If2b1768fbafda96c92084db45c0ba3e14a5bb01c
Reviewed-on: https://chromium-review.googlesource.com/c/1440502
Commit-Queue: Yi Gu <yigu@chromium.org>
Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Reviewed-by: default avatarMajid Valipour <majidvp@chromium.org>
Cr-Commit-Position: refs/heads/master@{#630080}
parent d3ff9d91
...@@ -29,7 +29,8 @@ AnimationWorklet::~AnimationWorklet() = default; ...@@ -29,7 +29,8 @@ AnimationWorklet::~AnimationWorklet() = default;
bool AnimationWorklet::NeedsToCreateGlobalScope() { bool AnimationWorklet::NeedsToCreateGlobalScope() {
return GetNumberOfGlobalScopes() < return GetNumberOfGlobalScopes() <
AnimationWorkletProxyClient::kNumStatelessGlobalScopes; static_cast<wtf_size_t>(
AnimationWorkletProxyClient::kNumStatelessGlobalScopes);
} }
WorkletGlobalScopeProxy* AnimationWorklet::CreateGlobalScope() { WorkletGlobalScopeProxy* AnimationWorklet::CreateGlobalScope() {
......
...@@ -30,7 +30,7 @@ const char AnimationWorkletProxyClient::kSupplementName[] = ...@@ -30,7 +30,7 @@ const char AnimationWorkletProxyClient::kSupplementName[] =
"AnimationWorkletProxyClient"; "AnimationWorkletProxyClient";
/* static */ /* static */
const wtf_size_t AnimationWorkletProxyClient::kNumStatelessGlobalScopes = 2u; const int8_t AnimationWorkletProxyClient::kNumStatelessGlobalScopes = 2;
AnimationWorkletProxyClient::AnimationWorkletProxyClient( AnimationWorkletProxyClient::AnimationWorkletProxyClient(
int worklet_id, int worklet_id,
...@@ -67,6 +67,16 @@ void AnimationWorkletProxyClient::SynchronizeAnimatorName( ...@@ -67,6 +67,16 @@ void AnimationWorkletProxyClient::SynchronizeAnimatorName(
const String& animator_name) { const String& animator_name) {
if (state_ == RunState::kDisposed) if (state_ == RunState::kDisposed)
return; return;
// Only proceed to synchronization when the animator has been registered on
// all global scopes.
auto* it = registered_animators_.insert(animator_name, 0).stored_value;
++it->value;
if (it->value != kNumStatelessGlobalScopes) {
DCHECK_LT(it->value, kNumStatelessGlobalScopes)
<< "We should not have registered the same name more than the number "
"of scopes times.";
return;
}
// Animator registration is processed before the loading promise being // Animator registration is processed before the loading promise being
// resolved which is also done with a posted task (See // resolved which is also done with a posted task (See
...@@ -135,6 +145,7 @@ void AnimationWorkletProxyClient::Dispose() { ...@@ -135,6 +145,7 @@ void AnimationWorkletProxyClient::Dispose() {
// AnimationWorkletGlobalScope and AnimationWorkletProxyClient. // AnimationWorkletGlobalScope and AnimationWorkletProxyClient.
global_scopes_.clear(); global_scopes_.clear();
mutator_items_.clear(); mutator_items_.clear();
registered_animators_.clear();
} }
std::unique_ptr<AnimationWorkletOutput> AnimationWorkletProxyClient::Mutate( std::unique_ptr<AnimationWorkletOutput> AnimationWorkletProxyClient::Mutate(
......
...@@ -34,7 +34,7 @@ class MODULES_EXPORT AnimationWorkletProxyClient ...@@ -34,7 +34,7 @@ class MODULES_EXPORT AnimationWorkletProxyClient
public: public:
static const char kSupplementName[]; static const char kSupplementName[];
static const wtf_size_t kNumStatelessGlobalScopes; static const int8_t kNumStatelessGlobalScopes;
// This client is hooked to the given |mutatee|, on the given // This client is hooked to the given |mutatee|, on the given
// |mutatee_runner|. // |mutatee_runner|.
...@@ -65,6 +65,8 @@ class MODULES_EXPORT AnimationWorkletProxyClient ...@@ -65,6 +65,8 @@ class MODULES_EXPORT AnimationWorkletProxyClient
FRIEND_TEST_ALL_PREFIXES(AnimationWorkletGlobalScopeTest, SelectGlobalScope); FRIEND_TEST_ALL_PREFIXES(AnimationWorkletGlobalScopeTest, SelectGlobalScope);
FRIEND_TEST_ALL_PREFIXES(AnimationWorkletProxyClientTest, FRIEND_TEST_ALL_PREFIXES(AnimationWorkletProxyClientTest,
AnimationWorkletProxyClientConstruction); AnimationWorkletProxyClientConstruction);
FRIEND_TEST_ALL_PREFIXES(AnimationWorkletProxyClientTest,
RegisteredAnimatorNameShouldSyncOnce);
// Separate global scope selectors are used instead of overriding // Separate global scope selectors are used instead of overriding
// Worklet::SelectGlobalScope since two different selection mechanisms are // Worklet::SelectGlobalScope since two different selection mechanisms are
...@@ -91,6 +93,7 @@ class MODULES_EXPORT AnimationWorkletProxyClient ...@@ -91,6 +93,7 @@ class MODULES_EXPORT AnimationWorkletProxyClient
WTF::Vector<MutatorItem> mutator_items_; WTF::Vector<MutatorItem> mutator_items_;
Vector<CrossThreadPersistent<AnimationWorkletGlobalScope>> global_scopes_; Vector<CrossThreadPersistent<AnimationWorkletGlobalScope>> global_scopes_;
HashMap<String, int8_t> registered_animators_;
enum RunState { kUninitialized, kWorking, kDisposed } state_; enum RunState { kUninitialized, kWorking, kDisposed } state_;
......
...@@ -5,18 +5,53 @@ ...@@ -5,18 +5,53 @@
#include "third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h" #include "third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h"
#include <memory> #include <memory>
#include <utility>
#include "base/memory/weak_ptr.h" #include "base/test/test_simple_task_runner.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h" #include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
namespace blink { namespace blink {
class MockMutatorClient : public MutatorClient {
public:
explicit MockMutatorClient(
std::unique_ptr<AnimationWorkletMutatorDispatcherImpl>);
void SetMutationUpdate(std::unique_ptr<AnimationWorkletOutput>) override {}
void NotifyAnimationsPending() override {}
void NotifyAnimationsReady() override {}
MOCK_METHOD1(SynchronizeAnimatorName, void(const String&));
std::unique_ptr<AnimationWorkletMutatorDispatcherImpl> mutator_;
};
MockMutatorClient::MockMutatorClient(
std::unique_ptr<AnimationWorkletMutatorDispatcherImpl> mutator)
: mutator_(std::move(mutator)) {
mutator_->SetClient(this);
}
class AnimationWorkletProxyClientTest : public RenderingTest { class AnimationWorkletProxyClientTest : public RenderingTest {
public: public:
AnimationWorkletProxyClientTest() AnimationWorkletProxyClientTest() = default;
: RenderingTest(SingleChildLocalFrameClient::Create()) {}
void SetUp() override {
RenderingTest::SetUp();
auto mutator =
std::make_unique<AnimationWorkletMutatorDispatcherImpl>(true);
mutator_task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>();
proxy_client_ = MakeGarbageCollected<AnimationWorkletProxyClient>(
1, nullptr, nullptr, mutator->GetWeakPtr(), mutator_task_runner_);
mutator_client_ = std::make_unique<MockMutatorClient>(std::move(mutator));
}
Persistent<AnimationWorkletProxyClient> proxy_client_;
std::unique_ptr<MockMutatorClient> mutator_client_;
scoped_refptr<base::TestSimpleTaskRunner> mutator_task_runner_;
}; };
TEST_F(AnimationWorkletProxyClientTest, TEST_F(AnimationWorkletProxyClientTest,
...@@ -29,18 +64,34 @@ TEST_F(AnimationWorkletProxyClientTest, ...@@ -29,18 +64,34 @@ TEST_F(AnimationWorkletProxyClientTest,
auto mutator = std::make_unique<AnimationWorkletMutatorDispatcherImpl>(true); auto mutator = std::make_unique<AnimationWorkletMutatorDispatcherImpl>(true);
scoped_refptr<base::SingleThreadTaskRunner> mutator_task_runner = scoped_refptr<base::SingleThreadTaskRunner> mutator_task_runner =
mutator->GetTaskRunner(); mutator->GetTaskRunner();
base::WeakPtrFactory<AnimationWorkletMutatorDispatcherImpl>
mutator_dispatcher_factory(mutator.get());
proxy_client = MakeGarbageCollected<AnimationWorkletProxyClient>( proxy_client = MakeGarbageCollected<AnimationWorkletProxyClient>(
1, nullptr, nullptr, mutator_dispatcher_factory.GetWeakPtr(), 1, nullptr, nullptr, mutator->GetWeakPtr(), mutator_task_runner);
mutator_task_runner);
EXPECT_EQ(proxy_client->mutator_items_.size(), 1u); EXPECT_EQ(proxy_client->mutator_items_.size(), 1u);
proxy_client = MakeGarbageCollected<AnimationWorkletProxyClient>( proxy_client = MakeGarbageCollected<AnimationWorkletProxyClient>(
1, mutator_dispatcher_factory.GetWeakPtr(), mutator_task_runner, 1, mutator->GetWeakPtr(), mutator_task_runner, mutator->GetWeakPtr(),
mutator_dispatcher_factory.GetWeakPtr(), mutator_task_runner); mutator_task_runner);
EXPECT_EQ(proxy_client->mutator_items_.size(), 2u); EXPECT_EQ(proxy_client->mutator_items_.size(), 2u);
} }
// Only sync when the animator is registered kNumStatelessGlobalScopes times.
TEST_F(AnimationWorkletProxyClientTest, RegisteredAnimatorNameShouldSyncOnce) {
String animator_name = "test_animator";
ASSERT_FALSE(proxy_client_->registered_animators_.Contains(animator_name));
for (int8_t i = 0;
i < AnimationWorkletProxyClient::kNumStatelessGlobalScopes - 1; ++i) {
EXPECT_CALL(*mutator_client_, SynchronizeAnimatorName(animator_name))
.Times(0);
proxy_client_->SynchronizeAnimatorName(animator_name);
testing::Mock::VerifyAndClearExpectations(mutator_client_.get());
}
EXPECT_CALL(*mutator_client_, SynchronizeAnimatorName(animator_name))
.Times(1);
proxy_client_->SynchronizeAnimatorName(animator_name);
mutator_task_runner_->RunUntilIdle();
}
} // namespace blink } // namespace blink
...@@ -76,6 +76,10 @@ class PLATFORM_EXPORT AnimationWorkletMutatorDispatcherImpl final ...@@ -76,6 +76,10 @@ class PLATFORM_EXPORT AnimationWorkletMutatorDispatcherImpl final
return host_queue_; return host_queue_;
} }
base::WeakPtr<AnimationWorkletMutatorDispatcherImpl> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
private: private:
class OutputVectorRef; class OutputVectorRef;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment