该系列文章总纲链接:Android GUI系统之SurfaceFlinger 系列文章目录


本章关键点总结 & 说明:

Android GUI系统之SurfaceFlinger(09)服务端分析3-handleMessageInvalidate处理_代码实现

本章节思维导图如上。主要讲述了SurfaceFlinger 处理Vsync机制的流程。上一章节是分析到handleMessageTransaction处理方法。该部分主要分析handleMessageInvalidate处理方法。


handleMessageInvalidate

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

继续分析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]);
        //确定这个Layer对象是否有需要更新的图层
        if (layer->hasQueuedFrame()) {
            frameQueued = true;
            if (layer->shouldPresentNow(mPrimaryDispSync)) {
                //把需要更新的Layer对象放到layersWithQueuedFrames中
                layersWithQueuedFrames.push_back(layer.get());
            }
        }
    }
    for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
        Layer* layer = layersWithQueuedFrames[i];
        //更新Layer对象的latchBuffer函数
        const Region dirty(layer->latchBuffer(visibleRegions));
        const Layer::State& s(layer->getDrawingState());
        //设置更新设备对象的更新区域
        invalidateLayerStack(s.layerStack, dirty);
    }

    mVisibleRegionsDirty |= visibleRegions;
    if (frameQueued && layersWithQueuedFrames.empty()) {
        signalLayerUpdate();
    }
    return !layersWithQueuedFrames.empty();
}

layer的hasQueuedFrame()的代码实现如下:

//只要Surface有数据写入,就会调用Layer的onFrameAvailable函数,然后mQueuedFrames值加1
bool hasQueuedFrame() const { return mQueuedFrames > 0 || mSidebandStreamChanged; }

所注意,只要Surface有数据,这里一定返回true。接下来专注分析latchBuffer函数,代码实现如下:

Region Layer::latchBuffer(bool& recomputeVisibleRegions)
{
    if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
        // mSidebandStreamChanged was true
        mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
        recomputeVisibleRegions = true;
        const State& s(getDrawingState());
        return s.transform.transform(Region(Rect(s.active.w, s.active.h)));
    }

    Region outDirtyRegion;
    if (mQueuedFrames > 0) {/mQueuedFrames>0说明有Surface更新的需求
        if (mRefreshPending) {
            return outDirtyRegion;
        }

        // Capture the old state of the layer for comparisons later
        const State& s(getDrawingState());
        const bool oldOpacity = isOpaque(s);
        sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
        
        struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
            //定义Reject结构体...
        };

        Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                getProducerStickyTransform() != 0);

        //更新纹理,得到需要的图像
        status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
                mFlinger->mPrimaryDispSync);
        //如果结果是推迟处理,发送Invalidate消息  
        if (updateResult == BufferQueue::PRESENT_LATER) {
            mFlinger->signalLayerUpdate();
            return outDirtyRegion;
        }

        { // Autolock scope
            Mutex::Autolock lock(mQueueItemLock);
            mQueueItems.removeAt(0);
        }

        //减少mQueuedFrames的值
        if (android_atomic_dec(&mQueuedFrames) > 1) {
            //如果还有更多frame需要处理,要发消息  
            mFlinger->signalLayerUpdate();
        }

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

        //更新mActiveBuffer,得到现在需要输出的图像数据
        mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
        if (mActiveBuffer == NULL) {
            return outDirtyRegion;//出错
        }

        mRefreshPending = true;
        mFrameLatencyNeeded = true;
        //下面根据各种情况是否重新计算更新区域
        if (oldActiveBuffer == NULL) {
            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;
        }

        Region dirtyRegion(Rect(s.active.w, s.active.h));
        outDirtyRegion = (s.transform.transform(dirtyRegion));
    }
    return outDirtyRegion;
}

latchBuffer函数调用updateTextImage来得到需要的图像。这里参数r是Reject对象,其作用是判断在缓冲区的尺寸是否符合要求。这里updateTextImage的代码实现如下:

status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
        const DispSync& dispSync)
{
    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;
    }

    BufferQueue::BufferItem item;
    err = acquireBufferLocked(&item, computeExpectedPresent(dispSync));
    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;
    }

    int buf = item.mBuf;
    if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR);
        return NO_ERROR;
    }

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

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

    return err;
}

这里先分析 Buffer的 acquireBufferLocked 和 updateAndReleaseLocked,之后分析bindTextureImageLocked的关键点。

1 acquireBufferLocked

acquireBufferLocked代码实现如下:

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

这里会继续调用GLConsumer的acquireBufferLocked,代码如下:

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

    if (item->mGraphicBuffer != NULL) {
        int slot = item->mBuf;
        mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
    }

    return NO_ERROR;
}

继续分析ConsumerBase的acquireBufferLocked,代码如下:

status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item,
        nsecs_t presentWhen) {
    status_t err = mConsumer->acquireBuffer(item, presentWhen);
    if (err != NO_ERROR) {
        return err;
    }

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

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

    return OK;
}

继续分析mConsumer的acquireBuffer,mConsumer是 BufferQueueConsumer类型的对象,即调用了BufferQueue的Acquire操作。

2 updateAndReleaseLocked

updateAndReleaseLocked的代码实现如下:

status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item)
{
    status_t err = NO_ERROR;
    int buf = item.mBuf;
    if (!mAttached) {
        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
                mEglDisplay, EGL_NO_SYNC_KHR);
        return INVALID_OPERATION;
    }

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

    err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
    if (err != NO_ERROR) {
        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
                mEglDisplay, EGL_NO_SYNC_KHR);
        return UNKNOWN_ERROR;
    }

    // Do whatever sync ops we need to do before releasing the old slot.
    err = syncForReleaseLocked(mEglDisplay);
    if (err != NO_ERROR) {
        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
                mEglDisplay, EGL_NO_SYNC_KHR);
        return err;
    }
    // release old buffer
    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
        status_t status = releaseBufferLocked(
                mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
                mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
        if (status < NO_ERROR) {
            err = status;
        }
    }

    // Update the GLConsumer state.
    mCurrentTexture = buf;
    mCurrentTextureImage = mEglSlots[buf].mEglImage;
    mCurrentCrop = item.mCrop;
    mCurrentTransform = item.mTransform;
    mCurrentScalingMode = item.mScalingMode;
    mCurrentTimestamp = item.mTimestamp;
    mCurrentFence = item.mFence;
    mCurrentFrameNumber = item.mFrameNumber;

    computeCurrentTransformMatrixLocked();

    return err;
}

这里专注分析releaseBufferLocked的实现,代码如下:

status_t GLConsumer::releaseBufferLocked(int buf,
        sp<GraphicBuffer> graphicBuffer,
        EGLDisplay display, EGLSyncKHR eglFence) {
    // release the buffer if it hasn't already been discarded by the
    // BufferQueue. This can happen, for example, when the producer of this
    // buffer has reallocated the original buffer slot after this buffer
    // was acquired.
    status_t err = ConsumerBase::releaseBufferLocked(
            buf, graphicBuffer, display, eglFence);
    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
    return err;
}

继续分析ConsumerBase的releaseBufferLocked,代码实现如下:

status_t ConsumerBase::releaseBufferLocked(
        int slot, const sp<GraphicBuffer> graphicBuffer,
        EGLDisplay display, EGLSyncKHR eglFence) {
    if (!stillTracking(slot, graphicBuffer)) {
        return OK;
    }

    status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
            display, eglFence, mSlots[slot].mFence);
    if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
        freeBufferLocked(slot);
    }

    mSlots[slot].mFence = Fence::NO_FENCE;

    return err;
}

这里依然是继续调用了mConsumer的releaseBufferLocked,mConsumer是 BufferQueueConsumer类型的对象,即调用了BufferQueue的Release操作。

3 BufferQueque简介

这里2.1 2.2最终都是调用了 BufferQueue的Acquire操作 和 Release操作,因此这里也对BufferQueue的操作做个简单的说明和总结,生产者 消费者 与Queue的关系图和说明如下所示:

Android GUI系统之SurfaceFlinger(09)服务端分析3-handleMessageInvalidate处理_代码实现_02

说明:这里消费者 是SurfaceFlinger,生产者是APP。同时申请内存只能是消费者来做。

4  bindTextureImageLocked分析

这里继续专注分析bindTextureImageLocked(似乎和opengl相关),代码实现如下:

status_t GLConsumer::bindTextureImageLocked() {
    if (mEglDisplay == EGL_NO_DISPLAY) {
        return INVALID_OPERATION;
    }

    GLint error;
    while ((error = glGetError()) != GL_NO_ERROR) {
        ST_LOGW("bindTextureImage: clearing GL error: %#04x", error);
    }

    glBindTexture(mTexTarget, mTexName);
    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
            mCurrentTextureImage == NULL) {
        return NO_INIT;
    }

    status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
                                                        mCurrentCrop);
    if (err != NO_ERROR) {
        return UNKNOWN_ERROR;
    }
    mCurrentTextureImage->bindToTextureTarget(mTexTarget);
    if ((error = glGetError()) != GL_NO_ERROR) {
        glBindTexture(mTexTarget, mTexName);
        status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
                                                            mCurrentCrop,
                                                            true);
        if (err != NO_ERROR) {
            return UNKNOWN_ERROR;
        }
        mCurrentTextureImage->bindToTextureTarget(mTexTarget);
        if ((error = glGetError()) != GL_NO_ERROR) {
            return UNKNOWN_ERROR;
        }
    }

    // Wait for the new buffer to be ready.
    return doGLFenceWaitLocked();
}

这里继续专注分析bindToTextureTarget(和opengl相关),代码实现如下:

void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
    glEGLImageTargetTexture2DOES(texTarget, (GLeglImageOES)mEglImage);
}

这里实际上就是 EGL相关的操作,最后我们回到updateTextImage函数,调用updateTextImage函数如果得到的结果是PRESENT_LATER,表示推迟处理,然后调用signalLayerUpdate函数来发送invalidate消息,这次绘制过程就不处理这个Surface的图像了。最后LatchBuffer函数调用mSurfaceFlingerConsumer的getCurrentBuffer来取回当前的图像缓冲区指针,保存在mActiveBuffer中。

总结下:该部分代码主要是处理各个Layer的Buffer更换,实际上就是使原来的界面无效,使用新的Buffer 对其进行更换。整理下流程,如下所示:

  1. 请求新的buffer
  2. 通过rejecter来判断申请的buffer是否满足surfaceflinger的要求。
  3. 释放之前的buffer