android surfaceflinger 代码,Android P 图形显示系统(七) SurfaceFlinger合...

SurfaceFlinger合成流程(二)

SurfaceFlinger合成流程

MessageQueue中分发两个消息,一个INVALIDATE,一个REFRESH,SurfaceFlinger对这两个消息的响应过程,就是合成的过程。

消息INVALIDATE处理

在onFrameAvailable时,调用signalLayerUpdate,将触发INVALIDATE消息。SurfaceFlinger收到这个消息的处理如下:

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

ATRACE_INT("FrameMissed", static_cast(frameMissed));

if (mPropagateBackpressure && frameMissed) {

signalLayerUpdate();

break;

}

updateVrFlinger();

bool refreshNeeded = handleMessageTransaction();

refreshNeeded |= handleMessageInvalidate();

refreshNeeded |= mRepaintEverything;

if (refreshNeeded) {

signalRefresh();

}

break;

}

case MessageQueue::REFRESH: {

handleMessageRefresh();

break;

}

}

}

在INVALIDATE过程中,主要做以下处理:

对丢帧的处理

如果丢帧,且mPropagateBackpressure为true,mPropagateBackpressure表示显示给压力了。显示说,太慢了,都丢帧了,给点压力,上层赶紧处理。mPropagateBackpressure是在SurfaceFlinger的构造函数中初始化的,受debug.sf.disable_backpressure属性的控制。

property_get("debug.sf.disable_backpressure", value, "0");

mPropagateBackpressure = !atoi(value);

更新VR updateVrFlinger

这个只有在VR模式下才会起作用,我们这里先不管VR的事。

处理Transition

Transition的处理,前面我们已经说过,只是当时不清楚是什么时候触发的,现在清楚了。Vsync到来后,触发INVALIDATE消息时先去处理Transition。处理的过程就是前面已经说过的handleMessageTransaction,有需要可以回头去看看。这个过程就是处理应用传过来的各种Transition,需要记住的是在commit Transition时,又个状态的更替,mCurrentState赋值给了mDrawingState。

void SurfaceFlinger::commitTransaction()

{

... ...

mDrawingState = mCurrentState;

mDrawingState.traverseInZOrder([](Layer* layer) {

layer->commitChildList();

});

... ...

}

所以SurfaceFlinger两个状态:

mCurrentState状态, 准备数据,应用传过来的数据保存在mCurrentState中。

mDrawingState状态,进程合成状态,需要进行合成的数据保存在mDrawingState中。

也就是说,每次合成时,先更新一下状态数据。每一层Layer也需要去更新状态数据。

处理Invalidate

这是一个重要的流程,handleMessageInvalidate函数如下:

bool SurfaceFlinger::handleMessageInvalidate() {

ATRACE_CALL();

return handlePageFlip();

}

主要是调用handlePageFlip,做Page的Flip。

bool SurfaceFlinger::handlePageFlip()

{

ALOGV("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 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 && (mLayersWithQueuedFrames.empty() || !newDataLatched)) {

signalLayerUpdate();

}

// Only continue with the refresh if there is actually new work to do

return !mLayersWithQueuedFrames.empty() && newDataLatched;

}

mLayersWithQueuedFrames,用于标记那些已经有Frame的Layer,这得从Layer的onFrameAvailable说起。

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

// Reset the frame number tracker when we receive the first buffer after

// a frame number reset

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

if (result != NO_ERROR) {

ALOGE("[%s] Timed out waiting on callback", mName.string());

}

}

mQueueItems.push_back(item);

android_atomic_inc(&mQueuedFrames);

// Wake up any pending callbacks

mLastFrameNumberReceived = item.mFrameNumber;

mQueueItemCondition.broadcast();

}

mFlinger->signalLayerUpdate();

}

onFrameAvailable时,先将Buffer的窗口属性保存在mInterceptor中,这里我们暂时不看,记得标记一下。然后对FrameNumber进行处理,一是确保FrameNumber被重置时,重置mLastFrameNumberReceived,二时,确保FrameNumber的顺序。之后,将新过来的BufferItem,push到mQueueItems中,对mQueuedFrames数进行+1。最后才触发SurfaceFlinger进行signalLayerUpdate。

回到handlePageFlip。所以,对于触发SurfaceFlinger进行signalLayerUpdate的Layer,hasQueuedFrame为true,是有Queued的Frame的。

但是mLayersWithQueuedFrames还要一个条件,shouldPresentNow。

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

ALOGW_IF(!isPlausible,

"[%s] Timestamp %" PRId64 " seems implausible "

"relative to expectedPresent %" PRId64,

mName.string(), timestamp, expectedPresent);

bool isDue = timestamp < expectedPresent;

return isDue || !isPlausible;

}

在shouldPresentNow的判断逻辑中,首先根据DispSync,去计算期望显示的时间。再看看Buffer的时间戳和期望显示的时间,如果Buffer的时间还没有到,且和期望显示的时间之间差不到1秒,那么shouldPresentNow成立。该Layer标记为mLayersWithQueuedFrames;否则,Layer使用空的DamageRegion。记住这个DamageRegion。

void BufferLayer::useEmptyDamage() {

surfaceDamageRegion.clear();

}

继续handlePageFlip函数分析。

对mLayersWithQueuedFrames标记的Layer进行处理

首先,通过latchBuffer获取Layer的Buffer;再更新Surface的Damage;再通过invalidateLayerStack去刷新脏区域,验证LayerStack。记住LayerStack这个概念。处理这块稍后继续~~~

注意这里重新signalLayerUpdate的逻辑。

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

signalLayerUpdate();

}

有BufferQueue过来,但是还没有到显示时间(mLayersWithQueuedFrames为空),或者没有获取到Buffer。重新触发一次更新~

注意handlePageFlip的返回值,有Layer要显示,且获取到Buffer时,才返回true。注意这里的mVisibleRegionsDirty,mVisibleRegionsDirty,脏区域,表示可见区域有更新。

handlePageFlip获取Buffer

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值