As APIs do RenderScript foram descontinuadas desde o Android 12. Os fabricantes de dispositivos e componentes já pararam de oferecer suporte à aceleração de hardware, e o suporte para o RenderScript será totalmente removido em uma versão futura.
O desempenho do código C/C++ pode ser adequado para muitos casos de uso. Se você dependia apenas do RenderScript para intrínsecos, poderá substituir esses casos usando o Kit de ferramentas de substituição de intrínsecos do RenderScript, que é mais fácil de usar e pode dobrar o desempenho.
Se você precisa aproveitar ao máximo a aceleração de GPU, recomendamos migrar seus scripts para o Vulkan. Outras opções de aceleração incluem migrar seus scripts para o OpenGL, usando Operações de imagem baseadas em tela ou usando a Linguagem de sombreamento gráfico do Android (AGSL, na sigla em inglês).
Após a descontinuação do RenderScript na plataforma Android, o suporte ao RenderScript foi removido do Plug-in do Android para Gradle. Na versão 7.2 do Plug-in do Android para Gradle e mais recentes, as APIs do RenderScript foram descontinuadas. Elas continuam funcionando, mas invocam avisos. As versões futuras do AGP não vão mais incluir suporte ao Renderscript. Este guia explica como migrar do RenderScript.
Migrar dos intrínsecos
As funções intrínsecas do RenderScript vão continuar funcionando após a descontinuação do RenderScript, contudo, elas poderão ser executadas apenas na CPU e não na GPU.
Para algumas dessas operações, há opções mais eficientes integradas à plataforma ou às bibliotecas do Jetpack.
Operações de aceleração de imagem integradas
A plataforma Android oferece suporte a operações de processamento de aceleração de imagem que podem ser aplicadas a imagens, independente dos intrínsecos do RenderScript. Por exemplo:
- Mesclar
- Desfocar
- Matriz de cores
- Redimensionar
Desfoque de imagem no Android 12 e versões mais recentes em uma visualização
O RenderEffect
com suporte ao desfoque foi adicionado no Android 12,
nível 31 da API, permitindo que você desfoque um RenderNode
. O RenderNode
é um elemento da lista de exibição que o Android usa para ajudar a acelerar
gráficos da plataforma.
O Android oferece um atalho para aplicar um efeito ao RenderNode
associado
a uma View
. Para desfocar uma View
, chame
View.setRenderEffect()
:
val blurRenderEffect = RenderEffect.createBlurEffect(radius, radius,
Shader.TileMode.MIRROR
)
view.setRenderEffect(blurRenderEffect)
Desfoque de imagem no Android 12 e versões mais recentes renderizado em um bitmap
Caso você precise que a imagem desfocada seja renderizada em um Bitmap
, o framework
oferece suporte à renderização acelerada com um HardwareRenderer
com um HardwareBuffer
de apoio. O código abaixo cria
HardwareRenderer
, RenderNode
e RenderEffect
para o desfoque:
val imageReader = ImageReader.newInstance(
bitmap.width, bitmap.height,
PixelFormat.RGBA_8888, numberOfOutputImages,
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE or HardwareBuffer.USAGE_GPU_COLOR_OUTPUT
)
val renderNode = RenderNode("BlurEffect")
val hardwareRenderer = HardwareRenderer()
hardwareRenderer.setSurface(imageReader.surface)
hardwareRenderer.setContentRoot(renderNode)
renderNode.setPosition(0, 0, imageReader.width, imageReader.height)
val blurRenderEffect = RenderEffect.createBlurEffect(
radius, radius,
Shader.TileMode.MIRROR
)
renderNode.setRenderEffect(blurRenderEffect)
A aplicação do efeito envolve o uso de uma
RecordingCanvas
interna para o RenderNode
. O código abaixo
grava a imagem, cria a solicitação de renderização e espera que a
solicitação seja concluída:
val renderCanvas = it.renderNode.beginRecording()
renderCanvas.drawBitmap(it.bitmap, 0f, 0f, null)
renderNode.endRecording()
hardwareRenderer.createRenderRequest()
.setWaitForPresent(true)
.syncAndDraw()
A imagem renderizada fica em um HardwareBuffer
associado ao
ImageReader
. O código abaixo extrai a Image
e
retorna um Bitmap
unido ao HardwareBuffer
.
val image = imageReader.acquireNextImage() ?: throw RuntimeException("No Image")
val hardwareBuffer = image.hardwareBuffer ?: throw RuntimeException("No HardwareBuffer")
val bitmap = Bitmap.wrapHardwareBuffer(hardwareBuffer, null)
?: throw RuntimeException("Create Bitmap Failed")
O código abaixo é limpo depois de renderizar a imagem. Observe que
ImageReader
, RenderNode
, RenderEffect
e HardwareRenderer
podem ser usados
para processar várias imagens.
hardwareBuffer.close()
image.close()
imageReader.close()
renderNode.discardDisplayList()
hardwareRenderer.destroy()
AGSL para processamento de imagens
A Linguagem de sombreamento gráfico do Android (AGSL, na sigla em inglês) é usada pelo Android 13 e versões mais recentes para
definir o comportamento de objetos
RuntimeShader
programáveis. A AGSL
compartilha grande parte da sintaxe com sombreadores de fragmentos GLSL, mas funciona no
sistema de renderização de gráficos do Android para personalizar a pintura na Canvas
e filtrar o conteúdo da View
. Isso pode ser usado para adicionar processamento personalizado de imagem
durante operações de renderizaçãoou usando um RenderNode
diretamente para renderizar uma
imagem em uma tela Bitmap
. O exemplo abaixo demonstra como aplicar um
sombreador personalizado para substituir o efeito de desfoque da imagem.
Comece criando um RuntimeShader
, instanciando-o com o código de sombreador
da AGSL. Esse sombreador é usado para aplicar uma matriz de cores para rotação de matiz:
val hueShader = RuntimeShader("""
uniform float2 iResolution; // Viewport resolution (pixels)
uniform float2 iImageResolution; // iImage1 resolution (pixels)
uniform float iRadian; // radian to rotate things around
uniform shader iImage1; // An input image
half4 main(float2 fragCoord) {
float cosR = cos(iRadian);
float sinR = sin(iRadian);
mat4 hueRotation =
mat4 (
0.299 + 0.701 * cosR + 0.168 * sinR, //0
0.587 - 0.587 * cosR + 0.330 * sinR, //1
0.114 - 0.114 * cosR - 0.497 * sinR, //2
0.0, //3
0.299 - 0.299 * cosR - 0.328 * sinR, //4
0.587 + 0.413 * cosR + 0.035 * sinR, //5
0.114 - 0.114 * cosR + 0.292 * sinR, //6
0.0, //7
0.299 - 0.300 * cosR + 1.25 * sinR, //8
0.587 - 0.588 * cosR - 1.05 * sinR, //9
0.114 + 0.886 * cosR - 0.203 * sinR, //10
0.0, //11
0.0, 0.0, 0.0, 1.0 ); //12,13,14,15
float2 scale = iImageResolution.xy / iResolution.xy;
return iImage1.eval(fragCoord * scale)*hueRotation;
}
""")
O sombreador pode ser aplicado a um RenderNode
, assim como qualquer outro RenderEffect
.
O exemplo abaixo demonstra como definir os uniformes no hueShader:
hueShader.setFloatUniform("iImageResolution", bitmap.width.toFloat(),
bitmap.height.toFloat())
hueShader.setFloatUniform("iResolution", bitmap.width.toFloat(),
bitmap.height.toFloat())
hueShader.setFloatUniform("iRadian", radian)
hueShader.setInputShader( "iImage1", BitmapShader(bitmap, Shader.TileMode.MIRROR,
Shader.TileMode.MIRROR))
val colorFilterEffect = RenderEffect.createShaderEffect(it.hueShader)
renderNode.setRenderEffect(colorFilterEffect)
Para gerar o Bitmap
, a mesma técnica do exemplo anterior de desfoque
de imagem é usada.
- A
RecordingCanvas
internA doRenderNode
aplica o sombreador. - A
Image
é extraída, retornando umBitmap
unido aoHardwareBuffer
.
Converter de planos YUV para RGB usando o CameraX
A conversão de planos YUV em RGB para uso no processamento de imagens tem suporte como parte do caso de uso da ImageAnalysis no CameraX do Jetpack.
Existem recursos sobre o uso da ImageAnalysis
como parte do codelab
Começar a usar o CameraX e no
repositório de
exemplos (link em inglês) da câmera do Android.
Kit de ferramentas de substituição de intrínsecos do Renderscript
Caso seu aplicativo use intrínsecos, você poderá usar a biblioteca de substituição independente. Nossos testes indicam que isso é mais rápido do que usar a implementação de CPU atual do RenderScript.
O kit de ferramentas inclui as seguintes funções:
- Mesclar
- Desfocar
- Matriz de cores
- Convolução
- Histograma e histogramDot
- Tabela de consulta (LUT) e LUT 3D
- Redimensionar
- YUV para RGB
Para ver todos os detalhes e as limitações, consulte os arquivos README.md
e Toolkit.kt
(links em inglês) do kit de ferramentas.
Siga estas etapas para fazer o download, adicionar e usar a biblioteca:
Faça o download do projeto. do GitHub.
Localize e crie o
renderscript-toolkit module
.Adicione a biblioteca ao projeto do Android Studio modificando o arquivo
build.gradle
do app.Invoque o método adequado do kit de ferramentas.
Exemplo: migrar da função ScriptIntrinsicBlur
Para substituir a função ScriptIntrinsicBlur
:
Para desfocar um bitmap, chame
Toolkit.blur
.var blurredBitmap = Toolkit.blur(myBitmap, radius)
Se você quiser desfocar uma imagem representada por uma matriz de bytes, especifique a largura, a altura e o número de bytes por pixel.
val outArray = Toolkit.blur(inputArray, bytesPerPixel, width, height, radius)
Migrar dos scripts
Se o caso de uso não puder ser resolvido com:
- O kit de ferramentas de substituição de intrínsecos do RenderScript
- Novas APIs na plataforma Android, como
RenderEffect
eAGSL
- APIs da biblioteca do Android Jetpack, como
CameraX
Além disso, seu caso de uso pode se beneficiar da aceleração de GPU. O Android oferece suporte à computação de GPU nas APIs multiplataforma Vulkan e OpenGL ES (GLES). Talvez você ache isso desnecessário porque, na maioria dos dispositivos, os scripts já estão em execução na CPU. em vez da GPU: o C/C++ pode ser mais rápido que o RenderScript, GLES ou Vulkan de computação em alguns casos de uso. (ou pelo menos rápido o suficiente para seu caso de uso)
Para entender melhor como migrar as funções, consulte o app de exemplo (link em inglês). O exemplo mostra como desfocar um bitmap e fazer a conversão de uma matriz de cores no RenderScript e tem o código equivalente do Vulkan.
Se o app precisa oferecer suporte a várias versões, use o RenderScript para
dispositivos com o Android 6 (nível 23 da API) ou versões anteriores e o Vulkan ou o GLES em
dispositivos com suporte ao Android 7 (nível 24 da API) ou mais recente. Se a
minSdkVersion
for 24 ou mais recente, talvez não seja necessário usar o RenderScript. É possível usar Vulkan ou
o GLES 3.1 em qualquer lugar em que você precise de suporte à computação da GPU.
O Android fornece vinculações de SDK para APIs GLES. Não é necessário usar o NDK ao trabalhar com OpenGL ES.
O Vulkan não fornece vinculações de SDK. Não há mapeamento direto do RenderScript para o Vulkan. Programe o código Vulkan usando o NDK e crie funções JNI para acessar esse código em Kotlin ou Java.
As páginas abaixo abordam aspectos da migração do RenderScript. O app de exemplo implementa quase todas essas considerações. Para entender melhor, compare o RenderScript e o código equivalente do Vulkan.