Skip to content

Commit ba204fa

Browse files
zeyapmeta-codesync[bot]
authored andcommitted
Use software snapshot capture unless featureflag (#56684)
Summary: Pull Request resolved: #56684 ## Changelog: [Android] [Added] - Use software snapshot capture unless featureflag Use software rendering (View.draw()) for view transition snapshots by default instead of PixelCopy. PixelCopy captures from the window surface, which includes content from overlapping views, popup layers, and hardware compositor surfaces that may visually obstruct the target view. Software rendering draws the view's subtree in isolation to an offscreen canvas, producing a snapshot of exactly the target view's content without interference from other views in the hierarchy. Reviewed By: christophpurrer Differential Revision: D103718490 fbshipit-source-id: cd2b3bebd00ea071d37ca0291050f1b510e6d49c
1 parent dd03f88 commit ba204fa

21 files changed

Lines changed: 153 additions & 32 deletions

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/ViewTransitionSnapshotManager.kt

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.facebook.react.bridge.UIManagerListener
2525
import com.facebook.react.bridge.UiThreadUtil
2626
import com.facebook.react.common.annotations.UnstableReactNativeAPI
2727
import com.facebook.react.fabric.mounting.MountingManager
28+
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
2829

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

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

90-
val window =
91-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
92+
if (
93+
ReactNativeFeatureFlags.viewTransitionUseHardwareBitmapAndroid() &&
94+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
95+
) {
96+
val window =
9297
(view.context as? com.facebook.react.bridge.ReactContext)?.getCurrentActivity()?.window
93-
} else {
94-
null
95-
}
96-
97-
if (window != null) {
98-
captureHardwareBitmap(view, reactTag, window)
98+
if (window != null) {
99+
captureHardwareBitmap(view, reactTag, window)
100+
} else {
101+
captureSoftwareBitmap(view)?.let { onBitmapCaptured(reactTag, it) }
102+
}
99103
} else {
100104
// Software fallback runs synchronously, so onBitmapCaptured always
101105
// completes before setViewSnapshot is called.

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<1eca66b21554b00725f2a9be894a0db9>>
7+
* @generated SignedSource<<61221e9b185b4e9b9f0db0c99c7c9dc1>>
88
*/
99

1010
/**
@@ -576,6 +576,12 @@ public object ReactNativeFeatureFlags {
576576
@JvmStatic
577577
public fun viewTransitionEnabled(): Boolean = accessor.viewTransitionEnabled()
578578

579+
/**
580+
* Use hardware bitmaps for view transition snapshots on Android.
581+
*/
582+
@JvmStatic
583+
public fun viewTransitionUseHardwareBitmapAndroid(): Boolean = accessor.viewTransitionUseHardwareBitmapAndroid()
584+
579585
/**
580586
* Initial prerender ratio for VirtualView.
581587
*/

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<76d977ea53cb2a37fc2ea8549e31cebd>>
7+
* @generated SignedSource<<f23dc5d7320599de13f35700a09d783a>>
88
*/
99

1010
/**
@@ -111,6 +111,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
111111
private var useUnorderedMapInDifferentiatorCache: Boolean? = null
112112
private var viewCullingOutsetRatioCache: Double? = null
113113
private var viewTransitionEnabledCache: Boolean? = null
114+
private var viewTransitionUseHardwareBitmapAndroidCache: Boolean? = null
114115
private var virtualViewPrerenderRatioCache: Double? = null
115116

116117
override fun commonTestFlag(): Boolean {
@@ -932,6 +933,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
932933
return cached
933934
}
934935

936+
override fun viewTransitionUseHardwareBitmapAndroid(): Boolean {
937+
var cached = viewTransitionUseHardwareBitmapAndroidCache
938+
if (cached == null) {
939+
cached = ReactNativeFeatureFlagsCxxInterop.viewTransitionUseHardwareBitmapAndroid()
940+
viewTransitionUseHardwareBitmapAndroidCache = cached
941+
}
942+
return cached
943+
}
944+
935945
override fun virtualViewPrerenderRatio(): Double {
936946
var cached = virtualViewPrerenderRatioCache
937947
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<a737810bf0211590401c2afb464aaf37>>
7+
* @generated SignedSource<<c398ef6325753f5666737fb84309c09e>>
88
*/
99

1010
/**
@@ -210,6 +210,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
210210

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

213+
@DoNotStrip @JvmStatic public external fun viewTransitionUseHardwareBitmapAndroid(): Boolean
214+
213215
@DoNotStrip @JvmStatic public external fun virtualViewPrerenderRatio(): Double
214216

215217
@DoNotStrip @JvmStatic public external fun override(provider: Any)

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<9e5b3192d1bec953c116d959ad63283d>>
7+
* @generated SignedSource<<4ba79f6843185d86bc9ad487b99d86a4>>
88
*/
99

1010
/**
@@ -205,5 +205,7 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
205205

206206
override fun viewTransitionEnabled(): Boolean = false
207207

208+
override fun viewTransitionUseHardwareBitmapAndroid(): Boolean = false
209+
208210
override fun virtualViewPrerenderRatio(): Double = 5.0
209211
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<378d6a8de497d26ebbbf55885be27a21>>
7+
* @generated SignedSource<<60a15dc6eb548f56216f284421c1e4da>>
88
*/
99

1010
/**
@@ -115,6 +115,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
115115
private var useUnorderedMapInDifferentiatorCache: Boolean? = null
116116
private var viewCullingOutsetRatioCache: Double? = null
117117
private var viewTransitionEnabledCache: Boolean? = null
118+
private var viewTransitionUseHardwareBitmapAndroidCache: Boolean? = null
118119
private var virtualViewPrerenderRatioCache: Double? = null
119120

120121
override fun commonTestFlag(): Boolean {
@@ -1027,6 +1028,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
10271028
return cached
10281029
}
10291030

1031+
override fun viewTransitionUseHardwareBitmapAndroid(): Boolean {
1032+
var cached = viewTransitionUseHardwareBitmapAndroidCache
1033+
if (cached == null) {
1034+
cached = currentProvider.viewTransitionUseHardwareBitmapAndroid()
1035+
accessedFeatureFlags.add("viewTransitionUseHardwareBitmapAndroid")
1036+
viewTransitionUseHardwareBitmapAndroidCache = cached
1037+
}
1038+
return cached
1039+
}
1040+
10301041
override fun virtualViewPrerenderRatio(): Double {
10311042
var cached = virtualViewPrerenderRatioCache
10321043
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<42e555a40da280b24f84e3ee5b45051d>>
7+
* @generated SignedSource<<b353ae56cf0cd23d93be23a675b30de1>>
88
*/
99

1010
/**
@@ -205,5 +205,7 @@ public interface ReactNativeFeatureFlagsProvider {
205205

206206
@DoNotStrip public fun viewTransitionEnabled(): Boolean
207207

208+
@DoNotStrip public fun viewTransitionUseHardwareBitmapAndroid(): Boolean
209+
208210
@DoNotStrip public fun virtualViewPrerenderRatio(): Double
209211
}

packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<d9ed25122f1ff64122bfc83f8e5e9545>>
7+
* @generated SignedSource<<93d9279dba687d7f660a6797549c0819>>
88
*/
99

1010
/**
@@ -585,6 +585,12 @@ class ReactNativeFeatureFlagsJavaProvider
585585
return method(javaProvider_);
586586
}
587587

588+
bool viewTransitionUseHardwareBitmapAndroid() override {
589+
static const auto method =
590+
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("viewTransitionUseHardwareBitmapAndroid");
591+
return method(javaProvider_);
592+
}
593+
588594
double virtualViewPrerenderRatio() override {
589595
static const auto method =
590596
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jdouble()>("virtualViewPrerenderRatio");
@@ -1050,6 +1056,11 @@ bool JReactNativeFeatureFlagsCxxInterop::viewTransitionEnabled(
10501056
return ReactNativeFeatureFlags::viewTransitionEnabled();
10511057
}
10521058

1059+
bool JReactNativeFeatureFlagsCxxInterop::viewTransitionUseHardwareBitmapAndroid(
1060+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
1061+
return ReactNativeFeatureFlags::viewTransitionUseHardwareBitmapAndroid();
1062+
}
1063+
10531064
double JReactNativeFeatureFlagsCxxInterop::virtualViewPrerenderRatio(
10541065
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
10551066
return ReactNativeFeatureFlags::virtualViewPrerenderRatio();
@@ -1359,6 +1370,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
13591370
makeNativeMethod(
13601371
"viewTransitionEnabled",
13611372
JReactNativeFeatureFlagsCxxInterop::viewTransitionEnabled),
1373+
makeNativeMethod(
1374+
"viewTransitionUseHardwareBitmapAndroid",
1375+
JReactNativeFeatureFlagsCxxInterop::viewTransitionUseHardwareBitmapAndroid),
13621376
makeNativeMethod(
13631377
"virtualViewPrerenderRatio",
13641378
JReactNativeFeatureFlagsCxxInterop::virtualViewPrerenderRatio),

packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<d87a80a2a88acb2187ea20b8181a7588>>
7+
* @generated SignedSource<<ef1a37cff6b7076193c47374eb6cca15>>
88
*/
99

1010
/**
@@ -303,6 +303,9 @@ class JReactNativeFeatureFlagsCxxInterop
303303
static bool viewTransitionEnabled(
304304
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
305305

306+
static bool viewTransitionUseHardwareBitmapAndroid(
307+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
308+
306309
static double virtualViewPrerenderRatio(
307310
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
308311

packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<ad7a835ef9cbe3a9a6121ac127038668>>
7+
* @generated SignedSource<<0a3c6a3353d22cf5909fd5a0f98a970e>>
88
*/
99

1010
/**
@@ -390,6 +390,10 @@ bool ReactNativeFeatureFlags::viewTransitionEnabled() {
390390
return getAccessor().viewTransitionEnabled();
391391
}
392392

393+
bool ReactNativeFeatureFlags::viewTransitionUseHardwareBitmapAndroid() {
394+
return getAccessor().viewTransitionUseHardwareBitmapAndroid();
395+
}
396+
393397
double ReactNativeFeatureFlags::virtualViewPrerenderRatio() {
394398
return getAccessor().virtualViewPrerenderRatio();
395399
}

0 commit comments

Comments
 (0)