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
12 changes: 12 additions & 0 deletions packages/react-native/React/Fabric/RCTScheduler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ void schedulerDidUpdateShadowTree(const std::unordered_map<Tag, folly::dynamic>
// This delegate method is not currently used on iOS.
}

void schedulerShouldResumeAnimationFrameCallbacks() override
{
// Does nothing.
// This delegate method is not currently used on iOS.
}

void schedulerShouldPauseAnimationFrameCallbacks() override
{
// Does nothing.
// This delegate method is not currently used on iOS.
}

private:
void *scheduler_;
};
Expand Down
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
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,10 @@ void FabricUIManagerBinding::schedulerDidUpdateShadowTree(
// no-op
}

void FabricUIManagerBinding::schedulerShouldResumeAnimationFrameCallbacks() {}

void FabricUIManagerBinding::schedulerShouldPauseAnimationFrameCallbacks() {}

void FabricUIManagerBinding::onAnimationStarted() {
auto mountingManager = getMountingManager("onAnimationStarted");
if (!mountingManager) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ class FabricUIManagerBinding : public jni::HybridClass<FabricUIManagerBinding>,

void schedulerDidUpdateShadowTree(const std::unordered_map<Tag, folly::dynamic> &tagToProps) override;

void schedulerShouldResumeAnimationFrameCallbacks() override;

void schedulerShouldPauseAnimationFrameCallbacks() override;

void setPixelDensity(float pointScaleFactor);

void driveCxxAnimations();
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 @@ -559,10 +559,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 @@ -8,6 +8,7 @@
#pragma once

#include <react/renderer/animated/MergedValueDispatcher.h>
#include <react/renderer/uimanager/UIManagerAnimationBackend.h>
#include <react/renderer/uimanager/UIManagerNativeAnimatedDelegate.h>
#include "NativeAnimatedNodesManager.h"

Expand All @@ -32,7 +33,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 @@ -15,15 +15,6 @@

namespace facebook::react {

static const auto layoutProps = std::set<PropName>{
WIDTH, HEIGHT, FLEX, MARGIN, PADDING,
POSITION, BORDER_WIDTH, ALIGN_CONTENT, ALIGN_ITEMS, ALIGN_SELF,
ASPECT_RATIO, BOX_SIZING, DISPLAY, FLEX_BASIS, FLEX_DIRECTION,
ROW_GAP, COLUMN_GAP, FLEX_GROW, FLEX_SHRINK, FLEX_WRAP,
JUSTIFY_CONTENT, MAX_HEIGHT, MAX_WIDTH, MIN_HEIGHT, MIN_WIDTH,
STYLE_OVERFLOW, POSITION_TYPE, DIRECTION, Z_INDEX,
};

UIManagerNativeAnimatedDelegateBackendImpl::
UIManagerNativeAnimatedDelegateBackendImpl(
std::weak_ptr<UIManagerAnimationBackend> animationBackend)
Expand Down Expand Up @@ -61,20 +52,15 @@ 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)),
std::shared_ptr<UIManager> uiManager)
: directManipulationCallback_(std::move(directManipulationCallback)),
animatedPropsRegistry_(std::make_shared<AnimatedPropsRegistry>()),
uiManager_(uiManager),
jsInvoker_(std::move(jsInvoker)),
commitHook_(uiManager, animatedPropsRegistry_) {}
commitHook_(uiManager, animatedPropsRegistry_) {
react_native_assert(directManipulationCallback_ != nullptr);
react_native_assert(uiManager_ != nullptr);
}

void AnimationBackend::onAnimationFrame(double timestamp) {
std::unordered_map<SurfaceId, SurfaceUpdates> surfaceUpdates;
Expand Down Expand Up @@ -110,21 +96,18 @@ void AnimationBackend::onAnimationFrame(double timestamp) {

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_) {
auto delegate = uiManager_->getDelegate();
delegate->uiManagerShouldResumeAnimationBackend();
isRenderCallbackStarted_ = true;
}
}

void AnimationBackend::stop(bool isAsync) {
if (stopOnRenderCallback_) {
stopOnRenderCallback_(isAsync);
if (isRenderCallbackStarted_) {
auto delegate = uiManager_->getDelegate();
delegate->uiManagerShouldPauseAnimationBackend();
isRenderCallbackStarted_ = false;
}
callbacks.clear();
}
Expand Down Expand Up @@ -178,6 +161,9 @@ void AnimationBackend::synchronouslyUpdateProps(

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
Expand All @@ -199,4 +185,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 @@ -50,36 +50,28 @@ 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 ResumeCallback = std::function<void()>;
using PauseCallback = std::function<void()>;
using DirectManipulationCallback = std::function<void(Tag, const folly::dynamic &)>;
using FabricCommitCallback = std::function<void(std::unordered_map<Tag, folly::dynamic> &)>;

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<UIManager> uiManager_;
std::shared_ptr<CallInvoker> jsInvoker_;
AnimationBackendCommitHook commitHook_;
bool isRenderCallbackStarted_{false};

AnimationBackend(
StartOnRenderCallback &&startOnRenderCallback,
StopOnRenderCallback &&stopOnRenderCallback,
DirectManipulationCallback &&directManipulationCallback,
FabricCommitCallback &&fabricCommitCallback,
UIManager *uiManager,
std::shared_ptr<CallInvoker> jsInvoker);
AnimationBackend(DirectManipulationCallback &&directManipulationCallback, 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 @@ -10,10 +10,11 @@
namespace facebook::react {

AnimationBackendCommitHook::AnimationBackendCommitHook(
UIManager* uiManager,
std::shared_ptr<UIManager> uiManager,
std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry)
: animatedPropsRegistry_(std::move(animatedPropsRegistry)) {
uiManager->registerCommitHook(*this);
: uiManager_(uiManager),
animatedPropsRegistry_(std::move(animatedPropsRegistry)) {
uiManager_->registerCommitHook(*this);
}

RootShadowNode::Unshared AnimationBackendCommitHook::shadowTreeWillCommit(
Expand Down Expand Up @@ -73,4 +74,8 @@ RootShadowNode::Unshared AnimationBackendCommitHook::shadowTreeWillCommit(
}));
}

AnimationBackendCommitHook::~AnimationBackendCommitHook() {
uiManager_->unregisterCommitHook(*this);
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,21 @@
namespace facebook::react {

class AnimationBackendCommitHook : public UIManagerCommitHook {
std::shared_ptr<UIManager> uiManager_;
std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry_;

public:
AnimationBackendCommitHook(UIManager *uiManager, std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry);
AnimationBackendCommitHook(
std::shared_ptr<UIManager> uiManager,
std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry);
RootShadowNode::Unshared shadowTreeWillCommit(
const ShadowTree &shadowTree,
const RootShadowNode::Shared &oldRootShadowNode,
const RootShadowNode::Unshared &newRootShadowNode,
const ShadowTreeCommitOptions &commitOptions) noexcept override;
void commitHookWasRegistered(const UIManager &uiManager) noexcept override {}
void commitHookWasUnregistered(const UIManager &uiManager) noexcept override {}
~AnimationBackendCommitHook() override;
};

} // 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 Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ Scheduler::Scheduler(
auto uiManager =
std::make_shared<UIManager>(runtimeExecutor_, contextContainer_);

auto directManipulationCallback = [delegate](
Tag tag, const folly::dynamic& props) {
delegate->schedulerShouldSynchronouslyUpdateViewOnUIThread(tag, props);
};

animationBackend_ = std::make_shared<AnimationBackend>(
std::move(directManipulationCallback), uiManager);
uiManager->unstable_setAnimationBackend(animationBackend_);

auto eventOwnerBox = std::make_shared<EventBeat::OwnerBox>();
eventOwnerBox->owner = eventDispatcher_;

Expand Down Expand Up @@ -168,6 +177,8 @@ Scheduler::~Scheduler() {
uiManager_->unregisterCommitHook(*commitHook);
}

animationBackend_ = nullptr;

// All Surfaces must be explicitly stopped before destroying `Scheduler`.
// The idea is that `UIManager` is allowed to call `Scheduler` only if the
// corresponding `ShadowTree` instance exists.
Expand Down Expand Up @@ -355,6 +366,18 @@ void Scheduler::uiManagerShouldRemoveEventListener(
removeEventListener(listener);
}

void Scheduler::uiManagerShouldResumeAnimationBackend() {
if (delegate_ != nullptr) {
delegate_->schedulerShouldResumeAnimationFrameCallbacks();
}
}

void Scheduler::uiManagerShouldPauseAnimationBackend() {
if (delegate_ != nullptr) {
delegate_->schedulerShouldPauseAnimationFrameCallbacks();
}
}

void Scheduler::uiManagerDidStartSurface(const ShadowTree& shadowTree) {
std::shared_lock lock(onSurfaceStartCallbackMutex_);
if (onSurfaceStartCallback_) {
Expand Down
Loading
Loading