这个系列最后一篇文章,简单总结下SurfaceFlinger的启动流程及合成视图过程。
一、SurfaceFlinger启动流程
SurfaceFlinger 进程是由 init 进程创建的,运行在独立进程中。
//init.rc
service surfaceflinger /system/bin/surfaceflinger
class core
user system
group graphics drmrpc
onrestart restart zygote
writepid /dev/cpuset/system-background/tasks
SurfaceFlinger 的创建会执行 main() 方法:
//main_surfaceflinger.cpp
int main(int, char**) {
ProcessState::self()->setThreadPoolMaxThreadCount(4);
sp ps(ProcessState::self());
ps->startThreadPool();
//实例化 surfaceflinger
sp flinger = new SurfaceFlinger();
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
set_sched_policy(0, SP_FOREGROUND);
//初始化
flinger->init();
//发布 surface flinger,注册到 ServiceManager
sp sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
// 运行在当前线程
flinger->run();
return 0;
}
事实上到这里,SurfaceFlinger进程就已经启动了。之后我们再来了解下SurfaceFlinger的一些初始化操作:
首先SurfaceFlinger 的实例化会执行到:onFirstRef()
//SurfaceFlinger.cpp
void SurfaceFlinger::onFirstRef() {
mEventQueue.init(this); //初始化MessageQueue , mEventQueue.init中又会创建Looper与Handler。
}
然后会执行到 SurfaceFlinger::init():
//SurfaceFlinger.cpp
void SurfaceFlinger::init() {
Mutex::Autolock _l(mStateLock);
//初始化 EGL,作为默认的显示
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(mEGLDisplay, NULL, NULL);
// 初始化硬件 composer 对象
mHwc = new HWComposer(this, *static_cast(this));
//获取 RenderEngine 引擎
mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
//检索创建的 EGL 上下文
mEGLContext = mRenderEngine->getEGLContext();
//初始化非虚拟显示屏
for (size_t i=0 ; iisConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
bool isSecure = true;
createBuiltinDisplayLocked(type);
wp token = mBuiltinDisplays[i];
sp producer;
sp consumer;
//创建 BufferQueue 的生产者和消费者
BufferQueue::createBufferQueue(&producer, &consumer,
new GraphicBufferAlloc());
sp fbs = new FramebufferSurface(*mHwc, i, consumer);
int32_t hwcId = allocateHwcDisplayId(type);
//创建显示设备
sp hw = new DisplayDevice(this,
type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
fbs, producer,
mRenderEngine->getEGLConfig());
if (i > DisplayDevice::DISPLAY_PRIMARY) {
hw->setPowerMode(HWC_POWER_MODE_NORMAL);
}
mDisplays.add(token, hw);
}
}
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
//当应用和 sf 的 vsync 偏移量一致时,则只创建一个 EventThread 线程
if (vsyncPhaseOffsetNs != sfVsyncPhaseOffsetNs) {
sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc);
sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);
} else {
//创建 DispSyncSource 对象
sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "sf-app");
//创建线程 EventThread
mEventThread = new EventThread(vsyncSrc);
//设置 EventThread
mEventQueue.setEventThread(mEventThread);
}
//创建 EventControl
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
//当不存在 HWComposer 时,则设置软件 vsync
if (mHwc->initCheck() != NO_ERROR) {
mPrimaryDispSync.setPeriod(16666667);
}
//初始化绘图状态
mDrawingState = mCurrentState;
//初始化显示设备
initializeDisplays();
//启动开机动画
startBootAnim();
}
该方法主要是执行一些初始化工作,包括:EGL标准下OpenGL环境的创建、创建 HWComposer、初始化非虚拟显示屏、启动 EventThread 线程、启动开机动画等等。
在这里,有几个比较重要的对象需要介绍下:
EGL:OpenGL是一个操作GPU的API,它通过驱动向GPU发送相关指令,控制图形渲染管线状态机的运行状态。但OpenGL需要本地视窗系统进行交互,这就需要一个中间控制层,最好与平台无关。EGL正是这个中间控制层,它作为OpenGL ES和本地窗口的桥梁,主要作用是:其主要作用是为OpenGL指令创建 Context 、绘制目标Surface 、配置Framebuffer属性、Swap提交绘制结果等。
HWComposer: 硬件组合抽象层,介于SurfaceFlinger和HAL之间,具体到代码级别就是一个类,封装对于Hwcomposer HAL和Gralloc HAL的使用。 主要作用是:一方面处理部分SurfaceFlinger委托过来的合成工作,另一方面就是产生vsync信号
EventThread: 它是Surfaceflinger中的一个线程 ,主要作用:接收VSync事件通知,并分发VSync通知给系统中的每一个感兴趣的注册者。
二、SurfaceFlinger图层合成过程
2.1 什么是图层合成
图层合成就是把多个图层按既定的显示区域,展现到显示屏上。
例如Android手机的Launcher主界面图层合成如下:
adb shell dumpsys SurfaceFlinger
com.android.systemui.ImageWallpaper
com.miui.home/com.miui.home.launcher.Launcher
StatusBar
2.2 SurfaceFlinger合成消息
SurfaceFlinger合成图层依赖于Android的异步消息处理机制。
首先,它包含了一个MessageQueue对象(消息队列)用于处理各种异步消息,在onFirstRef()中对消息队列进行了初始化:
//SurfaceFlinger.cpp
SurfaceFlinger::onFirstRef()
{
mEventQueue.init(this);
}
分析一下MessageQueue的实现:
//MessageQueue.cpp
void MessageQueue::init(const sp& flinger)
{
mFlinger = flinger;//保存MessageQueue的拥有者SurfaceFlinger
mLooper = new Looper(true);//创建Looper对象
mHandler = new Handler(*this);//创建Handler对象
}
调用Handler::handleMessage()处理INVALIDATE和REFRESH消息,并将其转发给SurfaceFlinger进行处理,调用onMessageReceived():
void MessageQueue::Handler::handleMessage(const Message& message) {
switch (message.what) {
case INVALIDATE:
android_atomic_and(~eventMaskInvalidate, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case REFRESH:
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
}
}
接下来看一下SurfaceFlinger对消息的处理:
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;
}
}
}
SurfaceFlinger处理的消息分为两种:
INVALIDATE消息:用于处理Layer或者display属性的变化以及Layer对应buffer的更新。
1) Layer或者Display属性的更新通过调用handleMessageTransaction()处理;
2) buffer的更新通过调用handleMessageInvalidate()处理。
REFRESH消息:表示SurfaceFlinger需要进行一次合成操作(Refresh),通过handleMessageRefresh()实现;主要有三种情况:
1) Layer属性的变化导致window state发生变化;
2) Layer有新的buffer到来;
3) HWC请求进行一次repaint。
如果这三种情况之一发生,则置refreshNeeded为true,调用signalRefresh()发出MessageQueue::REFRESH消息;
当VSync信号来之前,Layer或者display属性的变化会做本地保存,只有当VSync信号到来时,SurfaceFlinger才会通过INVALIDATE和REFRESH消息来做统一的合并渲染和输出的处理工作。
2.3 handleMessageTransaction()
处理之前对屏幕和应用程序窗口的改动。因这些改动很有可能会改变图层的可见区域,进而影响脏区域的计算。
主要处理以下几个方面的transaction:
1)Layer属性的变化;
2)Layer的增加和减少;
3)Display属性的变化;
4)Display的增加和减少;
2.4 handleMessageInvalidate()
主要调用handlePageFlip()函数。这里Page Flip是指从BufferQueue中取下一个图形缓冲区内容,就好像是“翻页”一样。该函数主要是从各Layer对应的BufferQueue中拿图形缓冲区数据,并根据内容更新脏区域(注:脏区域是需要重绘的屏幕区域。)。并且把GraphicBuffer映射为OpenGL的texture 。
2.5 handleMessageRefresh()
合并和渲染输出。
void SurfaceFlinger::handleMessageRefresh() {
...
preComposition(); //合成前的准备
rebuildLayerStacks();//重建layer堆栈
setUpHWComposer();//hwcomposer的设定
doComposition();//正式的合成处理
postComposition(refreshStartTime);//合成后期的处理
...
}
2.5.1 void SurfaceFlinger::preComposition()
合成前准备工作。首先得到当前所有layer的集合,然后对所有的Layer调用其onPreComposition()检查是否需要ExtralInvalidate,如果需要就调用一次signalLayerUpdate(),即通过EventThread安排一次vsync。
2.5.2 void SurfaceFlinger::rebuildLayerStacks()
计算可见layer及它们的可见区域。首先每个layer都有一个layerStack来区别它属于哪个Display,系统的Display可能不止一个,所以需要逐个处理Display,根据所有layers的当前状态通过SurfaceFlinger::computeVisibleRegions方法计算各个Layer在当前display上的可见区域和脏区域等。最后把需要绘制的layer添加到layersSortedByZ中。
2.5.3 void SurfaceFlinger::setUpHWComposer()
为合成搭建环境。这个HWComposer并不是真正的Hal模块,而是surfaceflinger为管理HWComposer模块而设计的一个类,路径是:frameworks/native/service/surfaceflinger/displayhardware/。依次处理各个Display,构造WorkList,合成过程既可以有Hwc模块完成,也可以通过OpengGlEs来完成,具体用哪种方式是有prepare()中的compositionType来决定的。
2.5.4 void SurfaceFlinger::doComposition()
执行合成操作。执行openGl合成 or HWC合成。
2.5.5 void SurfaceFlinger::postComposition(refreshStartTime)
将图像传递到物理屏幕。
最后借用一张流程图做最后的总结:
参考:
https://blog.csdn.net/jxt1234and2010/article/details/46057267
https://blog.csdn.net/freekiteyu/article/details/79483406
https://blog.csdn.net/u012878643/article/details/71104467