- What are hardware Bitmaps?
- Why should we use hardware Bitmaps?
- How do we enable hardware Bitmaps?
- How do we disable hardware Bitmaps?
- What’s broken when we use hardware Bitmaps?
- What’s less efficient when we use hardware Bitmaps?
What are hardware Bitmaps?
Bitmap.Config.HARDWARE is a new
Bitmap format that was added in Android O. Hardware
Bitmaps store pixel data only in graphics memory and are optimal for cases where the
Bitmap is only drawn to the screen.
Why should we use hardware Bitmaps?
Only one copy of pixel data is stored for hardware
Bitmaps. Normally there’s one copy of pixel data in application memory (the pixel byte array) and one copy in graphics memory (after the pixels are uploaded to the GPU). Hardware
Bitmaps retain only the copy uploaded to the GPU. As a result:
Bitmapsrequire ½ the memory of other Bitmap configurations
Bitmapsavoid jank caused by texture uploads at draw time.
How do we enable hardware Bitmaps?
Temporarily, set the default
DecodeFormat.PREFER_ARGB_8888 in your Glide requests. To do so for all requests in your application, set the
DecodeFormat in the default options in your
GlideModule, see the configuration page.
In the long run Glide will load hardware
Bitmaps by default and no changes will be needed to enable the format, only to disable it.
How do we disable hardware Bitmaps?
If you need to disable hardware
Bitmaps, you should try to do so only for requests where you need to do one of the slow or broken things below. You can disable hardware
Bitmaps for a particular request using
If you’re using the generated API:
GlideApp.with(fragment) .load(url) .disallowHardwareConfig() .into(imageView);
Or just via
RequestOptions options = new RequestOptions().disallowHardwareConfig(); Glide.with(fragment) .load(url) .apply(options) .into(imageView);
What’s broken when we use hardware Bitmaps?
Storing pixel data in graphics memory means that the pixel data isn’t readily accessible, which will cause exceptions in some cases. All of the known cases are listed below:
- Reading/writing pixel data in Java, including:
- Reading/writing pixel data in native code
- Rendering hardware
Bitmapswith a software Canvas:
Canvas canvas = new Canvas(normalBitmap) canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint());
- Using software layer types in views that draw Bitmaps (to draw a shadow for example)
ImageView imageView = … imageView.setImageBitmap(hardwareBitmap); imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
Opening too many file descriptors.
Bitmapconsumes a file descriptor. There’s a per process FD limit (O & earlier typically 1024, in some builds of O-MR1 & higher it’s 32k). Glide attempts to limit the number of hardware
Bitmapsallocated to stay under the limit, but if you’re already allocating large numbers of FDs, this may be an issue.
- Preconditions that expect
Screenshots triggered by code that try to draw the view hierarchy with
PixelCopycan be used instead on O+.
- Shared element transitions (fixed in OMR1)
An example trace will look something like this:
java.lang.IllegalStateException: Software rendering doesn't support hardware bitmaps at android.graphics.BaseCanvas.throwIfHwBitmapInSwMode(BaseCanvas.java:532) at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:62) at android.graphics.BaseCanvas.drawBitmap(BaseCanvas.java:120) at android.graphics.Canvas.drawBitmap(Canvas.java:1434) at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:529) at android.widget.ImageView.onDraw(ImageView.java:1367) [snip] at android.view.View.draw(View.java:19089) at android.transition.TransitionUtils.createViewBitmap(TransitionUtils.java:168) at android.transition.TransitionUtils.copyViewImage(TransitionUtils.java:102) at android.transition.Visibility.onDisappear(Visibility.java:380) at android.transition.Visibility.createAnimator(Visibility.java:249) at android.transition.Transition.createAnimators(Transition.java:732) at android.transition.TransitionSet.createAnimators(TransitionSet.java:396) [snip]
What’s less efficient when we use hardware Bitmaps?
In some cases to avoid breaking users, the
Bitmap class will perform an expensive copy of the graphics memory. In some cases where any of these methods are used, you should consider avoiding using the hardware
Bitmap configuration to begin with depending on the frequency the slow methods are used. If you do use these methods, the framework will log a message:
“Warning attempt to read pixels from hardware bitmap, which is very slow operation” and also trigger a