Android 重学系列 图元的消费

前言

经过前两篇文章的解析,我们彻底的理解GraphicBuffer的生产端究竟做了什么。本文就来讨论GraphicBuffer是怎么消费。

整个图元的消费到合成,最后到通过hwc发送到fb。由于整个流程十分长,中间有许多细节,我将会挑出核心的思想来和大家聊聊其中的原理。

还记得,我在GraphicBuffer的诞生里面具体了聊了queuebuffer最后会通过IConsumerListener的回调通知消费者进行消费。

我们接着继续看看接下来的逻辑。

如果遇到问题,可以到本文讨论https://www.jianshu.com/p/67c1e350fe0d

正文

让我们先来回忆一下,在图元缓冲队列初始化一文中曾经总结的UML图。

Layer与缓冲队列的设计.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。当进行回调时候就会回调到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的计数,mQueueItems添加一个BufferItem,并唤醒其他线程入队的阻塞。接着调用SF的signalLayerUpdate。

SurfaceFlinger signalLayerUpdate

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

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

接着调用到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.此时强制设置为0,说明只有调用requestNextVsync强制唤醒才会返回vysnc通知。

整体设计可以看我写第一篇SurfaceFlinger 的初始化。mResyncWithRateLimitCallback这个方法用于调整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,当设置了时间戳,将不会直接等待跳出死循环,为0则会。eventPending是由接进来的屏幕的mPendingEvents判断是否为空,不为空则是true。 如果EventThread有Connection接进来进行监听将会设置为waitForVSync为true。

当我们进行初始化的时候,由于没有屏幕接进来。因此第一个信号是DISPLAY_EVENT_VSYNC。进行刷新。

MessageQueue的回调

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的回调只接受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;
    }
}

发送了一个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的消息处理函数中SF处理了两种消息一种是INVALIDATE校验无效的区域。校验方式两个步骤:

  • 1.handleMessageTransaction 处理事务,如交换绘制mDrawState和mCurrentState的焦点状态,记录每一个Layer当前需要绘制的各自的Layer,如果判断到已经添加了Layer进来,则需要打开判断可视区域标志位。发现Layer被移除了需要更新脏(已经变动)区域
  • 2.handleMessageInvalidate 核心就是latch每一个Layer中的图元进行acquire的操作。一旦判断到每一Layer中有latch了图元,说有新的图元需要消费,或者还有图元没有消费的,则需要主动调用signalLayerUpdate()进行下一个循环的INVALIDATE发送。

最后是否需要调用signalRefresh,handleMessageTransaction需要处理事务或者handleMessageInvalidate判断到有新图元。则会通过signalRefresh进入下一个循环进行Refresh消息的发送。

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事务的标志位。一旦Layer,Display等和显示相关的数据结构发生变化都需要打开这个标志位。

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.第一个从底部向顶部循环遍历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方法。处理可视区域。
  • 3.检查每一个Layer中的所对应的显示屏id类型,同时更新里面的变换矩阵。
  • 4.如果通过Client添加过Layer就会打上mLayersAdded,此时将会关闭这个标志位,同时打开mVisibleRegionsDirty,让后续的步骤检测变动的可视区域。
  • 5.如果Layer有移除,则调用invalidateLayerStack更新DisplayDevice中原有的可视脏区。
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和上一帧已经绘制了的mDrawState的差距。如果发现两者的requested的区域发生了变动,则会调用setDefaultBufferSize,重新定义图元消费BufferLayerConsumer的默认宽高。
void BufferLayer::setDefaultBufferSize(uint32_t w, uint32_t h) {
    mConsumer->setDefaultBufferSize(w, h);
}
    1. 检测mCurrentState中requested和active之间的几何宽高。在每一个Layer::State中都会存在两个几何结构体requested和active。当我们设置了Surface了postion等在屏幕上显示的几何参数会先设置到mCurrentState.requested中。也就是说requested等待绘制的参数。active则是显示中的几何参数。一旦发生变化则设resizePending为true。
    1. isFixedSize则是判断当前对应的Layer是否被冻结不允许变化大小,假设此时是关闭的,且sidebandStream是空的。此时不会立即更新requested和active的区域。回到后面acquire步骤时候进行处理。
    1. 最后更新mCurrentState为mDrawState。

这里需要注意,和SF的State不一样。Layer::State将会记录Layer显示相关的参数。

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中对应处理完的事务状态。

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;
}

对应的每一个Layer同时会更新之后需要绘制的父Layer和子Layer。

handleMessageInvalidate 检测变动区域

文件:/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有了一个新的图元进来了,还没来的消费又进来了一个图元。此时我们需要再进行消费?假如出现了宽高变化怎么办?那不就浪费了doTransaction步骤的宽高变化记录吗。因此我们需要一个latch方法,锁住图元。

一旦检测到图元还有没有消费的或者还没有到了需要显示时候,就会调用signalLayerUpdate,让下一个循环回来消费。

这个方法判断是否需要refresh的依据,其实就是判断两个情况同时成立,第一个是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计算这一帧应该是什么显示。是否显示由下面的公式决定:

预期显示 - 入队时间 < 1s && 入队时间<预期时间

一旦允许显示则往mLayersWithQueuedFrames添加Layer。这个Layer集合就是需要绘制的图层。

BufferLayer latchBuffer

接着会遍历mLayersWithQueuedFrames每一层的Layer,并且调用latchBuffer进行图元锁定。

接下来这个方法很长。我把它拆开2部分来聊

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

 ...
    Region outDirtyRegion;
    if (mQueuedFrames <= 0 && !mAutoRefresh) {
        return outDirtyRegion;
    }
//已经latch过了就不需要了
    if (mRefreshPending) {
        return outDirtyRegion;
    }
//fence已经唤醒了,也不需要了
    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);
//根据消费返回的状态做处理
    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();
    }

//把已经消费的图元保存到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方法。在这里面经过判断,latch过的Layer就不会再进行latch。

经过updateTexImage处理后,会判断返回的状态码。如果需要延迟显示则直接返回空的脏区域。如果发现需要拒绝显示这个帧,将会丢弃mQueueItem中对应的图元参数和索引。如果消费失败了,则会处理清除mQueueItem中所有等待消费的图元。最后返回空脏区。

成功消费后,如果是从queueBuffer的步骤到这里的,将会移除mQueueItem第一项图元数据。剩下的图元还有剩下的,则需要进行下一轮invalidate消息。

最后会把消费后的图元,作为当前需要显示的图元保存在getBE().compositionInfo.mBuffer和mActiveBuffer,并且设置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;
        }
    }
//记录透明参数
    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.设置相关的参数,如帧数,裁剪参数,DataSpace,透明参数等。并且移除了代表当帧数之前mLocalSyncPoints。
  • 2.计算脏区是由mDrawState对应的active参数确定(此时requested和active已经交换了)。最后调用transform转化转化为脏区
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;
}

其实这个转化是查找每一个Layer的父Layer,并且根据父Layer的宽高和当前Layer比进行一次等比例缩小。

换句话说,实际上脏区的计算,从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 判断是否需要拒绝显示当前已经消费的图元。
  • 3.updateAndReleaseLocked更新当前Layer中需要显示的图元,同时释放之前的图元为Free状态。
  • 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数组中。

先来看看image对象对应的头文件:

    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图元,我们去看看RE::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;
}

这里调用了BufferQueueConsumer的acquireBuffer。并且把消费的值赋值到新的item对应的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限制,则不允许继续。
    1. 获取之前入队到mQueue的第一项front进行循环处理。首先获取之前计算出来的期待显示时间和当前入队的时间比较,找出和当前时间最接近的入队图元。如果入队的时间比期待的小一秒,并且入队的时间比期待的时间小。这样就会直接跳出mQueue处理的处理循环。

如果front.mIsStale为false说明这个图元已经过期了。将把mSlot的索引从mActiveBuffers转移到mFreeBuffer。同时计算为一个numDroppedBuffers丢帧计数处理。获取mQueue的下一项图元。

最后把当前的front图元返回,并且释放那些已经丢帧的图元。

LayerRejecter 判断是否需要拒绝显示当前已经消费的图元

文件:/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,此时已经进行交换,所以mDrawState是这一帧的内容。一旦发现requested和active的几何不一致。如果此时不是NATIVE_WINDOW_SCALING_MODE_FREEZE(冻结屏幕)。同时图元的宽高和requested相同,才会进行requested和active的交换。

如果是NATIVE_WINDOW_SCALING_MODE_FREEZE(冻结屏幕),则但是发现requested的宽高和图元需要的宽高不一致就会拒绝绘制,丢掉当前帧。其实思想很简单,实际上就这种NATIVE_WINDOW_SCALING_MODE_FREEZE模式下就是只绘制和当前窗口一样大小的图元。其他都不设置。

updateAndReleaseLocked更新当前Layer中需要显示的图元,同时释放之前的图元为Free状态

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的监听都达到了NO_ERROR,返回Signal状态。就进行下一步,同时进行释放上一帧的图元,进入到free状态。
  • 2.记录上一帧的数据到pendingRelease,以及本次准备渲染的帧数中相关的参数,如DataSpace,mSlot插槽中对应的index,以及携带GraphicBuffer的Image。

DataSpace小知识的记录

有了RGB,Ycbcr这些颜色format,为什么还需要DataSpace,色彩的数据空间呢?这里需要借助一篇文章
,这里稍作总结。

在现实世界中,当光强一倍,则亮度也会提升一倍,是一个线性关系。但是由于最早的显示器(阴极射线管)显示图像的时候,输出亮度和电压并不是成线性关系的,而是亮度等于电压的2.2次幂的非线性关系:l = u^{2.2}.

这个2.2也叫做Gama值。为了尽可能的达到现实世界的效果。因此需要一个Gama的纠正。也就是去除2.2次幂,因此会在处理之前先进行一次0.45次幂的处理,抵消这个2.2次幂的造成的异常。

而我们常用的sRGB的色彩空间也是这么一回事,就是指的是0.45次幂。而在上文中所有记录的DataSpace也是这个意思。

总结

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

此时我们已经分析接收到Invalidate消息之后判断是否需要刷新的判断处理。

  • 1.handleMessageTransaction将会处理每一个Layer的事务,最核心的事情就是把每一个Layer中的上一帧的mDrawState被当前帧的mCurrentState替代。一旦有事务需要处理,说明有Surface发生了状态的变化,如宽高如位置。此时就必须重新刷新整个界面。
  • 2.handleMessageInvalidate处理的核心:
  1. 首先检测哪一些图元需要显示,需要的则会添加到mLayersWithQueuedFrames。条件是入队时间不能超过预期时间的一秒,也能不能超过预期时间(mQueueItems是onFrameAvailable回调添加)。
  2. 遍历每一个需要显示的Layer,调用latchBuffer方法。这个方法核心是updateTexImage。这个方法分为3个步骤:
  1. acquireBufferLocked 本质上是获取mQueue的第一个加进来的图元作为即将显示的图元。但是如果遇到显示的时间和预期时间差大于1秒,同时发现这个图元已经过期了(free状态),则会跳帧,直到找到最近时间的一帧。

  2. LayerRejecter 判断是否有打开冻结窗口模式,打开了但是发现图元的大小不对则拒绝显示。相反,则会mDrawState的requested赋值给active。

  3. updateAndReleaseLocked 释放前一帧的图元,同时准备设置当前消费的图元作为准备绘制的画面。

我们回头来看看handleMessageInvalidate,它其实也是判断是否需要全局刷新。如果发现图元锁定之后有Layer消费了图元,则会决定进行调用refresh页面。发送Refresh消息。最后dirty区域将会依赖父Layer 的宽高。mVisibleRegions标志位最后是依赖latchBuffer返回的脏区和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 预处理合成
  • 2.rebuildLayerStacks 重新构建Layer栈
  • 3.setUpHWComposer HWC的渲染或者准备
  • 4.doDebugFlashRegions 打开debug绘制模式
  • 5.doTracing 跟踪打印
  • 6.doComposition 合成图元
  • 7.postComposition 图元合成后的vysnc等收尾工作。

下一篇文章将会和大家聊聊。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343