Android 重學系列 圖元的消費

前言

經(jīng)過前兩篇文章的解析,我們徹底的理解GraphicBuffer的生產(chǎn)端究竟做了什么胎挎。本文就來討論GraphicBuffer是怎么消費。

整個圖元的消費到合成,最后到通過hwc發(fā)送到fb谆趾。由于整個流程十分長,中間有許多細節(jié)叛本,我將會挑出核心的思想來和大家聊聊其中的原理沪蓬。

還記得,我在GraphicBuffer的誕生里面具體了聊了queuebuffer最后會通過IConsumerListener的回調(diào)通知消費者進行消費来候。

我們接著繼續(xù)看看接下來的邏輯跷叉。

如果遇到問題,可以到本文討論http://www.reibang.com/p/67c1e350fe0d

正文

讓我們先來回憶一下营搅,在圖元緩沖隊列初始化一文中曾經(jīng)總結(jié)的UML圖云挟。

Layer與緩沖隊列的設(shè)計.png

文件:frameworks/native/libs/gui/BufferQueueProducer.cpp

           frameAvailableListener = mCore->mConsumerListener;
        }
        Mutex::Autolock lock(mCallbackMutex);
        while (callbackTicket != mCurrentCallbackTicket) {
            mCallbackCondition.wait(mCallbackMutex);
        }

        if (frameAvailableListener != NULL) {
            frameAvailableListener->onFrameAvailable(item);
        } else if (frameReplacedListener != NULL) {
            frameReplacedListener->onFrameReplaced(item);
        }

frameAvailableListener就是ProxyConsumerListener。這個對象持有ConsumeBase转质。當進行回調(diào)時候就會回調(diào)到ConsumeBase的mFrameAvailableListener园欣。

void ConsumerBase::onFrameAvailable(const BufferItem& item) {

    sp<FrameAvailableListener> listener;
    { // scope for the lock
        Mutex::Autolock lock(mFrameAvailableMutex);
        listener = mFrameAvailableListener.promote();
    }

    if (listener != NULL) {
        listener-> (item);
    }
}

而ConsumeBase的mFrameAvailableListener是BufferLayer注冊進來的。到這里倒在緩沖隊列的初始化聊過休蟹。

BufferLayer onFrameAvailable

文件:/frameworks/native/services/surfaceflinger/BufferLayer.cpp

void BufferLayer::onFrameAvailable(const BufferItem& item) {
    // Add this buffer from our internal queue tracker
    { // Autolock scope
        Mutex::Autolock lock(mQueueItemLock);
        mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
                                                 item.mGraphicBuffer->getHeight(),
                                                 item.mFrameNumber);

        if (item.mFrameNumber == 1) {
            mLastFrameNumberReceived = 0;
        }

        // Ensure that callbacks are handled in order
        while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
            status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
                                                               ms2ns(500));
...
        }

        mQueueItems.push_back(item);
        android_atomic_inc(&mQueuedFrames);


        mLastFrameNumberReceived = item.mFrameNumber;
        mQueueItemCondition.broadcast();
    }

    mFlinger->signalLayerUpdate();
}

這里做的事情很簡單沸枯,增加mQueuedFrames的計數(shù),mQueueItems添加一個BufferItem赂弓,并喚醒其他線程入隊的阻塞绑榴。接著調(diào)用SF的signalLayerUpdate。

SurfaceFlinger signalLayerUpdate

文件:rameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::signalLayerUpdate() {
    mEventQueue->invalidate();
}

接著調(diào)用到MessageQueue的invalidate

void MessageQueue::invalidate() {
    mEvents->requestNextVsync();
}

在MessageQueue中請求下一個同步信號

EventThread::Connection::requestNextVsync

void EventThread::Connection::requestNextVsync() {
    mEventThread->requestNextVsync(this);
}
void EventThread::requestNextVsync(const sp<EventThread::Connection>& connection) {
    std::lock_guard<std::mutex> lock(mMutex);

    if (mResyncWithRateLimitCallback) {
        mResyncWithRateLimitCallback();
    }

    if (connection->count < 0) {
        connection->count = 0;
        mCondition.notify_all();
    }
}

EventThread::Connection的count的標志位實際上是指vysnc事件是每隔幾個事件通知盈魁。此時是count在初始化的時候是-1.此時強制設(shè)置為0彭沼,說明只有調(diào)用requestNextVsync強制喚醒才會返回vysnc通知。

整體設(shè)計可以看我寫第一篇SurfaceFlinger 的初始化备埃。mResyncWithRateLimitCallback這個方法用于調(diào)整DispSync的時間戳姓惑。假如是第一次初始化,因此count還是-1.因此直接喚醒waitForEventLocked中的等待按脚。

        if (!timestamp && !eventPending) {
            // wait for something to happen
            if (waitForVSync) {
                bool softwareSync = mUseSoftwareVSync;
                auto timeout = softwareSync ? 16ms : 1000ms;
                if (mCondition.wait_for(*lock, timeout) == std::cv_status::timeout) {
                    if (!softwareSync) {
                        ALOGW("Timed out waiting for hw vsync; faking it");
                    }
                    // FIXME: how do we decide which display id the fake
                    // vsync came from ?
                    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
                    mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
                    mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
                    mVSyncEvent[0].vsync.count++;
                }
            } else {
                mCondition.wait(*lock);
            }

此時timestamp一開始是0于毙,當設(shè)置了時間戳,將不會直接等待跳出死循環(huán)辅搬,為0則會唯沮。eventPending是由接進來的屏幕的mPendingEvents判斷是否為空脖旱,不為空則是true。 如果EventThread有Connection接進來進行監(jiān)聽將會設(shè)置為waitForVSync為true介蛉。

當我們進行初始化的時候萌庆,由于沒有屏幕接進來。因此第一個信號是DISPLAY_EVENT_VSYNC币旧。進行刷新践险。

MessageQueue的回調(diào)

int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
    ssize_t n;
    DisplayEventReceiver::Event buffer[8];
    while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
        for (int i = 0; i < n; i++) {
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                mHandler->dispatchInvalidate();
                break;
            }
        }
    }
    return 1;
}

能看到整個MessageQueue的回調(diào)只接受DISPLAY_EVENT_VSYNC,進行刷新吹菱。

void MessageQueue::Handler::dispatchInvalidate() {
    if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
        mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
    }
}

void MessageQueue::Handler::handleMessage(const Message& message) {
    switch (message.what) {
        case INVALIDATE:
            android_atomic_and(~eventMaskInvalidate, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case REFRESH:
            android_atomic_and(~eventMaskRefresh, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
    }
}

發(fā)送了一個INVALIDATE消息交給SF的onMessageReceive處理巍虫。

SF onMessageReceive 處理 INVALIDATE消息

void SurfaceFlinger::onMessageReceived(int32_t what) {
    ATRACE_CALL();
    switch (what) {
        case MessageQueue::INVALIDATE: {
            bool frameMissed = !mHadClientComposition &&
                    mPreviousPresentFence != Fence::NO_FENCE &&
                    (mPreviousPresentFence->getSignalTime() ==
                            Fence::SIGNAL_TIME_PENDING);

            if (frameMissed) {
                mTimeStats.incrementMissedFrames();
                if (mPropagateBackpressure) {
                    signalLayerUpdate();
                    break;
                }
            }

            updateVrFlinger();

            bool refreshNeeded = handleMessageTransaction();
            refreshNeeded |= handleMessageInvalidate();
            refreshNeeded |= mRepaintEverything;
            if (refreshNeeded) {
                signalRefresh();
            }
            break;
        }
        case MessageQueue::REFRESH: {
            handleMessageRefresh();
            break;
        }
    }
}

MessageQueue的消息處理函數(shù)中SF處理了兩種消息一種是INVALIDATE校驗無效的區(qū)域。校驗方式兩個步驟:

  • 1.handleMessageTransaction 處理事務(wù)鳍刷,如交換繪制mDrawState和mCurrentState的焦點狀態(tài)占遥,記錄每一個Layer當前需要繪制的各自的Layer,如果判斷到已經(jīng)添加了Layer進來输瓜,則需要打開判斷可視區(qū)域標志位瓦胎。發(fā)現(xiàn)Layer被移除了需要更新臟(已經(jīng)變動)區(qū)域
  • 2.handleMessageInvalidate 核心就是latch每一個Layer中的圖元進行acquire的操作。一旦判斷到每一Layer中有l(wèi)atch了圖元尤揣,說有新的圖元需要消費凛捏,或者還有圖元沒有消費的,則需要主動調(diào)用signalLayerUpdate()進行下一個循環(huán)的INVALIDATE發(fā)送芹缔。

最后是否需要調(diào)用signalRefresh坯癣,handleMessageTransaction需要處理事務(wù)或者handleMessageInvalidate判斷到有新圖元。則會通過signalRefresh進入下一個循環(huán)進行Refresh消息的發(fā)送最欠。

void SurfaceFlinger::signalRefresh() {
    mRefreshPending = true;
    mEventQueue->refresh();
}

知道核心思想示罗,我們再來每一個步驟中做了什么。

handleMessageTransaction

uint32_t SurfaceFlinger::peekTransactionFlags() {
    return android_atomic_release_load(&mTransactionFlags);
}

bool SurfaceFlinger::handleMessageTransaction() {
    uint32_t transactionFlags = peekTransactionFlags();
    if (transactionFlags) {
        handleTransaction(transactionFlags);
        return true;
    }
    return false;
}

我們先討論打開了mTransactionFlags事務(wù)的標志位芝硬。一旦Layer蚜点,Display等和顯示相關(guān)的數(shù)據(jù)結(jié)構(gòu)發(fā)生變化都需要打開這個標志位。

void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{

    State drawingState(mDrawingState);

    Mutex::Autolock _l(mStateLock);
    const nsecs_t now = systemTime();
...

    mVsyncModulator.onTransactionHandled();
    transactionFlags = getTransactionFlags(eTransactionMask);
    handleTransactionLocked(transactionFlags);

    mLastTransactionTime = systemTime() - now;

    invalidateHwcGeometry();
}

void SurfaceFlinger::invalidateHwcGeometry()
{
    mGeometryInvalid = true;
}

核心是handleTransactionLocked拌阴。

void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
    // 通知所有的Layer可以進行合成
    mCurrentState.traverseInZOrder([](Layer* layer) {
        layer->notifyAvailableFrames();
    });


    if (transactionFlags & eTraversalNeeded) {
        mCurrentState.traverseInZOrder([&](Layer* layer) {
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
            if (!trFlags) return;

            const uint32_t flags = layer->doTransaction(0);
            if (flags & Layer::eVisibleRegion)
                mVisibleRegionsDirty = true;
        });
    }

    /*
     * Perform display own transactions if needed
     */

    if (transactionFlags & eDisplayTransactionNeeded) {
        processDisplayChangesLocked();
        processDisplayHotplugEventsLocked();
    }

    if (transactionFlags & (eDisplayLayerStackChanged|eDisplayTransactionNeeded)) {

        sp<const DisplayDevice> disp;
        uint32_t currentlayerStack = 0;
        bool first = true;
        mCurrentState.traverseInZOrder([&](Layer* layer) {
            uint32_t layerStack = layer->getLayerStack();
            if (first || currentlayerStack != layerStack) {
                currentlayerStack = layerStack;
                disp.clear();
                for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                    sp<const DisplayDevice> hw(mDisplays[dpy]);
                    if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) {
                        if (disp == nullptr) {
                            disp = std::move(hw);
                        } else {
                            disp = nullptr;
                            break;
                        }
                    }
                }
            }

            if (disp == nullptr) {
                disp = getDefaultDisplayDeviceLocked();
            }

            if (disp != nullptr) {
                layer->updateTransformHint(disp);
            }

            first = false;
        });
    }


    if (mLayersAdded) {
        mLayersAdded = false;
        mVisibleRegionsDirty = true;
    }

    if (mLayersRemoved) {
        mLayersRemoved = false;
        mVisibleRegionsDirty = true;
        mDrawingState.traverseInZOrder([&](Layer* layer) {
            if (mLayersPendingRemoval.indexOf(layer) >= 0) {
                Region visibleReg;
                visibleReg.set(layer->computeScreenBounds());
                invalidateLayerStack(layer, visibleReg);
            }
        });
    }

    commitTransaction();

    updateCursorAsync();
}
  • 1.第一個從底部向頂部循環(huán)遍歷mCurrentState中的Layer绍绘,通知每一個被SyncPoint完成了doTransaction步驟而阻塞的Layer。讓Layer可以進行合成的準備迟赃。
void BufferLayer::notifyAvailableFrames() {
    auto headFrameNumber = getHeadFrameNumber();
    bool headFenceSignaled = headFenceHasSignaled();
    Mutex::Autolock lock(mLocalSyncPointMutex);
    for (auto& point : mLocalSyncPoints) {
        if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
            point->setFrameAvailable();
        }
    }
}
  • 2.從底部遍歷每一個Layer的doTransaction方法陪拘。處理可視區(qū)域。
  • 3.檢查每一個Layer中的所對應(yīng)的顯示屏id類型纤壁,同時更新里面的變換矩陣左刽。
  • 4.如果通過Client添加過Layer就會打上mLayersAdded,此時將會關(guān)閉這個標志位酌媒,同時打開mVisibleRegionsDirty欠痴,讓后續(xù)的步驟檢測變動的可視區(qū)域迄靠。
  • 5.如果Layer有移除,則調(diào)用invalidateLayerStack更新DisplayDevice中原有的可視臟區(qū)喇辽。
void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        const sp<DisplayDevice>& hw(mDisplays[dpy]);
        if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) {
            hw->dirtyRegion.orSelf(dirty);
        }
    }
}

讓我們看看doTransaction核心方法掌挚。

Layer doTransaction

文件:/frameworks/native/services/surfaceflinger/Layer.cpp

uint32_t Layer::doTransaction(uint32_t flags) {

    pushPendingState();
    Layer::State c = getCurrentState();
    if (!applyPendingStates(&c)) {
        return 0;
    }

    const Layer::State& s(getDrawingState());

    const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h);

    if (sizeChanged) {
...
        setDefaultBufferSize(c.requested.w, c.requested.h);
    }

    const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) &&
            (getBE().compositionInfo.mBuffer != nullptr);
    if (!isFixedSize()) {
        if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) {
            flags |= eDontUpdateGeometryState;
        }
    }

    if (!(flags & eDontUpdateGeometryState)) {
        Layer::State& editCurrentState(getCurrentState());

        if (mFreezeGeometryUpdates) {
            float tx = c.active.transform.tx();
            float ty = c.active.transform.ty();
            c.active = c.requested;
            c.active.transform.set(tx, ty);
            editCurrentState.active = c.active;
        } else {
            editCurrentState.active = editCurrentState.requested;
            c.active = c.requested;
        }
    }

    if (s.active != c.active) {
        flags |= Layer::eVisibleRegion;
    }

    if (c.sequence != s.sequence) {
        // invalidate and recompute the visible regions if needed
        flags |= eVisibleRegion;
        this->contentDirty = true;

        const uint8_t type = c.active.transform.getType();
        mNeedsFiltering = (!c.active.transform.preserveRects() || (type >= Transform::SCALE));
    }

    if (c.flags & layer_state_t::eLayerHidden) {
        clearSyncPoints();
    }

    // Commit the transaction
    commitTransaction(c);
    return flags;
}

void Layer::commitTransaction(const State& stateToCommit) {
    mDrawingState = stateToCommit;
}

  • 1.就是檢測BufferLayer中的mCurrentState和上一幀已經(jīng)繪制了的mDrawState的差距。如果發(fā)現(xiàn)兩者的requested的區(qū)域發(fā)生了變動菩咨,則會調(diào)用setDefaultBufferSize吠式,重新定義圖元消費BufferLayerConsumer的默認寬高。
void BufferLayer::setDefaultBufferSize(uint32_t w, uint32_t h) {
    mConsumer->setDefaultBufferSize(w, h);
}
    1. 檢測mCurrentState中requested和active之間的幾何寬高旦委。在每一個Layer::State中都會存在兩個幾何結(jié)構(gòu)體requested和active。當我們設(shè)置了Surface了postion等在屏幕上顯示的幾何參數(shù)會先設(shè)置到mCurrentState.requested中雏亚。也就是說requested等待繪制的參數(shù)缨硝。active則是顯示中的幾何參數(shù)。一旦發(fā)生變化則設(shè)resizePending為true罢低。
    1. isFixedSize則是判斷當前對應(yīng)的Layer是否被凍結(jié)不允許變化大小查辩,假設(shè)此時是關(guān)閉的,且sidebandStream是空的网持。此時不會立即更新requested和active的區(qū)域宜岛。回到后面acquire步驟時候進行處理功舀。
    1. 最后更新mCurrentState為mDrawState萍倡。

這里需要注意,和SF的State不一樣辟汰。Layer::State將會記錄Layer顯示相關(guān)的參數(shù)列敲。

SF commitTransaction

void SurfaceFlinger::commitTransaction()
{
    if (!mLayersPendingRemoval.isEmpty()) {
        // Notify removed layers now that they can't be drawn from
        for (const auto& l : mLayersPendingRemoval) {
            recordBufferingStats(l->getName().string(),
                    l->getOccupancyHistory(true));
            l->onRemoved();
        }
        mLayersPendingRemoval.clear();
    }


    mAnimCompositionPending = mAnimTransactionPending;

    mDrawingState = mCurrentState;
    mCurrentState.colorMatrixChanged = false;

    mDrawingState.traverseInZOrder([](Layer* layer) {
        layer->commitChildList();
    });
    mTransactionPending = false;
    mAnimTransactionPending = false;
    mTransactionCV.broadcast();
}

此時也會更新SF中的mDrawingState,同時會更新每一個Layer中對應(yīng)處理完的事務(wù)狀態(tài)帖汞。

BufferLayer commitChildList
void Layer::commitChildList() {
    for (size_t i = 0; i < mCurrentChildren.size(); i++) {
        const auto& child = mCurrentChildren[i];
        child->commitChildList();
    }
    mDrawingChildren = mCurrentChildren;
    mDrawingParent = mCurrentParent;
}

對應(yīng)的每一個Layer同時會更新之后需要繪制的父Layer和子Layer戴而。

handleMessageInvalidate 檢測變動區(qū)域

文件:/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

bool SurfaceFlinger::handleMessageInvalidate() {
    return handlePageFlip();
}
bool SurfaceFlinger::handlePageFlip()
{

    nsecs_t latchTime = systemTime();

    bool visibleRegions = false;
    bool frameQueued = false;
    bool newDataLatched = false;

    mDrawingState.traverseInZOrder([&](Layer* layer) {
        if (layer->hasQueuedFrame()) {
            frameQueued = true;
            if (layer->shouldPresentNow(mPrimaryDispSync)) {
                mLayersWithQueuedFrames.push_back(layer);
            } else {
                layer->useEmptyDamage();
            }
        } else {
            layer->useEmptyDamage();
        }
    });

    for (auto& layer : mLayersWithQueuedFrames) {
        const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
        layer->useSurfaceDamage();
        invalidateLayerStack(layer, dirty);
        if (layer->isBufferLatched()) {
            newDataLatched = true;
        }
    }

    mVisibleRegionsDirty |= visibleRegions;

    if (frameQueued && (mLayersWithQueuedFrames.empty() || !newDataLatched)) {
        signalLayerUpdate();
    }

    return !mLayersWithQueuedFrames.empty() && newDataLatched;
}

首先要注意,在這個方法開始SF需要正式消費圖元翩蘸。此時會有一個問題所意,比如有個Layer.此時線程1通知了Layer有了一個新的圖元進來了,還沒來的消費又進來了一個圖元催首。此時我們需要再進行消費扶踊?假如出現(xiàn)了寬高變化怎么辦?那不就浪費了doTransaction步驟的寬高變化記錄嗎郎任。因此我們需要一個latch方法姻檀,鎖住圖元。

一旦檢測到圖元還有沒有消費的或者還沒有到了需要顯示時候涝滴,就會調(diào)用signalLayerUpdate绣版,讓下一個循環(huán)回來消費胶台。

這個方法判斷是否需要refresh的依據(jù),其實就是判斷兩個情況同時成立杂抽,第一個是mLayersWithQueuedFrames不為空诈唬,有需要顯示的Layer。同時latch上鎖圖元成功了缩麸。

BufferLayer shouldPresentNow

文件:/frameworks/native/services/surfaceflinger/BufferLayer.cpp


bool BufferLayer::shouldPresentNow(const DispSync& dispSync) const {
    if (mSidebandStreamChanged || mAutoRefresh) {
        return true;
    }

    Mutex::Autolock lock(mQueueItemLock);
    if (mQueueItems.empty()) {
        return false;
    }
    auto timestamp = mQueueItems[0].mTimestamp;
    nsecs_t expectedPresent = mConsumer->computeExpectedPresent(dispSync);

    // Ignore timestamps more than a second in the future
    bool isPlausible = timestamp < (expectedPresent + s2ns(1));

    bool isDue = timestamp < expectedPresent;
    return isDue || !isPlausible;
}

該方法會通過computeExpectedPresent通過DispSync計算這一幀應(yīng)該是什么顯示铸磅。是否顯示由下面的公式?jīng)Q定:

預(yù)期顯示 - 入隊時間 < 1s && 入隊時間<預(yù)期時間

一旦允許顯示則往mLayersWithQueuedFrames添加Layer。這個Layer集合就是需要繪制的圖層杭朱。

BufferLayer latchBuffer

接著會遍歷mLayersWithQueuedFrames每一層的Layer阅仔,并且調(diào)用latchBuffer進行圖元鎖定。

接下來這個方法很長弧械。我把它拆開2部分來聊

Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {

 ...
    Region outDirtyRegion;
    if (mQueuedFrames <= 0 && !mAutoRefresh) {
        return outDirtyRegion;
    }
//已經(jīng)latch過了就不需要了
    if (mRefreshPending) {
        return outDirtyRegion;
    }
//fence已經(jīng)喚醒了八酒,也不需要了
    if (!headFenceHasSignaled()) {
        mFlinger->signalLayerUpdate();
        return outDirtyRegion;
    }

    const State& s(getDrawingState());
    const bool oldOpacity = isOpaque(s);
    sp<GraphicBuffer> oldBuffer = getBE().compositionInfo.mBuffer;

    if (!allTransactionsSignaled()) {
        mFlinger->signalLayerUpdate();
        return outDirtyRegion;
    }

    bool queuedBuffer = false;
    LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                    getProducerStickyTransform() != 0, mName.string(),
                    mOverrideScalingMode, mFreezeGeometryUpdates);
//核心
    status_t updateResult =
            mConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync,
                                                    &mAutoRefresh, &queuedBuffer,
                                                    mLastFrameNumberReceived);
//根據(jù)消費返回的狀態(tài)做處理
    if (updateResult == BufferQueue::PRESENT_LATER) {
        mFlinger->signalLayerUpdate();
        return outDirtyRegion;
    } else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) {
        if (queuedBuffer) {
            Mutex::Autolock lock(mQueueItemLock);
            mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber);
            mQueueItems.removeAt(0);
            android_atomic_dec(&mQueuedFrames);
        }
        return outDirtyRegion;
    } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
        if (queuedBuffer) {
            Mutex::Autolock lock(mQueueItemLock);
            mQueueItems.clear();
            android_atomic_and(0, &mQueuedFrames);
            mTimeStats.clearLayerRecord(getName().c_str());
        }

        mUpdateTexImageFailed = true;

        return outDirtyRegion;
    }
//從入隊到這里的queuedBuffer 都為true
    if (queuedBuffer) {
        // Autolock scope
        auto currentFrameNumber = mConsumer->getFrameNumber();

        Mutex::Autolock lock(mQueueItemLock);

        while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
            mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber);
            mQueueItems.removeAt(0);
            android_atomic_dec(&mQueuedFrames);
        }

        const std::string layerName(getName().c_str());
        mTimeStats.setAcquireFence(layerName, currentFrameNumber, mQueueItems[0].mFenceTime);
        mTimeStats.setLatchTime(layerName, currentFrameNumber, latchTime);

        mQueueItems.removeAt(0);
    }

    if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) ||
        mAutoRefresh) {
        mFlinger->signalLayerUpdate();
    }

//把已經(jīng)消費的圖元保存到SurfaceFlingerBE里面
    getBE().compositionInfo.mBuffer =
            mConsumer->getCurrentBuffer(&getBE().compositionInfo.mBufferSlot);

    mActiveBuffer = getBE().compositionInfo.mBuffer;
    if (getBE().compositionInfo.mBuffer == nullptr) {
        // this can only happen if the very first buffer was rejected.
        return outDirtyRegion;
    }

    mBufferLatched = true;
...
}

整個核心就是updateTexImage方法。在這里面經(jīng)過判斷刃唐,latch過的Layer就不會再進行l(wèi)atch羞迷。

經(jīng)過updateTexImage處理后,會判斷返回的狀態(tài)碼画饥。如果需要延遲顯示則直接返回空的臟區(qū)域衔瓮。如果發(fā)現(xiàn)需要拒絕顯示這個幀,將會丟棄mQueueItem中對應(yīng)的圖元參數(shù)和索引抖甘。如果消費失敗了热鞍,則會處理清除mQueueItem中所有等待消費的圖元。最后返回空臟區(qū)衔彻。

成功消費后碍现,如果是從queueBuffer的步驟到這里的,將會移除mQueueItem第一項圖元數(shù)據(jù)米奸。剩下的圖元還有剩下的昼接,則需要進行下一輪invalidate消息。

最后會把消費后的圖元悴晰,作為當前需要顯示的圖元保存在getBE().compositionInfo.mBuffer和mActiveBuffer慢睡,并且設(shè)置mBufferLatched。

核心的updateTexImage方法我們稍后注重考究铡溪。

//記錄上一幀序列
    mPreviousFrameNumber = mCurrentFrameNumber;
//記錄當前這一幀的序列
    mCurrentFrameNumber = mConsumer->getFrameNumber();

    {
//記錄上鎖時間
        Mutex::Autolock lock(mFrameEventHistoryMutex);
        mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
    }

    mRefreshPending = true;
    mFrameLatencyNeeded = true;
    if (oldBuffer == nullptr) {
        recomputeVisibleRegions = true;
    }
//記錄DataSpace
    ui::Dataspace dataSpace = mConsumer->getCurrentDataSpace();
    switch (dataSpace) {
        case ui::Dataspace::V0_SRGB:
            dataSpace = ui::Dataspace::SRGB;
            break;
        case ui::Dataspace::V0_SRGB_LINEAR:
            dataSpace = ui::Dataspace::SRGB_LINEAR;
            break;
        case ui::Dataspace::V0_JFIF:
            dataSpace = ui::Dataspace::JFIF;
            break;
        case ui::Dataspace::V0_BT601_625:
            dataSpace = ui::Dataspace::BT601_625;
            break;
        case ui::Dataspace::V0_BT601_525:
            dataSpace = ui::Dataspace::BT601_525;
            break;
        case ui::Dataspace::V0_BT709:
            dataSpace = ui::Dataspace::BT709;
            break;
        default:
            break;
    }
    mCurrentDataSpace = dataSpace;

    Rect crop(mConsumer->getCurrentCrop());
    const uint32_t transform(mConsumer->getCurrentTransform());
    const uint32_t scalingMode(mConsumer->getCurrentScalingMode());
    if ((crop != mCurrentCrop) ||
        (transform != mCurrentTransform) ||
        (scalingMode != mCurrentScalingMode)) {
        mCurrentCrop = crop;
        mCurrentTransform = transform;
        mCurrentScalingMode = scalingMode;
        recomputeVisibleRegions = true;
    }

    if (oldBuffer != nullptr) {
        uint32_t bufWidth = getBE().compositionInfo.mBuffer->getWidth();
        uint32_t bufHeight = getBE().compositionInfo.mBuffer->getHeight();
        if (bufWidth != uint32_t(oldBuffer->width) ||
            bufHeight != uint32_t(oldBuffer->height)) {
            recomputeVisibleRegions = true;
        }
    }
//記錄透明參數(shù)
    mCurrentOpacity = getOpacityForFormat(getBE().compositionInfo.mBuffer->format);
    if (oldOpacity != isOpaque(s)) {
        recomputeVisibleRegions = true;
    }

//移除mLocalSyncPoints中的阻塞
    {
        Mutex::Autolock lock(mLocalSyncPointMutex);
        auto point = mLocalSyncPoints.begin();
        while (point != mLocalSyncPoints.end()) {
            if (!(*point)->frameIsAvailable() || !(*point)->transactionIsApplied()) {
                // This sync point must have been added since we started
                // latching. Don't drop it yet.
                ++point;
                continue;
            }

            if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
                point = mLocalSyncPoints.erase(point);
            } else {
                ++point;
            }
        }
    }

    // FIXME: postedRegion should be dirty & bounds
    Region dirtyRegion(Rect(s.active.w, s.active.h));

    // transform the dirty region to window-manager space
    outDirtyRegion = (getTransform().transform(dirtyRegion));

    return outDirtyRegion;
  • 1.設(shè)置相關(guān)的參數(shù)漂辐,如幀數(shù),裁剪參數(shù)棕硫,DataSpace髓涯,透明參數(shù)等。并且移除了代表當幀數(shù)之前mLocalSyncPoints。
  • 2.計算臟區(qū)是由mDrawState對應(yīng)的active參數(shù)確定(此時requested和active已經(jīng)交換了)拱礁。最后調(diào)用transform轉(zhuǎn)化轉(zhuǎn)化為臟區(qū)
Transform Layer::getTransform() const {
    Transform t;
    const auto& p = mDrawingParent.promote();
    if (p != nullptr) {
        t = p->getTransform();

        if (p->isFixedSize() && p->getBE().compositionInfo.mBuffer != nullptr) {
            int bufferWidth;
            int bufferHeight;
            if ((p->mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) == 0) {
                bufferWidth = p->getBE().compositionInfo.mBuffer->getWidth();
                bufferHeight = p->getBE().compositionInfo.mBuffer->getHeight();
            } else {
                bufferHeight = p->getBE().compositionInfo.mBuffer->getWidth();
                bufferWidth = p->getBE().compositionInfo.mBuffer->getHeight();
            }
            float sx = p->getDrawingState().active.w / static_cast<float>(bufferWidth);
            float sy = p->getDrawingState().active.h / static_cast<float>(bufferHeight);
            Transform extraParentScaling;
            extraParentScaling.set(sx, 0, 0, sy);
            t = t * extraParentScaling;
        }
    }
    return t * getDrawingState().active.transform;
}

其實這個轉(zhuǎn)化是查找每一個Layer的父Layer,并且根據(jù)父Layer的寬高和當前Layer比進行一次等比例縮小一姿。

換句話說包各,實際上臟區(qū)的計算摘仅,從App進程角度來看是以Surface為一個單位進行計算。

BufferLayerConsumer updateTexImage

文件:/frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp

status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
                                             bool* autoRefresh, bool* queuedBuffer,
                                             uint64_t maxFrameNumber) {
    ATRACE_CALL();
    Mutex::Autolock lock(mMutex);

    if (mAbandoned) {
        return NO_INIT;
    }

    // Make sure RenderEngine is current
    if (!mRE.isCurrent()) {
        return INVALID_OPERATION;
    }

    BufferItem item;


    status_t err = acquireBufferLocked(&item, computeExpectedPresent(dispSync), maxFrameNumber);
    if (err != NO_ERROR) {
        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
            err = NO_ERROR;
        } else if (err == BufferQueue::PRESENT_LATER) {
            // return the error, without logging
        } else {
            BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
        }
        return err;
    }

    if (autoRefresh) {
        *autoRefresh = item.mAutoRefresh;
    }

    if (queuedBuffer) {
        *queuedBuffer = item.mQueuedBuffer;
    }

    int slot = item.mSlot;
    if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
        return BUFFER_REJECTED;
    }

    // Release the previous buffer.
    err = updateAndReleaseLocked(item, &mPendingRelease);
    if (err != NO_ERROR) {
        return err;
    }

    if (!SyncFeatures::getInstance().useNativeFenceSync()) {
        err = bindTextureImageLocked();
    }

    return err;
}

在這個方法中有兩個核心:

  • 1.acquireBufferLocked消費圖元问畅。
  • 2.LayerReject 判斷是否需要拒絕顯示當前已經(jīng)消費的圖元娃属。
  • 3.updateAndReleaseLocked更新當前Layer中需要顯示的圖元,同時釋放之前的圖元為Free狀態(tài)护姆。
  • 4.最后判斷OpenGL es是否攜帶EGL_KHR_fence_sync標志位矾端,代表OpenGL es的同步柵。如果是卵皂,則提前通過OpenGL es繪制Image秩铆。

BufferLayerConsumer acquireBufferLocked

文件:meworks/native/services/surfaceflinger/BufferLayerConsumer.cpp

status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
                                                  uint64_t maxFrameNumber) {
    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
    if (err != NO_ERROR) {
        return err;
    }


    if (item->mGraphicBuffer != nullptr) {
        mImages[item->mSlot] = new Image(item->mGraphicBuffer, mRE);
    }

    return NO_ERROR;
}
  • 1.ConsumerBase::acquireBufferLocked 從基類還是處理圖元消費。
  • 2.通過GraphicBuffer生成Image對象保存在mImages數(shù)組中渐裂。

先來看看image對象對應(yīng)的頭文件:

    class Image : public LightRefBase<Image> {
    public:
        Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEngine& engine);

        Image(const Image& rhs) = delete;
        Image& operator=(const Image& rhs) = delete;

        status_t createIfNeeded(const Rect& imageCrop);

        const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
        const native_handle* graphicBufferHandle() {
            return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
        }

        const RE::Image& image() const { return *mImage; }

    private:
        friend class LightRefBase<Image>;
        virtual ~Image();

        // mGraphicBuffer is the buffer that was used to create this image.
        sp<GraphicBuffer> mGraphicBuffer;

        std::unique_ptr<RE::Image> mImage;
        bool mCreated;
        int32_t mCropWidth;
        int32_t mCropHeight;
    };

其實很簡單豺旬,核心是持有了GraphicBuffer和RE::Image兩個對象钠惩。GraphicBuffer圖元柒凉,我們?nèi)タ纯碦E::Image對象是怎么生成的。

BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEngine& engine)
      : mGraphicBuffer(graphicBuffer),
        mImage{engine.createImage()},
        mCreated(false),
        mCropWidth(0),
        mCropHeight(0) {}
std::unique_ptr<RE::Image> RenderEngine::createImage() {
    return std::make_unique<Image>(*this);
}
class Image {
public:
    virtual ~Image() = 0;
    virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected,
                                       int32_t cropWidth, int32_t cropHeight) = 0;
};

namespace impl {

class RenderEngine;

class Image : public RE::Image {
public:
    explicit Image(const RenderEngine& engine);
    ~Image() override;

    Image(const Image&) = delete;
    Image& operator=(const Image&) = delete;

    bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, int32_t cropWidth,
                               int32_t cropHeight) override;

private:
    friend class RenderEngine;
    EGLSurface getEGLImage() const { return mEGLImage; }

    EGLDisplay mEGLDisplay;
    EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR;
};

} // namespace impl

其實Image對象實際上就是控制NativeBuffer篓跛,EGLDisplay膝捞,EGLSurface對象。這些對象實際上都是OpenGL es繪制的核心對象愧沟。所有的操作都是透過這個Image繪制蔬咬。

ConsumerBase acquireBufferLocked

文件:/frameworks/native/libs/gui/ConsumerBase.cpp

status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
        nsecs_t presentWhen, uint64_t maxFrameNumber) {
...
    status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
...
    if (item->mGraphicBuffer != NULL) {
        if (mSlots[item->mSlot].mGraphicBuffer != NULL) {
            freeBufferLocked(item->mSlot);
        }
        mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
    }

    mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
    mSlots[item->mSlot].mFence = item->mFence;

    return OK;
}

這里調(diào)用了BufferQueueConsumer的acquireBuffer。并且把消費的值賦值到新的item對應(yīng)的mSlots下標中沐寺。因為這個過程可能會選擇一些丟幀或者跳幀處理林艘。

BufferQueueConsumer acquireBuffer

文件:/frameworks/native/libs/gui/BufferQueueConsumer.cpp

status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
        nsecs_t expectedPresent, uint64_t maxFrameNumber) {
    ATRACE_CALL();

    int numDroppedBuffers = 0;
    sp<IProducerListener> listener;
    {
        Mutex::Autolock lock(mCore->mMutex);

        int numAcquiredBuffers = 0;
        for (int s : mCore->mActiveBuffers) {
            if (mSlots[s].mBufferState.isAcquired()) {
                ++numAcquiredBuffers;
            }
        }
        if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
            return INVALID_OPERATION;
        }

        bool sharedBufferAvailable = mCore->mSharedBufferMode &&
                mCore->mAutoRefresh && mCore->mSharedBufferSlot !=
                BufferQueueCore::INVALID_BUFFER_SLOT;


        if (mCore->mQueue.empty() && !sharedBufferAvailable) {
            return NO_BUFFER_AVAILABLE;
        }

        BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());

        if (expectedPresent != 0 && !mCore->mQueue.empty()) {
            const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second

            while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
                const BufferItem& bufferItem(mCore->mQueue[1]);

                if (maxFrameNumber && bufferItem.mFrameNumber > maxFrameNumber) {
                    break;
                }

                nsecs_t desiredPresent = bufferItem.mTimestamp;
                if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
                        desiredPresent > expectedPresent) {
                    break;
                }


                if (!front->mIsStale) {
                    // Front buffer is still in mSlots, so mark the slot as free
                    mSlots[front->mSlot].mBufferState.freeQueued();

                    if (!mCore->mSharedBufferMode &&
                            mSlots[front->mSlot].mBufferState.isFree()) {
                        mSlots[front->mSlot].mBufferState.mShared = false;
                    }

                    // Don't put the shared buffer on the free list
                    if (!mSlots[front->mSlot].mBufferState.isShared()) {
                        mCore->mActiveBuffers.erase(front->mSlot);
                        mCore->mFreeBuffers.push_back(front->mSlot);
                    }

                    listener = mCore->mConnectedProducerListener;
                    ++numDroppedBuffers;
                }

                mCore->mQueue.erase(front);
                front = mCore->mQueue.begin();
            }

            nsecs_t desiredPresent = front->mTimestamp;
            bool bufferIsDue = desiredPresent <= expectedPresent ||
                    desiredPresent > expectedPresent + MAX_REASONABLE_NSEC;
            bool consumerIsReady = maxFrameNumber > 0 ?
                    front->mFrameNumber <= maxFrameNumber : true;
            if (!bufferIsDue || !consumerIsReady) {
                return PRESENT_LATER;
            }

        }

        int slot = BufferQueueCore::INVALID_BUFFER_SLOT;

        if (sharedBufferAvailable && mCore->mQueue.empty()) {
           ....
        } else {
            slot = front->mSlot;
            *outBuffer = *front;
        }



        if (!outBuffer->mIsStale) {
            mSlots[slot].mAcquireCalled = true;
            if (mCore->mQueue.empty()) {
                mSlots[slot].mBufferState.acquireNotInQueue();
            } else {
                mSlots[slot].mBufferState.acquire();
            }
            mSlots[slot].mFence = Fence::NO_FENCE;
        }


        if (outBuffer->mAcquireCalled) {
            outBuffer->mGraphicBuffer = NULL;
        }

        mCore->mQueue.erase(front);

        mCore->mDequeueCondition.broadcast();

        mCore->mOccupancyTracker.registerOccupancyChange(mCore->mQueue.size());

        VALIDATE_CONSISTENCY();
    }

    if (listener != NULL) {
        for (int i = 0; i < numDroppedBuffers; ++i) {
            listener->onBufferReleased();
        }
    }

    return NO_ERROR;
}
    1. 處理圖元之前,首先檢測mActiveBuffers中活躍的圖元究竟有多少個混坞。如果超出mMaxAcquiredBufferCount限制狐援,則不允許繼續(xù)。
    1. 獲取之前入隊到mQueue的第一項front進行循環(huán)處理究孕。首先獲取之前計算出來的期待顯示時間和當前入隊的時間比較啥酱,找出和當前時間最接近的入隊圖元。如果入隊的時間比期待的小一秒厨诸,并且入隊的時間比期待的時間小镶殷。這樣就會直接跳出mQueue處理的處理循環(huán)。

如果front.mIsStale為false說明這個圖元已經(jīng)過期了微酬。將把mSlot的索引從mActiveBuffers轉(zhuǎn)移到mFreeBuffer绘趋。同時計算為一個numDroppedBuffers丟幀計數(shù)處理颤陶。獲取mQueue的下一項圖元。

最后把當前的front圖元返回埋心,并且釋放那些已經(jīng)丟幀的圖元指郁。

LayerRejecter 判斷是否需要拒絕顯示當前已經(jīng)消費的圖元

文件:/frameworks/native/services/surfaceflinger/LayerRejecter.cpp

bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
    if (buf == nullptr) {
        return false;
    }

    uint32_t bufWidth = buf->getWidth();
    uint32_t bufHeight = buf->getHeight();

    if (item.mTransform & Transform::ROT_90) {
        swap(bufWidth, bufHeight);
    }

    int actualScalingMode = mOverrideScalingMode >= 0 ? mOverrideScalingMode : item.mScalingMode;
    bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
    if (mFront.active != mFront.requested) {
        if (isFixedSize || (bufWidth == mFront.requested.w && bufHeight == mFront.requested.h)) {
            mFront.active = mFront.requested;

            mCurrent.active = mFront.active;
            mCurrent.modified = true;

            mRecomputeVisibleRegions = true;

            mFreezeGeometryUpdates = false;

            if (mFront.crop != mFront.requestedCrop) {
                mFront.crop = mFront.requestedCrop;
                mCurrent.crop = mFront.requestedCrop;
                mRecomputeVisibleRegions = true;
            }
            if (mFront.finalCrop != mFront.requestedFinalCrop) {
                mFront.finalCrop = mFront.requestedFinalCrop;
                mCurrent.finalCrop = mFront.requestedFinalCrop;
                mRecomputeVisibleRegions = true;
            }
        }

       
    }

    if (!isFixedSize && !mStickyTransformSet) {
        if (mFront.active.w != bufWidth || mFront.active.h != bufHeight) {
            return true;
        }
    }

   
    if (!mFront.activeTransparentRegion.isTriviallyEqual(mFront.requestedTransparentRegion)) {
        mFront.activeTransparentRegion = mFront.requestedTransparentRegion;

        mCurrent.activeTransparentRegion = mFront.activeTransparentRegion;

        mRecomputeVisibleRegions = true;
    }

    return false;
}

拒絕檢測圖元顯示。mFront其實就是上文通過doTransaction的mDrawState拷呆,此時已經(jīng)進行交換闲坎,所以mDrawState是這一幀的內(nèi)容。一旦發(fā)現(xiàn)requested和active的幾何不一致茬斧。如果此時不是NATIVE_WINDOW_SCALING_MODE_FREEZE(凍結(jié)屏幕)腰懂。同時圖元的寬高和requested相同,才會進行requested和active的交換项秉。

如果是NATIVE_WINDOW_SCALING_MODE_FREEZE(凍結(jié)屏幕)绣溜,則但是發(fā)現(xiàn)requested的寬高和圖元需要的寬高不一致就會拒絕繪制,丟掉當前幀娄蔼。其實思想很簡單怖喻,實際上就這種NATIVE_WINDOW_SCALING_MODE_FREEZE模式下就是只繪制和當前窗口一樣大小的圖元。其他都不設(shè)置岁诉。

updateAndReleaseLocked更新當前Layer中需要顯示的圖元锚沸,同時釋放之前的圖元為Free狀態(tài)

status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
                                                     PendingRelease* pendingRelease) {
    status_t err = NO_ERROR;

    int slot = item.mSlot;

    if (slot != mCurrentTexture) {
        err = syncForReleaseLocked();
        if (err != NO_ERROR) {
            releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
            return err;
        }
    }


    sp<Image> nextTextureImage = mImages[slot];

    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
        if (pendingRelease == nullptr) {
            status_t status =
                    releaseBufferLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer());
            if (status < NO_ERROR) {
                err = status;
            }
        } else {
            pendingRelease->currentTexture = mCurrentTexture;
            pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
            pendingRelease->isPending = true;
        }
    }

    // Update the BufferLayerConsumer state.
    mCurrentTexture = slot;
    mCurrentTextureImage = nextTextureImage;
    mCurrentCrop = item.mCrop;
    mCurrentTransform = item.mTransform;
    mCurrentScalingMode = item.mScalingMode;
    mCurrentTimestamp = item.mTimestamp;
    mCurrentDataSpace = static_cast<ui::Dataspace>(item.mDataSpace);
    mCurrentHdrMetadata = item.mHdrMetadata;
    mCurrentFence = item.mFence;
    mCurrentFenceTime = item.mFenceTime;
    mCurrentFrameNumber = item.mFrameNumber;
    mCurrentTransformToDisplayInverse = item.mTransformToDisplayInverse;
    mCurrentSurfaceDamage = item.mSurfaceDamage;
    mCurrentApi = item.mApi;

    computeCurrentTransformMatrixLocked();

    return err;
}
  • 1.syncForReleaseLocked 實際上是一次Fence阻塞,等待所有的Fence的監(jiān)聽都達到了NO_ERROR,返回Signal狀態(tài)涕癣。就進行下一步哗蜈,同時進行釋放上一幀的圖元,進入到free狀態(tài)坠韩。
  • 2.記錄上一幀的數(shù)據(jù)到pendingRelease距潘,以及本次準備渲染的幀數(shù)中相關(guān)的參數(shù),如DataSpace只搁,mSlot插槽中對應(yīng)的index音比,以及攜帶GraphicBuffer的Image。

DataSpace小知識的記錄

有了RGB氢惋,Ycbcr這些顏色format洞翩,為什么還需要DataSpace,色彩的數(shù)據(jù)空間呢明肮?這里需要借助一篇文章
菱农,這里稍作總結(jié)。

在現(xiàn)實世界中柿估,當光強一倍循未,則亮度也會提升一倍,是一個線性關(guān)系。但是由于最早的顯示器(陰極射線管)顯示圖像的時候的妖,輸出亮度和電壓并不是成線性關(guān)系的绣檬,而是亮度等于電壓的2.2次冪的非線性關(guān)系:l = u^{2.2}.

這個2.2也叫做Gama值。為了盡可能的達到現(xiàn)實世界的效果嫂粟。因此需要一個Gama的糾正娇未。也就是去除2.2次冪,因此會在處理之前先進行一次0.45次冪的處理星虹,抵消這個2.2次冪的造成的異常零抬。

而我們常用的sRGB的色彩空間也是這么一回事,就是指的是0.45次冪宽涌。而在上文中所有記錄的DataSpace也是這個意思平夜。

總結(jié)

            bool refreshNeeded = handleMessageTransaction();
            refreshNeeded |= handleMessageInvalidate();
            refreshNeeded |= mRepaintEverything;
            if (refreshNeeded) {
                signalRefresh();
            }

此時我們已經(jīng)分析接收到Invalidate消息之后判斷是否需要刷新的判斷處理。

  • 1.handleMessageTransaction將會處理每一個Layer的事務(wù)卸亮,最核心的事情就是把每一個Layer中的上一幀的mDrawState被當前幀的mCurrentState替代忽妒。一旦有事務(wù)需要處理,說明有Surface發(fā)生了狀態(tài)的變化兼贸,如寬高如位置段直。此時就必須重新刷新整個界面。
  • 2.handleMessageInvalidate處理的核心:
  1. 首先檢測哪一些圖元需要顯示溶诞,需要的則會添加到mLayersWithQueuedFrames鸯檬。條件是入隊時間不能超過預(yù)期時間的一秒,也能不能超過預(yù)期時間(mQueueItems是onFrameAvailable回調(diào)添加)很澄。
  2. 遍歷每一個需要顯示的Layer京闰,調(diào)用latchBuffer方法颜及。這個方法核心是updateTexImage甩苛。這個方法分為3個步驟:
  1. acquireBufferLocked 本質(zhì)上是獲取mQueue的第一個加進來的圖元作為即將顯示的圖元。但是如果遇到顯示的時間和預(yù)期時間差大于1秒俏站,同時發(fā)現(xiàn)這個圖元已經(jīng)過期了(free狀態(tài)),則會跳幀讯蒲,直到找到最近時間的一幀。

  2. LayerRejecter 判斷是否有打開凍結(jié)窗口模式肄扎,打開了但是發(fā)現(xiàn)圖元的大小不對則拒絕顯示墨林。相反,則會mDrawState的requested賦值給active犯祠。

  3. updateAndReleaseLocked 釋放前一幀的圖元旭等,同時準備設(shè)置當前消費的圖元作為準備繪制的畫面。

我們回頭來看看handleMessageInvalidate衡载,它其實也是判斷是否需要全局刷新搔耕。如果發(fā)現(xiàn)圖元鎖定之后有Layer消費了圖元,則會決定進行調(diào)用refresh頁面痰娱。發(fā)送Refresh消息弃榨。最后dirty區(qū)域?qū)蕾嚫窵ayer 的寬高菩收。mVisibleRegions標志位最后是依賴latchBuffer返回的臟區(qū)和Layer是否有添加過。

我們最后來看看Refresh做了什么鲸睛?

        case MessageQueue::REFRESH: {
            handleMessageRefresh();
            break;
        }
void SurfaceFlinger::handleMessageRefresh() {

    mRefreshPending = false;

    nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);

    preComposition(refreshStartTime);
    rebuildLayerStacks();
    setUpHWComposer();
    doDebugFlashRegions();
    doTracing("handleRefresh");
    logLayerStats();
    doComposition();
    postComposition(refreshStartTime);

...

    mLayersWithQueuedFrames.clear();
}

大致上娜饵,刷新屏幕分為7步驟:

  • 1.preComposition 預(yù)處理合成
  • 2.rebuildLayerStacks 重新構(gòu)建Layer棧
  • 3.setUpHWComposer HWC的渲染或者準備
  • 4.doDebugFlashRegions 打開debug繪制模式
  • 5.doTracing 跟蹤打印
  • 6.doComposition 合成圖元
  • 7.postComposition 圖元合成后的vysnc等收尾工作。

下一篇文章將會和大家聊聊官辈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末箱舞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子拳亿,更是在濱河造成了極大的恐慌褐缠,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件风瘦,死亡現(xiàn)場離奇詭異队魏,居然都是意外死亡,警方通過查閱死者的電腦和手機万搔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門胡桨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瞬雹,你說我怎么就攤上這事昧谊。” “怎么了酗捌?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵呢诬,是天一觀的道長。 經(jīng)常有香客問我胖缤,道長尚镰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任哪廓,我火速辦了婚禮狗唉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涡真。我一直安慰自己分俯,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布哆料。 她就那樣靜靜地躺著缸剪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪东亦。 梳的紋絲不亂的頭發(fā)上杏节,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音,去河邊找鬼拢锹。 笑死谣妻,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的卒稳。 我是一名探鬼主播蹋半,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼充坑!你這毒婦竟也來了减江?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤捻爷,失蹤者是張志新(化名)和其女友劉穎辈灼,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體也榄,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡巡莹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了甜紫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片降宅。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖囚霸,靈堂內(nèi)的尸體忽然破棺而出腰根,到底是詐尸還是另有隱情,我是刑警寧澤拓型,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布额嘿,位于F島的核電站,受9級特大地震影響劣挫,放射性物質(zhì)發(fā)生泄漏册养。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一揣云、第九天 我趴在偏房一處隱蔽的房頂上張望捕儒。 院中可真熱鬧冰啃,春花似錦邓夕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扇调,卻和暖如春矿咕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工碳柱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捡絮,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓莲镣,卻偏偏與公主長得像福稳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瑞侮,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345