Skip to content

[Impeller][GLES] Image.toByteData() crashes on OpenGL ES when the app has no surface (e.g. backgrounded) #195627

Closed

Description

@b-luk

Description

On Android with Impeller's OpenGL ES backend, calling Image.toByteData() on an image made by Picture.toImage() crashes the app if the call happens while Flutter has no window surface. This happens, for example, right after the app goes to the background, or before the surface is created.

This is a regression on main, caused by #191747. Flutter 3.47.5 does not crash in the same scenario.

This was encountered when trying to debug #193428 (comment) with the linked repro app.

Steps to reproduce

  1. Use an Android device on Impeller OpenGL ES. A device that uses Vulkan can be forced onto OpenGL ES in a debug or profile build by adding this to AndroidManifest.xml:
    <meta-data
        android:name="io.flutter.embedding.android.ImpellerBackend"
        android:value="opengles" />
  2. In a loop, draw something into a Picture, call toImage(), then call toByteData() on the result.
  3. Send the app to the background (or cover it with another activity) while the loop is running.

Using the repro app at #193428 (comment) works (if needed, modify it to force OpenGL ES instead of Vulkan).

Expected results

No crash.

Actual results

The app crashes on the raster thread.

Release/profile builds (SIGSEGV, null or garbage pointer):

BlitCopyBufferToTextureCommandGLES::Encode   blit_command_gles.cc:227
EncodeCommandsInReactor                      blit_pass_gles.cc
ReactorGLES::FlushOps / React                reactor_gles.cc
BlitPassGLES::EncodeCommands
ContentContext::ContentContext               content_context.cc
AiksContext::AiksContext
...

Debug builds fail at an earlier DCHECK:

[FATAL:flutter/impeller/renderer/backend/gles/reactor_gles.cc(204)] Check failed: CanReactOnCurrentThread().

ReactorGLES::CreateUntrackedHandle           reactor_gles.cc:204
TextureGLES::TextureGLES
ContentContext::ContentContext               content_context.cc:606
AiksContext::AiksContext
Rasterizer::GetAiksContext                   rasterizer.h:724
ImageEncodingImpeller::ConvertDlImageToSkImage  image_encoding_impeller.cc:157
...

Root cause

On OpenGL ES, GL calls only work on a thread that has a GL context "current". Normally the raster thread uses the window surface's context.

toByteData() on a raster-owned image runs on the raster thread and asks Rasterizer::GetAiksContext() for an AiksContext (here). When there is no window surface, GetAiksContext() builds a new AiksContext. Building one makes GL calls, so it requires a current GL context. With no surface, no GL context is current on the raster thread, so we end up crashing. In debug builds, a DCHECK catches the GL call made without a current context before a crash. Release/profile builds end up crashing later due to invalid pointers caused by this (here).

This started with #191747 (87c02198123, "[wimp] Turn on multithreading for wimp"), which made ImageEncodingImpeller::ConvertDlImageToSkImage get an AiksContext from GetAiksContext(). Before that, toByteData() never built an AiksContext, which is why 3.47.5 is not affected.

Activity

  1. self-assigned this
    on Oct 29, 2026
  2. added
    c: regressionIt was better in the past than it is now
    e: impellerImpeller rendering backend issues and features requests
    on Oct 29, 2026
  3. added
    P2Important issues not at the top of the work list
    on Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listc: regressionIt was better in the past than it is nowe: impellerImpeller rendering backend issues and features requestse: openglteam-engineOwned by Engine teamtriaged-engineTriaged by Engine team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions