Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> android Gui系統之SurfaceFlinger(3),androidgui系統

android Gui系統之SurfaceFlinger(3),androidgui系統

日期:2016/3/14 16:18:35      編輯:關於android開發

android Gui系統之SurfaceFlinger(3),androidgui系統


7.SurfaceFlinger

SurfaceFlinger在前面的篇幅了,多有涉及。

SurfaceFlinger是GUI刷新UI的核心,所以任何關於SurfaceFlinger的改進都會對android UI系統有重大影響。

SurfaceFlinger主要分為4個部分

1)黃油計劃---project butter

2)啟動過程

3)SurfaceFlinger & BufferQueue的關系

4)Vsync信號的處理

7.1黃油計劃

就是給android系統,圖上一層“黃油”。我們來看看andorid是怎麼給SurfaceFlinger塗上這層黃油的。

butter 由2個組成部分,Vsync & Triple buffer。

Triple buffer:

上面講到雙緩沖區技術,也提到FrameBufferNativeWindow 在申請buffer的時候,可以是2,或者是3.

這個3 就是馬上要講到的Triple Buffer技術。

我們先會過來看看雙緩沖技術。

之前說 雙緩沖,是把一個buffer放在bitmap上,等到這個所有元素都准備好以後,在把bitmap刷到屏幕上。

這樣會解決卡頓的感覺。

我們考慮一種情況,假設屏幕刷新頻率是66Hz,CPU頻率是100Hz.

之前已經講了雙緩沖技術,這裡簡單過一下。

如上面的假設,UI的刷新是0.015s,而buffer的准備是0.01s

一個Frame Buffer代表一幀圖像。

0.01s:

此時,buffer已經准備好數據,而顯示器只顯示了圖像的2/3

0.015s

顯示器顯示了第一幀圖像,而buffer已經填充了第二幀的1/3

0.02s

Buffer已經准備好了第二幀,而顯示器出現了問題,1/3的內容屬於第二幀,2/3的內容屬於第一幀。

這就是android引入雙緩沖技術的原因。

如果buffer准備的時間,比屏幕刷新圖像的速度慢呢?

顯示屏的每一次刷新,就是對顯示器屏幕的掃描,但是它是有間隔的(物理設備嘛,肯定有這個間隔)。

典型的PC顯示器屏幕刷新頻率是60Hz,這是因為一秒60幀,從人的角度看,就會覺得很流暢。

所以間隔1/60秒,也就是16ms 如果我們准備時間<=16ms,那就可以做到“無縫連接”。畫面就很流程。

這段空隙稱為VBI。 這個時間就是交換緩沖區最佳的時間。而這個交換的動作就是Vsync 也是SurfaceFlinger的重點。

如果我們圖像准備時間<=16ms. OK,畫面是很流暢的,但是我們無法保證設備性能一定很very good。所以也有可能畫面准備時間超過16ms


我們看看這張圖。 剛開始buffer裡面有數據A,這時候,可以直接顯示在屏幕上。 過了16ms以後,數據B還沒准備好,屏幕只能繼續顯示A。這樣就浪費了依次交換的機會。 到下一次交換,B被顯示在屏幕上。 這裡有段時間被浪費了。 等到下一次A的時候,過了16ms,還是沒有准備好,繼續浪費。所以雙緩沖區技術,也有很大浪費。 有沒有辦法規避呢, 比如上圖 B & A之間的這段時間,如果我增加一個buffer,C。 這樣B准備好以後,雖然C沒有好,但是B可以顯示在屏幕上,等到下一次16ms到了以後,C已經准備好了,這樣可以很大程度上減少CPU時間的浪費。 也就是空間換時間的一種思想。 所以多緩沖區就是,就是可以根據系統的實際內存情況,來判斷buffer的數量。  

7.2 SurfaceFlinger的啟動

SurfaceFlinger 我們前面已經說了,它其實就是一個service。

void SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);
}

初始化事件隊列。

void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
    mFlinger = flinger;
    mLooper = new Looper(true);
    mHandler = new Handler(*this);
}

創建了looper & Handler

但是這個looper什麼時候起來的呢?

void MessageQueue::waitMessage() {
    do {
        IPCThreadState::self()->flushCommands();
        int32_t ret = mLooper->pollOnce(-1);
        switch (ret) {
            case Looper::POLL_WAKE:
            case Looper::POLL_CALLBACK:
                continue;
            case Looper::POLL_ERROR:
                ALOGE("Looper::POLL_ERROR");
            case Looper::POLL_TIMEOUT:
                // timeout (should not happen)
                continue;
            default:
                // should not happen
                ALOGE("Looper::pollOnce() returned unknown status %d", ret);
                continue;
        }
    } while (true);
}

可以看到最終會調用looper啟動函數。可以看到Looper::POLL_TIMEOUT: android什麼都沒做,盡管它們不應該發生。

其實handler兜了一圈,發現最後還是回到surfaceflinger來處理:

void SurfaceFlinger::onMessageReceived(int32_t what) {
    ATRACE_CALL();
    switch (what) {
        case MessageQueue::TRANSACTION: {
            handleMessageTransaction();
            break;
        }
        case MessageQueue::INVALIDATE: {
            bool refreshNeeded = handleMessageTransaction();
            refreshNeeded |= handleMessageInvalidate();
            refreshNeeded |= mRepaintEverything;
            if (refreshNeeded) {
                // Signal a refresh if a transaction modified the window state,
                // a new buffer was latched, or if HWC has requested a full
                // repaint
                signalRefresh();
            }
            break;
        }
        case MessageQueue::REFRESH: {
            handleMessageRefresh();
            break;
        }
    }
}

7.3 client

任何有UI界面App都在surfaceflinger裡面有client。

所以是一個app對應一個surfaceflinger裡面的client(ISurfaceComposerClient)。

 

下面我們來分析surfaceflinger的2個重要函數:

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
{
    sp<ISurfaceComposerClient> bclient;
    sp<Client> client(new Client(this));
    status_t err = client->initCheck();
    if (err == NO_ERROR) {
        bclient = client;
    }
    return bclient;
}

返回ISurfaceComposerClient,也就是client的bind對象實體。

其實就上面標紅的一句,進行必要的有效性檢查,現在代碼:

status_t Client::initCheck() const {
    return NO_ERROR;
}

有了clinet以後,看下surface的產生。

status_t Client::createSurface(
        const String8& name,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp)
{
    /*
     * createSurface must be called from the GL thread so that it can
     * have access to the GL context.
     */

    class MessageCreateLayer : public MessageBase {
        SurfaceFlinger* flinger;
        Client* client;
        sp<IBinder>* handle;
        sp<IGraphicBufferProducer>* gbp;
        status_t result;
        const String8& name;
        uint32_t w, h;
        PixelFormat format;
        uint32_t flags;
    public:
        MessageCreateLayer(SurfaceFlinger* flinger,
                const String8& name, Client* client,
                uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
                sp<IBinder>* handle,
                sp<IGraphicBufferProducer>* gbp)
            : flinger(flinger), client(client),
              handle(handle), gbp(gbp),
              name(name), w(w), h(h), format(format), flags(flags) {
        }
        status_t getResult() const { return result; }
        virtual bool handler() {
            result = flinger->createLayer(name, client, w, h, format, flags,
                    handle, gbp);
            return true;
        }
    };

    sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
            name, this, w, h, format, flags, handle, gbp);
    mFlinger->postMessageSync(msg);
    return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}

到來到去,其實就2句話:

postMessageSync,其實就是一開始不會直接創建surface,然後放入surfaceflinger隊列裡,這樣不會打斷現在的操作。

然後啟動createlayer方法。這個方法之前已經分析過了。

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved