Bitmap.Config.HARDWARE vs Bitmap.Config.RGB_565

API 26 añade la nueva opción Bitmap.Config.HARDWARE :

Configuración especial, cuando el mapa de bits se almacena sólo en la memoria gráfica. Los mapas de bits en esta configuración son siempre inmutables. Es óptimo para casos, cuando la única operación con el mapa de bits es dibujarlo en una pantalla.

Preguntas que no se explican en documentos:

  1. ¿Debemos SIEMPRE preferir ahora Bitmap.Config.HARDWARE sobre Bitmap.Config.RGB_565 cuando la velocidad es de máxima prioridad y la calidad y la mutabilidad no son (por ejemplo, para las miniaturas, etc)?
  2. ¿Los datos de píxeles después de la decodificación utilizando esta opción NO consumen NINGUNA memoria heap y sólo residen en la memoria GPU? Si es así, esto parece ser finalmente un alivio para la preocupación de OutOfMemoryException al trabajar con imágenes.
  3. ¿Qué calidad en comparación con RGB_565, RGBA_F16 o ARGB_8888 debemos esperar de esta opción?
  4. ¿La velocidad de decodificación es la misma / mejor / vale la pena en comparación con la decodificación con RGB_565?
  5. (Gracias @CommonsWare por señalar en los comentarios) ¿Qué pasaría si superamos la memoria GPU al decodificar una imagen usando esta opción? ¿Se lanzaría alguna excepción (quizás la misma OutOfMemoryException :)?

La documentación y el código fuente público aún no se han introducido en el git de Google . Así que mi investigación se basa sólo en información parcial, algunos experimentos, y en mi propia experiencia de portar JVM a varios dispositivos.

Mi prueba creó un gran mapa de bits mutable y lo copió en un nuevo mapa de bits HARDWARE en un clic de un botón, agregándolo a una lista de mapa de bits. Me las arreglé para crear varias instancias de los mapas de bits grandes antes de que se estrelló.

Pude encontrar esto en el androide-o-preview-4 git push:

 +struct AHardwareBuffer; +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer); +#else +typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const struct AHardwareBuffer *buffer); 

Y buscando la documentación de AHardwareBuffer , bajo el capó está creando un EGLClientBuffer respaldado por ANativeWindowBuffer (buffer gráfico nativo) en la memoria compartida de Android ("ashmem"). Pero la implementación real puede variar según el hardware.

En cuanto a las preguntas:

  1. ¿Debemos SIEMPRE preferir ahora Bitmap.Config.HARDWARE sobre Bitmap.Config.RGB_565 …?

Para SDK> = 26, la configuración HARDWARE puede mejorar el dibujo de mapa de bits de nivel bajo evitando la necesidad de copiar los datos de píxeles en la GPU cada vez que el mismo mapa de bits vuelva a la pantalla. Supongo que puede evitar la pérdida de algunos marcos cuando se agrega un mapa de bits a la pantalla.

La memoria no se cuenta con su aplicación, y mi prueba confirmó esto.

Los documentos de la biblioteca nativa dicen que devolverá null si la asignación de memoria no tuvo éxito. Sin el código fuente, no está claro lo que la implementación de Java (los implementadores de API) hará en este caso – podría decidir lanzar OutOfMemoryException o OutOfMemoryException a un tipo diferente de asignación.

Actualización: el experimento revela que no se lanza OutOfMemoryException. Mientras que la asignación tiene éxito – todo funciona bien. Al fallar en la asignación – el emulador se estrelló (desaparecido). En otras ocasiones tengo una extraña NullPointerException al asignar Bitmap en la memoria de la aplicación.

Debido a la estabilidad impredecible, no recomendaría usar esta nueva API en la producción actual . Al menos no sin pruebas extensas.

  1. ¿Los datos de píxeles después de la decodificación utilizando esta opción NO consumen NINGUNA memoria heap y sólo residen en la memoria GPU? Si es así, esto parece ser finalmente un alivio para la preocupación de OutOfMemoryException al trabajar con imágenes.

Los datos de píxel estarán en memoria compartida (probablemente memoria de textura), pero todavía hay un pequeño objeto de Bitmap en Java referenciándolo (por lo que "CUALQUIERA" es inexacta).

Cada proveedor puede decidir implementar la asignación real de manera diferente, no es una API pública a la que están obligados. Así que OutOfMemoryException todavía puede ser un problema. No estoy seguro de cómo se puede manejar correctamente.

  1. ¿Qué calidad en comparación con RGB_565 / ARGB_8888?

El indicador HARDWARE no se trata de calidad, sino de ubicación de almacenamiento de píxeles. Dado que los indicadores de configuración no pueden ser OR -ed, supongo que el valor predeterminado ( ARGB_8888 ) se utiliza para la decodificación.

(En realidad, el enum HARDWARE parece un hack).

  1. ¿La velocidad de decodificación es la misma / mejor / peor …?

HARDWARE bandera parecen no relacionados con la decodificación, por lo que igual que ARGB_8888 .

  1. ¿Qué pasaría si superamos la memoria GPU?

Mi resultado de la prueba en cosas muy malas cuando la memoria se está acabando. El emulador se estrelló horriblemente a veces, y tengo inesperado NPE no relacionado en otras ocasiones. No se produjo una excepción OutOfMemoryException, y tampoco había forma de saber cuándo se agota la memoria de la GPU, así que no hay forma de prever esto.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.