SurfaceFlinger(2):整体绘制流程1(INVALIDATE)

先从SurfaceFlinger中分析绘制流程
收到case MessageQueue::INVALIDATE开始


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

主要做了几件事情 
1 handleMessageTransaction处理事务,也就是客户端告诉我们一些数据发生变化了,我们要把这些信息收集起来,进行状态切换
2 handleMessageInvalidate进行页面反转(主要是对buffer的处理)
3 第三步就是根据前两步的出理结果决定是否要刷新缓冲区

下面我们一一详细分析三个步骤

步骤一:

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

首先偷看下是否有外部作用使当前的状态发生变化,如果有则进行事务处理,这里我们直接分析handleTransaction函数

void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
    ATRACE_CALL();

    // here we keep a copy of the drawing state (that is the state that's
    // going to be overwritten by handleTransactionLocked()) outside of
    // mStateLock so that the side-effects of the State assignment
    // don't happen with mStateLock held (which can cause deadlocks).
    State drawingState(mDrawingState);

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

    // Here we're guaranteed that some transaction flags are set
    // so we can call handleTransactionLocked() unconditionally.
    // We call getTransactionFlags(), which will also clear the flags,
    // with mStateLock held to guarantee that mCurrentState won't change
    // until the transaction is committed.

    transactionFlags = getTransactionFlags(eTransactionMask);
    handleTransactionLocked(transactionFlags);

    mLastTransactionTime = systemTime() - now;
    mDebugInTransaction = 0;
    invalidateHwcGeometry();
    // here the transaction has been committed
}
注意这个函数全程持有    Mutex::Autolock _l(mStateLock);锁,所以在这个函数执行的时候事务不会被其他地方更改,
然后清除我们要处理的flags,之后使用handleTransactionLocked处理事务
最后使用invalidateHwcGeometry()函数更新mHwWorkListDirty,该变量用于通知hwc模块重新创建WorkList


我们把重点放在void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)函数,这个函数比较长我们也分段阅读
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
    const size_t count = currentLayers.size();

    // Notify all layers of available frames
    for (size_t i = 0; i < count; ++i) {
        currentLayers[i]->notifyAvailableFrames();
    }

    /*
     * Traversal of the children
     * (perform the transaction for each of them if needed)
     */

    if (transactionFlags & eTraversalNeeded) {
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(currentLayers[i]);
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
            if (!trFlags) continue;

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

第一部分 首先currentLayers[i]->notifyAvailableFrames(); 函数我们这里先不分析

eTraversalNeeded,eTraversalNeeded表示layer数据发生变化,如果设置了该标志,就要对每个有变化的layer处理.
那么如何判断layer是否有发生变化呢,使用layer->getTransactionFlags(eTransactionNeeded)进行处理.
在layer中也有个mTransactionFlags标志,如果layer发生变化就会设置相应的位
如果layer发生变化就要处理layer的事务,采用layer->doTransaction(0)函数处理
下面分析layer的doTransaction函数

uint32_t Layer::doTransaction(uint32_t flags) {
    ATRACE_CALL();

    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) {
        // the size changed, we need to ask our client to request a new buffer
        ALOGD_IF(DEBUG_RESIZE,
                "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
                "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
                "            requested={ wh={%4u,%4u} }}\n"
                "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
                "            requested={ wh={%4u,%4u} }}\n",
                this, getName().string(), mCurrentTransform,
                getEffectiveScalingMode(),
                c.active.w, c.active.h,
                c.crop.left,
                c.crop.top,
                c.crop.right,
                c.crop.bottom,
                c.crop.getWidth(),
                c.crop.getHeight(),
                c.requested.w, c.requested.h,
                s.active.w, s.active.h,
                s.crop.left,
                s.crop.top,
                s.crop.right,
                s.crop.bottom,
                s.crop.getWidth(),
                s.crop.getHeight(),
                s.requested.w, s.requested.h);

        // record the new size, form this point on, when the client request
        // a buffer, it'll get the new size.
        mSurfaceFlingerConsumer->setDefaultBufferSize(
                c.requested.w, c.requested.h);
    }

    const bool resizePending = (c.requested.w != c.active.w) ||
            (c.requested.h != c.active.h);
    if (!isFixedSize()) {
        if (resizePending && mSidebandStream == NULL) {
            // don't let Layer::doTransaction update the drawing state
            // if we have a pending resize, unless we are in fixed-size mode.
            // the drawing state will be updated only once we receive a buffer
            // with the correct size.
            //
            // in particular, we want to make sure the clip (which is part
            // of the geometry state) is latched together with the size but is
            // latched immediately when no resizing is involved.
            //
            // If a sideband stream is attached, however, we want to skip this
            // optimization so that transactions aren't missed when a buffer
            // never arrives

            flags |= eDontUpdateGeometryState;
        }
    }

    // always set active to requested, unless we're asked not to
    // this is used by Layer, which special cases resizes.
    if (flags & eDontUpdateGeometryState)  {
    } else {
        Layer::State& editCurrentState(getCurrentState());
        if (mFreezePositionUpdates) {
            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) {
        // invalidate and recompute the visible regions if needed
        flags |= Layer::eVisibleRegion;
    }

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

        // we may use linear filtering, if the matrix scales us
        const uint8_t type = c.active.transform.getType();
        mNeedsFiltering = (!c.active.transform.preserveRects() ||
                (type >= Transform::SCALE));
    }

    // If the layer is hidden, signal and clear out all local sync points so
    // that transactions for layers depending on this layer's frames becoming
    // visible are not blocked
    if (c.flags & layer_state_t::eLayerHidden) {
        Mutex::Autolock lock(mLocalSyncPointMutex);
        for (auto& point : mLocalSyncPoints) {
            point->setFrameAvailable();
        }
        mLocalSyncPoints.clear();
    }

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

这个函数理解起来也比较困难,首先pushPendingState()函数
这个函数很有意思 为了实现一个deferTransactionUntil的功能,意思是延迟执行事务直到某个layer的某一帧到来.一般用在SurfaceView上面
用于和父窗口同步绘制的(就是一起准备数据绘制某一帧)

void Layer::pushPendingState() {
    if (!mCurrentState.modified) {
        return;
    }

    // If this transaction is waiting on the receipt of a frame, generate a sync
    // point and send it to the remote layer.
    if (mCurrentState.handle != nullptr) {
        sp<IBinder> strongBinder = mCurrentState.handle.promote();
        sp<Handle> handle = nullptr;
        sp<Layer> handleLayer = nullptr;
        if (strongBinder != nullptr) {
            handle = static_cast<Handle*>(strongBinder.get());
            handleLayer = handle->owner.promote();
        }
        if (strongBinder == nullptr || handleLayer == nullptr) {
            ALOGE("[%s] Unable to promote Layer handle", mName.string());
            // If we can't promote the layer we are intended to wait on,
            // then it is expired or otherwise invalid. Allow this transaction
            // to be applied as per normal (no synchronization).
            mCurrentState.handle = nullptr;
        } else {
            auto syncPoint = std::make_shared<SyncPoint>(
                    mCurrentState.frameNumber);
            if (handleLayer->addSyncPoint(syncPoint)) {
                mRemoteSyncPoints.push_back(std::move(syncPoint));
            } else {
                // We already missed the frame we're supposed to synchronize
                // on, so go ahead and apply the state update
                mCurrentState.handle = nullptr;
            }
        }

        // Wake us up to check if the frame has been received
        setTransactionFlags(eTransactionNeeded);
    }
    mPendingStates.push_back(mCurrentState);
}

首先要执行pushPendingState的条件就是mCurrentState.modified==true,也就是当前状态有变化,在layer中有两个类型为State的变量,类似于双缓冲机制用于反转.分别是 State mCurrentState; 和State mDrawingState; mDrawingState是当前正在用于绘制的状态,mCurrentState是用于记录新的修改
所有关于layer的修改都会保存在在mCurrentState中.
另外一个条件就是mCurrentState.handle != nullptr,当满足上述条件后就会做一些操作
首先判断所要等待的layer存在,如果存在就向它的mLocalSyncPoints添加一个SyncPonit,并向自己的mRemoteSyncPoints里添加一个SyncPoint,
然后添加setTransactionFlags(eTransactionNeeded)标志,代表layer发生了变化,方便执行事务的时候处理这个layer,之后无乱如何都会执行
到mPendingStates.push_back(mCurrentState);方法 将mCurrentState放到mPendingStates中去. 
这里要说明下,调用pushPendingState()方法的地方只有两处

1 void Layer::deferTransactionUntil(const sp<IBinder>& handle,
        uint64_t frameNumber) {
    mCurrentState.handle = handle;
    mCurrentState.frameNumber = frameNumber;
    // We don't set eTransactionNeeded, because just receiving a deferral
    // request without any other state updates shouldn't actually induce a delay
    mCurrentState.modified = true;
    pushPendingState();
    mCurrentState.handle = nullptr;
    mCurrentState.frameNumber = 0;
    mCurrentState.modified = false;
}

设置mCurrentState.handle 的地方有这一处
这里执行完成pushPendingState()后就把frameNumber和handle设置成0了,所以第二个地方Layer::doTransaction(uint32_t flags)
如果有其他地方改变了layer属性,调用它的时候只会执行mPendingStates.push_back(mCurrentState).
还有一点值得注意的

 auto syncPoint = std::make_shared<SyncPoint>(
                    mCurrentState.frameNumber);
            if (handleLayer->addSyncPoint(syncPoint)) {
                mRemoteSyncPoints.push_back(std::move(syncPoint));

这里创建了一个shared变量并且使用move语义进行push_back说明二者使用的是统一快内存,一个状态变了另一个也会变
另外SyncPoint里面设置的frameNumber就是mCurrentState的frameNumber,也就是说要等到hanlde所对应的窗口到达它的frameNumber时候才进行处理自己的事务(这也反映了如何使两个窗口同步)
这里我们重新看一下前面SurfaceFlinger::handleTransactionLocked函数里面的

currentLayers[i]->notifyAvailableFrames()
void Layer::notifyAvailableFrames() {
    auto headFrameNumber = getHeadFrameNumber();
    bool headFenceSignaled = headFenceHasSignaled();
    Mutex::Autolock lock(mLocalSyncPointMutex);
    for (auto& point : mLocalSyncPoints) {
        if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
            point->setFrameAvailable();
        }
    }
}

这个函数发现有其他layer在等待自己的某一帧,如果这一帧已经绘制完成则会使用setFrameAvailable()设置SyncPoint的mFrameIsAvailable变量为true,代表所等待的帧已经到来,注意这时对应的layer的mRemoteSyncPoints里面的SyncPoint的值也会发生变化,我们后边会看到对设置好mFrameIsAvailable的帧的处理.
这里我们重新回到函数uint32_t Layer::doTransaction(uint32_t flags) 分析applyPendingStates()函数
函数的代码如下

bool Layer::applyPendingStates(State* stateToCommit) {
    bool stateUpdateAvailable = false;
    while (!mPendingStates.empty()) {
        if (mPendingStates[0].handle != nullptr) {
            if (mRemoteSyncPoints.empty()) {
                // If we don't have a sync point for this, apply it anyway. It
                // will be visually wrong, but it should keep us from getting
                // into too much trouble.
                ALOGE("[%s] No local sync point found", mName.string());
                popPendingState(stateToCommit);
                stateUpdateAvailable = true;
                continue;
            }

            if (mRemoteSyncPoints.front()->getFrameNumber() !=
                    mPendingStates[0].frameNumber) {
                ALOGE("[%s] Unexpected sync point frame number found",
                        mName.string());

                // Signal our end of the sync point and then dispose of it
                mRemoteSyncPoints.front()->setTransactionApplied();
                mRemoteSyncPoints.pop_front();
                continue;
            }

            if (mRemoteSyncPoints.front()->frameIsAvailable()) {
                // Apply the state update
                popPendingState(stateToCommit);
                stateUpdateAvailable = true;

                // Signal our end of the sync point and then dispose of it
                mRemoteSyncPoints.front()->setTransactionApplied();
                mRemoteSyncPoints.pop_front();
            } else {
                break;
            }
        } else {
            popPendingState(stateToCommit);
            stateUpdateAvailable = true;
        }
    }

    // If we still have pending updates, wake SurfaceFlinger back up and point
    // it at this layer so we can process them
    if (!mPendingStates.empty()) {
        setTransactionFlags(eTransactionNeeded);
        mFlinger->setTransactionFlags(eTraversalNeeded);
    }

    mCurrentState.modified = false;
    return stateUpdateAvailable;
}

这个函数就是对mPendingStates进行处理生成新的CurrentState的过程,大致进行下如下分析:
首先通过一个while循环去处理所有的mPendingStates, 函数体内是我们主要关注的内容.
先从由旧到新获取State,然后判断是否等到了hanlde所对应的layer的帧是否出现,如果没有出现stateUpdateAvailable肯定为false 了,另外还有一种对错误情况的处理,就是mRemoteSyncPoints.front()->getFrameNumber() !=
mPendingStates[0].frameNumber)所对应的条件,读者不妨详细读一下,这种方式确实可以控制事务的处理.
还有mPendingStates[0].handle == nullptr的情况.这里还要注意一种情况,就是break所对应的语句处,这种情况一个事务也不能处理,有可能mPendingStates
还不是空的就跳出循环了,所以要对其进行检查,重新设置flags方便下回处理.最后返回stateUpdateAvailable,代表是否有新的状态需要处理.

回到uint32_t Layer::doTransaction(uint32_t flags)的代码中
如果有新的事务需要处理则就会进入下面的代码,首先获取layerStack的栈变量 这时多线程操作中常用的手段,然后判断size是否发生变化.如代码第9行.这里的requested代表客户端请求的帧大小. 如果requestsize 发生了变化,是要通知给生产者和消费者的,mSurfaceFlingerConsumer->setDefaultBufferSize(
c.requested.w, c.requested.h)这个函数最终设置给了BufferQueueCore的defaultWidth和Buffer,BufferQueueCore是生产者和消费者共用的数据.

34行的代码判断请求的大小是否与active的大小一致(active的大小是经过变换后的大小)
35到47行代码判断如果我们在固定大小的模式,并且不包含边带数据,即使大小发生的变化我们也不去处理这种变化,所以给flags 添加了eDontUpdateGeometryState位.
下面就是对调整大小的部分进行处理,也分为两种情况:
第一中情况 if (mFreezePositionUpdates) { 说明当前是冻结状态,所以大小是没有变化的,变化的只有位置,这种情况下希望马上应用位置和变换,所以直接设置tx,ty,然后设置active还是为原来的active,其实三个数据已经都设置上了,因为这时候request.w request.h是和active中相等的. tx,ty也是相等的这里重新设置一下只是为了更新变换的类型.
第二种清空就是fixedsize的情况,直接赋值request到active.
60行代码判断经过变换后的大小还位置如果和当前正在绘制的有变化,则设置flags |= Layer::eVisibleRegion,用于通知Surfaceflinger region有发生变化需要重绘.
如果sequence发生了变化说明内容也有变化,则要设置this->contentDirty = true,表明内容发生变化需要重新绘制,如果内容没有发生变化,就只是简单的裁剪就可以了.裁剪的部分我们单独用一片文章去分析.这里说明一下引起sequence变化的原因,主要是layer的alpha变化,裁剪部分变化,flags变化,z轴变化,layerStack,矩阵,位置变化都会引起sequence变化.
第73-76行如果layer变乘隐藏状态则需要通知等待与之同步的layer帧可用.
最后79行提交事务

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

注意这个函数将mCurrentState的状态拷贝到了mDrawingState状态,其实在这个事务处理函数中mDrawingState的很多状态也发生的变化,但是它现在与mDrawingState的内容是一致的了.

现在layer的事务就处理完了,这里进行下总结,其实layer的事务中只处理了两件事情,1处理SyncPoint(同步点),主要是通过延迟事务处理完成 2 layer region变化的处理,主要就是requet到active的变化

回到void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)函数

 if (transactionFlags & eTraversalNeeded) {
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(currentLayers[i]);
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
            if (!trFlags) continue;

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

如果发现有layer发生变化了则设置mVisibleRegionsDirty=true,用于通知Surfaceflinger需要刷新下一帧.
后面的部分主要处理了display的变化,在多display管理一章中我们已经分析.这里就不重新分析了.所以直接跳到最后一部分代码

  const LayerVector& layers(mDrawingState.layersSortedByZ);
    if (currentLayers.size() > layers.size()) {
        // layers have been added
        mVisibleRegionsDirty = true;
    }

    // some layers might have been removed, so
    // we need to update the regions they're exposing.
    if (mLayersRemoved) {
        mLayersRemoved = false;
        mVisibleRegionsDirty = true;
        const size_t count = layers.size();
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(layers[i]);
            if (currentLayers.indexOf(layer) < 0) {
                // this layer is not visible anymore
                // TODO: we could traverse the tree from front to back and
                //       compute the actual visible region
                // TODO: we could cache the transformed region
                const Layer::State& s(layer->getDrawingState());
                Region visibleReg = s.active.transform.transform(
                        Region(Rect(s.active.w, s.active.h)));
                invalidateLayerStack(s.layerStack, visibleReg);
            }
        }
    }

    commitTransaction();

    updateCursorAsync();

layer的数量发生变化肯定要重新绘制. 
如果有layer被移除还要更新display的dirtyRegion,因为这里是最后一次处理被移除的layer的地方了.
最后提交事务

void SurfaceFlinger::commitTransaction()
{
    if (!mLayersPendingRemoval.isEmpty()) {
        // Notify removed layers now that they can't be drawn from
        for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
            recordBufferingStats(mLayersPendingRemoval[i]->getName().string(),
                    mLayersPendingRemoval[i]->getOccupancyHistory(true));
            mLayersPendingRemoval[i]->onRemoved();
        }
        mLayersPendingRemoval.clear();
    }

    // If this transaction is part of a window animation then the next frame
    // we composite should be considered an animation as well.
    mAnimCompositionPending = mAnimTransactionPending;

    mDrawingState = mCurrentState;
    mTransactionPending = false;
    mAnimTransactionPending = false;
    mTransactionCV.broadcast();
}

提交事务中先处理要移除的layer,这个过程中做了一些状态的记录,用于dump信息,另外就是调用mLayersPendingRemoval[i]->onRemoved();发送remove的通知,最终会调用到ConsumerBase的abandonLocked方法,
该方法中先释放buffer,然后调用 mConsumer->consumerDisconnect()做一些清理工作

void ConsumerBase::abandonLocked() {
    CB_LOGV("abandonLocked");
    if (mAbandoned) {
        CB_LOGE("abandonLocked: ConsumerBase is abandoned!");
        return;
    }
    for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
        freeBufferLocked(i);
    }
    // disconnect from the BufferQueue
    mConsumer->consumerDisconnect();
    mConsumer.clear();
}

回到void SurfaceFlinger::commitTransaction()中,除了要反转mDrawState和mCurrentState(注意layer和Surfaceflinger都要这个两个变量,layer中的主要处理一个window中的状态变换,而SurfaceFlinger代表全局的状态,其实主要就是Display状态变换),反转之后设置 mTransactionPending = false; 代表事物已经处理完成
mAnimTransactionPending = false; 动画事务处理完成
mTransactionCV.broadcast();发送广播唤醒等待事物处理的线程.

handleTransactionLocked函数的最后一项工作就是更新CursorLayer,cursorlayer也就是光标层

void SurfaceFlinger::updateCursorAsync()
{
    HWComposer& hwc(getHwComposer());
    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        sp<const DisplayDevice> hw(mDisplays[dpy]);
        const int32_t id = hw->getHwcDisplayId();
        if (id < 0) {
            continue;
        }
        const Vector< sp<Layer> >& currentLayers(
            hw->getVisibleLayersSortedByZ());
        const size_t count = currentLayers.size();
        HWComposer::LayerListIterator cur = hwc.begin(id);
        const HWComposer::LayerListIterator end = hwc.end(id);
        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
            if (cur->getCompositionType() != HWC_CURSOR_OVERLAY) {
                continue;
            }
            const sp<Layer>& layer(currentLayers[i]);
            Rect cursorPos = layer->getPosition(hw);
            hwc.setCursorPositionAsync(id, cursorPos);
            break;
        }
    }
}

因为layer已经发生变化,要找到它新的位置通知HWC组件,因为这样可以让硬件特殊处理该曾,减少光标滞后的问题.

我们在来回顾一下对于SurfaceFlinger的整体事务做了什么:

1 确认是否有区域变脏

2 处理没一个layer的事务

3 处理display的变化

4 处理layer的增加减少

到此事务的处理我们就看完了,接下来在在 case MessageQueue::INVALIDATE:中处理的就是页面反转

refreshNeeded |= handleMessageInvalidate();

handleMessageInvalidate是处理页面反转的函数.

bool SurfaceFlinger::handleMessageInvalidate() {
    ATRACE_CALL();
    return handlePageFlip(); }
bool SurfaceFlinger::handlePageFlip()
{
    Region dirtyRegion;

    bool visibleRegions = false;
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    bool frameQueued = false;

    // Store the set of layers that need updates. This set must not change as
    // buffers are being latched, as this could result in a deadlock.
    // Example: Two producers share the same command stream and:
    // 1.) Layer 0 is latched
    // 2.) Layer 0 gets a new frame
    // 2.) Layer 1 gets a new frame
    // 3.) Layer 1 is latched.
    // Display is now waiting on Layer 1's frame, which is behind layer 0's
    // second frame. But layer 0's second frame could be waiting on display.
    Vector<Layer*> layersWithQueuedFrames;
    for (size_t i = 0, count = layers.size(); i<count ; i++) {
        const sp<Layer>& layer(layers[i]);
        if (layer->hasQueuedFrame()) {
            frameQueued = true;
            if (layer->shouldPresentNow(mPrimaryDispSync)) {
                layersWithQueuedFrames.push_back(layer.get());
            } else {
                layer->useEmptyDamage();
            }
        } else {
            layer->useEmptyDamage();
        }
    }
    for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
        Layer* layer = layersWithQueuedFrames[i];
        const Region dirty(layer->latchBuffer(visibleRegions));
        layer->useSurfaceDamage();
        const Layer::State& s(layer->getDrawingState());
        invalidateLayerStack(s.layerStack, dirty);
    }

    mVisibleRegionsDirty |= visibleRegions;

    // If we will need to wake up at some time in the future to deal with a
    // queued frame that shouldn't be displayed during this vsync period, wake
    // up during the next vsync period to check again.
    if (frameQueued && layersWithQueuedFrames.empty()) {
        signalLayerUpdate();
    }

    // Only continue with the refresh if there is actually new work to do
    return !layersWithQueuedFrames.empty();
}

函数代码不太多,但是里面函数嵌套很多.我们先总体看下函数做了什么.
14行到21行就是收集那些有可用帧的layer,判断有可用帧的条件有两层,第一层用15行layer->hasQueuedFrame()函数判断是否有buffer数据已经入队列

  /*
     * Returns if a frame is queued.
     */
    bool hasQueuedFrame() const { return mQueuedFrames > 0 ||
            mSidebandStreamChanged || mAutoRefresh; }

函数很简单,在同步模式下主要看mQueuedFrames,一部模式主要看mAutoRefresh,还有中特殊情况就是视频边带数据改变.
第二层判断就是 if (layer->shouldPresentNow(mPrimaryDispSync)) 这个条件,

bool Layer::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 =
            mSurfaceFlingerConsumer->computeExpectedPresent(dispSync);

    // Ignore timestamps more than a second in the future
    bool isPlausible = timestamp < (expectedPresent + s2ns(1));
    ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible "
            "relative to expectedPresent %" PRId64, mName.string(), timestamp,
            expectedPresent);

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

函数也比较简单,就是判断落在下一个app vync时间之前的和落在下一个vsync(不包含偏移)一秒之后的帧都满足需求. 另外边带改变和mAutoRefresh也都满足.为什么1s以后的帧也要被收集呢,因为它是不合理的帧,要在这次刷新中处理掉.如果在收集过程中没有满足的帧则应该将layer的受损区域清空(受损区域是指数据发生变化的区域),因为还没有合适的buffer,所以也不用管那些帧.而我们锁定buffer之后就会从buffer中拿出来受损区域,重新赋值给layer.
接下来在页面反转的第二个for循环里面根据之前收集到的包含可用帧和无效帧的集合,对其中的没一个layer做处理,锁定buffer. 是页面反转最重要的一部分.
我们先不看锁定buffer的过程,先来分析下锁定之后的逻辑,第31到33行有新入队列的buffer却没有落在可以处理范围内的layer,这种情况说明很快layer就可以使用,所以要在下一个vsync的时候处理,发出signalLayerUpdate();用于接收下一个sf_vsync事件. 最后返回layersWithQueuedFrames是否不是空的(不为空说明有新的buffer被锁定了,所以要刷新显示)

现在我们回来看下latchBuffer的过程.函数比较长我们分成很多段来看.

Region Layer::latchBuffer(bool& recomputeVisibleRegions)
{
    ATRACE_CALL();

    if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
        // mSidebandStreamChanged was true
        mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
        if (mSidebandStream != NULL) {
            setTransactionFlags(eTransactionNeeded);
            mFlinger->setTransactionFlags(eTraversalNeeded);
        }
        recomputeVisibleRegions = true;

        const State& s(getDrawingState());
        return s.active.transform.transform(Region(Rect(s.active.w, s.active.h)));
    }

注意latchBuffer是对每一个layer处理的,首先如果边带数据改变则先处理边带变化,下一帧再处理其他变化,所以要先重新设置上事务,方便下一帧处理. 最后对边带数据变换,返回下一个buffer的边带region.返回前要经过变换处理,如何变换我们就不分析了,可以参考我的另一篇博客Surfaceflinger(3):变换.边带数据不是我们重点分析的对象,所以我们继续向下分析.

后面的所有逻辑都是在 if (mQueuedFrames > 0 || mAutoRefresh) 条件成立的情况下进行的,最后跳出该条件返回一个计算出的Dirty Region . 条件不难理解,之前说过收集要处理的buffer的时候要满足layer->hasQueuedFrame()条件,这个条件对应的情况有三个,其中第一个条件边带变化的情况已经处理完了,下面处理的就是后面的两种情况:包含QueuedFrames和mAutoRefresh的情况.
这段代码还是很长我们分段处理.其中开始部分是创建一个Reject对象,我们先跳过,用到的时候在去分析.

   auto headFrameNumber = getHeadFrameNumber();
        bool matchingFramesFound = false;
        bool allTransactionsApplied = true;
        {
            Mutex::Autolock lock(mLocalSyncPointMutex);
            for (auto& point : mLocalSyncPoints) {
                if (point->getFrameNumber() > headFrameNumber) {
                    break;
                }

                matchingFramesFound = true;

                if (!point->frameIsAvailable()) {
                    // We haven't notified the remote layer that the frame for
                    // this point is available yet. Notify it now, and then
                    // abort this attempt to latch.
                    point->setFrameAvailable();
                    allTransactionsApplied = false;
                    break;
                }

                allTransactionsApplied &= point->transactionIsApplied();
            }
        }

        if (matchingFramesFound && !allTransactionsApplied) {
            mFlinger->signalLayerUpdate();
            return outDirtyRegion;
        }

首先是对SyncPoint的处理,我们之前分析过,用于同步的两个数据结构mLocalSyncPoints和mRemoteSyncPoints.  mRemoteSyncPoints中存放的是表示正在等别的layer的帧的帧,而mLocalSyncPoints中存放的是用于通知帧已经到达的帧.这里如果queueBuffer的地一个buffer所代表的帧已经超过了mLocalSyncPoints要等待的帧,如果还没有通知mRemoteSyncPoints中对应的帧可用,我们就需要通知对应的mRemoteSyncPoints中的帧可用了.通过point->setFrameAvailable()方法去通知,我们前面也分析了该方法. 最后根据两种不同的情况去设置allTransactionsApplied变量.最后如果找到了可用的LocalSyncPoints,但是不是所有的LocalSyncPoints都变为可用,就要等待所有的LocalSyncPoints都可用后再去刷新这个layer,直接请求下一个sf_vync,然后返回.为什么要这么做呢? 因为要连个layer一起绘制同一个framenumber. 这里有可能拥有对应RemoteSyncPoint 的layer已经被遍历完成.

下面就进入了最为关键的一步,真正的锁定buffer(acquireBuffer)

 // This boolean is used to make sure that SurfaceFlinger's shadow copy
        // of the buffer queue isn't modified when the buffer queue is returning
        // BufferItem's that weren't actually queued. This can happen in shared
        // buffer mode.
        bool queuedBuffer = false;
        status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
                mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
                mLastFrameNumberReceived);

这个函数层层包装,我们自定向下进行分析.读者一定要留神每个段落分析的是哪个函数的哪部分,一定要对照代码去看下面的段落

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

    if (mAbandoned) {
        ALOGE("updateTexImage: GLConsumer is abandoned!");
        return NO_INIT;
    }

    // Make sure the EGL state is the same as in previous calls.
    status_t err = checkAndUpdateEglStateLocked();
    if (err != NO_ERROR) {
        return err;
    }

    BufferItem item;

    // Acquire the next buffer.
    // In asynchronous mode the list is guaranteed to be one buffer
    // deep, while in synchronous mode we use the oldest buffer.
    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 {
            ALOGE("updateTexImage: acquire failed: %s (%d)",
                strerror(-err), err);
        }
        return err;
    }

    // We call the rejecter here, in case the caller has a reason to
    // not accept this buffer.  This is used by SurfaceFlinger to
    // reject buffers which have the wrong size
    int slot = item.mSlot;
    if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer, EGL_NO_SYNC_KHR);
        return BUFFER_REJECTED;
    }

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

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

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

    if (!SyncFeatures::getInstance().useNativeFenceSync()) {
        // Bind the new buffer to the GL texture.
        //
        // Older devices require the "implicit" synchronization provided
        // by glEGLImageTargetTexture2DOES, which this method calls.  Newer
        // devices will either call this in Layer::onDraw, or (if it's not
        // a GL-composited layer) not at all.
        err = bindTextureImageLocked();
    }

    return err;
}

函数7-9行检查该layer是否已经被废弃.11行检查EGL状态.
函数18行是这个函数最关键的一部分,后面部分都是对该函数的返回结果做检查,我们先不分析后面的部分,跳入18行的函数进行分析,回来之后再分析这个函数的后半部分.

status_t SurfaceFlingerConsumer::acquireBufferLocked(BufferItem* item,
        nsecs_t presentWhen, uint64_t maxFrameNumber) {
    status_t result = GLConsumer::acquireBufferLocked(item, presentWhen,
            maxFrameNumber);
    if (result == NO_ERROR) {
        mTransformToDisplayInverse = item->mTransformToDisplayInverse;
        mSurfaceDamage = item->mSurfaceDamage;
    }
    return result;
}

首先说明下这个函数的三个参数,BufferItem* item传出参数,用于传出锁定的buffer,nsecs_t presentWhen下一个vsync的时间,maxFrameNumber最后收到的一个queueBuffer. 最后如果返回没有发生错误,设置layer的mTransformToDisplayInverse变量和mSurfaceDamage变量,mSurfaceDamage我们前面看到过,前面收集要处理的buffer的时候会把SurfaceDamage清除掉,这里设置了新的SurfaceDamage.

接着往里面追

status_t GLConsumer::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 is not null, this buffer has not been acquired
    // before, so any prior EglImage created is using a stale buffer. This
    // replaces any old EglImage with a new one (using the new buffer).
    if (item->mGraphicBuffer != NULL) {
        int slot = item->mSlot;
        mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
    }

    return NO_ERROR;
}

这汗函数有嵌套了一层acquireBufferLocked函数,在调用ConsumerBase::acquireBufferLocked返后如果发生了错误直接返回,如果没有发生操作就用获取的新的buffer创建一个EglImage,这个EglImage是用于快速的纹理拷贝,是GLES的扩展请参考https://software.intel.com/en-us/articles/using-opengl-es-to-accelerate-apps-with-legacy-2d-guis 链接文章.好了,接下来就可以进入有一个正题

status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
        nsecs_t presentWhen, uint64_t maxFrameNumber) {
    if (mAbandoned) {
        CB_LOGE("acquireBufferLocked: ConsumerBase is abandoned!");
        return NO_INIT;
    }

    status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
    if (err != NO_ERROR) {
        return err;
    }

    if (item->mGraphicBuffer != NULL) {
        mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
    }

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

    CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
            item->mSlot, item->mFrameNumber);

    return OK;
}

这里又嵌套了一层acquireBuffer,不要灰心,这个就是最后一个了,首先就是对layer状态的检查,之后mConsumer->acquireBuffer函数获取buffer,返回之后给自己的槽赋值,这样绘制的时候就可以使用ConsumerBase中的槽获取数据,就可以释放BufferQueueCore中的槽了(或许已经释放了),废话不多说,直接进入下一个acquireBuffer.

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

        // Check that the consumer doesn't currently have the maximum number of
        // buffers acquired. We allow the max buffer count to be exceeded by one
        // buffer so that the consumer can successfully set up the newly acquired
        // buffer before releasing the old one.
        int numAcquiredBuffers = 0;
        for (int s : mCore->mActiveBuffers) {
            if (mSlots[s].mBufferState.isAcquired()) {
                ++numAcquiredBuffers;
            }
        }
        if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
            BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
                    numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
            return INVALID_OPERATION;
        }

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

        // In asynchronous mode the list is guaranteed to be one buffer deep,
        // while in synchronous mode we use the oldest buffer.
        if (mCore->mQueue.empty() && !sharedBufferAvailable) {
            return NO_BUFFER_AVAILABLE;
        }

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

        // If expectedPresent is specified, we may not want to return a buffer yet.
        // If it's specified and there's more than one buffer queued, we may want
        // to drop a buffer.
        // Skip this if we're in shared buffer mode and the queue is empty,
        // since in that case we'll just return the shared buffer.
        if (expectedPresent != 0 && !mCore->mQueue.empty()) {
            const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second

            // The 'expectedPresent' argument indicates when the buffer is expected
            // to be presented on-screen. If the buffer's desired present time is
            // earlier (less) than expectedPresent -- meaning it will be displayed
            // on time or possibly late if we show it as soon as possible -- we
            // acquire and return it. If we don't want to display it until after the
            // expectedPresent time, we return PRESENT_LATER without acquiring it.
            //
            // To be safe, we don't defer acquisition if expectedPresent is more
            // than one second in the future beyond the desired present time
            // (i.e., we'd be holding the buffer for a long time).
            //
            // NOTE: Code assumes monotonic time values from the system clock
            // are positive.

            // Start by checking to see if we can drop frames. We skip this check if
            // the timestamps are being auto-generated by Surface. If the app isn't
            // generating timestamps explicitly, it probably doesn't want frames to
            // be discarded based on them.
            while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
                const BufferItem& bufferItem(mCore->mQueue[1]);

                // If dropping entry[0] would leave us with a buffer that the
                // consumer is not yet ready for, don't drop it.
                if (maxFrameNumber && bufferItem.mFrameNumber > maxFrameNumber) {
                    break;
                }

                // If entry[1] is timely, drop entry[0] (and repeat). We apply an
                // additional criterion here: we only drop the earlier buffer if our
                // desiredPresent falls within +/- 1 second of the expected present.
                // Otherwise, bogus desiredPresent times (e.g., 0 or a small
                // relative timestamp), which normally mean "ignore the timestamp
                // and acquire immediately", would cause us to drop frames.
                //
                // We may want to add an additional criterion: don't drop the
                // earlier buffer if entry[1]'s fence hasn't signaled yet.
                nsecs_t desiredPresent = bufferItem.mTimestamp;
                if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
                        desiredPresent > expectedPresent) {
                    // This buffer is set to display in the near future, or
                    // desiredPresent is garbage. Either way we don't want to drop
                    // the previous buffer just to get this on the screen sooner.
                    BQ_LOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
                            PRId64 " (%" PRId64 ") now=%" PRId64,
                            desiredPresent, expectedPresent,
                            desiredPresent - expectedPresent,
                            systemTime(CLOCK_MONOTONIC));
                    break;
                }

                BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
                        " size=%zu",
                        desiredPresent, expectedPresent, mCore->mQueue.size());

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

                    // After leaving shared buffer mode, the shared buffer will
                    // still be around. Mark it as no longer shared if this
                    // operation causes it to be free.
                    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();
            }

            // See if the front buffer is ready to be acquired
            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) {
                BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
                        " (%" PRId64 ") now=%" PRId64 " frame=%" PRIu64
                        " consumer=%" PRIu64,
                        desiredPresent, expectedPresent,
                        desiredPresent - expectedPresent,
                        systemTime(CLOCK_MONOTONIC),
                        front->mFrameNumber, maxFrameNumber);
                return PRESENT_LATER;
            }

            BQ_LOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
                    "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
                    desiredPresent - expectedPresent,
                    systemTime(CLOCK_MONOTONIC));
        }

        int slot = BufferQueueCore::INVALID_BUFFER_SLOT;

        if (sharedBufferAvailable && mCore->mQueue.empty()) {
            // make sure the buffer has finished allocating before acquiring it
            mCore->waitWhileAllocatingLocked();

            slot = mCore->mSharedBufferSlot;

            // Recreate the BufferItem for the shared buffer from the data that
            // was cached when it was last queued.
            outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;
            outBuffer->mFence = Fence::NO_FENCE;
            outBuffer->mCrop = mCore->mSharedBufferCache.crop;
            outBuffer->mTransform = mCore->mSharedBufferCache.transform &
                    ~static_cast<uint32_t>(
                    NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
            outBuffer->mScalingMode = mCore->mSharedBufferCache.scalingMode;
            outBuffer->mDataSpace = mCore->mSharedBufferCache.dataspace;
            outBuffer->mFrameNumber = mCore->mFrameCounter;
            outBuffer->mSlot = slot;
            outBuffer->mAcquireCalled = mSlots[slot].mAcquireCalled;
            outBuffer->mTransformToDisplayInverse =
                    (mCore->mSharedBufferCache.transform &
                    NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
            outBuffer->mSurfaceDamage = Region::INVALID_REGION;
            outBuffer->mQueuedBuffer = false;
            outBuffer->mIsStale = false;
            outBuffer->mAutoRefresh = mCore->mSharedBufferMode &&
                    mCore->mAutoRefresh;
        } else {
            slot = front->mSlot;
            *outBuffer = *front;
        }

        ATRACE_BUFFER_INDEX(slot);

        BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
                slot, outBuffer->mFrameNumber, outBuffer->mGraphicBuffer->handle);

        if (!outBuffer->mIsStale) {
            mSlots[slot].mAcquireCalled = true;
            // Don't decrease the queue count if the BufferItem wasn't
            // previously in the queue. This happens in shared buffer mode when
            // the queue is empty and the BufferItem is created above.
            if (mCore->mQueue.empty()) {
                mSlots[slot].mBufferState.acquireNotInQueue();
            } else {
                mSlots[slot].mBufferState.acquire();
            }
            mSlots[slot].mFence = Fence::NO_FENCE;
        }

        // If the buffer has previously been acquired by the consumer, set
        // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
        // on the consumer side
        if (outBuffer->mAcquireCalled) {
            outBuffer->mGraphicBuffer = NULL;
        }

        mCore->mQueue.erase(front);

        // We might have freed a slot while dropping old buffers, or the producer
        // may be blocked waiting for the number of buffers in the queue to
        // decrease.
        mCore->mDequeueCondition.broadcast();

        ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
        mCore->mOccupancyTracker.registerOccupancyChange(mCore->mQueue.size());

        VALIDATE_CONSISTENCY();
    }

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

    return NO_ERROR;
}

函数不算长,大部分都是注释和log.
10-17行检查获得的buffer数量是否大于最大数量,如果超出则返回INVALID_OPERATION
18-24行检查如果不是sharedBufferAvailable模式(同步模式)这种情况要从mQueue里面获取buffer,如果mQueue里没有buffer则返回 NO_BUFFER_AVAILABLE
37-103行所处理的情况是如果指定了下一帧预期的时间,并且mQueue中包含一些buffer,则可能要根据预期的时间丢弃一些没有用的帧,我们来分析这部分. 45-86行 判断如果时间不是自动生成的并且包含多个buffer,就要选择性的丢弃一些帧,48行判断maxFrameNumber的作用是防止不要把所有的帧都丢掉.57-66行可以看出,后面要进行丢处理的帧范围必须在预期的时间一秒内.70行判断是一个有效的buffer才被处理,在满足147行的buffer都是无效的buffer,需要被释放,所以这段代码块就是用于释放buffer,代码很简单就不解释了.85-86则换下一个buffer进行处理.跳出while循环的89-99行代码判断如果没有可以处理的帧则返回PRESENT_LATER(因为已经有buffer如队列,却不能处理所以要后面才能处理),返回PRESENT_LATER意味着要关心下一个sf_vsync事件.
函数进入到105行后则说明已经选好了可用的buffer. 
105-124行 是对sharedBuffer模式的处理,把sharedbuffer属性赋值给outBuffer输出.
125-126则是同步模式的赋值
131-139行 通过acquire函数增加槽的计数 并设置mFence=NO_FENCE
142-159行做的是最后的清理工作,并且通知生产者有新的槽可用

到这里最里曾的acquireBuffer就看完了,从这里看返回值就4种,分别是INVALID_OPERATION, NO_BUFFER_AVAILABLE,PRESENT_LATER,NO_ERROR,后面我们会关注返回值的处理.

回到status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,const DispSync& dispSync, bool* autoRefresh, bool* queuedBuffer,uint64_t maxFrameNumber)函数

19-26行 对出出错的返回 将NO_BUFFER_AVAILABLE变成NO_ERROR直接返回.其余的返回上一层函数返回的错误码
29-30行 使用reject判断是否要拒绝这个buffer,到这里我们就可以分析Reject类的实现了

struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
            Layer::State& front;
            Layer::State& current;
            bool& recomputeVisibleRegions;
            bool stickyTransformSet;
            const char* name;
            int32_t overrideScalingMode;
            bool& freezePositionUpdates;

            Reject(Layer::State& front, Layer::State& current,
                    bool& recomputeVisibleRegions, bool stickySet,
                    const char* name,
                    int32_t overrideScalingMode,
                    bool& freezePositionUpdates)
                : front(front), current(current),
                  recomputeVisibleRegions(recomputeVisibleRegions),
                  stickyTransformSet(stickySet),
                  name(name),
                  overrideScalingMode(overrideScalingMode),
                  freezePositionUpdates(freezePositionUpdates) {
            }

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

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

                // check that we received a buffer of the right size
                // (Take the buffer's orientation into account)
                if (item.mTransform & Transform::ROT_90) {
                    swap(bufWidth, bufHeight);
                }

                int actualScalingMode = overrideScalingMode >= 0 ?
                        overrideScalingMode : item.mScalingMode;
                bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
                if (front.active != front.requested) {

                    if (isFixedSize ||
                            (bufWidth == front.requested.w &&
                             bufHeight == front.requested.h))
                    {
                        // Here we pretend the transaction happened by updating the
                        // current and drawing states. Drawing state is only accessed
                        // in this thread, no need to have it locked
                        front.active = front.requested;

                        // We also need to update the current state so that
                        // we don't end-up overwriting the drawing state with
                        // this stale current state during the next transaction
                        //
                        // NOTE: We don't need to hold the transaction lock here
                        // because State::active is only accessed from this thread.
                        current.active = front.active;
                        current.modified = true;

                        // recompute visible region
                        recomputeVisibleRegions = true;
                    }

                    ALOGD_IF(DEBUG_RESIZE,
                            "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
                            "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
                            "            requested={ wh={%4u,%4u} }}\n",
                            name,
                            bufWidth, bufHeight, item.mTransform, item.mScalingMode,
                            front.active.w, front.active.h,
                            front.crop.left,
                            front.crop.top,
                            front.crop.right,
                            front.crop.bottom,
                            front.crop.getWidth(),
                            front.crop.getHeight(),
                            front.requested.w, front.requested.h);
                }

                if (!isFixedSize && !stickyTransformSet) {
                    if (front.active.w != bufWidth ||
                        front.active.h != bufHeight) {
                        // reject this buffer
                        ALOGE("[%s] rejecting buffer: "
                                "bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
                                name, bufWidth, bufHeight, front.active.w, front.active.h);
                        return true;
                    }
                }

                // if the transparent region has changed (this test is
                // conservative, but that's fine, worst case we're doing
                // a bit of extra work), we latch the new one and we
                // trigger a visible-region recompute.
                if (!front.activeTransparentRegion.isTriviallyEqual(
                        front.requestedTransparentRegion)) {
                    front.activeTransparentRegion = front.requestedTransparentRegion;

                    // We also need to update the current state so that
                    // we don't end-up overwriting the drawing state with
                    // this stale current state during the next transaction
                    //
                    // NOTE: We don't need to hold the transaction lock here
                    // because State::active is only accessed from this thread.
                    current.activeTransparentRegion = front.activeTransparentRegion;

                    // recompute visible region
                    recomputeVisibleRegions = true;
                }

                if (front.crop != front.requestedCrop) {
                    front.crop = front.requestedCrop;
                    current.crop = front.requestedCrop;
                    recomputeVisibleRegions = true;
                }
                freezePositionUpdates = false;

                return false;
            }
        };

28-55行更新Layer->mDrawState和Layer->mCurrentState的active状态
57-63行 如果更新后的宽高和buffer不符合,说明这个buffer是一个无效的buffer,拒绝提交
67-76行 如果透明区域发生变化,更新透明区域,设置recomputeVisibleRegions = true 用于告诉Surfaceflinger重新计算可见区域
78-81行 更新裁剪區域
82行 冻结区域的位置已经更新完了 设置成false
所以reject函数只拒绝那些不符合大小的buffer,并且完成一些状态的切换

回到status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync, bool* autoRefresh, bool* queuedBuffer, uint64_t maxFrameNumber)函数

被拒绝的buffer返回BUFFER_REJECTED
40-43行调用updateAndReleaseLocked方法,我们这里之分析hwc1的,后面会有文章总结1和2的区别

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

    int slot = item.mSlot;

    if (!mAttached) {
        GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
                "ES context");
        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
                mEglDisplay, EGL_NO_SYNC_KHR);
        return INVALID_OPERATION;
    }

    // Confirm state.
    err = checkAndUpdateEglStateLocked();
    if (err != NO_ERROR) {
        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
                mEglDisplay, EGL_NO_SYNC_KHR);
        return err;
    }

    // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
    // if nessessary, for the gralloc buffer currently in the slot in
    // ConsumerBase.
    // We may have to do this even when item.mGraphicBuffer == NULL (which
    // means the buffer was previously acquired).
    err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
    if (err != NO_ERROR) {
        GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
                mEglDisplay, slot);
        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
                mEglDisplay, EGL_NO_SYNC_KHR);
        return UNKNOWN_ERROR;
    }

    // Do whatever sync ops we need to do before releasing the old slot.
    if (slot != mCurrentTexture) {
        err = syncForReleaseLocked(mEglDisplay);
        if (err != NO_ERROR) {
            // Release the buffer we just acquired.  It's not safe to
            // release the old buffer, so instead we just drop the new frame.
            // As we are still under lock since acquireBuffer, it is safe to
            // release by slot.
            releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
                    mEglDisplay, EGL_NO_SYNC_KHR);
            return err;
        }
    }

    GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
            mCurrentTexture, mCurrentTextureImage != NULL ?
                    mCurrentTextureImage->graphicBufferHandle() : 0,
            slot, mSlots[slot].mGraphicBuffer->handle);

    // Hang onto the pointer so that it isn't freed in the call to
    // releaseBufferLocked() if we're in shared buffer mode and both buffers are
    // the same.
    sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;

    // release old buffer
    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
        if (pendingRelease == nullptr) {
            status_t status = releaseBufferLocked(
                    mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
                    mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
            if (status < NO_ERROR) {
                GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
                        strerror(-status), status);
                err = status;
                // keep going, with error raised [?]
            }
        } else {
            pendingRelease->currentTexture = mCurrentTexture;
            pendingRelease->graphicBuffer =
                    mCurrentTextureImage->graphicBuffer();
            pendingRelease->display = mEglDisplay;
            pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
            pendingRelease->isPending = true;
        }
    }

    // Update the GLConsumer state.
    mCurrentTexture = slot;
    mCurrentTextureImage = nextTextureImage;
    mCurrentCrop = item.mCrop;
    mCurrentTransform = item.mTransform;
    mCurrentScalingMode = item.mScalingMode;
    mCurrentTimestamp = item.mTimestamp;
    mCurrentFence = item.mFence;
    mCurrentFrameNumber = item.mFrameNumber;

    computeCurrentTransformMatrixLocked();

    return err;
}

5-16行检查gles状态
20 行在对应的槽上创建了一个EGLImageKHR用于纹理拷贝和当作纹理数据(注意这里可能有耗时的操作)就是如果当前槽的EGLImageKHR还没有处理完成要等待GPU渲染完成(eglTerminate(mEglDisplay)函数),这种情况应该出现在不了.因为新的buffer会创建信息的EGLImage,创建失败要releaseBuffer.返回UNKNOWN_ERROR,这里还有些fence的处理我们就不分析了,等到专门分析fence的文章在去分析,最后面绑定如下数据

 mCurrentTexture = slot;
    mCurrentTextureImage = nextTextureImage;
    mCurrentCrop = item.mCrop;
    mCurrentTransform = item.mTransform;
    mCurrentScalingMode = item.mScalingMode;
    mCurrentTimestamp = item.mTimestamp;
    mCurrentFence = item.mFence;
    mCurrentFrameNumber = item.mFrameNumber;
回到status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,const DispSync& dispSync, bool* autoRefresh, bool* queuedBuffer, uint64_t maxFrameNumber)函数

最后一部分对于老的设备,绑定纹理

最后总结下updateTexImage可能返回的错误类型

NVALID_OPERATION,NO_INIT, PRESENT_LATER,NO_ERROR ,NO_ERROR,BUFFER_REJECTED,UNKNOWN_ERROR

到这里就处理完成了updateTexImage函数,我们回到函数Region Layer::latchBuffer(bool& recomputeVisibleRegions)
 if (updateResult == BufferQueue::PRESENT_LATER) {
            // Producer doesn't want buffer to be displayed yet.  Signal a
            // layer update so we check again at the next opportunity.
            mFlinger->signalLayerUpdate();
            return outDirtyRegion;
        } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
            // If the buffer has been rejected, remove it from the shadow queue
            // and return early
            if (queuedBuffer) {
                Mutex::Autolock lock(mQueueItemLock);
                mQueueItems.removeAt(0);
                android_atomic_dec(&mQueuedFrames);
            }
            return outDirtyRegion;
        } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
            // This can occur if something goes wrong when trying to create the
            // EGLImage for this buffer. If this happens, the buffer has already
            // been released, so we need to clean up the queue and bug out
            // early.
            if (queuedBuffer) {
                Mutex::Autolock lock(mQueueItemLock);
                mQueueItems.clear();
                android_atomic_and(0, &mQueuedFrames);
            }

            // Once we have hit this state, the shadow queue may no longer
            // correctly reflect the incoming BufferQueue's contents, so even if
            // updateTexImage starts working, the only safe course of action is
            // to continue to ignore updates.
            mUpdateTexImageFailed = true;

            return outDirtyRegion;
        }

这一段都是对错误的处理,分为三种情况
1updateResult == BufferQueue::PRESENT_LATER 这种情况说明有入队列的buffer但是处理它的时机还没到,所以重新发起sf_vsync请求
2 updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED,buffer的大小不符合,从mQueueItems移除 
  注意前面acquire的时候只是从BufferQueueCore中移除该layer,并没有从Layer的mQueueItems中移除,这里才进行移除,这里注意并没有清理BufferQueueCore中的槽
3 (updateResult != NO_ERROR || mUpdateTexImageFailed) 其他错误也是清楚mQueueItems中的槽,然后设置mUpdateTexImageFailed用于忽略这个layer的下一个更新.
注意上面三步都没有清理BufferQueueCore中的槽

处理完成错误情况接下来往下看

 if (queuedBuffer) {
            // Autolock scope
            auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();

            Mutex::Autolock lock(mQueueItemLock);

            // Remove any stale buffers that have been dropped during
            // updateTexImage
            while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
                mQueueItems.removeAt(0);
                android_atomic_dec(&mQueuedFrames);
            }

            mQueueItems.removeAt(0);
        }

        // Decrement the queued-frames count.  Signal another event if we
        // have more frames pending.
        if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1)
                || mAutoRefresh) {
            mFlinger->signalLayerUpdate();
        }

移除mQueueItems中无用的槽和要绘制的槽,如果最后还有没处理的槽就需要请求下一个sf_vsync处理了

  if (updateResult != NO_ERROR) {
            // something happened!
            recomputeVisibleRegions = true;
            return outDirtyRegion;
        }

        // update the active buffer
        mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
        if (mActiveBuffer == NULL) {
            // this can only happen if the very first buffer was rejected.
            return outDirtyRegion;
        }

        mRefreshPending = true;
        mFrameLatencyNeeded = true;
        if (oldActiveBuffer == NULL) {
             // the first time we receive a buffer, we need to trigger a
             // geometry invalidation.
            recomputeVisibleRegions = true;
         }
  Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
        const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
        const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
        if ((crop != mCurrentCrop) ||
            (transform != mCurrentTransform) ||
            (scalingMode != mCurrentScalingMode))
        {
            mCurrentCrop = crop;
            mCurrentTransform = transform;
            mCurrentScalingMode = scalingMode;
            recomputeVisibleRegions = true;
        }

        if (oldActiveBuffer != NULL) {
            uint32_t bufWidth  = mActiveBuffer->getWidth();
            uint32_t bufHeight = mActiveBuffer->getHeight();
            if (bufWidth != uint32_t(oldActiveBuffer->width) ||
                bufHeight != uint32_t(oldActiveBuffer->height)) {
                recomputeVisibleRegions = true;
            }
        }

        mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
        if (oldOpacity != isOpaque(s)) {
            recomputeVisibleRegions = true;
        }

后面这段也比较简单,就是根据一些状态变化设置recomputeVisibleRegions(包括buffer变换和裁剪数据透明度变化,主要就是从Consumer到layer拿数据, 就不分析了
最后还有段对同步点的处理,主要就是清除可用的帧的同步点

 // Remove any sync points corresponding to the buffer which was just
        // latched
        {
            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;
                }
            }
        }
Region dirtyRegion(Rect(s.active.w, s.active.h));

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

最后返回变换后的dirtyRegion .

回到bool SurfaceFlinger::handlePageFlip()函数的分析
25行 拷贝消费者的surfaceDamageRegion(其实来在BufferItem)到layer中
26行 根据latchBuffer返回的Region更新每个Display的distyRegion

到这里页面翻转也分完成了

最后在onMessageReceived中判断是否有必要重绘数据决定是否要用signalRefresh发出请求

void SurfaceFlinger::onMessageReceived(int32_t what) {
    ATRACE_CALL();
    switch (what) {
        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;
        }
    }

历尽千辛万苦,终于分析完成了INVALIDATE的流程. 下周分析refersh的流程

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值