-
Notifications
You must be signed in to change notification settings - Fork 6k
Add native Android image decoders supported by API 28+ #26746
Conversation
726902a to
29d5d5c
Compare
dnfield
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs tests.
/cc @blasten FYI, @jason-simmons
| // Since this decoder is only installed for API 28 and 29, there is no | ||
| // supported way to work around this unfortunate copy. It's possible to | ||
| // produce an `SkImage` direcly from an `AHardwareBuffer`, but | ||
| // `AndroidBitmap_getHardwareBuffer` and `Bitmap.getHardwareBuffer` are only | ||
| // available in API 30+ and 31+ respectively. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is! But we'd have to do some dynamic lookups to see whether symbols are available.
I'm ok having this in place without doing that yet, but we should file an issue if one doesn't exist and add a TODO here for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got most of the way through resolving/calling AndroidBitmap_getHardwareBuffer at runtime, but even SkImage::MakeFromAHardwareBuffer and the underlying GrAHardwareBufferImageGenerator are preprocessed out with with __ANDROID_API__ >= 26 due to reliance on e.g. AHardwareBuffer_acquire... :(
I could probably propose a reasonable patch to cheaply resolve the symbols in Skia instead of gating like this, but we gotta make some behavior decisions/maybe provide a way to query support, and so I made a note to discuss with Skia friends and follow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would make sense to update Skia to check for the symbols rather than using the prepocessor to remove them entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for now we should just add a TODO to fix this when Skia API is available.
shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java
Outdated
Show resolved
Hide resolved
|
@dnfield Ah sorry, this is still quite broken/untested, but thanks for the helpful comments. :) |
|
Ahh ok, I saw the review request and started looking. Feel free to let me know when it's ready for another pass. |
b27c8d7 to
96dc5b5
Compare
7b196ce to
36358d3
Compare
aebdac6 to
4d859e6
Compare
93cdc4e to
846f27c
Compare
|
@dnfield I finally got around to fixing this up and it's good to go for another pass. |
|
Hmm, there's definitely a crash bug when running on arm64 caused by the |
846f27c to
f8d3df8
Compare
|
All fixed! |
| // The generator kicks off an IO task to decode everything, and calls to | ||
| // "GetInfo()" block until the header has been decoded. The decoder explicitly | ||
| // marks the height as -1 if the image is invalid or if the SDK image decoder | ||
| // is unavailable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this true? I'm not seeing any IO tasks getting kicked off, decoding is all happening on the platform thread right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AndroidImageGenerator::MakeFromData kicks off the task and is the only reasonable way to produce this ImageGenerator.
dnfield
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking closer
f8d3df8 to
54d2a59
Compare
a5c427b to
954170f
Compare
| return; | ||
| } | ||
|
|
||
| SkData::ReleaseProc on_release = [](const void* ptr, void* context) -> void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to do anything to make sure that this runs on the correct thread?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question -- I think this is safe as-is. In practice, this currently always happens on a different thread. No explicit mentioning of thread safety in the docs for AndroidBitmap_unlockPixels, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SkData is thread safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And if we end up on a different thread, AttachCurrentThread will make sure we're allowed to make JNI calls on it. Or reuse the JNIEnv for that thread if it already attached.
|
A rebase should fix the Linux Web Engine check. |
d237dad to
5962097
Compare
Relevant docs: flutter.dev/go/image-decoding-registry and flutter.dev/go/fallback-image-decoding
Continuation of flutter/flutter#17356 and flutter/flutter#82603.
Resolves flutter/flutter#20522 for API 28+.
ImageDecoderdoes not split the header parsing and image decoding stages into separate operations such that they can be executed by different threads -- instead, when image decoding starts, the SDK'sImageDecoderprovides the header data through a callback on the same thread before continuing on with decoding immediately.memcpyinGetPixelsby retrieving anAHardwareBufferfor the decoded SDKBitmapin order to produce anSkImagefrom it. But unfortunately,AndroidBitmap_getHardwareBuffer(NDK) andBitmap.getHardwareBuffer(SDK) are only available in API 30+ and 31 respectively, and I didn't manage to work out any other API-permitting ways to do this.Pre-launch Checklist
writing and running engine tests.
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.