Sitelet https://github.com/flutter/flutter/pull/190655
Skip to content

[Impeller] Dispatch make-current lifecycle event only on success - #190655

Closed
FelixMittermeier wants to merge 1 commit into
flutter:masterfrom
FelixMittermeier:fix/impeller-egl-make-current-lifecycle
Closed

FelixMittermeier wants to merge 1 commit into
flutter:masterfrom
FelixMittermeier:fix/impeller-egl-make-current-lifecycle

Conversation

@FelixMittermeier

Copy link
Copy Markdown
Contributor

Fixes #190640

When Android Impeller uses OpenGLES, Context::MakeCurrent currently dispatches kDidMakeCurrent to its lifecycle listeners even when the underlying eglMakeCurrent call fails. AndroidContextGLImpeller interprets that event as permission to run GLES reactor work on the current thread, so queued image resize blits can execute without a current OpenGL context and reach the fatal incomplete-framebuffer check seen in the issue.

The solution is to dispatch kDidMakeCurrent only after eglMakeCurrent succeeds while preserving the existing error logging and return value. This restores the lifecycle contract at the point where Impeller has the authoritative EGL result. A regression test uses EGL's cross-thread context ownership rule to make a second MakeCurrent call fail with EGL_BAD_ACCESS and verifies that only the successful bind emits the lifecycle event.

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
  • All existing and new tests are passing.

@github-actions github-actions Bot added platform-android Android applications specifically engine flutter/engine related. See also e: labels. e: impeller Impeller rendering backend issues and features requests team-android Owned by Android platform team labels Aug 6, 2026
@FelixMittermeier

Copy link
Copy Markdown
Contributor Author

Closing this in favor of #192158

Context: #190640 (comment)

pull Bot pushed a commit to Mu-L/flutter that referenced this pull request Sep 23, 2026
Addresses flutter#190640

## Reproduction

Public deterministic reproduction:
[dfdgsdfg/mali-crash-app](https://github.com/dfdgsdfg/mali-crash-app).
The workload and the historical matrix table are documented in the
[README](https://github.com/dfdgsdfg/mali-crash-app#diagnostic-ab-matrix).

## Evidence

Confirmed facts from the diagnostic engine and the same production-like
scenario:

- The shared renderer deletes a texture name.
- The same numeric name is regenerated on the resource context.
- The upload path ends with `isTexture=false` for that name.
- The first isolated error is `FramebufferTexture2D`:
`GL_INVALID_OPERATION`, followed by a missing framebuffer attachment.

The [trace matrix
7268086803036215683](https://console.firebase.google.com/project/us-app-ea67d/testlab/histories/bh.d17e9c8f630d19e0/matrices/7268086803036215683),
[force-rebind pass matrix
7248171571680282013](https://console.firebase.google.com/project/us-app-ea67d/testlab/histories/bh.d17e9c8f630d19e0/matrices/7248171571680282013),
and [verify-3 matrix
9163761808229023214](https://console.firebase.google.com/project/us-app-ea67d/testlab/histories/bh.d17e9c8f630d19e0/matrices/9163761808229023214)
are the key Test Lab runs.

Inference: the trace and A/B results are consistent with a deleted
object remaining bound and Mali treating a rebind to the same numeric
name as no state transition. This is an inference about the driver
behavior, not a claim that the GLES implementation violates the
object-name specification.

## Change

The direct GLES buffer-to-texture upload path now performs one extra
zero bind immediately before binding the destination texture. The final
binding state is unchanged. The RGBA unit test uses deterministic
texture name `7` and preserves the ordered `0` then `7` binding
sequence.

This is a minimal workaround and does not supersede
[flutter#190655](flutter#190655): that PR
covers a different make-current failure path, while this reproduction
had a successful/current resource context. flutter#190655 was not directly
tested here.

## Physical validation

Using a Flutter 3.44.8-based diagnostic engine with the same app,
Scenario 9, and Mali device:

- Four affected diagnostic runs crashed after approximately 7–10
seconds.
- The force-rebind A/B passed 4/4 runs, each running for 606 seconds,
with no `GL_INVALID_OPERATION`, FBO failure, `isTexture=false`, or fatal
signal observations.

The latest-master patch received the host validation below; the physical
Test Lab binaries were built from the Flutter 3.44.8-based diagnostic
engine, not from this latest-master patch.

## Host validation

- `BlitCommandGLESTest.BlitCopyBufferToTextureCommandGLESRGBA`: 1/1
passed
- `BlitCommandGLESTest.*`: 11/11 passed
- `ProcTableGLES.*`: 5/5 passed
- `ReactorGLES.*`: 6 passed, 1 skipped because the host does not support
labelling
- `ImageDecoderNoGLTest.*`: 6/6 passed
- Host `impeller_unittests` and `ui_unittests` builds passed
- clang-format and `git diff --check` passed

## Scope and trade-offs

This is a narrow workaround validated for one deterministic
reproduction; it is not an architectural redesign or a general fix for
all GLES texture-binding paths. The current physical mechanism is
inferred from the trace and A/B results; this does not prove that every
Mali crash in flutter#190640 has the same cause.

The workaround applies only to `BlitCopyBufferToTextureCommandGLES`;
other GLES bind/upload paths remain unchanged. It adds one additional
`glBindTexture` per direct buffer-to-texture upload. Affected callers
include image decode, glyph atlas, small utility textures, and Flutter
GPU buffer-to-texture overwrite/copy paths.

The extra bind is likely small compared with texel transfer for normal
uploads, but it has not been benchmarked; repeated small per-frame
uploads may be sensitive. GL names come from the driver via
`glGenTextures`, and Flutter cannot prevent numeric name reuse.

Reactor-level name-reuse prevention is not a simple alternative: delayed
deletion and `glFinish` add memory and stall cost, and do not directly
force the observed same-name state transition.

Reviewer guidance on performance and scope, including broader workaround
plumbing if needed, is welcome.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

e: impeller Impeller rendering backend issues and features requests engine flutter/engine related. See also e: labels. platform-android Android applications specifically team-android Owned by Android platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Impeller][GLES] ImageDecoderImpeller SIGABRT persists on Flutter 3.44.8 across Android 10 Mali devices

1 participant