当前位置:   article > 正文

简述Android图形绘制(SF)部分流程

简述Android图形绘制(SF)部分流程
1.显示渲染--SF消息分发流程:
        MessageQueue是SurfaceFlinger中的消息队列,mEventQueue是MessageQueue的一个对象,SF在初次引用时(sp强引用)会对对mEventQueue进行初始化。
  1. * frameworks/native/services/surfaceflinger/MessageQueue.cpp
  2. void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
  3. {
  4. mFlinger = flinger;
  5. mLooper = new Looper(true);
  6. mHandler = new Handler(*this);
  7. }
        MessageQueue初始化时,创建了一个Looper和一个Handler。此外,在SurfaceFlinger初始化时,创建了一个EventThread,并传给了MessageQueue(里面塞了一个EventThread,接收ET的VSYNC和HOTPLUG事件再发送)。
  1. void SurfaceFlinger::init() {
  2. ... ...
  3. sp<VSyncSource> sfVsyncSrc =
  4. new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
  5. mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
  6. mEventQueue.setEventThread(mSFEventThread);
        MessageQueue的setEventThread函数如下:
  1. void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
  2. {
  3. if (mEventThread == eventThread) {
  4. return;
  5. }
  6. if (mEventTube.getFd() >= 0) {
  7. mLooper->removeFd(mEventTube.getFd());
  8. }
  9. mEventThread = eventThread;
  10. mEvents = eventThread->createEventConnection();
  11. mEvents->stealReceiveChannel(&mEventTube);
  12. mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
  13. MessageQueue::cb_eventReceiver, this);
  14. }
........这里省略很多EventThread内部对象与MessageQueue的绑定关联代码。
        然后由于EventThread就是一个事件分发的线程,threadLoop函数内部会调用waitForEvent,等待事件Event。看看哪些Connection是被触发的,对于被触发的Connection,signalConnections, 通过postEvent将事件Event分发出去
        waitForEvent中,采用while循环,条件是signalConnections为空。EventThread中主要控制两事件,Vsync事件和显示屏的HotPlug热插拔事件。这两个事件到来时会调到对应的方法中。
        数据是什么地方接受的呢?回到SurfaceFlinger。SurfaceFlinger线程run时,启动一个死循环,循环等待事件。
  1. void SurfaceFlinger::run() {
  2. while (true) {
  3. mEventQueue->waitMessage();
  4. }
  5. }
        waitMessage,通过采用一个死循环,处理Looper的pollOnce。Looper内部的逻辑就不看了,主要是采用epoll_wait对fd进行监听,BitTube发送Event对象后,epoll_wait结束,调用callback,处理事件。
        最后通过Looper分发Message,MessageQueue中,两种Message,INVALIDATE和REFRESH。
  1. void MessageQueue::Handler::dispatchInvalidate() {
  2. if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
  3. mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
  4. }
  5. }
Message的分发略过,Handler对Message的处理如下:
  1. void MessageQueue::Handler::handleMessage(const Message& message) {
  2. switch (message.what) {
  3. case INVALIDATE:
  4. android_atomic_and(~eventMaskInvalidate, &mEventMask);
  5. mQueue.mFlinger->onMessageReceived(message.what);
  6. break;
  7. case REFRESH:
  8. android_atomic_and(~eventMaskRefresh, &mEventMask);
  9. mQueue.mFlinger->onMessageReceived(message.what);
  10. break;
  11. }
  12. }
收到消息后,再调回SurfaceFlinger在onMessageReceived中处理。
MessageQueue的类图
https://zhuanlan.zhihu.com/p/671941412
2.显示渲染--绘制处理流程:
        1.首先应用在onResume的时候会调用WMS的addView ,在 ViewRoot 进行 performTraversals 时,会向 WMS 申请一个 Surface 。WMS 在创建 Surface 时,会生成一个 SurfaceSession ,然后将这个 SurfaceSession 作为参数来构造 Surface,这个surface就是一个图像缓冲区,会向sf去申请创建一个layer。
        2.接下来应用会调到sf的createsurface,会调用createlayer,给创建一个layer出来;
        3.创建layer的时候,会创建bufferqueueproducer,然后应用可以去给这个layer设置一些参数,设置完了以后会去dq一块buffer出来,这个会调用allocator去用ion的方式去申请一块buffer出来,然后把它lock住,供应用进程使用。
        4.然后往这个buffer里面写内容,这个地方以前是cpu往里面写,也就是软件绘制,有了gpu以后,就是调opengl的接口去绘制内容,用硬件绘制,绘制完了就把buffer queue到bufferqueue里面,然后通知surfaceflinger绘制完成,sf就会调用signalLayerUpdate()去刷新。
  1. void SurfaceFlinger::signalLayerUpdate() {
  2. mEventQueue.invalidate();
  3. }
        5.signalLayerUpdate中,调用MQ的invalidate。
  1. void MessageQueue::invalidate() {
  2. mEvents->requestNextVsync();
  3. }
        MQ的invalidate的函数,将请求下一个Vsync。Vsync是一种同步机制,垂直同步,我们可以理解为SurfaceFlinger的工作节拍。
3.显示渲染--合成送显处理流程:
        surfaceflinger会在下一次vsync信号 和fence机制同步好了以后去,调用handleMessageRefresh(),然后会重新去组装这一帧的layer,根据z值。然后交给hwc去判断,用什么方式去合成。这个地方合成方式有两种,gpu和硬件,如果是gpu合成,就会调用gpu去合成,合成完了之后再返回给sf,sf再委托hwc通过显示驱动去显示。
4.显示渲染--图形缓冲区数据流程:
        1.App通过dequeuebuffer获得某一slot的使用权,这时slot的状态切换到DEQUEUED状态,随着dequeueBuffer方法返回的还有releaseFence对象。这时因为releaseFence还没有被signaled,因此此时CPU虽然拿到了buffer的使用权,但别的硬件还在使用这个buffer,所以GPU不能绘制这个buffer,它要等releaseFence signaled后才能绘制。
        2.CPU侧APP已经完成了queuebuffer操作,若此时GPU的执行时间较长,这时slot的状态已切换为QUEUED状态,或者vsync已经到来状态变为ACQUIRED状态,这在CPU侧代表该buffer给HWC去合成,但这时HWC的硬件MDP还不能去读里面的数据,它还需要等待acquireFence的signaled信号,只有等到acquireFence的signaled信号才代表GPU的绘制完成并且结束对帧缓冲区的访问。
        3.SurfaceFlinger执行到releasebuffer方法时,并不代表HWC已经完成合成任务,很可能它还在读取帧缓冲区,但不妨碍releasebuffer流程的执行。虽然HWC还在使用缓冲区做合成,但此时slot可能已经被应用申请变成DEQUEUED状态,这时GPU并不能直接存取它,要等待代表着HWC使用完毕的releaseFence的signaled信号。
5.显示渲染--应用和SF跨进程处理流程:
        1. 创建SurfaceComposerClient对象;
        2. SurfaceComposerClient::onFirstRef方法中透过ComposerService::getComposerService()获取到SurfaceFlinger服务的代理客户端;
        3. 调用SurfaceFlinger服务的代理客户端的createConnection方法,进而跨进程调用到SurfaceFlinger::createConnection方法;
        4. SurfaceFlinger::createConnection方法中创建一个Client对象,并透过Binder返回给SurfaceComposerClient::mClient;
        之后再调用SurfaceComposerClient中的方法时就可以通过mClient这个客户端去呼叫到SurfaceFlinger服务的功能了。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/269486
推荐阅读
相关标签
  

闽ICP备14008679号