Android图形显示系统2 图像消费者

一 概述

对于 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 的图像显示机制。

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

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

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

  • CPU→显卡驱动:CPU 通过软件绘制将绘制好的内容,或者直接将绘制指令(硬件加速),提交给显卡驱动
  • 显卡驱动→GPU:显卡驱动是硬件厂商编写的,能将接收到的渲染命令翻译成 GPU 能够理解的语言,所以显卡驱动是 Opengl 或者 DirectX 等图形编程接口的具体实现。我们可以将它理解成其他模块和显卡沟通的入口
  • GPU→帧缓冲:显卡对数据进行顶点处理,剪裁,光栅化等操作流程,再经过图层混合后将最终的数据提交到显存
  • 显存→显示器:如果显卡是 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,Camera Preview,NDK,OpenGl ES。MediaPlayer 和 Camera Previer 是通过直接读取图像源来生成图像数据,NDK(Skia),OpenGL ES 是通过自身的绘制能力生产的图像数据;图像的消费者有 SurfaceFlinger,OpenGL ES Apps,以及 HAL 中的 Hardware Composer。OpenGl ES 既可以是图像的生产者,也可以是图像的消费者,所以它也放在了图像消费模块中;图像缓冲区主要有 Surface 以及前面提到帧缓冲。

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

四 图像消费者

4.1 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 是如何在这一规则下,消费图像数据的。

4.1.1 接收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));
}

//创建BitTube通信信道
EventThread::Connection::Connection(const sp<EventThread>& eventThread)
    : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) 
{
}

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 垂直同步信号的操作,主要有这几个过程:

  • init 函数中,创建了 EventThread 线程来专门接收 VSYNC 垂直同步的信号,并调用 setEventThread 函数将 EventThread 添加到 EventQueue 中。
  • setEventThread 函数中,创建 EventThread 的连接,并将 EventThread 线程中通信的套接字通过 addFd 添加到 MessageQueue 的 Looper 中,这样 MessageQueue 就能接收 EventThread 的数据了。
  • 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));
    }
}
  • 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 主要是两件事情

  • 通过 mCondition.waitRelative 来接收 VSync
  • 将 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 是以什么样的方式消费图像数据的。

4.1.2 处理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

4.继续回到 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 真正处理图层合成的地方,它主要下面五个步骤。

  • preCompostion:合成前预处理
  • rebuildLayerStacks:重新构建 Layer 栈
  • setUpHWCompser:构建硬件合成的任务列表
  • doCompostion:图层混合
  • 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 中做的事情了,它主要是这几步操作:

  • 从 Layer Z 轴最上层开始遍历该显示设备中所有的 Layer
  • 计算该 Layer 的被覆盖区域,aboveCoveredLayers 和当前 Layer 除去非透明区域部分的交集
  • 将当前 Layer 除去非透明区域部分添加到 aboveCoveredLayers 中,为下一层 Layer 计算提供条件
  • 计算当前 Layer 的可见区域 , 即当前 Layer 除去非透明区域部分减掉 aboveOpaqueLayers
  • 计算脏区域,脏区域需要减去被遮盖的部分,并将当前 Layer 的脏区域累加到当前显示设备的脏区域 outDirtyRegion
  • 保存计算的 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;
}

4.2 HWComposer

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

4.2.1 创建硬件合成的任务列表

setUpHWCompser 主要做了下面几件事情

  • 遍历每一个 DisplayDevice 调用 beginFrame 方法,准备绘制图元
  • 遍历每一个 DisplayDevice 先判断他的色彩空间。并且设置颜色矩阵。接着获取 DisplayDevice 中需要绘制的 Layer,检查是否创建了 hwcLayer,没有则创建,创建失败则设置 forceClientComposition,强制设置为 Client 渲染模式,即 OpenGL ES 渲染。最后调用 setGeometry
  • 遍历每一个 DisplayDevice,根据 DataSpace,进一步处理是否需要强制使用 Client 渲染模式,最后调用 layer 的 setPerFrameData 方法
  • 遍历每一个 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);
    }
}

4.2.2 硬件混合图层

前面 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 主要做了这几件事情:

  • 如果有软件合成,则调用 OpenGL ES 进行软件合成
  • 如果硬件合成,则清除通过软件合成的 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 是怎么做软件合成的。

4.3 OpenGL ES

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

4.3.1 软件混合图层

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 的显示等知识。

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值