Skip to content

Android: migrate external texture to SurfaceProducer (fix transparency under Impeller)#173

Open
frenradar wants to merge 1 commit into
nmfisher:developfrom
frenradar:fren-surfaceproducer
Open

Android: migrate external texture to SurfaceProducer (fix transparency under Impeller)#173
frenradar wants to merge 1 commit into
nmfisher:developfrom
frenradar:fren-surfaceproducer

Conversation

@frenradar

Copy link
Copy Markdown

Problem

On Android, the plugin creates the Filament external texture via the legacy
TextureRegistry.createSurfaceTexture(). Under Impeller (now the default
Android renderer), that legacy SurfaceTexture external-texture path composites
a transparent Filament view (View.BlendMode.TRANSLUCENT over a
CONFIG_TRANSPARENT swapchain, which createView already sets up) with
incorrect premultiplied alpha — so the transparent regions of the render read as
a grey/dark veil over whatever is composited beneath the Texture widget.
iOS/Metal is unaffected.

Minimal repro: a ViewerWidget with background: Color(0x00000000) layered over
other content. The transparent area veils grey on Android with Impeller on;
correct with Impeller off (confirms it's the external-texture composite path,
not the Filament view config).

Fix

Migrate the Android texture from createSurfaceTexture() to the modern
TextureRegistry.createSurfaceProducer() (setSize / getSurface / id /
release), which composites premultiplied alpha correctly with Impeller on. The
native-window handoff (getNativeWindowFromSurface) and everything else are
unchanged; this is Android-only.

Compatibility

SurfaceProducer landed in Flutter 3.22. thermion_flutter's min Flutter is
>=3.23.0-0.1.pre, so createSurfaceProducer() is always available in the
supported range — no version guard needed.

Testing

Device-verified on a Samsung Galaxy A15 (Android 14) rendering a transparent
Filament model over a map basemap: the grey veil is gone with Impeller on and the
model renders correctly; survives a brief app background/resume.

Follow-up (not in this PR)

A SurfaceProducer.Callback (onSurfaceAvailable / onSurfaceCleanup) to
recreate the swapchain when Android destroys/recreates the surface under memory
pressure or long backgrounding. The common case (brief background) survives
without it in my testing; the callback would harden the worst case. Happy to add
it here or in a follow-up — let me know your preference.

…t transparency)

The legacy TextureRegistry.createSurfaceTexture() external-texture path
composites transparent Filament output with broken premultiplied alpha under
Impeller (default on Android since Flutter 3.22), so a transparent background
reads as a grey veil over bright content composited beneath it. iOS/Metal is
unaffected. Migrate to the modern createSurfaceProducer() API
(TextureRegistry.SurfaceProducer: setSize/getSurface/id/release), which
composites premultiplied alpha correctly with Impeller on.

FREN fork patch for GH#61 (3D nav puck). Minimal change; the
SurfaceProducer.Callback (surface recreate on background) is a follow-up.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant