该系列文章总纲链接:Android GUI系统之SurfaceFlinger 系列文章目录
本章关键点总结 & 说明:
本章节思维导图如上。主要讲述了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的关系图和说明如下所示:
说明:这里消费者 是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 对其进行更换。整理下流程,如下所示:
- 请求新的buffer
- 通过rejecter来判断申请的buffer是否满足surfaceflinger的要求。
- 释放之前的buffer