Android图形系统(十)-SurfaceFlinger启动及图层合成送显过程

这个系列最后一篇文章,简单总结下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 线程、启动开机动画等等。

在这里,有几个比较重要的对象需要介绍下:

  1. EGL:OpenGL是一个操作GPU的API,它通过驱动向GPU发送相关指令,控制图形渲染管线状态机的运行状态。但OpenGL需要本地视窗系统进行交互,这就需要一个中间控制层,最好与平台无关。EGL正是这个中间控制层,它作为OpenGL ES和本地窗口的桥梁,主要作用是:其主要作用是为OpenGL指令创建 Context 、绘制目标Surface 、配置Framebuffer属性、Swap提交绘制结果等。

  2. HWComposer: 硬件组合抽象层,介于SurfaceFlinger和HAL之间,具体到代码级别就是一个类,封装对于Hwcomposer HAL和Gralloc HAL的使用。 主要作用是:一方面处理部分SurfaceFlinger委托过来的合成工作,另一方面就是产生vsync信号

  3. EventThread: 它是Surfaceflinger中的一个线程 ,主要作用:接收VSync事件通知,并分发VSync通知给系统中的每一个感兴趣的注册者。

二、SurfaceFlinger图层合成过程

2.1 什么是图层合成

图层合成就是把多个图层按既定的显示区域,展现到显示屏上。

例如Android手机的Launcher主界面图层合成如下:


Android图形系统(十)-SurfaceFlinger启动及图层合成送显过程_第1张图片

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)

将图像传递到物理屏幕。

最后借用一张流程图做最后的总结:

Android图形系统(十)-SurfaceFlinger启动及图层合成送显过程_第2张图片
from Jeanboydev

参考:
https://blog.csdn.net/jxt1234and2010/article/details/46057267
https://blog.csdn.net/freekiteyu/article/details/79483406
https://blog.csdn.net/u012878643/article/details/71104467

你可能感兴趣的:(Android图形系统(十)-SurfaceFlinger启动及图层合成送显过程)