Android HWUI(Hardware Accelerated Rendering Engine for UI)是Android系統中用於處理UI渲染的硬體加速引擎。它的主要作用是利用GPU(圖形處理單元)來加速UI的渲染過程,從而提高渲染效率和流暢度。以下是Android HWUI工作的主要方式和步驟:
一、基本工作原理
傳統軟體的UI繪製是依靠CPU來完成的,硬體加速就是將繪製任務交由GPU來執行。
HWUI基於GPU加速,透過Skia Backend與GPU進行互動,將UI繪製任務從CPU轉移到GPU上執行。這種方式可以顯著提高繪製效能,特別是在高解析度螢幕和複雜UI場景下。
- GPU相比CPU更加適合完成光柵化、動畫變換等耗時任務,在移動裝置上比起使用CPU來完成這些任務,GPU會更加省電,帶來的使用者體驗也會更佳。
- 現代移動GPU支援可程式設計管線,可以高效地開發應用介面的一些特效(吸入、漸變、模糊、陰影)
Skia Backend有兩種:SkiaGl和SkiaVk,分別對應後端OpenGLES和Vulkan
二、核心元件
- Skia圖形庫:
- Skia是HWUI的核心圖形庫,提供了基礎的繪製功能,如圖形、文字、點陣圖等。
- 它支援硬體加速渲染,能夠充分利用GPU進行併發計算,加快UI介面的渲染速度。
- 程式碼示例
// 建立畫布 Canvas canvas = new Canvas(bitmap); // 繪製矩形 Paint paint = new Paint(); final int color = Color.BLUE; paint.setColor(color); RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); canvas.drawRoundRect(rect, 32, 32, paint);
- OpenGL ES/Vulkan:
- OpenGL ES/Vulkan是HWUI與GPU之間的橋樑,負責將Skia生成的繪製命令轉化為GPU能夠執行的指令序列。
- OpenGL ES 3.0是HWUI的預設版本,具有更好的功能和效能表現。未來HWUI的Backend預設會切換到Vulkan。
- DisplayList:
- DisplayList是HWUI的渲染列表,用於記錄繪製操作以及它們的位置、大小等資訊。
- 這些操作被顯式地快取起來,以便後續可以更快速地進行處理,並允許檢視樹中相同的部分在多個幀之間重複使用,從而節約記憶體和頻寬。
- 程式碼示例
// 建立DisplayList DisplayList displayList = new DisplayList("MyList"); displayList.start(512, 512); //設定寬高 // 新增繪製操作 Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); displayList.drawRect(64, 64, 256, 256, paint); // 結束DisplayList displayList.end();
- RenderNode:
- RenderNode是HWUI的渲染節點,對應於檢視層次結構中的一個節點。
- 每個View持有一個RenderNode,這些RenderNode組成樹形結構,用於管理和組織渲染任務。
- RenderNode負責儲存和管理View繪製過程中使用的各種屬性,如透明度和邊框等。
- 程式碼示例
// 建立RenderNode RenderNode renderNode = new RenderNode("MyNode"); // 更新RenderNode屬性 View view = findViewById(R.id.myView); renderNode.setPosition(view.getLeft(), view.getTop()); renderNode.setElevation(view.getElevation()); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon); renderNode.setBitmapCache(bitmap); // 新增子節點 RenderNode child = new RenderNode("MyChild"); //更新child屬性 renderNode.addChild(child);
- Layers
- Layer是HWUI的另一個重要概念,用於實現UI的專業效果和動畫效果。
- 在Android 10及以前的系統中,所有檢視都隸屬於共享的系統組層級。但是在Android 11及以後的系統中,每個視窗/活動/碎片都將擁有自己的獨立圖層級別,從而增強了效能和隱私管理。
- 程式碼示例
// 建立Layer Layer layer = mSurface.getLayer(); layer.setX(100); layer.setY(100); layer.setAlpha(0.5f); // 在Layer上繪製影像和文字 Canvas canvas = layer.lockCanvas(); canvas.drawBitmap(bitmap, 0, 0, paint); canvas.drawText(text, 30, 100, paint); layer.unlockCanvasAndPost(canvas);
- HardwareComposer
- HardwareComposer是Android系統中的硬體合成器,作為HWUI的主要介面之一。
- 它的作用是在GPU輸出影像到螢幕之前,對多個應用程式的渲染結果進行混合和組合,從而形成最終的顯示內容。
- 在硬體合成情況下,不需要將應用程式的UI渲染成一個幀快取(FrameBuffer)並上傳到系統RAM,從而減少記憶體和匯流排頻寬的負擔。
- 程式碼示例
RoutingTable routingTable = hwcomposer.createRoutingTable(); routingTable.setOutputConfig(new OutputConfiguration(mDisplayToken, Display.DEFAULT_DISPLAY)); Destination destination = routingTable.createDestination(); destination.setColorMode(ColorMode.SRGB); destination.setBufferStream(bufferStream); surfaceFlinger.setTransactionState(routingTable.getTransaction()); surfaceFlinger.applyTransaction();
- Threaded Rendering(多執行緒渲染):
- 為了最大化利用CPU效能,HWUI採用了多執行緒渲染模式。
- 通常包括UI執行緒和RenderThread(RT執行緒)。UI執行緒負責View的繪製邏輯和將繪製命令打包成Skia的繪製命令儲存到DisplayList;RT執行緒則負責取出這些繪製命令並執行實際的渲染操作。
三、工作流程
- UI執行緒繪製:
- 當View需要被繪製時,UI執行緒會呼叫相應的繪製方法(如onDraw())。
- 這些繪製方法透過Canvas類提供的介面進行繪製操作,Canvas的繪製命令會被轉化為Skia的繪製命令並儲存到DisplayList中。
- RenderThread渲染:
- RenderThread從DisplayList中取出繪製命令,並透過OpenGL ES介面將這些命令傳送給GPU執行。
- GPU完成繪製後,將渲染結果輸出到螢幕上。
- 效能最佳化:
- HWUI還採用了多種效能最佳化技術,如延時渲染列表(Deferred Display List)、繪製命令合併(Draw Op Batching)等。
- 這些技術透過減少GPU的呼叫次數、最佳化渲染狀態切換等方式來提高渲染效率。
四、總結
Android HWUI透過利用GPU進行硬體加速渲染,顯著提高了Android系統的UI渲染效能和流暢度。它透過Skia圖形庫、OpenGL ES介面、DisplayList、RenderNode以及多執行緒渲染等技術手段實現了高效的UI渲染過程。同時,HWUI還不斷引入新的效能最佳化技術來進一步提升渲染效率。