直接操作SurfaceFlinger畫圖並通過小demo深入分析SurfaceFlinger內部機制

SurfaceFlinger


摘要:本文將以 使用分析 兩部分來了解SurfaceFlinger。
首先使用,通過寫一個測試程序來直接使用SurfaceFlinger提供的服務,使界面顯示圖片。
然後分析,通過解剖測試程序和SurfaceFlinger之間的聯繫,來分析SurfaceFlinger的內部機制。
這樣先使用後分析,更容易理解。不然枯燥的去看代碼,效率非常低,並且很容易厭倦。


1. 測試SurfaceFlinger

  • 實驗目的:寫一個c++應用,調用SurfaceFlinger顯示顏色
  • 關鍵字:SurfaceFlinger
  • 實驗平臺:全志T7-android
  • 步驟:
    1. 編寫cpp代碼
      • 獲得SurfaceFlinger服務
      • 創建Surface
      • 得到buffer
      • 寫buffer
      • 提交buffer
    2. 測試
      • push到機器中看現象。

試驗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隱藏我們的顯示。

  • 步驟:
    1. 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輸出。


未完待續。。。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章