-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Clarify Android platform-view mechanics and HCPP requirements #13705
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -37,8 +37,8 @@ The following matrix summarizes the different implementations and their trade-of | |||||||||||
|
|
||||||||||||
| | Mode | Benefits | Considerations | Enabler | | ||||||||||||
| | :--- | :--- | :--- | :--- | | ||||||||||||
| | **Texture layer** | • Good Flutter performance<br>• Full widget transforms work | • Janky during quick scrolling<br>• SurfaceViews lose accessibility and text magnifier breaks | Default behavior or standard `AndroidView` | | ||||||||||||
| | **Hybrid composition** | • Full native fidelity<br>• Correct accessibility and SurfaceView support | • Causes thread merging of raster & platform, which degrades Flutter FPS<br>• Platform View -> Renders to texture -> Uploads to Impeller -> Impeller composites Flutter content and Platform View content |• `PlatformViewLink` with `AndroidViewSurface`<br>• [`AndroidViewController` builds either a TLHC or an HC Platform View][AC] | | ||||||||||||
| | **Texture layer** | • Good Flutter performance<br>• Full widget transforms work | • Janky during quick scrolling<br>• SurfaceViews lose accessibility and text magnifier breaks<br>• Platform View -> Renders to texture -> Uploads to Impeller -> Impeller composites Flutter content and Platform View content | Default behavior or standard `AndroidView` | | ||||||||||||
| | **Hybrid composition** | • Full native fidelity<br>• Correct accessibility and SurfaceView support | • Causes thread merging of raster & platform, which degrades Flutter FPS<br>• Platform View -> Renders into the Android view hierarchy as usual, Flutter content renders into `ImageReader`-backed `FlutterImageView`s (a background layer, plus an overlay layer for content drawn above a platform view), the Android view hierarchy composites them together |• `PlatformViewLink` with `AndroidViewSurface`<br>• [`AndroidViewController` builds either a TLHC or an HC Platform View][AC] | | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the description of the Hybrid composition rendering path, it mentions Consider revising this to: |
||||||||||||
| | **HCPP** (Experimental) | • Full fidelity and performance<br>• Solves original sync overhead | • Requires Android API 34+, Vulkan support, and use of the Impeller rendering engine<br>• Platform View -> Renders to native Android Surface, Impeller renders to native Android Surface, SurfaceFlinger composites the two together | • `<meta-data>` in `AndroidManifest.xml`<br>• `--enable-hcpp` local flag<br> •[`AndroidViewController` builds either a TLHC or an HC Platform View][AC] | | ||||||||||||
|
|
||||||||||||
| {:.table .table-striped} | ||||||||||||
|
|
@@ -47,9 +47,18 @@ The following matrix summarizes the different implementations and their trade-of | |||||||||||
|
|
||||||||||||
| ## Hybrid composition {: #hybrid-composition } | ||||||||||||
|
|
||||||||||||
| Platform Views are rendered as they are normally. | ||||||||||||
| Flutter content is rendered into a texture. | ||||||||||||
| SurfaceFlinger composes the Flutter content and the platform views. | ||||||||||||
| Platform views are rendered as they normally are, | ||||||||||||
| directly in the Android view hierarchy. | ||||||||||||
| Flutter content is rendered into `ImageReader`s and painted by | ||||||||||||
| `FlutterImageView`s that sit in the same window as the platform views, | ||||||||||||
|
Comment on lines
+52
to
+53
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We try to avoid making code font spans possessive. Would something like the following work/be accurate? It also switches to active voice.
Suggested change
|
||||||||||||
| so the Android view hierarchy composites them together. | ||||||||||||
|
|
||||||||||||
| Flutter uses two kinds of these layers. | ||||||||||||
| The main Flutter render surface is swapped for a background | ||||||||||||
| `FlutterImageView` once a platform view is added. | ||||||||||||
| Flutter content that draws on top of a platform view | ||||||||||||
| goes into an additional overlay `FlutterImageView`, | ||||||||||||
| allocated from a pool and recycled between frames. | ||||||||||||
|
|
||||||||||||
| ## Hybrid composition++ (HCPP) {: #hcpp } | ||||||||||||
|
|
||||||||||||
|
|
@@ -66,8 +75,10 @@ It is currently available as an opt-in feature. | |||||||||||
|
|
||||||||||||
| * **Android API 34 or later**: Required for native transaction | ||||||||||||
| synchronization capabilities. | ||||||||||||
| * **Vulkan rendering**: The device must be capable of rendering with Vulkan. | ||||||||||||
| Required for Impeller to be enabled. | ||||||||||||
| * **Impeller with the Vulkan backend**: The device must be capable of | ||||||||||||
| rendering with Vulkan. Impeller also has an OpenGLES backend, and | ||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
| falls back to it on devices without usable Vulkan support. | ||||||||||||
| HCPP is not available in that configuration. | ||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
|
|
||||||||||||
| If these requirements are not met on the end-user device, | ||||||||||||
| Flutter will automatically fall back to the existing platform view strategy | ||||||||||||
|
|
@@ -516,15 +527,21 @@ Check out the [existing Platform View issues][] on GitHub. | |||||||||||
| Platform views in Flutter come with performance trade-offs. | ||||||||||||
|
|
||||||||||||
| In a typical Flutter app, | ||||||||||||
| the Flutter UI is composed on a dedicated raster thread, | ||||||||||||
| while platform code runs on the UI/platform thread. | ||||||||||||
| This separation keeps Flutter rendering fast and fluid. | ||||||||||||
|
|
||||||||||||
| However, when a platform view is rendered on Android using hybrid | ||||||||||||
| composition, Flutter merges the raster and UI threads into a single thread to | ||||||||||||
| ensure correct synchronization between the native Android views and the Flutter canvas. | ||||||||||||
| Because of this thread merging, rendering complex Flutter widgets | ||||||||||||
| alongside a platform view can compete with OS messages and plugin interactions, | ||||||||||||
| Flutter rasterizes frames on a dedicated raster thread, | ||||||||||||
| while platform code, such as plugins and Android views, | ||||||||||||
| runs on the platform thread, which is the Android main thread. | ||||||||||||
| This separation keeps Flutter rendering fast and fluid, | ||||||||||||
| as the platform thread is not blocked by rasterization work. | ||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
|
|
||||||||||||
| However, when a platform view is rendered on Android using | ||||||||||||
| hybrid composition, | ||||||||||||
|
Comment on lines
+536
to
+537
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adjust the break here:
Suggested change
|
||||||||||||
| Flutter merges the raster thread into the platform thread | ||||||||||||
| to ensure correct synchronization between | ||||||||||||
| the native Android views and the Flutter canvas. | ||||||||||||
| Because of this thread merging, | ||||||||||||
| rasterizing complex Flutter widgets alongside a platform view | ||||||||||||
| competes with other work on the platform thread, | ||||||||||||
| such as OS messages and plugin interactions, | ||||||||||||
| potentially causing lower application FPS and frame drops. | ||||||||||||
|
|
||||||||||||
| Also, prior to Android 10, hybrid composition copied each Flutter frame | ||||||||||||
|
|
||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the description of the Texture layer rendering path, the phrase
Uploads to Impelleris technically inaccurate. Impeller is the rendering engine (software), not a GPU memory destination. The texture is uploaded to the GPU (or imported as a GPU texture), and then Impeller composites it.Consider revising this to:
Platform View -> Renders to texture -> Uploaded as a GPU texture -> Impeller composites Flutter content and Platform View content