Skip to content

[Android] Upon upgrading version 3.29, image.toByteData doesn't return correct image bytes in Emulators. #164459

Closed

Description

@maryamshal

Steps to reproduce

  1. Open flutter app with flutter version 3.29 an android emulator (tried on android 11)
  2. Add code that fetches ui.Image bytes in any encoding. image.toByteData
  3. Only reproduceable on emulators.
    (Does it possibly have anything to do with the decision to disable Vulkan on emulators starting v3.29?)

Expected results

1- Correct image data
2- Console free of opengl errors

Actual results

1- Image data is incorrect.
2- Console shoes opengl errors.

Code sample

Code sample
    ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
E/emuglGLESv2_enc( 6025): device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glBindFramebuffer:2710 GL error 0x500
E/emuglGLESv2_enc( 6025): device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glFramebufferTexture2D:2723 GL error 0x500
E/emuglGLESv2_enc( 6025): device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glBindFramebuffer:2710 GL error 0x500

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.29.0, on Microsoft Windows [Version 10.0.22631.4890], locale en-US)
[√] Windows Version (11 Enterprise 64-bit, 23H2, 2009)
[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop Windows apps (Visual Studio Enterprise 2022 17.12.5)
[√] Android Studio (version 2024.2)
[√] VS Code (version 1.97.1)
[√] Connected device (4 available)
[√] Network resources

• No issues found!

Activity

  1. changed the title [-]Upon upgrading version 3.29, image.toByteData doesn't return correct image bytes.[/-] [+][Android] Upon upgrading version 3.29, image.toByteData doesn't return correct image bytes in Emulators.[/+] on Mar 2, 2025
  2. jonahwilliams commented on Mar 2, 2025

    @jonahwilliams
    Contributor

    When you say incorrect, do you mean upside down?

  3. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Mar 2, 2025
  4. maryamshal commented on Mar 2, 2025

    @maryamshal
    Author

    When you say incorrect, do you mean upside down?

    no I mean it is blank. Image stored or transferred has size but it shows up blank.

  5. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Mar 2, 2025
  6. darshankawar commented on Mar 3, 2025

    @darshankawar
    Member

    @maryamshal
    I tried with below code sample and ran with Pixel 7 emulator api 35 on latest stable and master. The emulator showed the image properly.

    runnable code
    
    import 'dart:typed_data';
    import 'dart:ui' as ui;
    
    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    
    const url = 'https://wallpapercave.com/wp/wp8393935.jpg';
    
    Future<Uint8List> getEncodedImage() async {
      final bg = await http.get(Uri.parse(url)).then((resp) => decodeImageFromList(resp.bodyBytes));
      final byteData = await bg.toByteData(format: ui.ImageByteFormat.png).timed;
      assert(byteData != null);
      return byteData!.buffer.asUint8List();
    }
    
    void main() => runApp(const MyApp());
    
    extension<T> on Future<T> {
      Future<T> get timed {
        final start = DateTime.now();
        return this..whenComplete(() => print("Computing $T took ${DateTime.now().difference(start).inMilliseconds}ms"));
      }
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: MyHomePage(),
        );
      }
    }
    
    final fut = getEncodedImage();
    
    class MyHomePage extends StatelessWidget {
      const MyHomePage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: FutureBuilder(
              future: fut,
              builder: (context, snapshot) {
                if (snapshot.connectionState != ConnectionState.done) return const Center(child: CircularProgressIndicator());
                return Center(child: Image.memory(snapshot.data!));
              }),
        );
      }
    }
    
    
    Image

    If above doesn't represent your case, please provide us complete code sample and also emulator details.

  7. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Mar 3, 2025
  8. maryamshal commented on Mar 3, 2025

    @maryamshal
    Author

    The same code on the emulator i'm running on doesn't work, the screen shows up blank. Note that it used to previously work on previous Flutter versions.
    Emulator specs

    • Pixel 2 API 30
      [google/sdk_gphone_x86_64/generic_x86_64_arm64:11/RSR1.210722.013.A2/10067904:userdebug/dev-keys]
      [ro.opengles.version]: [131072]
      [ro.organization_owned]: [false]
      [ro.postinstall.fstab.prefix]: [/system]
      [ro.product.board]: [goldfish_x86_64]
      [ro.product.brand]: [google]
      [ro.product.build.date]: [Thu May 4 15:22:09 UTC 2023]
      [ro.product.build.date.utc]: [1683213729]

    But when tried on Pixel 6 pro API 34 it worked. Is this a regression related to a specific android version?

    Image

  9. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Mar 3, 2025
  10. darshankawar commented on Mar 4, 2025

    @darshankawar
    Member

    I tried on api 30 emulator in which the above code doesn't show the image. I get below in the log:

    E/libEGL  ( 4588): called unimplemented OpenGL ES API
    E/libEGL  ( 4588): called unimplemented OpenGL ES API
    E/libEGL  ( 4588): called unimplemented OpenGL ES API
    

    If I disable impeller, then the image is rendered properly:

    Image

    Will keep the issue open for team's tracking / attention.

    stable : 3.29.0
    master : 3.30.0-1.0.pre.307
    
  11. 22 remaining items

  12. jason-simmons commented on Aug 27, 2025

    @jason-simmons
    Contributor

    The issue that I described in #164459 (comment) happened on a cloud VM running Linux.

    It's a different issue from the one seen on Windows.

    On an API 30 emulator in my Linux setup, the app is able to render the image on screen when running in a standard engine build with assertions disabled. But in a local android_debug_unopt_x64 engine build, the app gets an assertion failure because glBindBufferRange produces an error code.

  13. gaaclarke commented on Aug 28, 2025

    @gaaclarke
    Member

    E/emuglGLESv2_enc( 6203): device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glBindFramebuffer:2710 GL error 0x500

    0x500 is GL_INVALID_ENUM. In opengl es 2 the only valid enum for glBindFramebuffer is GL_FRAMEBUFFER. In opengles 3 it's GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, or GL_FRAMEBUFFER. So it seems like we are using the READ or DRAW variants when we shouldn't be.

    BlitCopyTextureToBufferCommandGLES::Encode is definitely using the GL_READ_FRAMEBUFFER attachment in order to use glReadPixels in the reproduction code when executing on a opengles3 device.

    If we support opengles 2.0 there should be a switch in the logic for BlitCopyTextureToBufferCommandGLES to use GL_FRAMEBUFFER or GL_READ_FRAMEBUFFER depending on the context version. Although, I think we can probably safely just bind to GL_FRAMEBUFFER for both opengles 2 and opengles 3. Maybe that's slightly less efficient on opengles 3 contexts.

    In order to verify that I'll have to get a build environment for the engine setup on windows which will take some time.

  14. gaaclarke commented on Aug 28, 2025

    @gaaclarke
    Member

    I attempted to reproduce the problem on mac by forcing android_context_gl_impeller.cc to create a opengles 2 context, but that isn't sufficient. The above might fix the problem, writing a test may be difficult though. Maybe with ANGLE we can force it into a mode were we can reproduce the problem somehow.

  15. gaaclarke commented on Aug 28, 2025

    @gaaclarke
    Member

    I tried the following patch which removes the gl errors in the description:

    --- a/engine/src/flutter/impeller/renderer/backend/gles/blit_command_gles.cc
    +++ b/engine/src/flutter/impeller/renderer/backend/gles/blit_command_gles.cc
    @@ -344,10 +344,11 @@ bool BlitCopyTextureToBufferCommandGLES::Encode(
     
       GLuint read_fbo = GL_NONE;
       fml::ScopedCleanupClosure delete_fbos(
    -      [&gl, &read_fbo]() { DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER); });
    +      [&gl, &read_fbo]() { DeleteFBO(gl, read_fbo, GL_FRAMEBUFFER); });
     
       {
    -    auto read = ConfigureFBO(gl, source, GL_READ_FRAMEBUFFER);
    +    FML_LOG(ERROR) << "bind framebuffer!";
    +    auto read = ConfigureFBO(gl, source, GL_FRAMEBUFFER);
         if (!read.has_value()) {
           return false;
         }

    There is a crash however in the ndk translation afterwards. Presumably this is the layer that translates arm64 to x64. I built the test apk for arm64 on a mac and shipped it to a x64 windows computer for testing. I'm not sure if that duplicates how things work when doing flutter run directly on the windows machine. Locally it might make x64 android targets.

    the crash

    08-28 13:01:04.030  5878  5911 E flutter : [ERROR:flutter/impeller/renderer/backend/gles/blit_command_gles.cc(350)] bind framebuffer!
    08-28 13:01:04.379  5878  5911 E ndk_translation: Undefined instruction 0x5ea1b800 at 0x000070ea2368f880
    08-28 13:01:04.379  5878  5911 F libc    : Fatal signal 4 (SIGILL), code -6 (SI_TKILL) in tid 5911 (1.io), pid 5878 (mple.bug_164459)
    08-28 13:01:04.432  5937  5937 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
    08-28 13:01:04.434   292   292 I tombstoned: received crash request for pid 5911
    08-28 13:01:04.434  5937  5937 I crash_dump64: performing dump of process 5878 (target tid = 5911)
    08-28 13:01:04.439  5937  5937 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    08-28 13:01:04.439  5937  5937 F DEBUG   : Build fingerprint: 'google/sdk_gphone_x86_64/generic_x86_64_arm64:11/RSR1.240422.006/12134477:userdebug/dev-keys'
    08-28 13:01:04.439  5937  5937 F DEBUG   : Revision: '0'
    08-28 13:01:04.439  5937  5937 F DEBUG   : ABI: 'x86_64'
    08-28 13:01:04.439  5937  5937 F DEBUG   : Timestamp: 2025-08-28 13:01:04-0700
    08-28 13:01:04.439  5937  5937 F DEBUG   : pid: 5878, tid: 5911, name: 1.io  >>> com.example.bug_164459 <<<
    08-28 13:01:04.439  5937  5937 F DEBUG   : uid: 10168
    08-28 13:01:04.439  5937  5937 F DEBUG   : signal 4 (SIGILL), code -6 (SI_TKILL), fault addr --------
    08-28 13:01:04.439  5937  5937 F DEBUG   :     rax 0000000000000000  rbx 000070ea1b953fe8  rcx 000070f1148c6c77  rdx 0000000000000004
    08-28 13:01:04.439  5937  5937 F DEBUG   :     r8  0000000000000001  r9  0000000000000001  r10 00007ffe863430a8  r11 0000000000000202
    08-28 13:01:04.439  5937  5937 F DEBUG   :     r12 000000005ea1b800  r13 000000000070ea23  r14 0000000000000002  r15 0000000000000004
    08-28 13:01:04.439  5937  5937 F DEBUG   :     rdi 00000000000016f6  rsi 0000000000001717
    08-28 13:01:04.439  5937  5937 F DEBUG   :     rbp 000070ea1b9535c0  rsp 000070ea1b953368  rip 000070f1148c6c77
    08-28 13:01:04.443  5937  5937 F DEBUG   : backtrace:
    08-28 13:01:04.443  5937  5937 F DEBUG   :       #00 pc 00000000000b1c77  /apex/com.android.runtime/lib64/bionic/libc.so (tgkill+7) (BuildId: edf0af8d613e7bdf6a416ec8f4edeb0d)
    08-28 13:01:04.443  5937  5937 F DEBUG   :       #01 pc 00000000001473a2  /system/lib64/libndk_translation.so (ndk_translation::Decoder<ndk_translation::SemanticsPlayer<ndk_translation::(anonymous namespace)::Interpreter> >::DecodeSimdScalarTwoRegMisc()+642) (BuildId: 8d5bb5ddeee9364830ea3d7d46ef98b9)
    08-28 13:01:04.443  5937  5937 F DEBUG   :       #02 pc 000000000013f066  /system/lib64/libndk_translation.so (ndk_translation::Decoder<ndk_translation::SemanticsPlayer<ndk_translation::(anonymous namespace)::Interpreter> >::DecodeDataProcessingSimdAndFp()+2374) (BuildId: 8d5bb5ddeee9364830ea3d7d46ef98b9)
    08-28 13:01:04.443  5937  5937 F DEBUG   :       #03 pc 000000000013b2ca  /system/lib64/libndk_translation.so (ndk_translation::Decoder<ndk_translation::SemanticsPlayer<ndk_translation::(anonymous namespace)::Interpreter> >::Decode(unsigned int)+1114) (BuildId: 8d5bb5ddeee9364830ea3d7d46ef98b9)
    08-28 13:01:04.443  5937  5937 F DEBUG   :       #04 pc 000000000013ae26  /system/lib64/libndk_translation.so (ndk_translation::InterpretInsn(ndk_translation::ProcessState*)+118) (BuildId: 8d5bb5ddeee9364830ea3d7d46ef98b9)
    08-28 13:01:04.443  5937  5937 F DEBUG   :       #05 pc 0000000000170d3e  /system/lib64/libndk_translation.so (BuildId: 8d5bb5ddeee9364830ea3d7d46ef98b9)
    08-28 13:01:04.477     0     0 D logd    : logdr: UID=10168 GID=10168 PID=5937 n tail=50 logMask=8 pid=5878 start=0ns timeout=0ns
    08-28 13:01:04.479     0     0 D logd    : logdr: UID=10168 GID=10168 PID=5937 n tail=50 logMask=1 pid=5878 start=0ns timeout=0ns
    08-28 13:01:04.552     0     0 D logd    : logdr: UID=10168 GID=10168 PID=5937 n tail=0 logMask=8 pid=5878 start=0ns timeout=0ns
    08-28 13:01:04.554     0     0 D logd    : logdr: UID=10168 GID=10168 PID=5937 n tail=0 logMask=1 pid=5878 start=0ns timeout=0ns
    0
    
  16. gaaclarke commented on Aug 28, 2025

    @gaaclarke
    Member

    When I built with the x64 target the patch in #164459 (comment) fixes this problem. Now the tricky part of trying to come up with a test.

  17. moved this from Emulator to Done in Slimpelleron Sep 2, 2025
  18. added
    r: fixedIssue is closed as already fixed in a newer version
    on Sep 3, 2025
  19. github-actions commented on Sep 17, 2025

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  20. locked as resolved and limited conversation to collaborators on Sep 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: renderingUI glitches reported at the engine/skia or impeller rendering levele: OS-version specificAffects only some versions of the relevant operating systeme: impellerImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.found in release: 3.29Found to occur in 3.29found in release: 3.30Found to occur in 3.30has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-androidAndroid applications specificallyr: fixedIssue is closed as already fixed in a newer versionslimpellerEngine binary size reduction. go/slimpellerteam-engineOwned by Engine teamtriaged-engineTriaged by Engine team

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions