Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions packages/react-native/ReactCommon/React-Fabric.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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_ =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
Expand All @@ -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,
Expand Down Expand Up @@ -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) {
Expand All @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "AnimatedProps.h"
#include "AnimatedPropsRegistry.h"
#include "AnimationBackendCommitHook.h"
#include "AnimationChoreographer.h"

namespace facebook::react {

Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Loading
Loading