From 3bd7da84730cc3709baccf45d4ca4627c0ac37dc Mon Sep 17 00:00:00 2001 From: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:10:22 -0700 Subject: [PATCH] Add config version, and invalidate layout on config change Summary: This is a continuation of the previous PR: https://github.com/facebook/react-native/pull/45047 I made the change more generic for allowing any kind of config change to invalidate layout. X-link: https://github.com/facebook/yoga/pull/1674 Differential Revision: D59286992 Pulled By: NickGerleman --- .../yoga/yoga/algorithm/CalculateLayout.cpp | 2 ++ .../ReactCommon/yoga/yoga/config/Config.cpp | 29 +++++++++++++++---- .../ReactCommon/yoga/yoga/config/Config.h | 3 ++ .../yoga/yoga/node/LayoutResults.cpp | 1 + .../yoga/yoga/node/LayoutResults.h | 1 + .../ReactCommon/yoga/yoga/node/Node.cpp | 5 ++++ 6 files changed, 36 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index 58394a4563210b..8db5fa41de131c 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -2140,6 +2140,7 @@ bool calculateLayoutInternal( const bool needToVisitNode = (node->isDirty() && layout->generationCount != generationCount) || + layout->configVersion != node->getConfig()->getVersion() || layout->lastOwnerDirection != ownerDirection; if (needToVisitNode) { @@ -2255,6 +2256,7 @@ bool calculateLayoutInternal( reason); layout->lastOwnerDirection = ownerDirection; + layout->configVersion = node->getConfig()->getVersion(); if (cachedResults == nullptr) { layoutMarkerData.maxMeasureCache = std::max( diff --git a/packages/react-native/ReactCommon/yoga/yoga/config/Config.cpp b/packages/react-native/ReactCommon/yoga/yoga/config/Config.cpp index 881a377360e903..0f5fb019cb1888 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/config/Config.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/config/Config.cpp @@ -31,7 +31,10 @@ bool Config::useWebDefaults() const { void Config::setExperimentalFeatureEnabled( ExperimentalFeature feature, bool enabled) { - experimentalFeatures_.set(static_cast(feature), enabled); + if (isExperimentalFeatureEnabled(feature) != enabled) { + experimentalFeatures_.set(static_cast(feature), enabled); + version_++; + } } bool Config::isExperimentalFeatureEnabled(ExperimentalFeature feature) const { @@ -43,15 +46,24 @@ ExperimentalFeatureSet Config::getEnabledExperiments() const { } void Config::setErrata(Errata errata) { - errata_ = errata; + if (errata_ != errata) { + errata_ = errata; + version_++; + } } void Config::addErrata(Errata errata) { - errata_ |= errata; + if (!hasErrata(errata)) { + errata_ |= errata; + version_++; + } } void Config::removeErrata(Errata errata) { - errata_ &= (~errata); + if (hasErrata(errata)) { + errata_ &= (~errata); + version_++; + } } Errata Config::getErrata() const { @@ -63,7 +75,10 @@ bool Config::hasErrata(Errata errata) const { } void Config::setPointScaleFactor(float pointScaleFactor) { - pointScaleFactor_ = pointScaleFactor; + if (pointScaleFactor_ != pointScaleFactor) { + pointScaleFactor_ = pointScaleFactor; + version_++; + } } float Config::getPointScaleFactor() const { @@ -78,6 +93,10 @@ void* Config::getContext() const { return context_; } +uint32_t Config::getVersion() const noexcept { + return version_; +} + void Config::setLogger(YGLogger logger) { logger_ = logger; } diff --git a/packages/react-native/ReactCommon/yoga/yoga/config/Config.h b/packages/react-native/ReactCommon/yoga/yoga/config/Config.h index 4db25bd0f4d2c1..7bcffd1484c941 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/config/Config.h +++ b/packages/react-native/ReactCommon/yoga/yoga/config/Config.h @@ -53,6 +53,8 @@ class YG_EXPORT Config : public ::YGConfig { void setContext(void* context); void* getContext() const; + uint32_t getVersion() const noexcept; + void setLogger(YGLogger logger); void log( const yoga::Node* node, @@ -72,6 +74,7 @@ class YG_EXPORT Config : public ::YGConfig { bool useWebDefaults_ : 1 = false; + uint32_t version_ = 0; ExperimentalFeatureSet experimentalFeatures_{}; Errata errata_ = Errata::None; float pointScaleFactor_ = 1.0f; diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.cpp index fd70870e65b3a7..acc37a1b4a72f3 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.cpp @@ -21,6 +21,7 @@ bool LayoutResults::operator==(LayoutResults layout) const { direction() == layout.direction() && hadOverflow() == layout.hadOverflow() && lastOwnerDirection == layout.lastOwnerDirection && + configVersion == layout.configVersion && nextCachedMeasurementsIndex == layout.nextCachedMeasurementsIndex && cachedLayout == layout.cachedLayout && computedFlexBasis == layout.computedFlexBasis; diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h index f42c27795c107d..9f0aeaf7843083 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h @@ -30,6 +30,7 @@ struct LayoutResults { // Instead of recomputing the entire layout every single time, we cache some // information to break early when nothing changed uint32_t generationCount = 0; + uint32_t configVersion = 0; Direction lastOwnerDirection = Direction::Inherit; uint32_t nextCachedMeasurementsIndex = 0; diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp index abda52f5cfe93c..f1f9633901b146 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp @@ -136,6 +136,11 @@ void Node::setConfig(yoga::Config* config) { if (yoga::configUpdateInvalidatesLayout(*config_, *config)) { markDirtyAndPropagate(); + layout_.configVersion = 0; + } else { + // If the config is functionally the same, then align the configVersion so + // that we can reuse the layout cache + layout_.configVersion = config->getVersion(); } config_ = config;