Le API RenderScript sono deprecate a partire da Android 12. I produttori di dispositivi e componenti hanno già smesso di fornire supporto per l'accelerazione hardware e il supporto di RenderScript verrà rimosso completamente in una versione futura.
Le prestazioni di C/C++ possono essere adeguate per molti casi d'uso e, se facevi affidamento solo su RenderScript per funzionalità intrinseche, puoi sostituire questi utilizzi con il Toolkit per la sostituzione di RenderScript Intrinsics, che è più facile da utilizzare e offre un potenziale miglioramento delle prestazioni raddoppiato.
Se hai bisogno di sfruttare appieno l'accelerazione GPU, ti consigliamo di eseguire la migrazione degli script a Vulkan. Altre opzioni accelerate includono la migrazione degli script a OpenGL, l'utilizzo di operazioni per le immagini basate su Canvas o l'utilizzo di Android Graphics Shading Language (AGSL).
In seguito al ritiro di RenderScript sulla piattaforma Android, il supporto per RenderScript verrà rimosso dal plug-in Android per Gradle. A partire dal plug-in Android per Gradle 7.2, le API RenderScript sono deprecate. Continuano a funzionare, ma richiamano avvisi. Le versioni future di AGP non includeranno più il supporto di Renderscript. Questa guida spiega come eseguire la migrazione da RenderScript.
Esegui la migrazione dalle funzionalità intrinseche
Sebbene le funzioni intrinseche di RenderScript continueranno a funzionare dopo il ritiro di RenderScript, potrebbero essere eseguite solo sulla CPU anziché sulla GPU.
Per alcune di queste operazioni, ora esistono opzioni più efficienti integrate nella piattaforma o nelle librerie Jetpack.
Operazioni integrate sulle immagini accelerate
La piattaforma Android supporta operazioni di elaborazione accelerata delle immagini che possono essere applicate alle immagini, indipendentemente dalle funzioni intrinseche di RenderScript. Tra gli esempi possibili:
- Mix
- Sfocatura
- Matrice dei colori
- Ridimensiona
Sfocatura delle immagini su Android 12 e versioni successive in una visualizzazione
RenderEffect
con supporto per la sfocatura è stato aggiunto ad Android 12,
livello API 31, per consentirti di sfocare un RenderNode
. RenderNode
è un costrutto dell'elenco di visualizzazione utilizzato da Android per accelerare la grafica della piattaforma.
Android fornisce una scorciatoia per applicare un effetto al RenderNode
associato
a un View
. Per sfocare un View
, chiama
View.setRenderEffect()
:
val blurRenderEffect = RenderEffect.createBlurEffect(radius, radius,
Shader.TileMode.MIRROR
)
view.setRenderEffect(blurRenderEffect)
Sfocatura immagine su Android 12 e versioni successive visualizzata in una bitmap
Se vuoi che l'immagine sfocata venga visualizzata in un elemento Bitmap
, il framework
supporta il rendering accelerato con un elemento HardwareRenderer
supportato da HardwareBuffer
. Il seguente codice crea HardwareRenderer
, RenderNode
e RenderEffect
per la sfocatura:
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)
L'applicazione dell'effetto prevede l'utilizzo del
RecordingCanvas
interno per RenderNode
. Il seguente codice registra il disegno, crea la richiesta di rendering e attende il completamento della richiesta:
val renderCanvas = it.renderNode.beginRecording()
renderCanvas.drawBitmap(it.bitmap, 0f, 0f, null)
renderNode.endRecording()
hardwareRenderer.createRenderRequest()
.setWaitForPresent(true)
.syncAndDraw()
L'immagine visualizzata è in una HardwareBuffer
associata all'elemento ImageReader
. Il seguente codice acquisisce Image
e restituisce un Bitmap
che esegue il wrapping del relativo 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")
Il seguente codice esegue la pulizia dopo il rendering dell'immagine. Tieni presente che ImageReader
, RenderNode
, RenderEffect
e HardwareRenderer
possono essere utilizzati per elaborare più immagini.
hardwareBuffer.close()
image.close()
imageReader.close()
renderNode.discardDisplayList()
hardwareRenderer.destroy()
AGSL per l'elaborazione delle immagini
L'Android Graphics Shading Language (AGSL) viene utilizzato da Android 13 e versioni successive per
definire il comportamento degli oggetti
RuntimeShader
programmabili. AGSL condivide gran parte della sua sintassi con gli ombreggiatori dei frammenti GLSL, ma funziona all'interno del sistema di rendering della grafica Android per personalizzare la pittura all'interno di Canvas
e filtrare i contenuti View
. Può essere utilizzata per aggiungere un'elaborazione personalizzata di immagini
durante le operazioni di disegno o utilizzando RenderNode
direttamente per eseguire il rendering
di un'immagine in un canvas Bitmap
. L'esempio seguente mostra come applicare uno
scuratore personalizzato per sostituire l'effetto di sfocatura dell'immagine.
Per iniziare, crea un valore RuntimeShader
, creando un'istanza con il codice mesh AGSL. Questo ombreggiatore viene utilizzato per applicare una matrice dei colori per la rotazione delle tonalità:
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;
}
""")
Lo Shader può essere applicato a un RenderNode
, come qualsiasi altro RenderEffect
.
L'esempio seguente mostra come impostare le uniformi in 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)
Per ottenere Bitmap
, viene utilizzata la stessa tecnica del precedente campione di sfocatura dell'immagine.
- L'elemento
RecordingCanvas
interno perRenderNode
applica lo meshr. - L'oggetto
Image
viene acquisito, restituendo unBitmap
che aggrega il suoHardwareBuffer
.
Converti da YUV planare a RGB utilizzando CameraX
La conversione da YUV planare a RGB per l'utilizzo nell'elaborazione delle immagini è supportata nell'ambito del caso d'uso di ImageAnalysis all'interno di CameraX di Jetpack.
Sono disponibili risorse sull'utilizzo di ImageAnalysis
nell'ambito del codelab Getting Started with CameraX e nel repository Esempi delle videocamere Android.
Il toolkit di sostituzione intrinseco di Renderscript
Se la tua applicazione utilizza funzionalità intrinseche, puoi utilizzare la libreria sostitutiva autonoma; i nostri test indicano che è più veloce rispetto all'utilizzo dell'implementazione esistente della CPU RenderScript.
Il toolkit include le seguenti funzioni:
- Mix
- Sfocatura
- Matrice colore
- Convolvere
- Istogram e istogramDot
- Tabella di ricerca (LUT) e LUT 3D
- Ridimensiona
- Da YUV a RGB
Per informazioni dettagliate e limitazioni, vedi README.md
e Toolkit.kt
del toolkit.
di copertina.
Per scaricare, aggiungere e utilizzare la libreria, procedi nel seguente modo:
Scarica il progetto da GitHub.
Individua e crea
renderscript-toolkit module
.Aggiungi la libreria al progetto Android Studio modificando il file
build.gradle
dell'app.Richiama il metodo appropriato del toolkit.
Esempio: eseguire la migrazione dalla funzione ScriptIntrinsicBlur
Per sostituire la funzione ScriptIntrinsicBlur
:
Per sfocare una bitmap, chiama
Toolkit.blur
.var blurredBitmap = Toolkit.blur(myBitmap, radius)
Se vuoi sfocare un'immagine rappresentata da un array di byte, specifica la larghezza, l'altezza e il numero di byte per pixel.
val outArray = Toolkit.blur(inputArray, bytesPerPixel, width, height, radius)
Esegui la migrazione dagli script
Se il tuo caso d'uso non può essere risolto con:
- Il Toolkit per la sostituzione di RenderScript Intrinsics
- Nuove API all'interno della piattaforma Android come
RenderEffect
eAGSL
- API della libreria Android Jetpack come
CameraX
Inoltre, il tuo caso d'uso può trarre vantaggio dall'accelerazione GPU: Android supporta il calcolo GPU sulle API multipiattaforma Vulkan e OpenGL ES (GLES). Questo potrebbe non essere necessario perché sulla maggior parte dei dispositivi gli script sono già in esecuzione sulla CPU anziché sulla GPU: in alcuni casi d'uso C/C++ può essere più veloce del calcolo di RenderScript, GLES o Vulkan. (o almeno abbastanza veloce per il tuo caso d'uso)
Per comprendere meglio come eseguire la migrazione, esamina l'app di esempio. L'esempio mostra come sfocare una bitmap ed eseguire una conversione a matrice dei colori in RenderScript e ha un codice equivalente in Vulkan e OpenGL.
Se la tua applicazione deve supportare una serie di release, utilizza RenderScript per i dispositivi con Android 6 (livello API 23) e versioni precedenti, nonché Vulkan o GLES sui dispositivi supportati con Android 7 (livello API 24) e versioni successive. Se minSdkVersion
è 24 o superiore, potrebbe non essere necessario utilizzare RenderScript. Vulkan o GLES 3.1 possono essere utilizzati ovunque sia necessario il supporto del calcolo GPU.
Android fornisce associazioni di SDK per le API GLES, quindi non è necessario utilizzare l'NDK quando si lavora in OpenGL ES.
Vulkan non fornisce associazioni di SDK, quindi non esiste una mappatura diretta da RenderScript a Vulkan; si scrive il codice Vulkan utilizzando l'NDK e si crea funzioni JNI per accedere a questo codice da Kotlin o Java.
Le pagine seguenti illustrano alcuni aspetti della migrazione da RenderScript. L'app di esempio implementa quasi tutte queste considerazioni. Per comprenderli meglio, confronta il codice equivalente di RenderScript e Vulkan.