flutter / flutter/flutter

Web (CanvasKit): the rendered UI is malformed or missing in an Android WebView on Samsung Xclipse GPUs (ANGLE-on-Vulkan) — regression between 3.38.5 and 3.41

Open
#188,164 13 comments 7 reactions 0 assignees View on GitHub
c: regression e: web_canvaskit e: web_skwasm e: webgl found in release: 3.41 has reproducible steps P2 platform-web team-web triaged-web
Dominant language
Dart
Stars
179k
Forks
31.1k
PR merge metrics
PR metrics pending

Description

### Steps to reproduce

So far, the failure has only reproduced inside an Android System WebView on certain
Samsung Xclipse-GPU devices (WebGL served via ANGLE-on-Vulkan), and it is a Flutter
*version* regression. The cleanest way to see it is the self-contained A/B repro at
https://github.com/sluit/flutter-canvaskit-webview-repro: one APK that loads the
*same* app — compiled by three different Flutter SDKs — into a native WebView, so the
only variable is the Flutter version.

1. On an affected Samsung Xclipse device (e.g. Galaxy A55 `SM-A556B`,
`ANGLE (Samsung Xclipse 530) on Vulkan`), install the repro APK (no network
needed; everything is bundled).
2. Tap "Flutter 3.38.5" → the screen renders correctly: app-bar title, a heading,
and four buttons *with* their text labels (see screenshot).
3. Press back, tap "Flutter 3.41.0" (or "Flutter 3.41.9") → this is NOT a white/blank
page: the screen is clearly up and the app-bar — including its text — renders, but
the Scaffold body below shows none of its content: no heading, no icon, no button
shapes, no labels (see screenshots). On 3.38.5 that same body renders fully.

Equivalent manual reproduction without the harness:

1. Build any Flutter Web app with the default CanvasKit renderer on Flutter
3.41.0 or 3.41.9 (`flutter build web`); serve it over HTTPS.
2. Load it inside an Android System WebView (standalone or via `webview_flutter`)
on an affected Samsung Xclipse device.
3. Observe: the page is clearly up (it is not a white/blank screen) but part of the
UI is misformed or missing — it does not render the way it should. In a
single-screen app the body region shows none of its content; in a larger app (our
production app) backgrounds and container/button shapes draw while text, images
and icons are misformed or missing — i.e. whichever content composites onto the
non-presenting CanvasKit overlay surface is misformed or disappears.
4. Rebuild the same app on Flutter 3.38.5, load it on the same device → it renders
correctly.

Notes:
- We don't have a failing device on hand: the failing-device results and
screenshots come from a tester, so we can't run arbitrary on-device experiments
quickly. The repro APK is built to be self-contained so a tester only has to
install it and tap each version.
- The device side is device-state-specific: not every unit with the same model +
GPU + firmware + WebView reproduces it (we saw 1 fail and 2 render among
identical Galaxy A55 units). The reliable, deterministic signal is the Flutter
version flip on a *confirmed-failing* device.

### Expected results

The full UI renders correctly — as it does on iOS WKWebView, on desktop Chrome,
on non-Samsung Android, on Samsung Adreno (Snapdragon) devices, and on the very
same Samsung Xclipse devices when the app is built with Flutter 3.38.5.

### Actual results

Same app, same device, same WebView — only the Flutter version differs (each build
self-identifies its engine revision on-screen):

| Flutter | Engine | Result |
|---------|------------|-------------------------------------------------|
| 3.38.5 | 1527ae0ec5 | renders fully |
| 3.41.0 | 3452d735bd | fails — app-bar ok, body content misformed/missing |
| 3.41.9 | 42d3d75a56 | fails — app-bar ok, body content misformed/missing |

To be clear, this is NOT a white/blank page — the screen is clearly up and part of
it renders correctly; the problem is that some content is misformed or missing — it
does not render the way it should. On 3.41.0 and 3.41.9 the engine boots and the
app-bar — including its text — renders, but the Scaffold body (heading + four buttons
+ their labels) shows none of its content. In our production app the backgrounds,
readability scrim and container/button shapes draw while text, images and icons are
misformed or missing. On 3.38.5 the same content renders fully. So it is not "all
text fails" and not a blank canvas: a whole part of the scene is misformed or does
not present while the rest renders.

No `webglcontextlost` / `webglcontextcreationerror` events fire — the WebGL context
is created and is not lost; part of the content simply never presents.

The one thing the failing devices share is the WebGL renderer string
`ANGLE (Samsung Xclipse …) on Vulkan`:

Under test: Galaxy A55 SM-A556B / "ANGLE (Samsung Xclipse 530) on Vulkan 1.3.279" / Android 16 / WebView Chromium 148.0.7778.178
Also fails: Galaxy S26 SM-S942B / Xclipse 960
Never fails: Adreno (Snapdragon) Android devices and all iPhones (iOS WKWebView / Metal)

We also saw this in our production app: there, Flutter 3.44.0 (engine 4c525dac5e)
fails the same way, and the failure shows as container/button shapes rendering
while there is no text (or transparent text) and images and icons are misformed or
missing.

What we tested and ruled out (all on the actual failing device):
- FP16 / wide-color-gamut compositor buffer: this is the mechanism reported in the
closely-related #185026 (Flutter Web blank in `webview_flutter` on Samsung, with
gralloc4 `R16G16B16A16_FLOAT` allocation failures in logcat). We do NOT reproduce
that mechanism — toggling the WebView window colorMode 8-bit vs 16-bit makes no
difference (fails either way), and we see none of those gralloc4 errors (see Logs).

Possibly related (same family, not ruled out, different surface):
- #188151 — Web/CanvasKit in an Android WebView on a Samsung Galaxy Z Fold 7
renders correctly in Chrome but fails in the WebView (blank CJK glyphs, over-tall
layout, incomplete `RepaintBoundary.toImage()` off-screen capture). Same
Chrome-works / WebView-fails CanvasKit family. Differences: the failing surface is
text/glyphs there vs a whole scene region here, it isn't bisected to a version like
ours, and no WebGL renderer string is given — so the GPU is unconfirmed (the Fold 7
ships Snapdragon/Adreno, which would be the opposite of the Xclipse-on-Vulkan
signal we see, if so).
- #187905 — Impeller-Vulkan on Samsung Xclipse (Exynos) exhausts the kernel CMA pool
→ renderer freeze + glyph-atlas corruption. Same Xclipse/ANGLE-on-Vulkan GPU
family and texture/glyph-allocation fault class, but native rather than web — i.e.
corroborating evidence that this GPU stack mishandles texture allocation, not a
duplicate.

- DOM/CSS/viewport layout: every DOM metric (`innerHeight`,
`visualViewport.height`, `documentElement.clientHeight`, 100vh) is identical
between failing and working sessions; no height collapse.
- Flutter engine view geometry: on the failing device the engine view is correct
and full-size (`implicitView.physicalSize.height / dpr == window.innerHeight`,
real canvas backing store full size at top of viewport, `cvTop == 0`, visible).
- Software CanvasKit and skwasm (`--wasm`): both also fail (both WebGL-based).
- Firmware build / WebView version / GPU model / OS API level: none of these
split fail-vs-work. Among Galaxy A55 units matching the failing unit's exact
model, GPU, firmware (`BP4A.251205.006`) and WebView, we saw 1 fail and 2 render.
Only the Flutter version flips the outcome deterministically on a given device.

Workarounds we tried on the failing device that did NOT help (only the Flutter
3.38.5 downgrade worked):
- `canvasKitMaximumSurfaces: 1` — still fails.
- `canvasKitForceCpuOnly: true` (runtime, Xclipse-gated) and compile-time
`--dart-define=FLUTTER_WEB_CANVASKIT_FORCE_CPU_ONLY=true` — still fail.
- WebView `colorMode` 8-bit vs wide-gamut/16-bit — no difference (rules out the
#185026 FP16 path).
- `WebView.setLayerType(LAYER_TYPE_SOFTWARE)` — white screen (disables WebGL).
- `--wasm` (skwasm) on and off — both fail.
- Removing offscreen GPU effects (shimmer / `BackdropFilter`) — no change.

### Code sample

The self-contained repro is at https://github.com/sluit/flutter-canvaskit-webview-repro
— it bundles the Flutter web source and a native Android WebView host that loads three
Flutter-SDK builds (3.38.5 / 3.41.0 / 3.41.9) behind an in-app version picker. Build the
APK with `./gradlew installDebug` (see the repo README), or download the prebuilt APK from
the v1.0 release. The bug requires a native Android WebView on a specific device, so a single
`flutter run -d chrome` will NOT reproduce it — desktop Chrome renders fine.

Repro repo: https://github.com/sluit/flutter-canvaskit-webview-repro
Prebuilt APK: https://github.com/sluit/flutter-canvaskit-webview-repro/releases/download/v1.0/canvaskit-texture-repro-3.38.5-3.41.0-3.41.9.apk

Minimal Flutter web source (the app loaded in the WebView):

Code sample

```dart
import 'package:flutter/material.dart';

void main() => runApp(const ReproApp());

class ReproApp extends StatelessWidget {
const ReproApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'CanvasKit texture repro',
debugShowCheckedModeBanner: false,
theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF2C3E50))),
home: const ReproPage(),
);
}
}

class ReproPage extends StatelessWidget {
const ReproPage({super.key});

@override
Widget build(BuildContext context) {
// On an affected Samsung Xclipse device this is not a white/blank page: the
// app-bar renders, but the body below (heading, icon, button shapes and labels)
// is misformed or missing — a whole part of the scene does not present correctly.
return Scaffold(
appBar: AppBar(title: const Text('CanvasKit texture repro')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Texture repro', style: Theme.of(context).textTheme.headlineMedium),
const SizedBox(height: 16),
const Icon(Icons.star, size: 48), // icon = image texture
const SizedBox(height: 16),
ElevatedButton(onPressed: () {}, child: const Text('Elevated button')),
FilledButton(onPressed: () {}, child: const Text('Filled button')),
OutlinedButton(onPressed: () {}, child: const Text('Outlined button')),
TextButton(onPressed: () {}, child: const Text('Text button')),
],
),
),
);
}
}
```

### Screenshots or Video

Screenshots / Video demonstration

Same device, same WebView, only the Flutter version differs. Note these are not
white/blank pages — the screen is up and partly drawn; some content is misformed or
missing:

**Flutter 3.38.5** — renders fully (app-bar, heading, four labelled buttons):

![Flutter 3.38.5 renders fully](https://github.com/sluit/flutter-canvaskit-webview-repro/raw/main/flutter_3.38.5.jpg)

**Flutter 3.41.0** — app-bar (incl. its text) renders; body content misformed/missing:

![Flutter 3.41.0 — body content misformed or missing](https://github.com/sluit/flutter-canvaskit-webview-repro/raw/main/flutter_3.41.0.jpg)

**Flutter 3.41.9** — app-bar (incl. its text) renders; body content misformed/missing:

![Flutter 3.41.9 — body content misformed or missing](https://github.com/sluit/flutter-canvaskit-webview-repro/raw/main/flutter_3.41.9.jpg)

### Logs

The failure is silent: on the affected device no JavaScript error, no
`webglcontextlost` and no `webglcontextcreationerror` fire — the WebGL context is
created successfully and is not lost; part of the content simply never presents.
There is therefore no error log to attach from the failing path.

Notably, we do NOT see the logs reported in the related #185026 (which we
investigated and ruled out as a different cause). On our failing device there are:
- NO gralloc4 buffer-allocation errors (no "Format allocation info not found",
no failed `R16G16_UINT` / `R16G16B16A16_FLOAT` (FP16) allocations);
- NO "FlutterRenderer: Width is zero. 0,0";
- NO "updateSurface: has no frame".
The WebGL context, the canvas and the engine surface are all created at the
correct full size — the content texture simply never presents.

The one meaningful difference between a failing and a working device is the WebGL
renderer string:

FAILS (Samsung Xclipse): UNMASKED_RENDERER_WEBGL = "ANGLE (Samsung Xclipse 960) on Vulkan 1.4.304"
RENDERS (Adreno): UNMASKED_RENDERER_WEBGL = "ANGLE (Adreno (TM) 750), OpenGL ES 3.2 ..."

### Flutter Doctor output

Doctor output

```console
[✓] Flutter (Channel stable, 3.41.9, on macOS 26.4.1 25E253 darwin-arm64, locale en-NL)
• Flutter version 3.41.9 on channel stable
• Framework revision 00b0c91f06 (2026-04-29), Engine revision 42d3d75a56
• Dart version 3.11.5
• DevTools version 2.54.2

[!] Android toolchain - develop for Android devices (Android SDK version 36.0.0-rc3)
• Platform android-36, build-tools 36.0.0-rc3
• Java version OpenJDK Runtime Environment (build 21.0.7)
! Some Android licenses not accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 26.4.1)
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Connected device (3 available)
• Chrome (web) • chrome • web-javascript • Google Chrome 148.0.7778.216

[✓] Network resources
• All expected network resources are available.
```

Contributor guide

Open the contributing guide

Research direction

Start with the self-contained canvaskit-webview-repro repository and its README; build or install the APK with ./gradlew installDebug on an affected Samsung Xclipse device. Compare Flutter 3.38.5 with 3.41.0/3.41.9 and investigate the CanvasKit/WebView rendering regression between engine revisions 1527ae0ec5 and 3452d735bd. Done means the repro body renders fully on affected devices without regressing the working version.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, dart
Domain
computer-graphics, mobile-dev, web-dev
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.