mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Integrate execution of C++ ViewManagers in React Native Android renderer
Summary: Execution of C++ ViewManagers in RN Android renderer changelog: [internal] internal Reviewed By: sammy-SC Differential Revision: D38725770 fbshipit-source-id: cd18e02940c4cb2559acdaf535e60f98b4cada13
This commit is contained in:
committed by
Facebook GitHub Bot
parent
0519dfeeaf
commit
5fb0ad0a48
+11
@@ -16,6 +16,7 @@ import com.facebook.common.logging.FLog;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.ReactMarker;
|
||||
import com.facebook.react.bridge.ReactMarkerConstants;
|
||||
import com.facebook.react.fabric.CppViewMutationsWrapper;
|
||||
import com.facebook.react.fabric.events.EventEmitterWrapper;
|
||||
import com.facebook.react.fabric.mounting.MountingManager;
|
||||
import com.facebook.react.fabric.mounting.SurfaceMountingManager;
|
||||
@@ -50,6 +51,7 @@ public class IntBufferBatchMountItem implements MountItem {
|
||||
static final int INSTRUCTION_UPDATE_PADDING = 512;
|
||||
static final int INSTRUCTION_UPDATE_OVERFLOW_INSET = 1024;
|
||||
static final int INSTRUCTION_REMOVE_DELETE_TREE = 2048;
|
||||
static final int INSTRUCTION_RUN_CPP_VIEWS = 4096;
|
||||
|
||||
private final int mSurfaceId;
|
||||
private final int mCommitNumber;
|
||||
@@ -97,6 +99,10 @@ public class IntBufferBatchMountItem implements MountItem {
|
||||
return obj != null ? (EventEmitterWrapper) obj : null;
|
||||
}
|
||||
|
||||
private static CppViewMutationsWrapper castToCppViewMutationWrapper(Object obj) {
|
||||
return obj != null ? (CppViewMutationsWrapper) obj : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NonNull MountingManager mountingManager) {
|
||||
SurfaceMountingManager surfaceMountingManager = mountingManager.getSurfaceManager(mSurfaceId);
|
||||
@@ -178,6 +184,8 @@ public class IntBufferBatchMountItem implements MountItem {
|
||||
} else if (type == INSTRUCTION_UPDATE_EVENT_EMITTER) {
|
||||
surfaceMountingManager.updateEventEmitter(
|
||||
mIntBuffer[i++], castToEventEmitter(mObjBuffer[j++]));
|
||||
} else if (type == INSTRUCTION_RUN_CPP_VIEWS) {
|
||||
castToCppViewMutationWrapper(mObjBuffer[j++]).runCppViewMutations();
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid type argument to IntBufferBatchMountItem: " + type + " at index: " + i);
|
||||
@@ -280,6 +288,9 @@ public class IntBufferBatchMountItem implements MountItem {
|
||||
} else if (type == INSTRUCTION_UPDATE_EVENT_EMITTER) {
|
||||
j += 1;
|
||||
s.append(String.format("UPDATE EVENTEMITTER [%d]\n", mIntBuffer[i++]));
|
||||
} else if (type == INSTRUCTION_RUN_CPP_VIEWS) {
|
||||
j += 1;
|
||||
s.append(String.format("RUN CPP_VIEWS [%d]\n", mIntBuffer[i++]));
|
||||
} else {
|
||||
FLog.e(TAG, "String so far: " + s.toString());
|
||||
throw new IllegalArgumentException(
|
||||
|
||||
@@ -24,6 +24,7 @@ rn_xplat_cxx_library(
|
||||
soname = "libfabricjni.$(ext)",
|
||||
visibility = ["PUBLIC"],
|
||||
deps = [
|
||||
react_native_xplat_target("butter:butter"),
|
||||
react_native_xplat_target("react/renderer/mapbuffer:mapbuffer"),
|
||||
react_native_xplat_target("react/config:config"),
|
||||
react_native_xplat_target("react/renderer/animations:animations"),
|
||||
|
||||
@@ -382,13 +382,17 @@ void Binding::installFabricUIManager(
|
||||
<< this << ").";
|
||||
}
|
||||
|
||||
sharedCppComponentRegistry_ =
|
||||
std::shared_ptr<const facebook::react::CppComponentRegistry>(
|
||||
cppComponentRegistry ? cppComponentRegistry : nullptr);
|
||||
|
||||
// Use std::lock and std::adopt_lock to prevent deadlocks by locking mutexes
|
||||
// at the same time
|
||||
std::unique_lock<butter::shared_mutex> lock(installMutex_);
|
||||
|
||||
auto globalJavaUiManager = make_global(javaUIManager);
|
||||
mountingManager_ =
|
||||
std::make_shared<FabricMountingManager>(config, globalJavaUiManager);
|
||||
mountingManager_ = std::make_shared<FabricMountingManager>(
|
||||
config, sharedCppComponentRegistry_, globalJavaUiManager);
|
||||
|
||||
ContextContainer::Shared contextContainer =
|
||||
std::make_shared<ContextContainer>();
|
||||
|
||||
@@ -73,6 +73,7 @@ struct CppMountItem final {
|
||||
UpdatePadding = 512,
|
||||
UpdateOverflowInset = 1024,
|
||||
RemoveDeleteTree = 2048,
|
||||
RunCPPMutations = 4096
|
||||
};
|
||||
|
||||
#pragma mark - Fields
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "FabricMountingManager.h"
|
||||
#include "CppViewMutationsWrapper.h"
|
||||
#include "EventEmitterWrapper.h"
|
||||
#include "StateWrapperImpl.h"
|
||||
#include "viewPropConversions.h"
|
||||
@@ -38,8 +39,10 @@ static bool getFeatureFlagValue(const char *name) {
|
||||
|
||||
FabricMountingManager::FabricMountingManager(
|
||||
std::shared_ptr<const ReactNativeConfig> &config,
|
||||
std::shared_ptr<const CppComponentRegistry> &cppComponentRegistry,
|
||||
global_ref<jobject> &javaUIManager)
|
||||
: javaUIManager_(javaUIManager),
|
||||
cppComponentRegistry_(cppComponentRegistry),
|
||||
enableEarlyEventEmitterUpdate_(
|
||||
config->getBool("react_fabric:enable_early_event_emitter_update")),
|
||||
disablePreallocateViews_(
|
||||
@@ -82,6 +85,8 @@ static inline int getIntBufferSizeForType(CppMountItem::Type mountItemType) {
|
||||
return 7; // tag, parentTag, x, y, w, h, DisplayType
|
||||
case CppMountItem::Type::UpdateOverflowInset:
|
||||
return 5; // tag, left, top, right, bottom
|
||||
case CppMountItem::Type::RunCPPMutations:
|
||||
return 1;
|
||||
case CppMountItem::Undefined:
|
||||
case CppMountItem::Multiple:
|
||||
return -1;
|
||||
@@ -124,7 +129,8 @@ static inline void computeBufferSizes(
|
||||
std::vector<CppMountItem> &cppUpdatePaddingMountItems,
|
||||
std::vector<CppMountItem> &cppUpdateLayoutMountItems,
|
||||
std::vector<CppMountItem> &cppUpdateOverflowInsetMountItems,
|
||||
std::vector<CppMountItem> &cppUpdateEventEmitterMountItems) {
|
||||
std::vector<CppMountItem> &cppUpdateEventEmitterMountItems,
|
||||
ShadowViewMutationList &cppViewMutations) {
|
||||
CppMountItem::Type lastType = CppMountItem::Type::Undefined;
|
||||
int numSameType = 0;
|
||||
for (auto const &mountItem : cppCommonMountItems) {
|
||||
@@ -183,6 +189,11 @@ static inline void computeBufferSizes(
|
||||
cppDeleteMountItems.size(),
|
||||
batchMountItemIntsSize,
|
||||
batchMountItemObjectsSize);
|
||||
|
||||
if (cppViewMutations.size() > 0) {
|
||||
batchMountItemIntsSize++;
|
||||
batchMountItemObjectsSize++;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void writeIntBufferTypePreamble(
|
||||
@@ -293,7 +304,7 @@ void FabricMountingManager::executeMount(
|
||||
std::vector<CppMountItem> cppUpdateLayoutMountItems;
|
||||
std::vector<CppMountItem> cppUpdateOverflowInsetMountItems;
|
||||
std::vector<CppMountItem> cppUpdateEventEmitterMountItems;
|
||||
|
||||
auto cppViewMutations = ShadowViewMutationList();
|
||||
{
|
||||
std::lock_guard allocatedViewsLock(allocatedViewsMutex_);
|
||||
|
||||
@@ -318,6 +329,25 @@ void FabricMountingManager::executeMount(
|
||||
|
||||
bool isVirtual = mutation.mutatedViewIsVirtual();
|
||||
|
||||
// Detect if the mutation instruction belongs to C++ view managers
|
||||
if (cppComponentRegistry_) {
|
||||
auto componentName = newChildShadowView.componentName
|
||||
? newChildShadowView.componentName
|
||||
: oldChildShadowView.componentName;
|
||||
auto name = std::string(componentName);
|
||||
if (cppComponentRegistry_->containsComponentManager(name)) {
|
||||
// is this thread safe?
|
||||
cppViewMutations.push_back(mutation);
|
||||
|
||||
// This is a hack that could be avoided by using Portals
|
||||
// Only execute mutations instructions for Root C++ ViewManagers
|
||||
// because Root C++ Components have a Android view counterpart.
|
||||
if (!cppComponentRegistry_->isRootComponent(name)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (mutationType) {
|
||||
case ShadowViewMutation::Create: {
|
||||
bool revisionCheck =
|
||||
@@ -502,7 +532,8 @@ void FabricMountingManager::executeMount(
|
||||
cppUpdatePaddingMountItems,
|
||||
cppUpdateLayoutMountItems,
|
||||
cppUpdateOverflowInsetMountItems,
|
||||
cppUpdateEventEmitterMountItems);
|
||||
cppUpdateEventEmitterMountItems,
|
||||
cppViewMutations);
|
||||
|
||||
static auto createMountItemsIntBufferBatchContainer =
|
||||
jni::findClassStatic(UIManagerJavaDescriptor)
|
||||
@@ -809,6 +840,36 @@ void FabricMountingManager::executeMount(
|
||||
}
|
||||
}
|
||||
|
||||
if (cppViewMutations.size() > 0) {
|
||||
writeIntBufferTypePreamble(
|
||||
CppMountItem::Type::RunCPPMutations,
|
||||
1,
|
||||
env,
|
||||
intBufferArray,
|
||||
intBufferPosition);
|
||||
|
||||
// TODO review this logic and memory mamangement
|
||||
// this might not be necessary:
|
||||
// temp[0] = 1234;
|
||||
// env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp);
|
||||
// intBufferPosition += 1;
|
||||
|
||||
// Do not hold a reference to javaCppMutations from the C++ side.
|
||||
auto javaCppMutations = CppViewMutationsWrapper::newObjectJavaArgs();
|
||||
CppViewMutationsWrapper *cppViewMutationsWrapper = cthis(javaCppMutations);
|
||||
|
||||
// TODO move this to init methods
|
||||
cppViewMutationsWrapper->cppComponentRegistry = cppComponentRegistry_;
|
||||
// TODO is moving the cppViewMutations safe / thread safe?
|
||||
// cppViewMutations will be accessed from the UI Thread in a near future
|
||||
// can they dissapear?
|
||||
cppViewMutationsWrapper->cppViewMutations =
|
||||
std::make_shared<std::vector<facebook::react::ShadowViewMutation>>(
|
||||
std::move(cppViewMutations));
|
||||
|
||||
(*objBufferArray)[objBufferPosition++] = javaCppMutations.get();
|
||||
}
|
||||
|
||||
// If there are no items, we pass a nullptr instead of passing the object
|
||||
// through the JNI
|
||||
auto batch = createMountItemsIntBufferBatchContainer(
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CppComponentRegistry.h"
|
||||
#include "FabricMountItem.h"
|
||||
|
||||
#include <react/config/ReactNativeConfig.h>
|
||||
@@ -33,6 +34,7 @@ class FabricMountingManager final {
|
||||
|
||||
FabricMountingManager(
|
||||
std::shared_ptr<const ReactNativeConfig> &config,
|
||||
std::shared_ptr<const CppComponentRegistry> &cppComponentRegistry,
|
||||
jni::global_ref<jobject> &javaUIManager);
|
||||
|
||||
void onSurfaceStart(SurfaceId surfaceId);
|
||||
@@ -68,6 +70,7 @@ class FabricMountingManager final {
|
||||
|
||||
butter::map<SurfaceId, butter::set<Tag>> allocatedViewRegistry_{};
|
||||
std::recursive_mutex allocatedViewsMutex_;
|
||||
std::shared_ptr<const CppComponentRegistry> cppComponentRegistry_;
|
||||
|
||||
bool const enableEarlyEventEmitterUpdate_{false};
|
||||
bool const disablePreallocateViews_{false};
|
||||
|
||||
Reference in New Issue
Block a user