Android4.4深入浅出之SurfaceFlinger (二)

五 SF到底做了什么事     

   接上篇文章,我们来看一下init()都做了什么事。以下是源码:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void SurfaceFlinger::init() {  
  2.     ALOGI(  "SurfaceFlinger's main thread ready to run. "  
  3.             "Initializing graphics H/W...");  
  4.   
  5.     status_t err;  
  6.     Mutex::Autolock _l(mStateLock);  
  7.   
  8.     // initialize EGL for the default display  
  9.     mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);  
  10.     eglInitialize(mEGLDisplay, NULL, NULL);  
  11.   
  12.     // Initialize the H/W composer object.  There may or may not be an  
  13.     // actual hardware composer underneath.  
  14.     mHwc = new HWComposer(this,  
  15.             *static_cast<HWComposer::EventHandler *>(this));  
  16.   
  17.     // First try to get an ES2 config  
  18.     err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT,  
  19.             &mEGLConfig);  
  20.     if (err != NO_ERROR) {  
  21.         // If ES2 fails, try ES1  
  22.         err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(),  
  23.                 EGL_OPENGL_ES_BIT, &mEGLConfig);  
  24.     }  
  25.   
  26.     if (err != NO_ERROR) {  
  27.         // still didn't work, probably because we're on the emulator...  
  28.         // try a simplified query  
  29.         ALOGW("no suitable EGLConfig found, trying a simpler query");  
  30.         err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig);  
  31.     }  
  32.   
  33.     if (err != NO_ERROR) {  
  34.         // this EGL is too lame for android  
  35.         LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");  
  36.     }  
  37.   
  38.     // print some debugging info  
  39.     EGLint r,g,b,a;  
  40.     eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE,   &r);  
  41.     eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g);  
  42.     eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE,  &b);  
  43.     eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a);  
  44.     ALOGI("EGL informations:");  
  45.     ALOGI("vendor    : %s", eglQueryString(mEGLDisplay, EGL_VENDOR));  
  46.     ALOGI("version   : %s", eglQueryString(mEGLDisplay, EGL_VERSION));  
  47.     ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS));  
  48.     ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported");  
  49.     ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig);  
  50.   
  51.     // get a RenderEngine for the given display / config (can't fail)  
  52.     mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig);  
  53.   
  54.     // retrieve the EGL context that was selected/created  
  55.     mEGLContext = mRenderEngine->getEGLContext();  
  56.   
  57.     // figure out which format we got  
  58.     eglGetConfigAttrib(mEGLDisplay, mEGLConfig,  
  59.             EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId);  
  60.   
  61.     LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,  
  62.             "couldn't create EGLContext");  
  63.   
  64.     // initialize our non-virtual displays  
  65.     for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {  
  66.         DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);  
  67.         // set-up the displays that are already connected  
  68.         if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {  
  69.             // All non-virtual displays are currently considered secure.  
  70.             bool isSecure = true;  
  71.             createBuiltinDisplayLocked(type);  
  72.             wp<IBinder> token = mBuiltinDisplays[i];  
  73.   
  74.             sp<BufferQueue> bq = new BufferQueue(new GraphicBufferAlloc());  
  75.             sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, bq);  
  76.             sp<DisplayDevice> hw = new DisplayDevice(this,  
  77.                     type, allocateHwcDisplayId(type), isSecure, token,  
  78.                     fbs, bq,  
  79.                     mEGLConfig,  
  80.                     mHardwareOrientation);  
  81.             if (i > DisplayDevice::DISPLAY_PRIMARY) {  
  82.                 // FIXME: currently we don't get blank/unblank requests  
  83.                 // for displays other than the main display, so we always  
  84.                 // assume a connected display is unblanked.  
  85.                 ALOGD("marking display %d as acquired/unblanked", i);  
  86.                 hw->acquireScreen();  
  87.             }  
  88.             mDisplays.add(token, hw);  
  89.         }  
  90.     }  
  91.   
  92.     // make the GLContext current so that we can create textures when creating Layers  
  93.     // (which may happens before we render something)  
  94.     getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);  
  95.   
  96.     // start the EventThread  
  97.     sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,  
  98.             vsyncPhaseOffsetNs, true);  
  99.     mEventThread = new EventThread(vsyncSrc);  
  100.     sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,  
  101.             sfVsyncPhaseOffsetNs, false);  
  102.     mSFEventThread = new EventThread(sfVsyncSrc);  
  103.     mEventQueue.setEventThread(mSFEventThread);  
  104.   
  105.     mEventControlThread = new EventControlThread(this);  
  106.     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);  
  107.   
  108.     // set a fake vsync period if there is no HWComposer  
  109.     if (mHwc->initCheck() != NO_ERROR) {  
  110.         mPrimaryDispSync.setPeriod(16666667);  
  111.     }  
  112.   
  113.     // initialize our drawing state  
  114.     mDrawingState = mCurrentState;  
  115.   
  116.     // set initial conditions (e.g. unblank default device)  
  117.     initializeDisplays();  
  118.   
  119.     char value[PROPERTY_VALUE_MAX];  
  120.     memset(value,0,PROPERTY_VALUE_MAX);  
  121.     property_get("sys.enable.wfd.optimize", value, "0");  
  122.     mWfdOptimize = atoi(value);  
  123.     // start boot animation  
  124.     startBootAnim();  
  125. }  


 如上代码量太大了我稍微总结了下,它做了以下几件事:

1.初始化EGL,这是干嘛用?首先介绍下EGL,EGLOpenGL ES和底层Native平台视窗系统之间的接口,也就是说初始化了openGL的API。

2.初始化H/W composer,也就是HardWare的一些事,具体不去研究

3.获得一个显示器的渲染引擎,RendEngine,这是OPENGL发挥作用的平台

4.初始化显示器的一些东西,代码太多,没看懂做了哪些事。

5.启动了线程,EventThread,这个线程在以后的研究中会涉及到。

6.初始化了一些状态条件等。

 

好了先告一段落,初始化做了一些事情,肯定是为以后做铺垫,暂且继续研究下去。

前一篇文章,研究到了addService(),接下去的一行是:flinger->run();

 我们来看下run的实体函数,他定义在SF类中:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void SurfaceFlinger::run() {  
  2.     do {  
  3.         waitForEvent();  
  4.     } while (true);  
  5. }  

最核心的代码就是waitForEvent();继续跟踪:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void SurfaceFlinger::waitForEvent() {  
  2.     mEventQueue.waitMessage();  
  3. }  


再继续:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void MessageQueue::waitMessage() {  
  2.     do {  
  3.         IPCThreadState::self()->flushCommands();  
  4.         int32_t ret = mLooper->pollOnce(-1);  
  5.         switch (ret) {  
  6.             case ALOOPER_POLL_WAKE:  
  7.             case ALOOPER_POLL_CALLBACK:  
  8.                 continue;  
  9.             case ALOOPER_POLL_ERROR:  
  10.                 ALOGE("ALOOPER_POLL_ERROR");  
  11.             case ALOOPER_POLL_TIMEOUT:  
  12.                 // timeout (should not happen)  
  13.                 continue;  
  14.             default:  
  15.                 // should not happen  
  16.                 ALOGE("Looper::pollOnce() returned unknown status %d", ret);  
  17.                 continue;  
  18.         }  
  19.     } while (true);  
  20. }  


到这里,晕了没,看出眉头来了没,这是个庞大的事件机制,稍后给出一张图诠释一下这个事件机制,这张图是网上的大牛画的佩服的五体投地,一看马上拨开云雾见青天。我们还是看下代码把,关键代码在第四行pollOnece(),其实我不敢在写下去,因为里面文章太多,我查阅了网上的一些资料网址如下,大家可参考下:http://blog.csdn.net/broadview2006/article/details/8552148 ,然后我简单说下这里扯到了Looper,这可不是一个好鸟,庞大的事件机制军团中的一员,他配合着Message Handle Thread MessageQueue 完成了太多的事情,以后再去讨论。在这里简单说就是它搞了一个睡眠等待事件,然后等着被唤醒。结合到SF中就是说,这里开了一个线程等待surface的刷新,而做出相关的操作。至于是怎么唤醒的可以参考那个连接博文,这里不再赘述。

    既然被睡眠了,那研究该如何进行下去,于是我开始研究是谁把它唤醒的。开始复杂了,要费脑袋了。

这里我先给一张图:

   

     这张图是网上一位大牛博文中的,忘记链接地址了,如有侵权,还请告知我。好了开始正文:

我刚刚说的那个睡眠事件其实就是蓝色框框流程图的走向,图中标的是线程2。这里说一下其他线程分别是什么时候创建的

主线程:在SF中的onFirstRef()创建的,这里有个问题,是谁调用onFirstRef()?Android里面 当一个对象第一次被一个强指针应用时,那么这个对象的成员函数onFirstRef就会被调用,如上所说它一早就被调用了,我们看看它的实体:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void SurfaceFlinger::onFirstRef()  
  2. {  
  3.     mEventQueue.init(this);  
  4. }  

继续跟踪:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void MessageQueue::init(const sp<SurfaceFlinger>& flinger)  
  2. {  
  3.     mFlinger = flinger;  
  4.     mLooper = new Looper(true);  
  5.     mHandler = new Handler(*this);  
  6. }  

这里new了Looper和Handle,关于这两个什么东西,推荐一片博文:http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html  里面讲的很详细。好了这个是主线程1的创建。

线程2:前面说过,当调用SF::run();时就开始了。

线程3:在SF::init();中创建。也就是初始化中创建:创建关键代码如下:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. mEventThread = new EventThread(vsyncSrc);  
  2.     sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,  
  3.             sfVsyncPhaseOffsetNs, false);  
  4.     mSFEventThread = new EventThread(sfVsyncSrc);  
  5.     mEventQueue.setEventThread(mSFEventThread);  

这里我们分两个路线来讲:

1.EventThread继承了Thread线程类,还有它的基类中有RefBase所以当其定义的时候会调用onFirstRef,这个函数里面就一句 run();这里EventThread中的 threadLoop成员函数会被调用,这里看一下函数实体:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. bool EventThread::threadLoop() {  
  2.     DisplayEventReceiver::Event event;  
  3.     Vector< sp<EventThread::Connection> > signalConnections;  
  4.     signalConnections = waitForEvent(&event);  
  5.   
  6.     // dispatch events to listeners...  
  7.     const size_t count = signalConnections.size();  
  8.     for (size_t i=0 ; i<count ; i++) {  
  9.         const sp<Connection>& conn(signalConnections[i]);  
  10.         // now see if we still need to report this event  
  11.         status_t err = conn->postEvent(event);  
  12.         if (err == -EAGAIN || err == -EWOULDBLOCK) {  
  13.             // The destination doesn't accept events anymore, it's probably  
  14.             // full. For now, we just drop the events on the floor.  
  15.             // FIXME: Note that some events cannot be dropped and would have  
  16.             // to be re-sent later.  
  17.             // Right-now we don't have the ability to do this.  
  18.             ALOGW("EventThread: dropping event (%08x) for connection %p",  
  19.                     event.header.type, conn.get());  
  20.         } else if (err < 0) {  
  21.             // handle any other error on the pipe as fatal. the only  
  22.             // reasonable thing to do is to clean-up this connection.  
  23.             // The most common error we'll get here is -EPIPE.  
  24.             removeDisplayEventConnection(signalConnections[i]);  
  25.         }  
  26.     }  
  27.     return true;  
  28. }  

这里的waitForEvent就是在等待消息了,官方给出这个函数的作用是:

This will return when (1) a vsync event has been received, and (2) there was at least one connection interested in receiving it when we started waiting.大概意思就是等待vsync事件,如果有就返回正常值。那么是谁给他发的这个信号了,那必然是客户端请求渲染一个surface的时候了。这里以后会有研究。

   如果收到一个vsync的消息,就会往下执行到status_t err = conn->postEvent(event);这里是将事件信息写入到BitTube,也就是已建立连接的套接字队的一个套接字中,注册的接收端通过另一个套接字接收数据。这里注册的接收端就下面要阐述的第二点。到这里为止EventThread线程发送了一个套接字信息。

2. 到底是谁来接收套接字呢?当中的setEventThread就是扯到了套接字,跟之前说的pollOnce有关联,这里打住。我们看看这个函数的实体:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void MessageQueue::setEventThread(const sp<EventThread>& eventThread)  
  2. {  
  3.     mEventThread = eventThread;  
  4.     mEvents = eventThread->createEventConnection();// 这里创建了一个到EventThread的连接     
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. mEventTube = mEvents->getDataChannel();//得到发送VSync事件通知的BitTube  
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT,  
  2.         MessageQueue::cb_eventReceiver, this);  

在这里addFd当中的第一个参数就是获得套接字队中的信息,一旦有东西就会回调cb_eventReceiver这个函数,我们跟踪那个回调函数:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {  
  2.     MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);  
  3.     return queue->eventReceiver(fd, events);  
  4. }  

第二行是得到事件的queue,以便于下面返回事件接收者。继续跟踪:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. int MessageQueue::eventReceiver(int fd, int events) {  
  2.     ssize_t n;  
  3.     DisplayEventReceiver::Event buffer[8];  
  4.     while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {  
  5.         for (int i=0 ; i<n ; i++) {  
  6.             if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {  
  7. #if INVALIDATE_ON_VSYNC  
  8.                 mHandler->dispatchInvalidate();  
  9. #else  
  10.                 mHandler->dispatchRefresh();  
  11. #endif  
  12.                 break;  
  13.             }  
  14.         }  
  15.     }  
  16.     return 1;  
  17. }  


这个函数大概的意思就是,主循环一直在等待事件的接收,并判断事件的类型是不是DISPLAY_EVENT_VSYNC,如果是就开始执行下一步了,因为文件头有定义#define INVALIDATE_ON_VSYNC 1 所以走的是mHandler->dispatchInvalidate();这个函数。好了到这里,已经出现太多跟VSync有关的字眼,好像也起了很大的作用,这里暂不做研究,之后就会真相大白。不过还是推荐一篇博文大家参考下http://blog.csdn.net/broadview2006/article/details/8541727  继续跟踪dispatchInvalidate()这个函数。

 

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void MessageQueue::Handler::dispatchInvalidate() {  
  2.     if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {  
  3.         mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));  
  4.     }  
  5. }  


看到了一个关键的函数,sendMessage();发出去的消息是 INVALIDATE.看过事件机制的就知道,这里发出的消息是由handleMessage()来接收处理的。到底是哪边的handleMessage()来处理了,还记得之前的主线程2在睡眠等待消息?对就是在它里面。看上面那张图可以知道应该是在pollInner中处理消息的,由于这个消息机制过于复杂这里就略过了,不过推荐大家一篇博文很详细的阐述了 pollOnce和pollInner之间的关系 :http://book.2cto.com/201208/1946.html ,你会发现在函数pollInner中有个处理函数handleMessage();这里继续跟踪:

 

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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.         case TRANSACTION:  
  12.             android_atomic_and(~eventMaskTransaction, &mEventMask);  
  13.             mQueue.mFlinger->onMessageReceived(message.what);  
  14.             break;  
  15.     }  
  16. }  


用switch来判断接收的消息到底是什么,刚刚发送的是INVALDATE,所以执行第一条,跟踪onMessageReceived();

 

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void SurfaceFlinger::onMessageReceived(int32_t what) {  
  2.     ATRACE_CALL();  
  3.     if(mDelayFlag) {  
  4.         usleep(20000);  
  5.         mDelayFlag = 0;  
  6.     }  
  7.     switch (what) {  
  8.     case MessageQueue::TRANSACTION:  
  9.         handleMessageTransaction();  
  10.         break;  
  11.     case MessageQueue::INVALIDATE:  
  12.         handleMessageTransaction();  
  13.         handleMessageInvalidate();  
  14.         signalRefresh();  
  15.         break;  
  16.     case MessageQueue::REFRESH:  
  17.         handleMessageRefresh();  
  18.         break;  
  19.     }  
  20. }  

这里走的是第二个分支,第一个函数handleTransaction();这里处理了各种事务,如窗口状态属性变化,继续跟踪handleMessageInvalidate,他调用了一个handlePageFlip()函数,该函数的作用是便利各图层,计算得到需要更新的区域。在走下一个函数会发现其实最终都是走到第三个分支。那么就跟踪handleMessageRefresh():

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void SurfaceFlinger::handleMessageRefresh() {  
  2.     ATRACE_CALL();  
  3.     preComposition();  
  4.     rebuildLayerStacks();  
  5.     setUpHWComposer();  
  6.     doDebugFlashRegions();  
  7.     doComposition();  
  8.     postComposition();  
  9.     /* Dynamic check debug.sf.fps ,if 1 then print fps*/  
  10.     if(frm_count++%300==0) {  
  11.         frm_count = 1;  
  12.         char value[PROPERTY_VALUE_MAX];  
  13.         property_get("debug.sf.fps", value, "0");  
  14.         mDebugFPS = atoi(value);  
  15.     }                                                                                                                                    

到这里为止还是属于SF这一层,在接下去就是Layer层对surface的绘制问题了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值