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 @@ -25,6 +25,7 @@ import com.facebook.react.bridge.UIManagerListener
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.fabric.mounting.MountingManager
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags

/**
* Manages bitmap snapshots of views during view transitions. Captures bitmaps from old views and
Expand Down Expand Up @@ -76,9 +77,10 @@ internal class ViewTransitionSnapshotManager(
}

/**
* Captures a bitmap snapshot of the view identified by the given tag. On API 26+, uses PixelCopy
* to capture directly from the GPU-composited surface (faster for complex views, captures
* hardware-accelerated content). Falls back to View.draw() on older APIs.
* Captures a bitmap snapshot of the view identified by the given tag. When
* [ReactNativeFeatureFlags.viewTransitionUseHardwareBitmapAndroid] is enabled and API 26+, uses
* PixelCopy to capture directly from the GPU-composited surface. Otherwise falls back to
* View.draw() which runs synchronously.
*/
fun captureViewSnapshot(reactTag: Int, surfaceId: Int) {
UiThreadUtil.runOnUiThread {
Expand All @@ -87,15 +89,17 @@ internal class ViewTransitionSnapshotManager(
val view = smm.getView(reactTag)
if (view.width <= 0 || view.height <= 0) return@runOnUiThread

val window =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (
ReactNativeFeatureFlags.viewTransitionUseHardwareBitmapAndroid() &&
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
) {
val window =
(view.context as? com.facebook.react.bridge.ReactContext)?.getCurrentActivity()?.window
} else {
null
}

if (window != null) {
captureHardwareBitmap(view, reactTag, window)
if (window != null) {
captureHardwareBitmap(view, reactTag, window)
} else {
captureSoftwareBitmap(view)?.let { onBitmapCaptured(reactTag, it) }
}
} else {
// Software fallback runs synchronously, so onBitmapCaptured always
// completes before setViewSnapshot is called.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<1eca66b21554b00725f2a9be894a0db9>>
* @generated SignedSource<<61221e9b185b4e9b9f0db0c99c7c9dc1>>
*/

/**
Expand Down Expand Up @@ -576,6 +576,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun viewTransitionEnabled(): Boolean = accessor.viewTransitionEnabled()

/**
* Use hardware bitmaps for view transition snapshots on Android.
*/
@JvmStatic
public fun viewTransitionUseHardwareBitmapAndroid(): Boolean = accessor.viewTransitionUseHardwareBitmapAndroid()

/**
* Initial prerender ratio for VirtualView.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<76d977ea53cb2a37fc2ea8549e31cebd>>
* @generated SignedSource<<f23dc5d7320599de13f35700a09d783a>>
*/

/**
Expand Down Expand Up @@ -111,6 +111,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var useUnorderedMapInDifferentiatorCache: Boolean? = null
private var viewCullingOutsetRatioCache: Double? = null
private var viewTransitionEnabledCache: Boolean? = null
private var viewTransitionUseHardwareBitmapAndroidCache: Boolean? = null
private var virtualViewPrerenderRatioCache: Double? = null

override fun commonTestFlag(): Boolean {
Expand Down Expand Up @@ -932,6 +933,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}

override fun viewTransitionUseHardwareBitmapAndroid(): Boolean {
var cached = viewTransitionUseHardwareBitmapAndroidCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.viewTransitionUseHardwareBitmapAndroid()
viewTransitionUseHardwareBitmapAndroidCache = cached
}
return cached
}

override fun virtualViewPrerenderRatio(): Double {
var cached = virtualViewPrerenderRatioCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<a737810bf0211590401c2afb464aaf37>>
* @generated SignedSource<<c398ef6325753f5666737fb84309c09e>>
*/

/**
Expand Down Expand Up @@ -210,6 +210,8 @@ public object ReactNativeFeatureFlagsCxxInterop {

@DoNotStrip @JvmStatic public external fun viewTransitionEnabled(): Boolean

@DoNotStrip @JvmStatic public external fun viewTransitionUseHardwareBitmapAndroid(): Boolean

@DoNotStrip @JvmStatic public external fun virtualViewPrerenderRatio(): Double

@DoNotStrip @JvmStatic public external fun override(provider: Any)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<9e5b3192d1bec953c116d959ad63283d>>
* @generated SignedSource<<4ba79f6843185d86bc9ad487b99d86a4>>
*/

/**
Expand Down Expand Up @@ -205,5 +205,7 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi

override fun viewTransitionEnabled(): Boolean = false

override fun viewTransitionUseHardwareBitmapAndroid(): Boolean = false

override fun virtualViewPrerenderRatio(): Double = 5.0
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<378d6a8de497d26ebbbf55885be27a21>>
* @generated SignedSource<<60a15dc6eb548f56216f284421c1e4da>>
*/

/**
Expand Down Expand Up @@ -115,6 +115,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var useUnorderedMapInDifferentiatorCache: Boolean? = null
private var viewCullingOutsetRatioCache: Double? = null
private var viewTransitionEnabledCache: Boolean? = null
private var viewTransitionUseHardwareBitmapAndroidCache: Boolean? = null
private var virtualViewPrerenderRatioCache: Double? = null

override fun commonTestFlag(): Boolean {
Expand Down Expand Up @@ -1027,6 +1028,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}

override fun viewTransitionUseHardwareBitmapAndroid(): Boolean {
var cached = viewTransitionUseHardwareBitmapAndroidCache
if (cached == null) {
cached = currentProvider.viewTransitionUseHardwareBitmapAndroid()
accessedFeatureFlags.add("viewTransitionUseHardwareBitmapAndroid")
viewTransitionUseHardwareBitmapAndroidCache = cached
}
return cached
}

override fun virtualViewPrerenderRatio(): Double {
var cached = virtualViewPrerenderRatioCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<42e555a40da280b24f84e3ee5b45051d>>
* @generated SignedSource<<b353ae56cf0cd23d93be23a675b30de1>>
*/

/**
Expand Down Expand Up @@ -205,5 +205,7 @@ public interface ReactNativeFeatureFlagsProvider {

@DoNotStrip public fun viewTransitionEnabled(): Boolean

@DoNotStrip public fun viewTransitionUseHardwareBitmapAndroid(): Boolean

@DoNotStrip public fun virtualViewPrerenderRatio(): Double
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<d9ed25122f1ff64122bfc83f8e5e9545>>
* @generated SignedSource<<93d9279dba687d7f660a6797549c0819>>
*/

/**
Expand Down Expand Up @@ -585,6 +585,12 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}

bool viewTransitionUseHardwareBitmapAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("viewTransitionUseHardwareBitmapAndroid");
return method(javaProvider_);
}

double virtualViewPrerenderRatio() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jdouble()>("virtualViewPrerenderRatio");
Expand Down Expand Up @@ -1050,6 +1056,11 @@ bool JReactNativeFeatureFlagsCxxInterop::viewTransitionEnabled(
return ReactNativeFeatureFlags::viewTransitionEnabled();
}

bool JReactNativeFeatureFlagsCxxInterop::viewTransitionUseHardwareBitmapAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::viewTransitionUseHardwareBitmapAndroid();
}

double JReactNativeFeatureFlagsCxxInterop::virtualViewPrerenderRatio(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::virtualViewPrerenderRatio();
Expand Down Expand Up @@ -1359,6 +1370,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"viewTransitionEnabled",
JReactNativeFeatureFlagsCxxInterop::viewTransitionEnabled),
makeNativeMethod(
"viewTransitionUseHardwareBitmapAndroid",
JReactNativeFeatureFlagsCxxInterop::viewTransitionUseHardwareBitmapAndroid),
makeNativeMethod(
"virtualViewPrerenderRatio",
JReactNativeFeatureFlagsCxxInterop::virtualViewPrerenderRatio),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<d87a80a2a88acb2187ea20b8181a7588>>
* @generated SignedSource<<ef1a37cff6b7076193c47374eb6cca15>>
*/

/**
Expand Down Expand Up @@ -303,6 +303,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool viewTransitionEnabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool viewTransitionUseHardwareBitmapAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static double virtualViewPrerenderRatio(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<ad7a835ef9cbe3a9a6121ac127038668>>
* @generated SignedSource<<0a3c6a3353d22cf5909fd5a0f98a970e>>
*/

/**
Expand Down Expand Up @@ -390,6 +390,10 @@ bool ReactNativeFeatureFlags::viewTransitionEnabled() {
return getAccessor().viewTransitionEnabled();
}

bool ReactNativeFeatureFlags::viewTransitionUseHardwareBitmapAndroid() {
return getAccessor().viewTransitionUseHardwareBitmapAndroid();
}

double ReactNativeFeatureFlags::virtualViewPrerenderRatio() {
return getAccessor().virtualViewPrerenderRatio();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<8b4288e3f5a8b26951150a3c75ad4356>>
* @generated SignedSource<<1756053d723019847c7c52bb0f663281>>
*/

/**
Expand Down Expand Up @@ -494,6 +494,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool viewTransitionEnabled();

/**
* Use hardware bitmaps for view transition snapshots on Android.
*/
RN_EXPORT static bool viewTransitionUseHardwareBitmapAndroid();

/**
* Initial prerender ratio for VirtualView.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<a2484c897651fcd970b33d8eef7d70f0>>
* @generated SignedSource<<b9bf95c8caeecac9fe6dd7ea6363953c>>
*/

/**
Expand Down Expand Up @@ -1667,6 +1667,24 @@ bool ReactNativeFeatureFlagsAccessor::viewTransitionEnabled() {
return flagValue.value();
}

bool ReactNativeFeatureFlagsAccessor::viewTransitionUseHardwareBitmapAndroid() {
auto flagValue = viewTransitionUseHardwareBitmapAndroid_.load();

if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(91, "viewTransitionUseHardwareBitmapAndroid");

flagValue = currentProvider_->viewTransitionUseHardwareBitmapAndroid();
viewTransitionUseHardwareBitmapAndroid_ = flagValue;
}

return flagValue.value();
}

double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
auto flagValue = virtualViewPrerenderRatio_.load();

Expand All @@ -1676,7 +1694,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(91, "virtualViewPrerenderRatio");
markFlagAsAccessed(92, "virtualViewPrerenderRatio");

flagValue = currentProvider_->virtualViewPrerenderRatio();
virtualViewPrerenderRatio_ = flagValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<17621e5f711352812633c125b7858537>>
* @generated SignedSource<<ff10d7b0f20f4d16eaf879a872e671f2>>
*/

/**
Expand Down Expand Up @@ -123,6 +123,7 @@ class ReactNativeFeatureFlagsAccessor {
bool useUnorderedMapInDifferentiator();
double viewCullingOutsetRatio();
bool viewTransitionEnabled();
bool viewTransitionUseHardwareBitmapAndroid();
double virtualViewPrerenderRatio();

void override(std::unique_ptr<ReactNativeFeatureFlagsProvider> provider);
Expand All @@ -135,7 +136,7 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;

std::array<std::atomic<const char*>, 92> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 93> accessedFeatureFlags_;

std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> cdpInteractionMetricsEnabled_;
Expand Down Expand Up @@ -228,6 +229,7 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> useUnorderedMapInDifferentiator_;
std::atomic<std::optional<double>> viewCullingOutsetRatio_;
std::atomic<std::optional<bool>> viewTransitionEnabled_;
std::atomic<std::optional<bool>> viewTransitionUseHardwareBitmapAndroid_;
std::atomic<std::optional<double>> virtualViewPrerenderRatio_;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<3d1718afe5b2ed63a918ffe09a4a36b1>>
* @generated SignedSource<<86113211dcbece29ea894a2fcfa7dce5>>
*/

/**
Expand Down Expand Up @@ -391,6 +391,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}

bool viewTransitionUseHardwareBitmapAndroid() override {
return false;
}

double virtualViewPrerenderRatio() override {
return 5.0;
}
Expand Down
Loading
Loading