美文网首页
Android图形渲染原理上

Android图形渲染原理上

作者: 子者不语 | 来源:发表于2020-09-13 15:45 被阅读0次

    对于Android开发者来说,我们或多或少有了解过Android图像显示的知识点,刚刚学习Android开发的人会知道,在Actvity的onCreate方法中设置我们的View后,再经过onMeasure,onLayout,onDraw的流程,界面就显示出来了;对Android比较熟悉的开发者会知道,onDraw流程分为软件绘制和硬件绘制两种模式,软绘是通过调用Skia来操作,硬绘是通过调用Opengl ES来操作;对Android非常熟悉的开发者会知道绘制出来的图形数据最终都通过GraphiBuffer内共享内存传递给SurfaceFlinger去做图层混合,图层混合完成后将图形数据送到帧缓冲区,于是,图形就在我们的屏幕显示出来了。

    但我们所知道的Activity或者是应用App界面的显示,只属于Android图形显示的一部分。同样可以在Android系统上展示图像的WebView,Flutter,或者是通过Unity开发的3D游戏,他们的界面又是如何被绘制和显现出来的呢?他们和我们所熟悉的Acitvity的界面显示又有什么异同点呢?我们可以不借助Activity的setView或者InflateView机制来实现在屏幕上显示出我们想要的界面吗?Android系统显示界面的方式又和IOS,或者Windows等系统有什么区别呢?……

    去探究这些问题,比仅仅知道Acitvity的界面是如何显示出来更加的有价值,因为想要回答这些问题,就需要我们真正的掌握Android图像显示的底层原理,当我们掌握了底层的显示原理后,我们会发现WebView,Flutter或者未来会出现的各种新的图形显示技术,原来都是大同小异。

    我会花三篇文章的篇幅,去深入的讲解Android图形显示的原理,OpenGL ES和Skia的绘制图像的方式,他们如何使用,以及他们在Android中的使用场景,如开机动画,Activity界面的软件绘制和硬件绘制,以及Flutter的界面绘制。那么,我们开始对Android图像显示原理的探索吧。

    屏幕图像显示原理

    在讲解Android图像的显示之前,我会先讲一下屏幕图像的显示原理,毕竟我们图像,最终都是在手机屏幕上显示出来的,了解这一块的知识会让我们更容易的理解Android在图像显示上的机制。

    图像显示的完整过程,分为下面几个阶段:

    图像数据→CPU→显卡驱动→显卡(GPU)→显存(帧缓冲)→显示器

    我详细介绍一下这几个阶段:

    1. CPU→显卡驱动:CPU通过软件绘制将绘制好的内容,或者直接将绘制指令(硬件加速),提交给显卡驱动 。

    2. 显卡驱动→GPU:显卡驱动是硬件厂商编写的,能将接收到的渲染命令翻译成GPU能够理解的语言,所以显卡驱动是Opengl或者DirectX等图形编程接口的具体实现。我们可以将它理解成其他模块和显卡沟通的入口。

    3. GPU→帧缓冲:显卡对数据进行顶点处理,剪裁,光栅化等操作流程,再经过图层混合后将最终的数据提交到显存。

    4. 显存→显示器:如果显卡是VGA接口类型,则需要将数字信号转换为模型信号后才能送到显示屏,如果是HDMI或者DVI类型的接口,则可以直接将数字信号送到显示器。

    实际上显卡驱动,显卡和显存,包括数模转换模块都是属于显卡的模块。但为了能能详细的讲解经历的步骤,这里做了拆分。

    当显存中有数据后,显示器又是怎么根据显存里面的数据来进行界面的显示的呢?这里以LCD液晶屏为例,显卡会将显存里的数据,按照从左至右,从上到下的顺序同步到屏幕上的每一个像素晶体管,一个像素晶体管就代表了一个像素。


    如果我们的屏幕分辨率是1080x1920像素,就表示有1080x1920个像素像素晶体管,每个橡素点的颜色越丰富,描述这个像素的数据就越大,比如单色,每个像素只需要1bit,16色时,只需要4bit,256色时,就需要一个字节。那么1080x1920的分辨率的屏幕下,如果要以256色显示,显卡至少需要1080x1920个字节,也就是2M的大小。

    刚刚说了,屏幕上的像素数据是从左到右,从上到下进行同步的,当这个过程完成了,就表示一帧绘制完成了,于是会开始下一帧的绘制,大部分的显示屏都是以60HZ的频率在屏幕上绘制完一帧,也就是16ms,并且每次绘制新的一帧时,都会发出一个垂直同步信号(VSync)。我们已经知道,图像数据都是放在帧缓冲中的,如果帧缓冲的缓冲区只有一个,那么屏幕在绘制这一帧的时候,图像数据便没法放入帧缓冲中了,只能等待这一帧绘制完成,在这种情况下,会有很大了效率问题。所以为了解决这一问题,帧缓冲引入两个缓冲区,即双缓冲机制。双缓冲虽然能解决效率问题,但会引入一个新的问题。当屏幕这一帧还没绘制完成时,即屏幕内容刚显示一半时,GPU 将新的一帧内容提交到帧缓冲区并把两个缓冲区进行交换后,显卡的像素同步模块就会把新的一帧数据的下半段显示到屏幕上,造成画面撕裂现象。

    为了解决撕裂问题,就需要在收到垂直同步的时候才将帧缓冲中的两个缓冲区进行交换。Android4.1黄油计划中有一个优化点,就是CPU和GPU都只有收到垂直同步的信号时,才会开始进行图像的绘制操作,以及缓冲区的交换工作。

    Android图像显示原理

    我们已经了解了屏幕图像显示的原理了,那么接着开始对Android图像显示的学习。

    从上一章已经知道,计算机渲染界面必须要有GPU和帧缓冲。对于Linux系统来说,用户进程是没法直接操作帧缓冲的,但我们想要显示图像就必须要操作帧缓冲,所以Linux系统设计了一个虚拟设备文件,来作为对帧缓冲的映射,通过对该文件的I/O读写,我们就可以实现读写屏操作。帧缓冲对应的设备文件于/dev/fb* ,*表示对多个显示设备的支持, 设备号从0到31,如/dev/fb0就表示第一块显示屏,/dev/fb1就表示第二块显示屏。对于Android系统来说,默认使用/dev/fb0这一个设帧缓冲作为主屏幕,也就是我们的手机屏幕。我们Android手机屏幕上显示的图像数据,都是存储在/dev/fb0里,早期AndroidStuio中的DDMS工具实现截屏的原理就是直接读取/dev/fb0设备文件。

    我们知道了手机屏幕上的图形数据都存储在帧缓冲中,所以Android手机图像界面的原理就是将我们的图像数据写入到帧缓冲内。那么,写入到帧缓冲的图像数据是怎么生成的,又是怎样加工的呢?图形数据是怎样送到帧缓冲去的,中间经历了哪些步骤和过程呢?了解了这几个问题,我们就了解了Android图形渲染的原理,那么带着这几个疑问,接着往下看。

    想要知道图像数据是怎么产生的,我们需要知道图像生产者有哪些,他们分别是如何生成图像的,想要知道图像数据是怎么被消费的,我们需要知道图像消费者有哪些,他们又分别是如何消费图像的,想要知道中间经历的步骤和过程,我们需要知道图像缓冲区有哪些,他们是如何被创建,如何分配存储空间,又是如何将数据从生产者传递到消费者的,图像显示是一个很经典的消费者生产者的模型,只有对这个模型各个模块的击破,了解他们之间的流动关系,我们才能找到一条更容易的路径去掌握Android图形显示原理。我们看看谷歌提供的官方的架构图是怎样描述这一模型的模块及关系的。

    如图,图像的生产者主要有MediaPlayer,CameraPrevier,NDK,OpenGl ES。MediaPlayer和Camera Previer是通过直接读取图像源来生成图像数据,NDK(Skia),OpenGL ES是通过自身的绘制能力生产的图像数据;图像的消费者有SurfaceFlinger,OpenGL ES Apps,以及HAL中的Hardware Composer。OpenGl ES既可以是图像的生产者,也可以是图像的消费者,所以它也放在了图像消费模块中;图像缓冲区主要有Surface以及前面提到帧缓冲。

    Android图像显示的原理,会仅仅围绕图像的生产者图像的消费者图像缓冲区来展开,在这一篇文章中,我们先看看Android系统中的图像消费者。

    图像消费者

    SurfaceFlinger

    SurfaceFlinger是Android系统中最重要的一个图像消费者,Activity绘制的界面图像,都会传递到SurfaceFlinger来,SurfaceFlinger的作用主要是接收图像缓冲区数据,然后交给HWComposer或者OpenGL做合成,合成完成后,SurfaceFlinger会把最终的数据提交给帧缓冲。

    那么SurfaceFlinger是如何接收图像缓冲区的数据的呢?我们需要先了解一下Layer(层)的概念,一个Layer包含了一个Surface,一个Surface对应了一块图形缓冲区,而一个界面是由多个Surface组成的,所以他们会一一对应到SurfaceFlinger的Layer中。SurfaceFlinger通过读取Layer中的缓冲数据,就相当于读取界面上Surface的图像数据。Layer本质上是Surface和SurfaceControl的组合,Surface是图形生产者和图像消费之间传递数据的缓冲区,SurfaceControl是Surface的控制类。

    前面在屏幕图像显示原理中讲到,为了防止图像的撕裂,Android系统会在收到VSync垂直同步时才会开始处理图像的绘制和合成工作,而Surfaceflinger作为一个图像的消费者,同样也是遵守这一规则,所以我们通过源码来看看SurfaceFlinger是如何在这一规则下,消费图像数据的。

    接收VSync信号

    SurfaceFlinger专门创建了一个EventThread线程用来接收VSync。EventThread通过Socket将VSync信号同步到EventQueue中,而EventQueue又通过回调的方式,将VSync信号同步到SurfaceFlinger内。我们看一下源码实现。

    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    void SurfaceFlinger::init() {
        { 
            //……
           
            sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                    vsyncPhaseOffsetNs, true, "app");
            //创建App的VSYNC信号接收线程
            mEventThread = new EventThread(vsyncSrc, *this, false);
            sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                    sfVsyncPhaseOffsetNs, true, "sf");
             //创建SurfaceFlinger的VSYNC信号接收线程
            mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
            mEventQueue.setEventThread(mSFEventThread);
            //……
        }
        //……
    }
    
    //文件-->/frameworks/native/services/surfaceflinger/MessageQueue.cpp
    void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
    {
        mEventThread = eventThread;
        //创建连接
        mEvents = eventThread->createEventConnection();
        //获取EventThread的通信接口
        mEvents->stealReceiveChannel(&mEventTube);
        //监听EventThread,有数据则调用cb_eventReceiver
        mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
                MessageQueue::cb_eventReceiver, this);
    }
    
    //文件-->/frameworks/native/services/surfaceflinger/EventThread.cpp
    sp<EventThread::Connection> EventThread::createEventConnection() const {
        return new Connection(const_cast<EventThread*>(this));
    }
    
    
    EventThread::Connection::Connection(const sp<EventThread>& eventThread)
        : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) //创建BitTube通信信道
    {
    }
    
    void EventThread::Connection::onFirstRef() {
        // NOTE: mEventThread doesn't hold a strong reference on us
        mEventThread->registerDisplayEventConnection(this);
    }
    
    
    status_t EventThread::registerDisplayEventConnection(
            const sp<EventThread::Connection>& connection) {
        //将Connection添加到mDisplayEventConnections中
        mDisplayEventConnections.add(connection);
        return NO_ERROR;
    }
    

    上面主要是SurfaceFlinger初始化接收VSYNC垂直同步信号的操作,主要有这几个过程:

    1. init函数中,创建了EventThread线程来专门接收VSYNC垂直同步的信号,并调用setEventThread函数将EventThread添加到EventQueue中。
    2. setEventThread函数中,创建EventThread的连接,并将EventThread线程中通信的套接字通过addFd添加到MessageQueue的Looper中,这样MessageQueue就能接收EventThrea的数据了。
    3. EventThread执行Connection函数,函数的构造方法会创建BitTube,BitTube实际是一个socket,所以EventThread和MessageQueue是通过socket通信,我们可以看看BitTube的实现源码。
    //文件-->/frameworks/native/libs/gui/BitTube.cpp
    BitTube::BitTube(size_t bufsize) {
        // 创建socket pair,用于发送事件
        init(bufsize, bufsize);
    }
    void BitTube::init(size_t rcvbuf, size_t sndbuf) {
        int sockets[2];
        if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
            size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
            // 设置socket buffer
            setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
            setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
            // since we don't use the "return channel", we keep it small...
            setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
            setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
            fcntl(sockets[0], F_SETFL, O_NONBLOCK);
            fcntl(sockets[1], F_SETFL, O_NONBLOCK);
            // socket[0]用于接收端,最终通过Binder IPC返回给客户端应用
            mReceiveFd.reset(sockets[0]);
            // socket[1]用于发送端
            mSendFd.reset(sockets[1]);
        } else {
            mReceiveFd.reset();
            ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
        }
    }
    
    1. Connection方法中const_cast智能指针会调用onFirstRef函数,将当前的connection添加到mDisplayEventConnections中,mDisplayEventConnections又是什么?它其实一个专门用来保存接收VSYNC的Connection的容器,除了我们的SurfaceFlinger用来接收VSYNC的EventThread,还会有其他EventThread来接收VSync,如客户端的EventThread,也都是保存在mDisplayEventConnections中。

    经过上面几个步骤,我们接收VSync的初始化工作都准备好了,EventThread也开始运转了,接着看一下EventThread的运转函数threadLoop做的事情。

    //文件-->/frameworks/native/services/surfaceflinger/EventThread.cpp
    bool EventThread::threadLoop() {
        DisplayEventReceiver::Event event;
        Vector< sp<EventThread::Connection> > signalConnections;
        signalConnections = waitForEvent(&event);
    
        // 将事件分发给想要接收VSync的Connction
        const size_t count = signalConnections.size();
        for (size_t i=0 ; i<count ; i++) {
            const sp<Connection>& conn(signalConnections[i]);
            status_t err = conn->postEvent(event);
            if (err == -EAGAIN || err == -EWOULDBLOCK) {          
                ALOGW("EventThread: dropping event (%08x) for connection %p",
                        event.header.type, conn.get());
            } else if (err < 0) {
                removeDisplayEventConnection(signalConnections[i]);
            }
        }
        return true;
    }
    
    Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
            DisplayEventReceiver::Event* event)
    {
        Mutex::Autolock _l(mLock);
        Vector< sp<EventThread::Connection> > signalConnections;
    
        do {
            //……
            // 查找等待接收事件的connection
            size_t count = mDisplayEventConnections.size();
            for (size_t i=0 ; i<count ; i++) {
                sp<Connection> connection(mDisplayEventConnections[i].promote());
                if (connection != NULL) {
                    bool added = false;
                    //connection的数量要大于0
                    if (connection->count >= 0) {                 
                        waitForVSync = true;
                        if (timestamp) {                      
                            if (connection->count == 0) {
                                connection->count = -1;
                                signalConnections.add(connection);
                                added = true;
                            } else if (connection->count == 1 ||
                                    (vsyncCount % connection->count) == 0) {
                                signalConnections.add(connection);
                                added = true;
                            }
                        }
                    }
    
                    if (eventPending && !timestamp && !added) {                  
                        signalConnections.add(connection);
                    }
                } else {            
                    mDisplayEventConnections.removeAt(i);
                    --i; --count;
                }
            }
    
            //……
            
            if (!timestamp && !eventPending) {
                if (waitForVSync) {
                    
                    bool softwareSync = mUseSoftwareVSync;
                    nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
                    //接收VSync信号
                    if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
                        if (!softwareSync) {
                            ALOGW("Timed out waiting for hw vsync; faking it");
                        }
                        //接收软件产生的VSync
                        mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
                        mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
                        mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
                        mVSyncEvent[0].vsync.count++;
                    }
                } else {
                    //无接收VSync的connection,则进入休眠
                    mCondition.wait(mLock);
                }
            }
        } while (signalConnections.isEmpty());
        return signalConnections;
    }
    

    threadLoop主要是两件事情

    1. 通过mCondition.waitRelative来接收VSync

    2. 将VSync分发给所有的Connection

    mConditon又是怎么接收VSync的呢?我们来看一下

    //文件-->/frameworks/native/services/surfaceflinger/EventThread.cpp
    void EventThread::onVSyncEvent(nsecs_t timestamp) {
        Mutex::Autolock _l(mLock);
        mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
        mVSyncEvent[0].header.id = 0;
        mVSyncEvent[0].header.timestamp = timestamp;
        mVSyncEvent[0].vsync.count++;
        mCondition.broadcast();
    }
    
    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp/DispSyncSource
    virtual void onDispSyncEvent(nsecs_t when) {
        sp<VSyncSource::Callback> callback;
        {
            Mutex::Autolock lock(mCallbackMutex);
            callback = mCallback;
    
            if (mTraceVsync) {
                mValue = (mValue + 1) % 2;
                ATRACE_INT(mVsyncEventLabel.string(), mValue);
            }
        }
    
        if (callback != NULL) {
            //回调onVSyncEvent
            callback->onVSyncEvent(when);
        }
    }
    
    
    

    可以看到,mCondition的VSync信号实际是DispSyncSource通过onVSyncEvent回调传入的,但是DispSyncSource的VSync又是怎么接收的呢?在上面讲到的SurfaceFlinger的init函数,在创建EventThread的实现中,我们可以发现答案——mPrimaryDispSync

    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                    sfVsyncPhaseOffsetNs, true, "sf");
    //创建SurfaceFlinger的VSYNC信号接收线程
    mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
    mEventQueue.setEventThread(mSFEventThread);
    

    DispSyncSource的构造方法传入了mPrimaryDispSync,mPrimaryDispSync实际是一个DispSyncThread线程,我们看看这个线程的threadLoop方法

    //文件-->/frameworks/native/services/surfaceflinger/DispSync.cpp
    virtual bool threadLoop() {
        status_t err;
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        while (true) {
            Vector<CallbackInvocation> callbackInvocations;
            nsecs_t targetTime = 0;
    
            { 
                //……
                //判断是否阻塞
                if (mPeriod == 0) {
                    err = mCond.wait(mMutex);
                    if (err != NO_ERROR) {
                        ALOGE("error waiting for new events: %s (%d)",
                              strerror(-err), err);
                        return false;
                    }
                    continue;
                }
                targetTime = computeNextEventTimeLocked(now);
    
                bool isWakeup = false;
    
                if (now < targetTime) {
                    if (kTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
    
                    if (targetTime == INT64_MAX) {
                        ALOGV("[%s] Waiting forever", mName);
                        err = mCond.wait(mMutex);
                    } else {
                        ALOGV("[%s] Waiting until %" PRId64, mName,
                              ns2us(targetTime));
                        err = mCond.waitRelative(mMutex, targetTime - now);
                    }
    
                    if (err == TIMED_OUT) {
                        isWakeup = true;
                    } else if (err != NO_ERROR) {
                        ALOGE("error waiting for next event: %s (%d)",
                              strerror(-err), err);
                        return false;
                    }
                }
    
                now = systemTime(SYSTEM_TIME_MONOTONIC);
    
                // Don't correct by more than 1.5 ms
                static const nsecs_t kMaxWakeupLatency = us2ns(1500);
    
                if (isWakeup) {
                    mWakeupLatency = ((mWakeupLatency * 63) +
                                      (now - targetTime)) / 64;
                    mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
                    if (kTraceDetailedInfo) {
                        ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
                        ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
                    }
                }
    
                callbackInvocations = gatherCallbackInvocationsLocked(now);
            }
    
            if (callbackInvocations.size() > 0) {
                //回调VSync给DispSyncSource
                fireCallbackInvocations(callbackInvocations);
            }
        }
    
        return false;
    }
    
    void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
        if (kTraceDetailedInfo) ATRACE_CALL();
        for (size_t i = 0; i < callbacks.size(); i++) {
            callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
        }
    }
    

    DispSyncThread的threadLoop会通过mPeriod来判断是否进行阻塞或者进行VSync回调,那么mPeriod又是哪儿被设置的呢?这里又回到SurfaceFlinger了,我们可以发现在SurfaceFlinger的resyncToHardwareVsync函数中有对mPeriod的赋值。

    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
        Mutex::Autolock _l(mHWVsyncLock);
    
        if (makeAvailable) {
            mHWVsyncAvailable = true;
        } else if (!mHWVsyncAvailable) {
            // Hardware vsync is not currently available, so abort the resync
            // attempt for now
            return;
        }
    
        const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
        const nsecs_t period = activeConfig->getVsyncPeriod();
    
        mPrimaryDispSync.reset();
        //设置DispSyncThread的period
        mPrimaryDispSync.setPeriod(period);
        //……
    }
    

    可以看到,这里最终通过HWComposer,也就是硬件层拿到了period。终于追踪到了VSync的最终来源了,它从HWCompser产生,回调至DispSync线程,然后DispSync线程回调到DispSyncSource,DispSyncSource又回调到EventThread,EventThread再通过Socket分发到MessageQueue中

    我们已经知道了VSync信号来自于HWCompser,但SurfaceFlinger并不会一直监听VSync信号,监听VSync的线程大部分时间都是休眠状态,只有需要做合成工作时,才会监听VSync,这样即保证图像合成的操作能和VSync保持一致,也节省了性能。SurfaceFlinger提供了一些主动注册监听VSync的操作函数。

    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    void SurfaceFlinger::signalTransaction() {
        mEventQueue.invalidate();
    }
    
    void SurfaceFlinger::signalLayerUpdate() {
        mEventQueue.invalidate();
    }
    
    void MessageQueue::invalidate() {
        mEvents->requestNextVsync();
    }
    
    void EventThread::requestNextVsync(
            const sp<EventThread::Connection>& connection) {
        Mutex::Autolock _l(mLock);
    
        mFlinger.resyncWithRateLimit();
    
        if (connection->count < 0) {
            connection->count = 0;
            mCondition.broadcast();
        }
    }
    
    void SurfaceFlinger::resyncWithRateLimit() {
        static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
    
        static nsecs_t sLastResyncAttempted = 0;
        const nsecs_t now = systemTime();
        if (now - sLastResyncAttempted > kIgnoreDelay) {
            //注册VSync
            resyncToHardwareVsync(false);
        }
        sLastResyncAttempted = now;
    }
    

    可以看到,只有当SurfaceFlinger调用signalTransaction或者signalLayerUpdate函数时,才会注册监听VSync信号。那么signalTransaction或者signalLayerUpdate什么时候被调用呢?它可以由图像的生产者通知调用,也可以由SurfaceFlinger根据自己的逻辑来判断是否调用。

    现在假设App层已经生成了我们界面的图像数据,并调用了signalTransaction通知SurfaceFlinger注册监听VSync,于是VSync信号便会传递到了MessageQueue中了,我们接着看看MessageQueue又是怎么处理VSync的吧。

    //文件-->/frameworks/native/services/surfaceflinger/MessageQueue.cpp
    int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
        ssize_t n;
        DisplayEventReceiver::Event buffer[8];
        while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
            for (int i=0 ; i<n ; i++) {
                if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                    mHandler->dispatchInvalidate();
                    break;
                }
            }
        }
        return 1;
    }
    
    void MessageQueue::Handler::dispatchInvalidate() {
        if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
            mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
        }
    }
    
    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;
        }
    }
    

    MessageQueue收到VSync信号后,最终回调到了SurfaceFlinger的onMessageReceived中,当SurfaceFlinger接收到VSync后,便开始以一个图像消费者的角色来处理图像数据了。我们接着看SurfaceFlinger是以什么样的方式消费图像数据的。

    处理VSync信号

    VSync信号最终被SurfaceFlinger的onMessageReceived函数中的INVALIDATE模块处理。

    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    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<int>(frameMissed));
                if (mPropagateBackpressure && frameMissed) {
                    ALOGD("Backpressure trigger, skipping transaction & refresh!");
                    //如果掉帧则请求下一次VSync,跳过这一次请求
                    signalLayerUpdate();
                    break;
                }
    
                //更新VR模式的Flinger
                updateVrFlinger();
    
                bool refreshNeeded = handleMessageTransaction();
                refreshNeeded |= handleMessageInvalidate();
                refreshNeeded |= mRepaintEverything;
                if (refreshNeeded) {
                    //判断是否要做刷新
                    signalRefresh();
                }
                break;
            }
            case MessageQueue::REFRESH: {
                handleMessageRefresh();
                break;
            }
        }
    }
    

    INVALIDATE的流程如下:

    1. 判断是否掉帧,如果掉帧则执行signalLayerUpdate函数,这个函数在上面提到过,它的作用是请求下一个VSync信号,然后跳过这一次的处理

    2. 更新VR模式的Flinger

    3. 通过handleMessageTransaction函数来判断是否要处理这一次的Vsync,我们看一下handleMessageTransaction是如何判断的

    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    bool SurfaceFlinger::handleMessageTransaction() {
        uint32_t transactionFlags = peekTransactionFlags();
        if (transactionFlags) {
            handleTransaction(transactionFlags);
            return true;
        }
        return false;
    }
    
    void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
    {
        //……
        transactionFlags = getTransactionFlags(eTransactionMask);
        handleTransactionLocked(transactionFlags);
        //……
    }
    
    void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
    {
        // 通知所有的Layer可以做合成了
        mCurrentState.traverseInZOrder([](Layer* layer) {
            layer->notifyAvailableFrames();
        });
    
        //遍历每一个Layer的doTransaction方法,处理可视区域
        if (transactionFlags & eTraversalNeeded) {
            mCurrentState.traverseInZOrder([&](Layer* layer) {
                uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
                if (!trFlags) return;
    
                const uint32_t flags = layer->doTransaction(0);
                if (flags & Layer::eVisibleRegion)
                    mVisibleRegionsDirty = true;
            });
        }
    
        //处理每个显示设备(屏幕)的变化
        if (transactionFlags & eDisplayTransactionNeeded) {
            const KeyedVector<  wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
            const KeyedVector<  wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
            if (!curr.isIdenticalTo(draw)) {
                mVisibleRegionsDirty = true;
                const size_t cc = curr.size();
                      size_t dc = draw.size();
    
                // 寻找被移除的屏幕以及处理发了改变的屏幕
                for (size_t i=0 ; i<dc ; i++) {
                    const ssize_t j = curr.indexOfKey(draw.keyAt(i));
                    if (j < 0) {
                        // 如果curr找不到这个显示设备,表示已经移除,会执行断开连接的操作
                        if (!draw[i].isMainDisplay()) {
                            // Call makeCurrent() on the primary display so we can
                            // be sure that nothing associated with this display
                            // is current.
                            const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
                            defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
                            sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
                            if (hw != NULL)
                                hw->disconnect(getHwComposer());
                            if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
                                mEventThread->onHotplugReceived(draw[i].type, false);
                            mDisplays.removeItem(draw.keyAt(i));
                        } else {
                            ALOGW("trying to remove the main display");
                        }
                    } else {
                        // 判断设备显示是否发生改变
                        const DisplayDeviceState& state(curr[j]);
                        const wp<IBinder>& display(curr.keyAt(j));
                        const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
                        const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
                        if (state_binder != draw_binder) {
                            // 如果state_binder和draw_binder不一致,表示Surface可能销毁了,这里会做移除处理
                            sp<DisplayDevice> hw(getDisplayDeviceLocked(display));
                            if (hw != NULL)
                                hw->disconnect(getHwComposer());
                            mDisplays.removeItem(display);
                            mDrawingState.displays.removeItemsAt(i);
                            dc--; i--;
                            continue;
                        }
    
                        const sp<DisplayDevice> disp(getDisplayDeviceLocked(display));
                        if (disp != NULL) {
                            if (state.layerStack != draw[i].layerStack) {
                                disp->setLayerStack(state.layerStack);
                            }
                            if ((state.orientation != draw[i].orientation)
                                    || (state.viewport != draw[i].viewport)
                                    || (state.frame != draw[i].frame))
                            {
                                disp->setProjection(state.orientation,
                                        state.viewport, state.frame);
                            }
                            if (state.width != draw[i].width || state.height != draw[i].height) {
                                disp->setDisplaySize(state.width, state.height);
                            }
                        }
                    }
                }
    
                // 寻找增加的显示设备
                for (size_t i=0 ; i<cc ; i++) {
                    if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                        const DisplayDeviceState& state(curr[i]);
    
                        sp<DisplaySurface> dispSurface;
                        sp<IGraphicBufferProducer> producer;
                        sp<IGraphicBufferProducer> bqProducer;
                        sp<IGraphicBufferConsumer> bqConsumer;
                        BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
    
                        int32_t hwcId = -1;
                        if (state.isVirtualDisplay()) {                
                            if (state.surface != NULL) {
                                // VR设备的处理
                                //……                        
                                sp<VirtualDisplaySurface> vds =
                                        new VirtualDisplaySurface(*mHwc,
                                                hwcId, state.surface, bqProducer,
                                                bqConsumer, state.displayName);
    
                                dispSurface = vds;
                                producer = vds;
                            }
                        } else {                     
                            hwcId = state.type;
                            dispSurface = new FramebufferSurface(*mHwc, hwcId, bqConsumer);
                            producer = bqProducer;
                        }
    
                        const wp<IBinder>& display(curr.keyAt(i));
                        if (dispSurface != NULL) {
                            sp<DisplayDevice> hw =
                                    new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
                                                      dispSurface, producer,
                                                      mRenderEngine->getEGLConfig(),
                                                      hasWideColorDisplay);
                            hw->setLayerStack(state.layerStack);
                            hw->setProjection(state.orientation,
                                    state.viewport, state.frame);
                            hw->setDisplayName(state.displayName);
                            mDisplays.add(display, hw);
                            if (!state.isVirtualDisplay()) {
                                mEventThread->onHotplugReceived(state.type, true);
                            }
                        }
                    }
                }
            }
        }
    
        //设置Layer的TransformHint,主要是设备方向
        if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
            sp<const DisplayDevice> disp;
            uint32_t currentlayerStack = 0;
            bool first = true;
            mCurrentState.traverseInZOrder([&](Layer* layer) {
                uint32_t layerStack = layer->getLayerStack();
                if (first || currentlayerStack != layerStack) {
                    currentlayerStack = layerStack;               
                    disp.clear();
                    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                        sp<const DisplayDevice> hw(mDisplays[dpy]);
                        if (hw->getLayerStack() == currentlayerStack) {
                            if (disp == NULL) {
                                disp = hw;
                            } else {
                                disp = NULL;
                                break;
                            }
                        }
                    }
                }
                if (disp == NULL) {              
                    disp = getDefaultDisplayDeviceLocked();
                }
                layer->updateTransformHint(disp);
    
                first = false;
            });
        }
    
        //有新的Layer增加,标记为脏区
        if (mLayersAdded) {
            mLayersAdded = false;
            // Layers have been added.
            mVisibleRegionsDirty = true;
        }
    
        //有Layer移除,重新检查可视区域,更新LayerStack
        if (mLayersRemoved) {
            mLayersRemoved = false;
            mVisibleRegionsDirty = true;
            mDrawingState.traverseInZOrder([&](Layer* layer) {
                if (mLayersPendingRemoval.indexOf(layer) >= 0) {
                    // this layer is not visible anymore
                    // TODO: we could traverse the tree from front to back and
                    //       compute the actual visible region
                    // TODO: we could cache the transformed region
                    Region visibleReg;
                    visibleReg.set(layer->computeScreenBounds());
                    invalidateLayerStack(layer->getLayerStack(), visibleReg);
                }
            });
        }
    
        commitTransaction();
    
        updateCursorAsync();
    }
    
    

    handleMessageTransaction的处理比较长,处理的事情也比较多,它主要做的事情有这些

    • 遍历Layer执行doTransaction,处理可视区 ,它的实现如下
    //文件-->/frameworks/native/services/surfaceflinger/Layer.cpp
    uint32_t Layer::doTransaction(uint32_t flags) {
        pushPendingState();
        Layer::State c = getCurrentState();
        if (!applyPendingStates(&c)) {
            return 0;
        }
    
        const Layer::State& s(getDrawingState());
    
        const bool sizeChanged = (c.requested.w != s.requested.w) ||
                                 (c.requested.h != s.requested.h);
    
        if (sizeChanged) {
            // 尺寸发生改变,重新调整图像缓冲区的大小
            mSurfaceFlingerConsumer->setDefaultBufferSize(
                    c.requested.w, c.requested.h);
        }
    
        //……
        if (!(flags & eDontUpdateGeometryState)) {
            Layer::State& editCurrentState(getCurrentState());
            if (mFreezeGeometryUpdates) {
                float tx = c.active.transform.tx();
                float ty = c.active.transform.ty();
                c.active = c.requested;
                c.active.transform.set(tx, ty);
                editCurrentState.active = c.active;
            } else {
                editCurrentState.active = editCurrentState.requested;
                c.active = c.requested;
            }
        }
    
        if (s.active != c.active) {
            // 重新计算可见区域
            flags |= Layer::eVisibleRegion;
        }
    
        if (c.sequence != s.sequence) {
            // 重新计算可见区域
            flags |= eVisibleRegion;
            this->contentDirty = true;
    
            // we may use linear filtering, if the matrix scales us
            const uint8_t type = c.active.transform.getType();
            mNeedsFiltering = (!c.active.transform.preserveRects() ||
                    (type >= Transform::SCALE));
        }
        //……
        commitTransaction(c);
        return flags;
    }
    
    • 检查屏幕的变化

    • 设置Layer的TransformHint

    • 检查Layer的变化

    • 提交transaction

    1. 继续回到INVALIDATE的处理函数,它做的最后一件事情就是执行signalRefresh函数,signalRefresh最终会调用SurfaceFlinger的handleMessageRefresh()函数。
    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    void SurfaceFlinger::signalRefresh() {
        mEventQueue.refresh();
    }
    
    void SurfaceFlinger::onMessageReceived(int32_t what) {
        ATRACE_CALL();
        switch (what) {
            case MessageQueue::INVALIDATE: {
                //……
            }
            case MessageQueue::REFRESH: {
                handleMessageRefresh();
                break;
            }
        }
    }
    
    void SurfaceFlinger::handleMessageRefresh() {
        ATRACE_CALL();
    
        nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
    
        preComposition(refreshStartTime);
        //合成前预处理
        rebuildLayerStacks();
        //创建HWC硬件合成的任务列表
        setUpHWComposer();
        //调试模式的帧率显示
        doDebugFlashRegions();
        //图层混合
        doComposition();
        //合成完毕后的处理工作
        postComposition(refreshStartTime);
    
        mPreviousPresentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
    
        mHadClientComposition = false;
        for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
            const sp<DisplayDevice>& displayDevice = mDisplays[displayId];
            mHadClientComposition = mHadClientComposition ||
                    mHwc->hasClientComposition(displayDevice->getHwcDisplayId());
        }
    
        mLayersWithQueuedFrames.clear();
    }
    

    handleMessageRefresh函数,便是SurfaceFlinger真正处理图层合成的地方,它主要下面五个步骤。

    1. preCompostion:合成前预处理

    2. rebuildLayerStacks:重新构建Layer栈

    3. setUpHWCompser:构建硬件合成的任务列表

    4. doCompostion:图层混合

    5. postCompsition:合成完毕后的处理工作

    我会详细介绍每一个步骤的具体操作

    合成前预处理

    合成前预处理会判断Layer是否发生变化,当Layer中有新的待处理的Buffer帧(mQueuedFrames>0),或者mSidebandStreamChanged发生了变化, 都表示Layer发生了变化,如果变化了,就调用signalLayerUpdate,注册下一次的VSync信号。如果Layer没有发生变化,便只会做这一次的合成工作,不会注册下一次VSync了。

    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
    {
        bool needExtraInvalidate = false;
        mDrawingState.traverseInZOrder([&](Layer* layer) {
            if (layer->onPreComposition(refreshStartTime)) {
                needExtraInvalidate = true;
            }
        });
    
        if (needExtraInvalidate) {
            signalLayerUpdate();
        }
    }
    
    bool Layer::onPreComposition() {
        mRefreshPending = false;
        return mQueuedFrames > 0 || mSidebandStreamChanged;
    }
    

    重建Layer栈

    重建Layer栈会遍历Layer,计算和存储每个Layer的脏区, 然后和当前的显示设备进行比较,看Layer的脏区域是否在显示设备的显示区域内,如果在显示区域内的话说明该layer是需要绘制的,则更新到显示设备的VisibleLayersSortedByZ列表中,等待被合成

    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    void SurfaceFlinger::rebuildLayerStacks() {
        // mVisibleRegionsDirty表示Visible相关的显示区域是否发生变化,如果发生变化则需要重新构造LayerStack
        if (CC_UNLIKELY(mVisibleRegionsDirty)) {
            ATRACE_CALL();
            mVisibleRegionsDirty = false;
            invalidateHwcGeometry();
            //遍历所有显示设备,计算显示设备中dirtyRegion(变化区域)和opaqueRegion(半透明区域)
            for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                Region opaqueRegion;
                Region dirtyRegion;
                Vector<sp<Layer>> layersSortedByZ;
                const sp<DisplayDevice>& displayDevice(mDisplays[dpy]);
                const Transform& tr(displayDevice->getTransform());
                const Rect bounds(displayDevice->getBounds());
                if (displayDevice->isDisplayOn()) {
                    //计算Layer的变化区域和非透明区域
                    computeVisibleRegions(
                            displayDevice->getLayerStack(), dirtyRegion,
                            opaqueRegion);
                    //以Z轴顺序遍历Layer,计算是否需要被合成
                    mDrawingState.traverseInZOrder([&](Layer* layer) {
                        if (layer->getLayerStack() == displayDevice->getLayerStack()) {
                            Region drawRegion(tr.transform(
                                    layer->visibleNonTransparentRegion));
                            drawRegion.andSelf(bounds);
                            if (!drawRegion.isEmpty()) {
                                layersSortedByZ.add(layer);
                            } else {
                                // Clear out the HWC layer if this layer was
                                // previously visible, but no longer is
                                layer->setHwcLayer(displayDevice->getHwcDisplayId(),
                                        nullptr);
                            }
                        } else {
                            // WM changes displayDevice->layerStack upon sleep/awake.
                            // Here we make sure we delete the HWC layers even if
                            // WM changed their layer stack.
                            layer->setHwcLayer(displayDevice->getHwcDisplayId(),
                                    nullptr);
                        }
                    });
                }
                displayDevice->setVisibleLayersSortedByZ(layersSortedByZ);
                displayDevice->undefinedRegion.set(bounds);
                displayDevice->undefinedRegion.subtractSelf(
                        tr.transform(opaqueRegion));
                displayDevice->dirtyRegion.orSelf(dirtyRegion);
            }
        }
    }
    

    rebuildLayerStacks中最重要的一步是computeVisibleRegions,也就是对Layer的变化区域和非透明区域的计算,为什么要对变化区域做计算呢?我们先看看SurfaceFlinger对界面显示区域的分类:

    • opaqueRegion:非透明区域,表示界面上不完全透明的区域
    • visibleRegion:可见区域,表示完全不透明的区域,被不完全透明区域遮挡的区域依然是完全透明区域
    • coveredRegion: 被遮盖区域,被完全不透明的区域覆盖的区域
    • transparentRegion: 完全透明的区域,一般从合成列表中移除,因为完全透明的Layer没必要做任何合成操作
    • aboveOpaqueLayers : 当前Layer上层所有Layer不透明区域的累加
    • aboveCoveredLayers : 当前Layer上层所有Layer可见区域的累加

    还是以这张图做例子,可以看到我们的状态栏是半透明的,所以它是一个opaqueRegion区域,微信界面和虚拟按键是完全不透明的,他是一个visibleRegion,除了这三个Layer外,还有一个我们看不到的Layer——壁纸,它被上方visibleRegion遮挡了,所以是coveredRegion


    对这几个区域的概念清楚了,我们就可以去了解computeVisibleRegions中做的事情了,它主要是这几步操作:

    1. 从Layer Z轴最上层开始遍历该显示设备中所有的Layer
    2. 计算该Layer的被覆盖区域,aboveCoveredLayers和当前Layer除去非透明区域部分的交集
    3. 将当前Layer除去非透明区域部分添加到aboveCoveredLayers中,为下一层Layer计算提供条件
    4. 计算当前Layer的可见区域 , 即当前Layer除去非透明区域部分减掉aboveOpaqueLayers
    5. 计算脏区域,脏区域需要减去被遮盖的部分,并将当前Layer的脏区域累加到当前显示设备的脏区域outDirtyRegion
    6. 保存计算的Region到Layer中

    我们看一下这个函数具体的代码实现

    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack,
            Region& outDirtyRegion, Region& outOpaqueRegion)
    {
        ATRACE_CALL();
        ALOGV("computeVisibleRegions");
    
        Region aboveOpaqueLayers;
        Region aboveCoveredLayers;
        Region dirty;
    
        outDirtyRegion.clear();
    
        //按照Z轴顺序遍历Layer
        mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
    
            //非透明区域
            Region opaqueRegion;
            //可见区域
            Region visibleRegion;
            //被遮盖区域
            Region coveredRegion;
            //完全透明区域
            Region transparentRegion;
    
            if (CC_LIKELY(layer->isVisible())) {
                const bool translucent = !layer->isOpaque(s);
                Rect bounds(layer->computeScreenBounds());
                visibleRegion.set(bounds);
                Transform tr = layer->getTransform();
                if (!visibleRegion.isEmpty()) {
                    // 从可见区域中移除完全透明区域
                    if (translucent) {
                        if (tr.preserveRects()) {                     
                            transparentRegion = tr.transform(s.activeTransparentRegion);
                        } else {                       
                            transparentRegion.clear();
                        }
                    }
    
                    // 计算非透明区域
                    const int32_t layerOrientation = tr.getOrientation();
                    if (s.alpha == 1.0f && !translucent &&
                            ((layerOrientation & Transform::ROT_INVALID) == false)) {
                        // the opaque region is the layer's footprint
                        opaqueRegion = visibleRegion;
                    }
                }
            }
    
            // 做覆盖区域和可见区域的交集
            coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
    
            // 累加当前Layer和上层Layer的可见区域
            aboveCoveredLayers.orSelf(visibleRegion);
    
            // 从可见区域中减去非透明区域
            visibleRegion.subtractSelf(aboveOpaqueLayers);
    
            // 计算脏区
            if (layer->contentDirty) {          
                dirty = visibleRegion;
                dirty.orSelf(layer->visibleRegion);
                layer->contentDirty = false;
            } else {
                //计算暴露区域对策变化
                const Region newExposed = visibleRegion - coveredRegion;
                const Region oldVisibleRegion = layer->visibleRegion;
                const Region oldCoveredRegion = layer->coveredRegion;
                const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
                dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
            }
            //在脏区中减去被覆盖的区域
            dirty.subtractSelf(aboveOpaqueLayers);
    
            // 累加脏区
            outDirtyRegion.orSelf(dirty);
    
            //添加非透明区域
            aboveOpaqueLayers.orSelf(opaqueRegion);
    
            // 存储可见区域
            layer->setVisibleRegion(visibleRegion);
            layer->setCoveredRegion(coveredRegion);
            layer->setVisibleNonTransparentRegion(
                    visibleRegion.subtract(transparentRegion));
        });
    
        outOpaqueRegion = aboveOpaqueLayers;
    }
    

    讲完了合成前预处理和重新构建Layer这两步,接下来就是构建硬件合成的任务列表,合成图元以及合成后的处理这三步了,由于构建硬件合成的任务列表以及图层混合是HWComposer处理的,我会把它列为图像的消费者之一,单独来讲,所以这里跳过这两步,直接讲最一步操作:图层混合结束后的处理

    图层混合结束后的处理

    此时,我们的图层已经混合完成了,图像数据也被送到了帧缓冲,并在屏幕上显示了,但SurfaceFlinger还会由一些收尾的工作需要处理,比如释放图像缓冲区,更新时间戳等工作,我们看一下源码实现,不需要做太深入的了解。

    //文件-->/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
    void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
    {
        ATRACE_CALL();
        ALOGV("postComposition");
    
        // 释放掉Layer中的buffer
        nsecs_t dequeueReadyTime = systemTime();
        for (auto& layer : mLayersWithQueuedFrames) {
            layer->releasePendingBuffer(dequeueReadyTime);
        }
    
        // |mStateLock| not needed as we are on the main thread
        const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
    
        std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
        if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
            glCompositionDoneFenceTime =
                    std::make_shared<FenceTime>(hw->getClientTargetAcquireFence());
            mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
        } else {
            glCompositionDoneFenceTime = FenceTime::NO_FENCE;
        }
        mGlCompositionDoneTimeline.updateSignalTimes();
    
        sp<Fence> presentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
        auto presentFenceTime = std::make_shared<FenceTime>(presentFence);
        mDisplayTimeline.push(presentFenceTime);
        mDisplayTimeline.updateSignalTimes();
    
        nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
        nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
    
        // We use the refreshStartTime which might be sampled a little later than
        // when we started doing work for this frame, but that should be okay
        // since updateCompositorTiming has snapping logic.
        updateCompositorTiming(
            vsyncPhase, vsyncInterval, refreshStartTime, presentFenceTime);
        CompositorTiming compositorTiming;
        {
            std::lock_guard<std::mutex> lock(mCompositorTimingLock);
            compositorTiming = mCompositorTiming;
        }
    
        mDrawingState.traverseInZOrder([&](Layer* layer) {
            bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
                    presentFenceTime, compositorTiming);
            if (frameLatched) {
                recordBufferingStats(layer->getName().string(),
                        layer->getOccupancyHistory(false));
            }
        });
    
        if (presentFence->isValid()) {
            if (mPrimaryDispSync.addPresentFence(presentFence)) {
                enableHardwareVsync();
            } else {
                disableHardwareVsync(false);
            }
        }
    
        if (!hasSyncFramework) {
            if (hw->isDisplayOn()) {
                enableHardwareVsync();
            }
        }
    
        if (mAnimCompositionPending) {
            mAnimCompositionPending = false;
    
            if (presentFenceTime->isValid()) {
                mAnimFrameTracker.setActualPresentFence(
                        std::move(presentFenceTime));
            } else {
                // The HWC doesn't support present fences, so use the refresh
                // timestamp instead.
                nsecs_t presentTime =
                        mHwc->getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
                mAnimFrameTracker.setActualPresentTime(presentTime);
            }
            mAnimFrameTracker.advanceFrame();
        }
    
        if (hw->getPowerMode() == HWC_POWER_MODE_OFF) {
            return;
        }
    
        nsecs_t currentTime = systemTime();
        if (mHasPoweredOff) {
            mHasPoweredOff = false;
        } else {
            nsecs_t elapsedTime = currentTime - mLastSwapTime;
            size_t numPeriods = static_cast<size_t>(elapsedTime / vsyncInterval);
            if (numPeriods < NUM_BUCKETS - 1) {
                mFrameBuckets[numPeriods] += elapsedTime;
            } else {
                mFrameBuckets[NUM_BUCKETS - 1] += elapsedTime;
            }
            mTotalTime += elapsedTime;
        }
        mLastSwapTime = currentTime;
    }
    

    HWComposer

    讲完了SurfaceFLinger这一图像消费者,现在轮到第二个图像消费者——HWComposer了。上面已经讲到,SurfaceFlinger在重新构建Layer栈后,便会构建硬件的合成任务列表,然后将Layer交给了HWComposer去做图层混合。我们接着看HWComposer作为图像的消费者,是怎么通过图层混合的方式去消费图像数据的。

    创建硬件合成的任务列表

    setUpHWCompser主要做了下面几件事情

    1. 遍历每一个DisplayDevice调用beginFrame方法,准备绘制图元。

    2. 遍历每一个DisplayDevice先判断他的色彩空间。并且设置颜色矩阵。接着获取DisplayDevice中需要绘制的Layer,检查是否创建了hwcLayer,没有则创建,创建失败则设置forceClientComposition,强制设置为Client渲染模式,即OpenGL ES渲染。最后调用setGeometry。

    3. 遍历每一个DisplayDevice,根据DataSpace,进一步处理是否需要强制使用Client渲染模式,最后调用layer的setPerFrameData方法。

    4. 遍历每一个DisplayDevice,调用prepareFrame准备数据。

    我们看一下具体的源码实现

    void SurfaceFlinger::setUpHWComposer() {
        ATRACE_CALL();
        ALOGV("setUpHWComposer");
    
        //遍历每一个DisplayDevice调用beginFrame方法,准备绘制图元。
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
            bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
            bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
            bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
    
            //如果没有脏区或者没有可见的Layer,这不进行合成
            bool mustRecompose = dirty && !(empty && wasEmpty);
    
            mDisplays[dpy]->beginFrame(mustRecompose);
    
            if (mustRecompose) {
                mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
            }
        }
    
        // 构建HWComposer硬件工作任务
        if (CC_UNLIKELY(mGeometryInvalid)) {
            mGeometryInvalid = false;
            for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
                const auto hwcId = displayDevice->getHwcDisplayId();
                if (hwcId >= 0) {
                    const Vector<sp<Layer>>& currentLayers(
                            displayDevice->getVisibleLayersSortedByZ());
                    for (size_t i = 0; i < currentLayers.size(); i++) {
                        const auto& layer = currentLayers[i];
                        if (!layer->hasHwcLayer(hwcId)) {
                            //为每个Layer创建hwcLayer
                            auto hwcLayer = mHwc->createLayer(hwcId);
                            if (hwcLayer) {
                                layer->setHwcLayer(hwcId, std::move(hwcLayer));
                            } else {
                                //hwcLayer创建失败是采用OpenGL ES渲染
                                layer->forceClientComposition(hwcId);
                                continue;
                            }
                        }
                        //设置Layer的尺寸
                        layer->setGeometry(displayDevice, i);
                        if (mDebugDisableHWC || mDebugRegion) {
                            layer->forceClientComposition(hwcId);
                        }
                    }
                }
            }
        }
    
        mat4 colorMatrix = mColorMatrix * mDaltonizer();
    
    
        for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
            auto& displayDevice = mDisplays[displayId];
            const auto hwcId = displayDevice->getHwcDisplayId();
    
            if (hwcId < 0) {
                continue;
            }
            // 设置每个Dispaly的颜色矩阵
            if (colorMatrix != mPreviousColorMatrix) {
                status_t result = mHwc->setColorTransform(hwcId, colorMatrix);           
            }
            //设置每一层Layer的显示数据
            for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
                layer->setPerFrameData(displayDevice);
            }
    
            if (hasWideColorDisplay) {
                android_color_mode newColorMode;
                android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
    
                for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
                    newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace);
                }
                newColorMode = pickColorMode(newDataSpace);
    
                setActiveColorModeInternal(displayDevice, newColorMode);
            }
        }
    
        mPreviousColorMatrix = colorMatrix;
    
        for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
            auto& displayDevice = mDisplays[displayId];
            if (!displayDevice->isDisplayOn()) {
                continue;
            }
    
            status_t result = displayDevice->prepareFrame(*mHwc);
        }
    }
    

    硬件混合图层

    前面HWComposer已经构建好了合成列表任务,合成的数据也都准备好了,现在就开始图像的混合工作了。doComposition中调用doDisplayComposition函数进行合成工作,我们看一下合成工作的具体流程。

    void SurfaceFlinger::doComposition() {
        ATRACE_CALL();
        const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
            const sp<DisplayDevice>& hw(mDisplays[dpy]);
            if (hw->isDisplayOn()) {
                //获取rebuildLayerStacks时计算的当前显示设备的脏区域DirtyRegion,。如果是强制重画,mRepaintEverything为true,那么脏区域就是整个屏幕的大小。
                const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
    
                // 软件合成处理
                doDisplayComposition(hw, dirtyRegion);
                //……
              
            }
            hw->compositionComplete();
        }
        //硬件合成
        postFramebuffer();
    }
    

    doComposition函数主要通过doDisplayComposition进程软件合成以及postFramebuffer函数进程硬件合成,我们先看一下doDisplayComposition的实现逻辑

    void SurfaceFlinger::doDisplayComposition(
            const sp<const DisplayDevice>& displayDevice,
            const Region& inDirtyRegion)
    {
        
        //不需要Hwc处理或者脏区不为空
        bool isHwcDisplay = displayDevice->getHwcDisplayId() >= 0;
        if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
            ALOGV("Skipping display composition");
            return;
        }
    
        ALOGV("doDisplayComposition");
    
        Region dirtyRegion(inDirtyRegion);
    
        displayDevice->swapRegion.orSelf(dirtyRegion);
    
        uint32_t flags = displayDevice->getFlags();
        if (flags & DisplayDevice::SWAP_RECTANGLE) {        
            dirtyRegion.set(displayDevice->swapRegion.bounds());
        } else {
            if (flags & DisplayDevice::PARTIAL_UPDATES) {         
                dirtyRegion.set(displayDevice->swapRegion.bounds());
            } else {          
                dirtyRegion.set(displayDevice->bounds());
                displayDevice->swapRegion = dirtyRegion;
            }
        }
    
        if (!doComposeSurfaces(displayDevice, dirtyRegion)) return;
    
        // update the swap region and clear the dirty region
        displayDevice->swapRegion.orSelf(dirtyRegion);
    
        // Display交换Buffer
        displayDevice->swapBuffers(getHwComposer());
    }
    
    
    

    doDisplayComposition函数又调用doComposeSurfaces完成了图像合成,我们继续深入看看doComposeSurfaces函数中又是怎么做合成的。

    bool SurfaceFlinger::doComposeSurfaces(
            const sp<const DisplayDevice>& displayDevice, const Region& dirty)
    {
        
        const auto hwcId = displayDevice->getHwcDisplayId();
        mat4 oldColorMatrix;
        const bool applyColorMatrix = !mHwc->hasDeviceComposition(hwcId) &&
                !mHwc->hasCapability(HWC2::Capability::SkipClientColorTransform);
        if (applyColorMatrix) {
            mat4 colorMatrix = mColorMatrix * mDaltonizer();
            oldColorMatrix = getRenderEngine().setupColorTransform(colorMatrix);
        }
    
        
        bool hasClientComposition = mHwc->hasClientComposition(hwcId);
        //判断是否有软件合成,如果有软件合成,则用OpenGL ES合成
        if (hasClientComposition) {    
            //……
        }
    
        const Transform& displayTransform = displayDevice->getTransform();
        //硬件合成处理部分
        if (hwcId >= 0) {        
            bool firstLayer = true;
            for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
                //计算Layer在屏幕可见区域内的clip
                const Region clip(dirty.intersect(
                        displayTransform.transform(layer->visibleRegion)));
                ALOGV("Layer: %s", layer->getName().string());
                ALOGV("  Composition type: %s",
                        to_string(layer->getCompositionType(hwcId)).c_str());
                if (!clip.isEmpty()) {
                    switch (layer->getCompositionType(hwcId)) {
                        case HWC2::Composition::Cursor:
                        case HWC2::Composition::Device:
                        case HWC2::Composition::Sideband:
                        case HWC2::Composition::SolidColor: {
                            const Layer::State& state(layer->getDrawingState());
                            if (layer->getClearClientTarget(hwcId) && !firstLayer &&
                                    layer->isOpaque(state) && (state.alpha == 1.0f)
                                    && hasClientComposition) {
                                // never clear the very first layer since we're
                                // guaranteed the FB is already cleared
                                layer->clearWithOpenGL(displayDevice);
                            }
                            break;
                        }
                        case HWC2::Composition::Client: {
                            //软件合成则直接draw到clip上
                            layer->draw(displayDevice, clip);
                            break;
                        }
                        default:
                            break;
                    }
                } else {
                    ALOGV("  Skipping for empty clip");
                }
                firstLayer = false;
            }
        } else {
            // we're not using h/w composer
            for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
                const Region clip(dirty.intersect(
                        displayTransform.transform(layer->visibleRegion)));
                if (!clip.isEmpty()) {
                    layer->draw(displayDevice, clip);
                }
            }
        }
    
        if (applyColorMatrix) {
            getRenderEngine().setupColorTransform(oldColorMatrix);
        }
    
        // disable scissor at the end of the frame
        mRenderEngine->disableScissor();
        return true;
    }
    

    doComposeSurfaces主要做了这几件事情:

    1. 如果有软件合成,则调用OpenGL ES进行软件合成
    2. 如果硬件合成,则清除通过软件合成的Layer

    通过OpenGL ES进行软件合成的部分我会在下面讲OpenGL ES这个图形消费者的时候再深入讲。这里我们接着看postFramebuffer,也就是硬件合成的部分。

    void SurfaceFlinger::postFramebuffer()
    {
        ATRACE_CALL();
        ALOGV("postFramebuffer");
    
        const nsecs_t now = systemTime();
        mDebugInSwapBuffers = now;
    
        for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
            auto& displayDevice = mDisplays[displayId];
            if (!displayDevice->isDisplayOn()) {
                continue;
            }
            const auto hwcId = displayDevice->getHwcDisplayId();
            if (hwcId >= 0) {
                //硬件合成
                mHwc->presentAndGetReleaseFences(hwcId);
            }
            //swap buffer接收
            displayDevice->onSwapBuffersCompleted();
            //为下一帧做初始化
            displayDevice->makeCurrent(mEGLDisplay, mEGLContext);
            for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
                sp<Fence> releaseFence = Fence::NO_FENCE;
                if (layer->getCompositionType(hwcId) == HWC2::Composition::Client) {
                    releaseFence = displayDevice->getClientTargetAcquireFence();
                } else {
                    auto hwcLayer = layer->getHwcLayer(hwcId);
                    releaseFence = mHwc->getLayerReleaseFence(hwcId, hwcLayer);
                }
                layer->onLayerDisplayed(releaseFence);
            }
            if (hwcId >= 0) {
                mHwc->clearReleaseFences(hwcId);
            }
        }
    
        mLastSwapBufferTime = systemTime() - now;
        mDebugInSwapBuffers = 0;
    
        // |mStateLock| not needed as we are on the main thread
        uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
        if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
            logFrameStats();
        }
    }
    

    到这里我们的硬件混合部分就处理完了,接下来SurfaceFlinger就会执行合成后的收尾工作。

    在混合的时候,分为了软件混合和硬件混合两部分,我已经讲了硬件混合的部分,下面接着来看OpenGL ES是怎么做软件合成的。

    OpenGL ES

    OPenGL ES既是图像的生产者,也是图像的消费者,作为一个消费者,它可以进行图层的混合,我们看一下doComposeSurfaces函数中软件合成是怎样处理的。

    软件混合图层

    bool SurfaceFlinger::doComposeSurfaces(
            const sp<const DisplayDevice>& displayDevice, const Region& dirty)
    {
        const auto hwcId = displayDevice->getHwcDisplayId();
    
        mat4 oldColorMatrix;
        const bool applyColorMatrix = !mHwc->hasDeviceComposition(hwcId) &&
                !mHwc->hasCapability(HWC2::Capability::SkipClientColorTransform);
        if (applyColorMatrix) {
            mat4 colorMatrix = mColorMatrix * mDaltonizer();
            oldColorMatrix = getRenderEngine().setupColorTransform(colorMatrix);
        }
    
        bool hasClientComposition = mHwc->hasClientComposition(hwcId);
        if (hasClientComposition) {
            ALOGV("hasClientComposition");
            #ifdef USE_HWC2
                    mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
                    mRenderEngine->setWideColor(displayDevice->getWideColorSupport());
            #endif
            if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
                ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
                      displayDevice->getDisplayName().string());
                eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    
                // |mStateLock| not needed as we are on the main thread
                if(!getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext)) {
                  ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
                }
                return false;
            }
    
            // Never touch the framebuffer if we don't have any framebuffer layers
            const bool hasDeviceComposition = mHwc->hasDeviceComposition(hwcId);
            if (hasDeviceComposition) {
                //清除mRenderEngine的状态
                mRenderEngine->clearWithColor(0, 0, 0, 0);
            } else {
                //……
            }
    
            if (displayDevice->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
                // just to be on the safe side, we don't set the
                // scissor on the main display. It should never be needed
                // anyways (though in theory it could since the API allows it).
                const Rect& bounds(displayDevice->getBounds());
                const Rect& scissor(displayDevice->getScissor());
                if (scissor != bounds) {
                    // scissor doesn't match the screen's dimensions, so we
                    // need to clear everything outside of it and enable
                    // the GL scissor so we don't draw anything where we shouldn't
    
                    // enable scissor for this frame
                    const uint32_t height = displayDevice->getHeight();
                    mRenderEngine->setScissor(scissor.left, height - scissor.bottom,
                            scissor.getWidth(), scissor.getHeight());
                }
            }
        }
        //……
        return true;
    }
    

    软件混合的逻辑中,主要通过mRenderEngine来进行处理,主要做的事情有这几件

    • 指定颜色矩阵 setupColorTransform
    • 指定是否用WideColor setWideColor
    • 指定颜色模式 setColorMode
    • 设置剪切区 setScissor

    RenderEngine是在SurfaceFlinger的init函数中初始化的,

    void SurfaceFlinger::init() {
        //……
        // Get a RenderEngine for the given display / config (can't fail)
        mRenderEngine = RenderEngine::create(mEGLDisplay,
        HAL_PIXEL_FORMAT_RGBA_8888);
        //……
    
     }
    

    它是对GPU渲染的封装,包括了 EGLDisplay,EGLContext, EGLConfig,EGLSurface等。至于OpenGL ES到底是什么,又是怎么使用的,我们在这儿只把它当作一个图像的消费者有一个简单的认识,再下一篇文章中,会详细的介绍图像的生成者,OpenGL ES作为一个重要的生产者之一,我们会对他有一个更加深入的了解。

    总结

    在这一文章帐,我主要讲解Android系统中的图像消费者这一模块,我们了解了SurfaceFlinger,HWComposer,OPenGL ES作为图像的消费者是如何消费图像的,当然,我们也可以不使用图像消费者,直接将图像数据送到帧缓冲中,但这样方式,便没有了交互式的界面,一个可交互式的界面是由多个界面层级组成的,而我们提到的SurfaceFlinger,HWComposer,OPenGL ES是Android中做图层混合必不可少的三个工具。有很多细节的部分,我没有太深入展开,因为这三个模块都是非常庞大的模块,但掌握了主要的流程和关键部分的代码,细节的部分,都可以待时间充裕时在区慢慢探索。

    在下一篇文章里,我会讲解图像的生产者,OpenGL ES和Skia,以及他们是如何生产图像数据,还会讲解通过OpenGL ES和Skia在Android中的实际使用,如界面的软件绘制,硬件绘制,开机动画,Flutter的显示等知识。

    相关文章

      网友评论

          本文标题:Android图形渲染原理上

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