duguyihou / react-native-turbo-image

Performant image component for React Native
https://www.npmjs.com/package/react-native-turbo-image
MIT License
167 stars 8 forks source link

Android error: Software rendering doesn't support hardware bitmaps #279

Closed Anas-7 closed 3 months ago

Anas-7 commented 4 months ago

Describe the bug App shuts down when trying to navigate to hamburger menu made with @react-navigation/drawer. Currently, we show a feed where images are displayed with TurboImage. The images load and cache correctly, but on clicking the menu the app closes.

We tried a different library, but faced a similar error. Our crashlytics log point to an error related to Coil and is attached below.

To Reproduce I don't have an example set up yet but I'll add it over the weekend. This occurs on Android 14 and 13 too, having tested the former with a physical device and the latter as a virtual device.

Expected behavior App shouldn't crash due to coil.drawable.CrossfadeDrawable.draw

Screenshots

Fatal Exception: java.lang.IllegalArgumentException: Software rendering doesn't support hardware bitmaps at android.graphics.BaseCanvas.throwIfHwBitmapInSwMode(BaseCanvas.java:726) at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:81) at android.graphics.BaseCanvas.drawBitmap(BaseCanvas.java:139) at android.graphics.Canvas.drawBitmap(Canvas.java:1665) at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:549) at coil.drawable.CrossfadeDrawable.draw(CrossfadeDrawable.kt:79) at android.widget.ImageView.onDraw(ImageView.java:1446) at android.view.View.draw(View.java:24627) at android.view.View.draw(View.java:24499) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24630) at android.view.View.draw(View.java:24499) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24630) at android.view.View.draw(View.java:24499) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at android.view.View.draw(View.java:24630) at android.widget.ScrollView.draw(ScrollView.java:2019) at com.facebook.react.views.scroll.ReactScrollView.draw(ReactScrollView.java:587) at android.view.View.draw(View.java:24499) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at android.view.View.draw(View.java:24630) at android.widget.ScrollView.draw(ScrollView.java:2019) at com.facebook.react.views.scroll.ReactScrollView.draw(ReactScrollView.java:587) at android.view.View.draw(View.java:24499) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at android.view.View.draw(View.java:24630) at android.view.View.draw(View.java:24499) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24630) at android.view.View.draw(View.java:24499) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24630) at android.view.View.draw(View.java:24499) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24630) at android.view.View.draw(View.java:24499) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:836) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:809) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at com.facebook.react.ReactRootView.dispatchDraw(ReactRootView.java:296) at android.view.View.draw(View.java:24497) at android.view.ViewGroup.drawChild(ViewGroup.java:4576) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4337) at android.view.View.draw(View.java:24630) at eightbitlab.com.blurview.PreDrawBlurController.updateBlur(PreDrawBlurController.java:119) at eightbitlab.com.blurview.PreDrawBlurController$1.onPreDraw(PreDrawBlurController.java:50) at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1176) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4029) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2718) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9937) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1406) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1415) at android.view.Choreographer.doCallbacks(Choreographer.java:1015) at android.view.Choreographer.doFrame(Choreographer.java:945) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1389) at android.os.Handler.handleCallback(Handler.java:959) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loopOnce(Looper.java:232) at android.os.Looper.loop(Looper.java:317) at android.app.ActivityThread.main(ActivityThread.java:8592) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)

Smartphone (please complete the following information):

Additional context This seems to be triggered due to hardware acceleration. I tried testing it with android:hardwareAcceleration="false" and while the code didn't crash, the performance suffered way more than acceptable for us. The last working version of this library seems to be 0.14.0 for sure, and it crashes on 0.16.0. We can't use the 0.14.0 version as that is giving us a lot of errors.

Anas-7 commented 4 months ago

I think Coil does mention this here. Considering the react-navigation-drawer relies on Animated elements it makes sense to have this crash. I tried using a library but that didn't work. Is there any feasible fix for this?

duguyihou commented 4 months ago

@Anas-7 can you provide a reproduce example as you mentioned?

duguyihou commented 4 months ago

@Anas-7 I did a quick test. Is this the correct step to reproduce the crash?

https://github.com/user-attachments/assets/6371d7cd-46d5-428a-9608-e2d29a82049f

Anas-7 commented 4 months ago

Hey @duguyihou ours is very similar to how you have implemented it but our app crashes as soon as we click on the menu. Can you share the kotlin version that you used for this test app from your android/build.gradle?

Our file currently looks like this:

buildscript {
    ext {
        buildToolsVersion = "33.0.0"
        minSdkVersion = 23
        compileSdkVersion = 34
        targetSdkVersion = 34
        // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
        ndkVersion = "23.1.7779620"
        kotlinVersion = "1.8.0"
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath("com.android.tools.build:gradle")
        classpath("com.facebook.react:react-native-gradle-plugin")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
        classpath("com.google.gms:google-services:4.3.15")
        classpath('com.google.firebase:firebase-crashlytics-gradle:3.0.0')
    }
}

My guess is that kotlin version may cause issue. In any case, I will try and create a reproducible example this weekend. Thanks for getting back quickly!

Anas-7 commented 4 months ago

Alright so we found the cause of the issue. We were using Blurview inside the drawer and removing that works. This issue in Blurview is documented here. I should have caught this earlier as I saw the logs and it had the following:

at eightbitlab.com.blurview.PreDrawBlurController.updateBlur(PreDrawBlurController.java:119) at eightbitlab.com.blurview.PreDrawBlurController$1.onPreDraw(PreDrawBlurController.java:50)

To replicate this, can you try wrapping the two options inside your drawer in a BlurView and then open it?

duguyihou commented 4 months ago

@Anas-7 Is it an issue for TurboImage or BlurView?

Update: I created a new release 1.9.0. With this version, you can disable hardware bitmaps.

https://github.com/user-attachments/assets/1bbb5fb8-e701-41b2-a5f2-a6adb542241d

Anas-7 commented 3 months ago

It was the issue with BlurView and not TurboImage, as another library I mentioned in the thread above had the same issue and the logs point to an error in BlurView files, i.e., something related to eightbitlabs. I have created another issue in BlurView repo. Thanks a lot for the option of disabling hardware!

duguyihou commented 3 months ago

Thanks @Anas-7 , I will close this issue.