Android图形系统(十)-SurfaceFlinger启动及

作者: Stan_Z | 来源:发表于2018-11-20 13:52 被阅读203次

    这个系列最后一篇文章,简单总结下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<ProcessState> ps(ProcessState::self());
        ps->startThreadPool();
        //实例化 surfaceflinger
        sp<SurfaceFlinger> flinger =  new SurfaceFlinger();
        setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
        set_sched_policy(0, SP_FOREGROUND);
        //初始化
        flinger->init();
        //发布 surface flinger,注册到 ServiceManager
        sp<IServiceManager> 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<HWComposer::EventHandler *>(this));
        //获取 RenderEngine 引擎
        mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
        //检索创建的 EGL 上下文
        mEGLContext = mRenderEngine->getEGLContext();
        //初始化非虚拟显示屏
        for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
            DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
            //建立已连接的显示设备
            if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
                bool isSecure = true;
                createBuiltinDisplayLocked(type);
                wp<IBinder> token = mBuiltinDisplays[i];
                sp<IGraphicBufferProducer> producer;
                sp<IGraphicBufferConsumer> consumer;
                //创建 BufferQueue 的生产者和消费者
                BufferQueue::createBufferQueue(&producer, &consumer,
                        new GraphicBufferAlloc());
                sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, consumer);
                int32_t hwcId = allocateHwcDisplayId(type);
                //创建显示设备
                sp<DisplayDevice> 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<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                    vsyncPhaseOffsetNs, true, "app");
            mEventThread = new EventThread(vsyncSrc);
            sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                    sfVsyncPhaseOffsetNs, true, "sf");
            mSFEventThread = new EventThread(sfVsyncSrc);
            mEventQueue.setEventThread(mSFEventThread);
        } else {
            //创建 DispSyncSource 对象
            sp<VSyncSource> 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主界面图层合成如下:


    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<SurfaceFlinger>& 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)

    将图像传递到物理屏幕。

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

    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启动及

        本文链接:https://www.haomeiwen.com/subject/mwotqqtx.html