mirror of
https://github.com/react/react-native.git
synced 2026-09-29 16:58:04 +08:00
Move AnimationBackend initialization from Animated (#55103)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/55103 This diff decouples AnimationBackend from Animated. Now the backend is intialized in the Scheduler, from where it's passed to UIManager. Animation frontends (such as Animated) can then obtain a reference to the backend, and use it to schedule animation frame updates. # Changelog [General] [Changed] - Moved AnimationBackend initiailzation to `Scheduler` [General] [Added] - `AnimationChoreographer` interface with an implementation for fantom tests Reviewed By: zeyap Differential Revision: D89663251 fbshipit-source-id: 428a83d78ef92a89095989fe3121c578cf8d3983
This commit is contained in:
committed by
meta-codesync[bot]
parent
5a70daa80d
commit
f8564b47fd
@@ -82,6 +82,7 @@ add_react_common_subdir(react/debug)
|
||||
add_react_common_subdir(react/featureflags)
|
||||
add_react_common_subdir(react/performance/cdpmetrics)
|
||||
add_react_common_subdir(react/performance/timeline)
|
||||
add_react_common_subdir(react/renderer/animationbackend)
|
||||
add_react_common_subdir(react/renderer/animations)
|
||||
add_react_common_subdir(react/renderer/attributedstring)
|
||||
add_react_common_subdir(react/renderer/componentregistry)
|
||||
@@ -200,6 +201,7 @@ add_library(reactnative
|
||||
$<TARGET_OBJECTS:react_newarchdefaults>
|
||||
$<TARGET_OBJECTS:react_performance_cdpmetrics>
|
||||
$<TARGET_OBJECTS:react_performance_timeline>
|
||||
$<TARGET_OBJECTS:react_renderer_animationbackend>
|
||||
$<TARGET_OBJECTS:react_renderer_animations>
|
||||
$<TARGET_OBJECTS:react_renderer_attributedstring>
|
||||
$<TARGET_OBJECTS:react_renderer_componentregistry>
|
||||
@@ -293,6 +295,7 @@ target_include_directories(reactnative
|
||||
$<TARGET_PROPERTY:react_newarchdefaults,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_performance_cdpmetrics,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_performance_timeline,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_renderer_animationbackend,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_renderer_animations,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_renderer_attributedstring,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:react_renderer_componentregistry,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
|
||||
@@ -157,6 +157,7 @@ Pod::Spec.new do |s|
|
||||
ss.source_files = podspec_sources("react/renderer/scheduler/**/*.{m,mm,cpp,h}", "react/renderer/scheduler/**/*.h")
|
||||
ss.header_dir = "react/renderer/scheduler"
|
||||
|
||||
ss.dependency "React-Fabric/animationbackend"
|
||||
ss.dependency "React-performancecdpmetrics"
|
||||
ss.dependency "React-performancetimeline"
|
||||
ss.dependency "React-Fabric/observers/events"
|
||||
|
||||
+2
-8
@@ -35,10 +35,6 @@
|
||||
#include <react/renderer/animated/nodes/ValueAnimatedNode.h>
|
||||
#include <react/renderer/core/EventEmitter.h>
|
||||
|
||||
#ifdef RN_USE_ANIMATION_BACKEND
|
||||
#include <react/renderer/animationbackend/AnimatedPropsBuilder.h>
|
||||
#endif
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
// Global function pointer for getting current time. Current time
|
||||
@@ -559,10 +555,8 @@ void NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool isAsync) {
|
||||
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
|
||||
#ifdef RN_USE_ANIMATION_BACKEND
|
||||
if (auto animationBackend = animationBackend_.lock()) {
|
||||
std::static_pointer_cast<AnimationBackend>(animationBackend)
|
||||
->start(
|
||||
[this](float /*f*/) { return pullAnimationMutations(); },
|
||||
isAsync);
|
||||
animationBackend->start(
|
||||
[this](float /*f*/) { return pullAnimationMutations(); }, isAsync);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+6
-13
@@ -88,24 +88,17 @@ NativeAnimatedNodesManagerProvider::getOrCreate(
|
||||
|
||||
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
|
||||
#ifdef RN_USE_ANIMATION_BACKEND
|
||||
// TODO: this should be initialized outside of animated, but for now it
|
||||
// was convenient to do it here
|
||||
animationBackend_ = std::make_shared<AnimationBackend>(
|
||||
std::move(startOnRenderCallback_),
|
||||
std::move(stopOnRenderCallback_),
|
||||
std::move(directManipulationCallback),
|
||||
std::move(fabricCommitCallback),
|
||||
uiManager,
|
||||
jsInvoker);
|
||||
auto animationBackend = uiManager->unstable_getAnimationBackend().lock();
|
||||
react_native_assert(
|
||||
animationBackend != nullptr && "animationBackend is nullptr");
|
||||
animationBackend->registerJSInvoker(jsInvoker);
|
||||
|
||||
nativeAnimatedNodesManager_ =
|
||||
std::make_shared<NativeAnimatedNodesManager>(animationBackend_);
|
||||
std::make_shared<NativeAnimatedNodesManager>(animationBackend);
|
||||
|
||||
nativeAnimatedDelegate_ =
|
||||
std::make_shared<UIManagerNativeAnimatedDelegateBackendImpl>(
|
||||
animationBackend_);
|
||||
|
||||
uiManager->unstable_setAnimationBackend(animationBackend_);
|
||||
animationBackend);
|
||||
#endif
|
||||
} else {
|
||||
nativeAnimatedNodesManager_ =
|
||||
|
||||
-1
@@ -32,7 +32,6 @@ class NativeAnimatedNodesManagerProvider {
|
||||
std::shared_ptr<EventEmitterListener> getEventEmitterListener();
|
||||
|
||||
private:
|
||||
std::shared_ptr<UIManagerAnimationBackend> animationBackend_;
|
||||
std::shared_ptr<NativeAnimatedNodesManager> nativeAnimatedNodesManager_;
|
||||
|
||||
std::shared_ptr<EventEmitterListenerContainer> eventEmitterListenerContainer_;
|
||||
|
||||
+47
-34
@@ -6,11 +6,13 @@
|
||||
*/
|
||||
|
||||
#include "AnimationBackend.h"
|
||||
#include "AnimatedPropsRegistry.h"
|
||||
|
||||
#include <react/debug/react_native_assert.h>
|
||||
#include <react/renderer/animationbackend/AnimatedPropsSerializer.h>
|
||||
#include <react/renderer/graphics/Color.h>
|
||||
#include <chrono>
|
||||
#include "AnimatedPropsRegistry.h"
|
||||
#include <utility>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
@@ -51,20 +53,14 @@ static inline Props::Shared cloneProps(
|
||||
}
|
||||
|
||||
AnimationBackend::AnimationBackend(
|
||||
StartOnRenderCallback&& startOnRenderCallback,
|
||||
StopOnRenderCallback&& stopOnRenderCallback,
|
||||
DirectManipulationCallback&& directManipulationCallback,
|
||||
FabricCommitCallback&& fabricCommitCallback,
|
||||
UIManager* uiManager,
|
||||
std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: startOnRenderCallback_(std::move(startOnRenderCallback)),
|
||||
stopOnRenderCallback_(std::move(stopOnRenderCallback)),
|
||||
directManipulationCallback_(std::move(directManipulationCallback)),
|
||||
fabricCommitCallback_(std::move(fabricCommitCallback)),
|
||||
animatedPropsRegistry_(std::make_shared<AnimatedPropsRegistry>()),
|
||||
uiManager_(uiManager),
|
||||
jsInvoker_(std::move(jsInvoker)),
|
||||
commitHook_(uiManager, animatedPropsRegistry_) {}
|
||||
std::shared_ptr<AnimationChoreographer> animationChoreographer,
|
||||
std::shared_ptr<UIManager> uiManager)
|
||||
: animatedPropsRegistry_(std::make_shared<AnimatedPropsRegistry>()),
|
||||
animationChoreographer_(std::move(animationChoreographer)),
|
||||
commitHook_(*uiManager, animatedPropsRegistry_),
|
||||
uiManager_(std::move(uiManager)) {
|
||||
react_native_assert(uiManager_.expired() == false);
|
||||
}
|
||||
|
||||
void AnimationBackend::onAnimationFrame(double timestamp) {
|
||||
std::unordered_map<SurfaceId, SurfaceUpdates> surfaceUpdates;
|
||||
@@ -98,23 +94,18 @@ void AnimationBackend::onAnimationFrame(double timestamp) {
|
||||
requestAsyncFlushForSurfaces(asyncFlushSurfaces);
|
||||
}
|
||||
|
||||
void AnimationBackend::start(const Callback& callback, bool isAsync) {
|
||||
void AnimationBackend::start(const Callback& callback, bool /*isAsync*/) {
|
||||
callbacks.push_back(callback);
|
||||
// TODO: startOnRenderCallback_ should provide the timestamp from the
|
||||
// platform
|
||||
if (startOnRenderCallback_) {
|
||||
startOnRenderCallback_(
|
||||
[this]() {
|
||||
onAnimationFrame(
|
||||
std::chrono::steady_clock::now().time_since_epoch().count() /
|
||||
1000);
|
||||
},
|
||||
isAsync);
|
||||
if (!isRenderCallbackStarted_) {
|
||||
animationChoreographer_->resume();
|
||||
isRenderCallbackStarted_ = true;
|
||||
}
|
||||
}
|
||||
void AnimationBackend::stop(bool isAsync) {
|
||||
if (stopOnRenderCallback_) {
|
||||
stopOnRenderCallback_(isAsync);
|
||||
|
||||
void AnimationBackend::stop(bool /*isAsync*/) {
|
||||
if (isRenderCallbackStarted_) {
|
||||
animationChoreographer_->pause();
|
||||
isRenderCallbackStarted_ = false;
|
||||
}
|
||||
callbacks.clear();
|
||||
}
|
||||
@@ -127,9 +118,15 @@ void AnimationBackend::trigger() {
|
||||
void AnimationBackend::commitUpdates(
|
||||
SurfaceId surfaceId,
|
||||
SurfaceUpdates& surfaceUpdates) {
|
||||
auto uiManager = uiManager_.lock();
|
||||
if (!uiManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& surfaceFamilies = surfaceUpdates.families;
|
||||
auto& updates = surfaceUpdates.propsMap;
|
||||
uiManager_->getShadowTreeRegistry().visit(
|
||||
|
||||
uiManager->getShadowTreeRegistry().visit(
|
||||
surfaceId, [&surfaceFamilies, &updates](const ShadowTree& shadowTree) {
|
||||
shadowTree.commit(
|
||||
[&surfaceFamilies,
|
||||
@@ -160,19 +157,28 @@ void AnimationBackend::synchronouslyUpdateProps(
|
||||
const std::unordered_map<Tag, AnimatedProps>& updates) {
|
||||
for (auto& [tag, animatedProps] : updates) {
|
||||
// TODO: We shouldn't repack it into dynamic, but for that a rewrite
|
||||
// of directManipulationCallback_ is needed
|
||||
// of synchronouslyUpdateViewOnUIThread is needed
|
||||
auto dyn = animationbackend::packAnimatedProps(animatedProps);
|
||||
directManipulationCallback_(tag, std::move(dyn));
|
||||
if (auto uiManager = uiManager_.lock()) {
|
||||
uiManager->synchronouslyUpdateViewOnUIThread(tag, dyn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationBackend::requestAsyncFlushForSurfaces(
|
||||
const std::set<SurfaceId>& surfaces) {
|
||||
react_native_assert(
|
||||
jsInvoker_ != nullptr ||
|
||||
surfaces.empty() && "jsInvoker_ was not provided");
|
||||
for (const auto& surfaceId : surfaces) {
|
||||
// perform an empty commit on the js thread, to force the commit hook to
|
||||
// push updated shadow nodes to react through RSNRU
|
||||
jsInvoker_->invokeAsync([this, surfaceId]() {
|
||||
uiManager_->getShadowTreeRegistry().visit(
|
||||
jsInvoker_->invokeAsync([weakUIManager = uiManager_, surfaceId]() {
|
||||
auto uiManager = weakUIManager.lock();
|
||||
if (!uiManager) {
|
||||
return;
|
||||
}
|
||||
uiManager->getShadowTreeRegistry().visit(
|
||||
surfaceId, [](const ShadowTree& shadowTree) {
|
||||
shadowTree.commit(
|
||||
[](const RootShadowNode& oldRootShadowNode) {
|
||||
@@ -189,4 +195,11 @@ void AnimationBackend::clearRegistry(SurfaceId surfaceId) {
|
||||
animatedPropsRegistry_->clear(surfaceId);
|
||||
}
|
||||
|
||||
void AnimationBackend::registerJSInvoker(
|
||||
std::shared_ptr<CallInvoker> jsInvoker) {
|
||||
if (!jsInvoker_) {
|
||||
jsInvoker_ = jsInvoker;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
+11
-17
@@ -19,6 +19,7 @@
|
||||
#include "AnimatedProps.h"
|
||||
#include "AnimatedPropsRegistry.h"
|
||||
#include "AnimationBackendCommitHook.h"
|
||||
#include "AnimationChoreographer.h"
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
@@ -49,36 +50,29 @@ struct AnimationMutations {
|
||||
class AnimationBackend : public UIManagerAnimationBackend {
|
||||
public:
|
||||
using Callback = std::function<AnimationMutations(float)>;
|
||||
using StartOnRenderCallback = std::function<void(std::function<void()> &&, bool /* isAsync */)>;
|
||||
using StopOnRenderCallback = std::function<void(bool /* isAsync */)>;
|
||||
using DirectManipulationCallback = std::function<void(Tag, const folly::dynamic &)>;
|
||||
using FabricCommitCallback = std::function<void(std::unordered_map<Tag, folly::dynamic> &)>;
|
||||
using ResumeCallback = std::function<void()>;
|
||||
using PauseCallback = std::function<void()>;
|
||||
|
||||
std::vector<Callback> callbacks;
|
||||
const StartOnRenderCallback startOnRenderCallback_;
|
||||
const StopOnRenderCallback stopOnRenderCallback_;
|
||||
const DirectManipulationCallback directManipulationCallback_;
|
||||
const FabricCommitCallback fabricCommitCallback_;
|
||||
std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry_;
|
||||
UIManager *uiManager_;
|
||||
std::shared_ptr<CallInvoker> jsInvoker_;
|
||||
std::shared_ptr<AnimationChoreographer> animationChoreographer_;
|
||||
AnimationBackendCommitHook commitHook_;
|
||||
std::weak_ptr<UIManager> uiManager_;
|
||||
std::shared_ptr<CallInvoker> jsInvoker_;
|
||||
bool isRenderCallbackStarted_{false};
|
||||
|
||||
AnimationBackend(
|
||||
StartOnRenderCallback &&startOnRenderCallback,
|
||||
StopOnRenderCallback &&stopOnRenderCallback,
|
||||
DirectManipulationCallback &&directManipulationCallback,
|
||||
FabricCommitCallback &&fabricCommitCallback,
|
||||
UIManager *uiManager,
|
||||
std::shared_ptr<CallInvoker> jsInvoker);
|
||||
std::shared_ptr<AnimationChoreographer> animationChoreographer,
|
||||
std::shared_ptr<UIManager> uiManager);
|
||||
void commitUpdates(SurfaceId surfaceId, SurfaceUpdates &surfaceUpdates);
|
||||
void synchronouslyUpdateProps(const std::unordered_map<Tag, AnimatedProps> &updates);
|
||||
void requestAsyncFlushForSurfaces(const std::set<SurfaceId> &surfaces);
|
||||
void clearRegistry(SurfaceId surfaceId) override;
|
||||
void registerJSInvoker(std::shared_ptr<CallInvoker> jsInvoker) override;
|
||||
|
||||
void onAnimationFrame(double timestamp) override;
|
||||
void trigger() override;
|
||||
void start(const Callback &callback, bool isAsync);
|
||||
void start(const Callback &callback, bool isAsync) override;
|
||||
void stop(bool isAsync) override;
|
||||
};
|
||||
} // namespace facebook::react
|
||||
|
||||
+4
-2
@@ -7,13 +7,15 @@
|
||||
|
||||
#include <react/renderer/animationbackend/AnimationBackendCommitHook.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
AnimationBackendCommitHook::AnimationBackendCommitHook(
|
||||
UIManager* uiManager,
|
||||
UIManager& uiManager,
|
||||
std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry)
|
||||
: animatedPropsRegistry_(std::move(animatedPropsRegistry)) {
|
||||
uiManager->registerCommitHook(*this);
|
||||
uiManager.registerCommitHook(*this);
|
||||
}
|
||||
|
||||
RootShadowNode::Unshared AnimationBackendCommitHook::shadowTreeWillCommit(
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ class AnimationBackendCommitHook : public UIManagerCommitHook {
|
||||
std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry_;
|
||||
|
||||
public:
|
||||
AnimationBackendCommitHook(UIManager *uiManager, std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry);
|
||||
AnimationBackendCommitHook(UIManager &uiManager, std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry);
|
||||
RootShadowNode::Unshared shadowTreeWillCommit(
|
||||
const ShadowTree &shadowTree,
|
||||
const RootShadowNode::Shared &oldRootShadowNode,
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/renderer/uimanager/UIManagerAnimationBackend.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
/*
|
||||
* This class serves as an interface for native animation frame scheduling that can be used as abstraction in
|
||||
* ReactCxxPlatform.
|
||||
*/
|
||||
class AnimationChoreographer {
|
||||
public:
|
||||
virtual ~AnimationChoreographer() = default;
|
||||
|
||||
virtual void resume() = 0;
|
||||
virtual void pause() = 0;
|
||||
void setAnimationBackend(std::weak_ptr<UIManagerAnimationBackend> animationBackend)
|
||||
{
|
||||
animationBackend_ = animationBackend;
|
||||
}
|
||||
void onAnimationFrame(float timestamp) const
|
||||
{
|
||||
if (auto animationBackend = animationBackend_.lock()) {
|
||||
animationBackend->onAnimationFrame(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::weak_ptr<UIManagerAnimationBackend> animationBackend_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -20,7 +20,6 @@ target_link_libraries(react_renderer_animationbackend
|
||||
react_renderer_graphics
|
||||
react_renderer_mounting
|
||||
react_renderer_uimanager
|
||||
react_renderer_scheduler
|
||||
glog
|
||||
folly_runtime
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ target_link_libraries(react_renderer_scheduler
|
||||
react_featureflags
|
||||
react_performance_cdpmetrics
|
||||
react_performance_timeline
|
||||
react_renderer_animationbackend
|
||||
react_renderer_componentregistry
|
||||
react_renderer_core
|
||||
react_renderer_debug
|
||||
@@ -36,3 +37,4 @@ target_link_libraries(react_renderer_scheduler
|
||||
)
|
||||
target_compile_reactnative_options(react_renderer_scheduler PRIVATE)
|
||||
target_compile_options(react_renderer_scheduler PRIVATE -Wpedantic)
|
||||
target_compile_definitions(react_renderer_scheduler PRIVATE RN_USE_ANIMATION_BACKEND)
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#include <react/renderer/runtimescheduler/RuntimeScheduler.h>
|
||||
#include <react/renderer/uimanager/UIManager.h>
|
||||
#include <react/renderer/uimanager/UIManagerBinding.h>
|
||||
#ifdef RN_USE_ANIMATION_BACKEND
|
||||
#include <react/renderer/animationbackend/AnimationBackend.h>
|
||||
#endif
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
@@ -55,6 +58,18 @@ Scheduler::Scheduler(
|
||||
auto uiManager =
|
||||
std::make_shared<UIManager>(runtimeExecutor_, contextContainer_);
|
||||
|
||||
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
|
||||
#ifdef RN_USE_ANIMATION_BACKEND
|
||||
auto animationBackend = std::make_shared<AnimationBackend>(
|
||||
schedulerToolbox.animationChoreographer, uiManager);
|
||||
|
||||
schedulerToolbox.animationChoreographer->setAnimationBackend(
|
||||
animationBackend);
|
||||
|
||||
uiManager->unstable_setAnimationBackend(animationBackend);
|
||||
#endif
|
||||
}
|
||||
|
||||
auto eventOwnerBox = std::make_shared<EventBeat::OwnerBox>();
|
||||
eventOwnerBox->owner = eventDispatcher_;
|
||||
|
||||
|
||||
@@ -46,8 +46,6 @@ class Scheduler final : public UIManagerDelegate {
|
||||
|
||||
/*
|
||||
* Registers and unregisters a `SurfaceHandler` object in the `Scheduler`.
|
||||
* All registered `SurfaceHandler` objects must be unregistered
|
||||
* (with the same `Scheduler`) before their deallocation.
|
||||
*/
|
||||
void registerSurface(const SurfaceHandler &surfaceHandler) const noexcept;
|
||||
void unregisterSurface(const SurfaceHandler &surfaceHandler) const noexcept;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include <ReactCommon/RuntimeExecutor.h>
|
||||
#include <react/renderer/animationbackend/AnimationChoreographer.h>
|
||||
#include <react/renderer/componentregistry/ComponentDescriptorFactory.h>
|
||||
#include <react/renderer/core/EventBeat.h>
|
||||
#include <react/renderer/leakchecker/LeakChecker.h>
|
||||
@@ -58,6 +59,12 @@ struct SchedulerToolbox final {
|
||||
* A list of `UIManagerCommitHook`s that should be registered in `UIManager`.
|
||||
*/
|
||||
std::vector<std::shared_ptr<UIManagerCommitHook>> commitHooks;
|
||||
|
||||
/*
|
||||
* Platform-specific choreographer for scheduling animation frame
|
||||
* callbacks. Required when useSharedAnimatedBackend() is enabled.
|
||||
*/
|
||||
std::shared_ptr<AnimationChoreographer> animationChoreographer;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
@@ -207,9 +207,7 @@ void UIManager::completeSurface(
|
||||
surfaceId, shadowTree.getCurrentRevision().rootShadowNode);
|
||||
|
||||
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
|
||||
if (auto animationBackend = animationBackend_.lock()) {
|
||||
animationBackend->clearRegistry(surfaceId);
|
||||
}
|
||||
animationBackend_->clearRegistry(surfaceId);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -437,8 +435,8 @@ void UIManager::setNativeProps_DEPRECATED(
|
||||
if (family.nativeProps_DEPRECATED) {
|
||||
// Values in `rawProps` patch (take precedence over)
|
||||
// `nativeProps_DEPRECATED`. For example, if both `nativeProps_DEPRECATED`
|
||||
// and `rawProps` contain key 'A'. Value from `rawProps` overrides what was
|
||||
// previously in `nativeProps_DEPRECATED`.
|
||||
// and `rawProps` contain key 'A'. Value from `rawProps` overrides what
|
||||
// was previously in `nativeProps_DEPRECATED`.
|
||||
family.nativeProps_DEPRECATED =
|
||||
std::make_unique<folly::dynamic>(mergeDynamicProps(
|
||||
*family.nativeProps_DEPRECATED,
|
||||
@@ -529,9 +527,9 @@ std::shared_ptr<const ShadowNode> UIManager::findShadowNodeByTag_DEPRECATED(
|
||||
// pointer to a root node because of the possible data race.
|
||||
// To work around this, we ask for a commit and immediately cancel it
|
||||
// returning `nullptr` instead of a new shadow tree.
|
||||
// We don't want to add a way to access a stored pointer to a root node
|
||||
// because this `findShadowNodeByTag` is deprecated. It is only added
|
||||
// to make migration to the new architecture easier.
|
||||
// We don't want to add a way to access a stored pointer to a root
|
||||
// node because this `findShadowNodeByTag` is deprecated. It is only
|
||||
// added to make migration to the new architecture easier.
|
||||
shadowTree.tryCommit(
|
||||
[&](const RootShadowNode& oldRootShadowNode) {
|
||||
rootShadowNode = &oldRootShadowNode;
|
||||
@@ -687,7 +685,7 @@ void UIManager::setNativeAnimatedDelegate(
|
||||
}
|
||||
|
||||
void UIManager::unstable_setAnimationBackend(
|
||||
std::weak_ptr<UIManagerAnimationBackend> animationBackend) {
|
||||
std::shared_ptr<UIManagerAnimationBackend> animationBackend) {
|
||||
animationBackend_ = animationBackend;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class UIManager final : public ShadowTreeDelegate {
|
||||
/**
|
||||
* Sets and gets UIManager's AnimationBackend reference.
|
||||
*/
|
||||
void unstable_setAnimationBackend(std::weak_ptr<UIManagerAnimationBackend> animationBackend);
|
||||
void unstable_setAnimationBackend(std::shared_ptr<UIManagerAnimationBackend> animationBackend);
|
||||
std::weak_ptr<UIManagerAnimationBackend> unstable_getAnimationBackend();
|
||||
|
||||
/**
|
||||
@@ -248,7 +248,7 @@ class UIManager final : public ShadowTreeDelegate {
|
||||
|
||||
std::unique_ptr<LazyShadowTreeRevisionConsistencyManager> lazyShadowTreeRevisionConsistencyManager_;
|
||||
|
||||
std::weak_ptr<UIManagerAnimationBackend> animationBackend_;
|
||||
std::shared_ptr<UIManagerAnimationBackend> animationBackend_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
+7
-1
@@ -7,20 +7,26 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ReactCommon/CallInvoker.h>
|
||||
#include <react/renderer/components/view/BaseViewProps.h>
|
||||
#include <react/renderer/core/ShadowNodeFamily.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
struct AnimationMutations;
|
||||
|
||||
class UIManagerAnimationBackend {
|
||||
public:
|
||||
using Callback = std::function<AnimationMutations(float)>;
|
||||
|
||||
virtual ~UIManagerAnimationBackend() = default;
|
||||
|
||||
virtual void onAnimationFrame(double timestamp) = 0;
|
||||
// TODO: T240293839 Move over start() function and mutation types
|
||||
virtual void start(const Callback &callback, bool isAsync) = 0;
|
||||
virtual void stop(bool isAsync) = 0;
|
||||
virtual void clearRegistry(SurfaceId surfaceId) = 0;
|
||||
virtual void trigger() = 0;
|
||||
virtual void registerJSInvoker(std::shared_ptr<CallInvoker> jsInvoker) = 0;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <react/devsupport/IDevUIDelegate.h>
|
||||
#include <react/devsupport/PackagerConnection.h>
|
||||
#include <react/devsupport/inspector/Inspector.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/http/IHttpClient.h>
|
||||
#include <react/http/IWebSocketClient.h>
|
||||
#include <react/io/ResourceLoader.h>
|
||||
@@ -52,6 +53,7 @@ struct ReactInstanceData {
|
||||
std::shared_ptr<NativeAnimatedNodesManagerProvider>
|
||||
animatedNodesManagerProvider;
|
||||
ReactInstance::BindingsInstallFunc bindingsInstallFunc;
|
||||
std::shared_ptr<AnimationChoreographer> animationChoreographer;
|
||||
};
|
||||
|
||||
ReactHost::ReactHost(
|
||||
@@ -66,7 +68,8 @@ ReactHost::ReactHost(
|
||||
std::shared_ptr<SurfaceDelegate> logBoxSurfaceDelegate,
|
||||
std::shared_ptr<NativeAnimatedNodesManagerProvider>
|
||||
animatedNodesManagerProvider,
|
||||
ReactInstance::BindingsInstallFunc bindingsInstallFunc)
|
||||
ReactInstance::BindingsInstallFunc bindingsInstallFunc,
|
||||
std::shared_ptr<AnimationChoreographer> animationChoreographer)
|
||||
: reactInstanceConfig_(std::move(reactInstanceConfig)) {
|
||||
auto componentRegistryFactory =
|
||||
mountingManager->getComponentRegistryFactory();
|
||||
@@ -82,7 +85,8 @@ ReactHost::ReactHost(
|
||||
.turboModuleProviders = std::move(turboModuleProviders),
|
||||
.logBoxSurfaceDelegate = logBoxSurfaceDelegate,
|
||||
.animatedNodesManagerProvider = animatedNodesManagerProvider,
|
||||
.bindingsInstallFunc = std::move(bindingsInstallFunc)});
|
||||
.bindingsInstallFunc = std::move(bindingsInstallFunc),
|
||||
.animationChoreographer = std::move(animationChoreographer)});
|
||||
if (!reactInstanceData_->contextContainer
|
||||
->find<MessageQueueThreadFactory>(MessageQueueThreadFactoryKey)
|
||||
.has_value()) {
|
||||
@@ -223,11 +227,13 @@ void ReactHost::createReactInstance() {
|
||||
return runLoopObserverManager->createEventBeat(
|
||||
ownerBox, *runtimeScheduler);
|
||||
};
|
||||
toolbox.animationChoreographer = reactInstanceData_->animationChoreographer;
|
||||
|
||||
schedulerDelegate_ = std::make_unique<SchedulerDelegateImpl>(
|
||||
reactInstanceData_->mountingManager);
|
||||
scheduler_ =
|
||||
std::make_unique<Scheduler>(toolbox, nullptr, schedulerDelegate_.get());
|
||||
|
||||
surfaceManager_ = std::make_unique<SurfaceManager>(*scheduler_);
|
||||
|
||||
reactInstanceData_->mountingManager->setSchedulerTaskExecutor(
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <react/logging/DefaultLogger.h>
|
||||
#include <react/nativemodule/JavaScriptModule.h>
|
||||
#include <react/nativemodule/TurboModuleProvider.h>
|
||||
#include <react/renderer/animationbackend/AnimationChoreographer.h>
|
||||
#include <react/renderer/scheduler/Scheduler.h>
|
||||
#include <react/runtime/ReactInstance.h>
|
||||
#include <react/utils/RunLoopObserverManager.h>
|
||||
@@ -51,7 +52,8 @@ class ReactHost {
|
||||
TurboModuleProviders turboModuleProviders = {},
|
||||
std::shared_ptr<SurfaceDelegate> logBoxSurfaceDelegate = nullptr,
|
||||
std::shared_ptr<NativeAnimatedNodesManagerProvider> animatedNodesManagerProvider = nullptr,
|
||||
ReactInstance::BindingsInstallFunc bindingsInstallFunc = nullptr);
|
||||
ReactInstance::BindingsInstallFunc bindingsInstallFunc = nullptr,
|
||||
std::shared_ptr<AnimationChoreographer> animationChoreographer = nullptr);
|
||||
ReactHost(const ReactHost &) = delete;
|
||||
ReactHost &operator=(const ReactHost &) = delete;
|
||||
ReactHost(ReactHost &&) noexcept = delete;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "TesterAnimationChoreographer.h"
|
||||
#include <react/renderer/core/ReactPrimitives.h>
|
||||
#include <react/runtime/ReactInstanceConfig.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
void TesterAnimationChoreographer::resume() {
|
||||
isPaused_ = false;
|
||||
}
|
||||
void TesterAnimationChoreographer::pause() {
|
||||
isPaused_ = true;
|
||||
}
|
||||
|
||||
void TesterAnimationChoreographer::runUITick(float timestamp) {
|
||||
if (!isPaused_) {
|
||||
onAnimationFrame(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/renderer/animationbackend/AnimationChoreographer.h>
|
||||
#include <react/renderer/core/ReactPrimitives.h>
|
||||
#include <react/runtime/ReactInstanceConfig.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class TesterAnimationChoreographer : public AnimationChoreographer {
|
||||
public:
|
||||
void resume() override;
|
||||
void pause() override;
|
||||
void runUITick(float timestamp);
|
||||
|
||||
private:
|
||||
bool isPaused_{false};
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <folly/json.h>
|
||||
#include <glog/logging.h>
|
||||
#include <logger/react_native_log.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/io/ImageLoaderModule.h>
|
||||
#include <react/logging/DefaultOnJsErrorHandler.h>
|
||||
#include <react/nativemodule/cputime/NativeCPUTime.h>
|
||||
@@ -109,11 +110,19 @@ TesterAppDelegate::TesterAppDelegate(
|
||||
|
||||
g_setNativeAnimatedNowTimestampFunction(StubClock::now);
|
||||
|
||||
auto provider = std::make_shared<NativeAnimatedNodesManagerProvider>(
|
||||
[this](std::function<void()>&& onRender, bool /*isAsync*/) {
|
||||
onAnimationRender_ = std::move(onRender);
|
||||
},
|
||||
[this](bool /*isAsync*/) { onAnimationRender_ = nullptr; });
|
||||
std::shared_ptr<NativeAnimatedNodesManagerProvider> provider;
|
||||
|
||||
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
|
||||
provider = std::make_shared<NativeAnimatedNodesManagerProvider>();
|
||||
} else {
|
||||
provider = std::make_shared<NativeAnimatedNodesManagerProvider>(
|
||||
[this](std::function<void()>&& onRender, bool /*isAsync*/) {
|
||||
onAnimationRender_ = std::move(onRender);
|
||||
},
|
||||
[this](bool /*isAsync*/) { onAnimationRender_ = nullptr; });
|
||||
}
|
||||
|
||||
animationChoreographer_ = std::make_shared<TesterAnimationChoreographer>();
|
||||
|
||||
reactHost_ = std::make_unique<ReactHost>(
|
||||
reactInstanceConfig,
|
||||
@@ -125,7 +134,9 @@ TesterAppDelegate::TesterAppDelegate(
|
||||
nullptr,
|
||||
turboModuleProviders,
|
||||
nullptr,
|
||||
std::move(provider));
|
||||
std::move(provider),
|
||||
nullptr,
|
||||
animationChoreographer_);
|
||||
|
||||
// Ensure that the ReactHost initialisation is completed.
|
||||
// This will call `setupJSNativeFantom`.
|
||||
@@ -253,7 +264,12 @@ void TesterAppDelegate::produceFramesForDuration(double milliseconds) {
|
||||
}
|
||||
|
||||
void TesterAppDelegate::runUITick() {
|
||||
if (onAnimationRender_) {
|
||||
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
|
||||
auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
StubClock::now().time_since_epoch())
|
||||
.count();
|
||||
animationChoreographer_->runUITick(static_cast<float>(microseconds) / 1000);
|
||||
} else if (onAnimationRender_) {
|
||||
onAnimationRender_();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "TesterAnimationChoreographer.h"
|
||||
#include "TesterMountingManager.h"
|
||||
|
||||
namespace facebook::jsi {
|
||||
@@ -72,6 +73,8 @@ class TesterAppDelegate {
|
||||
|
||||
std::shared_ptr<TesterMountingManager> mountingManager_;
|
||||
|
||||
std::shared_ptr<TesterAnimationChoreographer> animationChoreographer_;
|
||||
|
||||
private:
|
||||
void runUITick();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user