前景提要:
当HWComposer接收到Vsync信号时,唤醒DisSync线程,在其中唤醒EventThread线程,调用DisplayEventReceiver的sendObjects像BitTub发送消息,由于在SurfaceFlinger的init过程中创建了EventThread线程,并添加到MQ中进行创建Connection并监听对应的BitTube信息,因此最后会在MQ中接收到通知调用Handler的发送消息到SF的主线程中,SF的handlerMessage方法去处理该消息并执行对应的绘制流程。
回调每个图层onPreComposition方法
第一步preComposition中,获取到所有参与绘制的layer图层信息,并回调onPreComposition方法,观察是否有图层发生变化(通过方法返回值判断)
【通过判断MQueuedFrames是否大于0,代表图层发生变化,在onFrameAvailable中会对这个字段+1】
SurfaceFlinger可以控制某些Layer不参与绘制过程,比如需要将悬浮按钮图层隐藏。
如果有则向MQ中发送invalidata消息,SurfaceFliger的MQ接收到之后会调用 handleMessageTransaction()方法和handleMessageInvalidate() 方法,根据是否刷新调用signalRefresh方法。
代码部分:
void SurfaceFlinger::preComposition()
{
bool needExtraInvalidate = false;
const LayerVector& layers(mDrawingState.layersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; i
if (layers[i]->onPreComposition()) {
needExtraInvalidate = true;
}
}
//当存在图层有变化,则发送invalidate消息
if (needExtraInvalidate) {
signalLayerUpdate();
}
}
//图层是否发生变化是通过mQueuedFrames字段确定
bool Layer::onPreComposition() {
mRefreshPending = false;
return mQueuedFrames > 0 || mSidebandStreamChanged;
}
当Layer可见时会调用onFrameAvailable方法,对mQueuedFrames+1
代码部分:
void Layer::onFrameAvailable(const BufferItem& item) {
{ // Autolock scope
Mutex::Autolock lock(mQueueItemLock);
if (item.mFrameNumber == 1) {
mLastFrameNumberReceived = 0;
}
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
ms2ns(500));
}
mQueueItems.push_back(item);
android_atomic_inc(&mQueuedFrames); //加1操作
//唤醒所有pending的回调方法
mLastFrameNumberReceived = item.mFrameNumber;
mQueueItemCondition.broadcast();
}
//和上面一样的操作通知flinger图层发生更新
mFlinger->signalLayerUpdate();
}
比较上次Layer的状态(宽高)和此次Layer的状态(宽高)判断Layer尺寸是否发生变化,当尺寸发生变化时调整Surface的缓冲区大小,并调用Layer的invalidate重新计算可见区域大小,并接着同步当前Layer状态,接着再更新光标情况
获取所有的layer,将更新的图层放入到layerWithQueuedFrames中,接着取出调用各个图层的latchBuffer处理。
获取每个显示屏中的所有可见图层列表,计算每个图层的可见区域,根据Z轴的深度把所有图层添加进来
重建所有显示屏的各个可见Layer,并重新根据Z轴调整Layer图层的顺序
后续分析
将Layer添加到HWComposer中
HWComposer更新frameBuffer缓冲区(通过转换后的屏幕坐标判断是局部区域更新还是整个屏幕都需要更新),Display从缓冲区中取出数据进行显示
原文链接:SurfaceFliger绘制流程 - 掘金 (juejin.cn)