SurfaceFlinger
摘要:本文將以 使用 和 分析 兩部分來了解SurfaceFlinger。
首先使用,通過寫一個測試程序來直接使用SurfaceFlinger提供的服務,使界面顯示圖片。
然後分析,通過解剖測試程序和SurfaceFlinger之間的聯繫,來分析SurfaceFlinger的內部機制。
這樣先使用後分析,更容易理解。不然枯燥的去看代碼,效率非常低,並且很容易厭倦。
文章目錄
1. 測試SurfaceFlinger
- 實驗目的:寫一個c++應用,調用SurfaceFlinger顯示顏色
- 關鍵字:SurfaceFlinger
- 實驗平臺:全志T7-android
- 步驟:
- 編寫cpp代碼
- 獲得SurfaceFlinger服務
- 創建Surface
- 得到buffer
- 寫buffer
- 提交buffer
- 測試
- push到機器中看現象。
- 編寫cpp代碼
試驗1:顯示綠色的圖片。
步驟:編譯代碼,push到機器中,運行!
#include <cutils/memory.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <android/native_window.h>
using namespace android;
int main(int argc, char** argv)
{
// set up the thread-pool
sp<ProcessState> proc(ProcessState::self()); //binder獲取surfaceFlinger服務
ProcessState::self()->startThreadPool();
// create a client to surfaceflinger
sp<SurfaceComposerClient> client = new SurfaceComposerClient();
sp<SurfaceControl> surfaceControl = client->createSurface(String8("surfaceTest"),
160, 240, PIXEL_FORMAT_RGB_565, 0);
sp<Surface> surface = surfaceControl->getSurface();
SurfaceComposerClient::openGlobalTransaction();
surfaceControl->setLayer(100000);//設置z軸,越大顯示月靠前
SurfaceComposerClient::closeGlobalTransaction();
ANativeWindow_Buffer outBuffer;
surface->lock(&outBuffer, NULL);
ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height);
ALOGD("bpr = %d; outBuffer.height = %d;\n", bpr, outBuffer.height);
surface->unlockAndPost();
SurfaceComposerClient::openGlobalTransaction();
surfaceControl->setSize(320, 240);
SurfaceComposerClient::closeGlobalTransaction();
IPCThreadState::self()->joinThreadPool();
return 0;
}
結果:
成功! 綠色部分就是我們顯示的。
試驗二:顯示紅、綠、藍(RGB)
- 步驟:增加以下代碼:
sleep(1);
surface->lock(&outBuffer, NULL);
android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height);
surface->unlockAndPost();
sleep(1);
surface->lock(&outBuffer, NULL);
android_memset16((uint16_t*)outBuffer.bits, 0x001F, bpr*outBuffer.height);
surface->unlockAndPost();
sleep(1);
- 結果:啓動應用程序後先後順序顯示紅、綠、藍。時間間隔1s。
試驗三:通過設置layer隱藏我們的顯示。
- 步驟:
- dumpsys SurfaceFlinger查看當前顯示的所有layer
+ Layer 0xb69cc000 (surfaceTest)
Region transparentRegion (this=0xb69cc230, count=1)
[ 0, 0, 0, 0]
Region visibleRegion (this=0xb69cc008, count=1)
[ 0, 0, 160, 240]
Region surfaceDamageRegion (this=0xb69cc044, count=1)
[ 0, 0, -1, -1]
layerStack= 0, z= 100000, pos=(0,0), size=( 160, 240), crop=( 0, 0, -1, -1), finalCrop=( 0, 0, -1, -1), isOpaque=1, invalidate=0, alpha=0xff, flags=0x00000000, tr=[1.00, 0.00][0.00, 1.00]
client=0xb6620540
format= 4, activeBuffer=[ 160x 240: 160, 4], queued-frames=0, mRefreshPending=0
mTexName=7 mCurrentTexture=1
mCurrentCrop=[0,0,0,0] mCurrentTransform=0
mAbandoned=0
-BufferQueue mMaxAcquiredBufferCount=1, mMaxDequeuedBufferCount=2, mDequeueBufferCannotBlock=0 mAsyncMode=0, default-size=[160x240], default-format=4, transform-hint=00, FIFO(0)={}
>[01:0xb661be60] state=ACQUIRED, 0xb66345b0 [ 160x 240: 160, 4]
[00:0xb661b140] state=FREE , 0xb66342a0 [ 160x 240: 160, 4]
[02:0x0] state=FREE
以我們的測試層序爲例,layer的結構。其中"z= 100000"指的z軸數據。
2. 修改surfaceControl->setLayer(100000);中的數值小於所有layer的z軸值。
修改:surfaceControl->setLayer(10);
- 結果:
試驗結論
通過SurfaceFlinger獲取Surface,設置z軸,填充buffer,post輸出。