接上篇文章,我们来看一下init()都做了什么事。以下是源码:
void SurfaceFlinger::init() { ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); status_t err; Mutex::Autolock _l(mStateLock); // initialize EGL for the default display mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(mEGLDisplay, NULL, NULL); // Initialize the H/W composer object. There may or may not be an // actual hardware composer underneath. mHwc = new HWComposer(this, *static_cast<HWComposer::EventHandler *>(this)); // First try to get an ES2 config err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT, &mEGLConfig); if (err != NO_ERROR) { // If ES2 fails, try ES1 err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES_BIT, &mEGLConfig); } if (err != NO_ERROR) { // still didn't work, probably because we're on the emulator... // try a simplified query ALOGW("no suitable EGLConfig found, trying a simpler query"); err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig); } if (err != NO_ERROR) { // this EGL is too lame for android LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); } // print some debugging info EGLint r,g,b,a; eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE, &r); eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g); eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE, &b); eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a); ALOGI("EGL informations:"); ALOGI("vendor : %s", eglQueryString(mEGLDisplay, EGL_VENDOR)); ALOGI("version : %s", eglQueryString(mEGLDisplay, EGL_VERSION)); ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS)); ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported"); ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig); // get a RenderEngine for the given display / config (can't fail) mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig); // retrieve the EGL context that was selected/created mEGLContext = mRenderEngine->getEGLContext(); // figure out which format we got eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId); LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT, "couldn't create EGLContext"); // initialize our non-virtual displays for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) { DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i); // set-up the displays that are already connected if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) { // All non-virtual displays are currently considered secure. bool isSecure = true; createBuiltinDisplayLocked(type); wp<IBinder> token = mBuiltinDisplays[i]; sp<BufferQueue> bq = new BufferQueue(new GraphicBufferAlloc()); sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, bq); sp<DisplayDevice> hw = new DisplayDevice(this, type, allocateHwcDisplayId(type), isSecure, token, fbs, bq, mEGLConfig, mHardwareOrientation); if (i > DisplayDevice::DISPLAY_PRIMARY) { // FIXME: currently we don't get blank/unblank requests // for displays other than the main display, so we always // assume a connected display is unblanked. ALOGD("marking display %d as acquired/unblanked", i); hw->acquireScreen(); } mDisplays.add(token, hw); } } // make the GLContext current so that we can create textures when creating Layers // (which may happens before we render something) getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext); // start the EventThread sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true); mEventThread = new EventThread(vsyncSrc); sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, false); mSFEventThread = new EventThread(sfVsyncSrc); mEventQueue.setEventThread(mSFEventThread); mEventControlThread = new EventControlThread(this); mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY); // set a fake vsync period if there is no HWComposer if (mHwc->initCheck() != NO_ERROR) { mPrimaryDispSync.setPeriod(16666667); } // initialize our drawing state mDrawingState = mCurrentState; // set initial conditions (e.g. unblank default device) initializeDisplays(); char value[PROPERTY_VALUE_MAX]; memset(value,0,PROPERTY_VALUE_MAX); property_get("sys.enable.wfd.optimize", value, "0"); mWfdOptimize = atoi(value); // start boot animation startBootAnim(); }
如上代码量太大了我稍微总结了下,它做了以下几件事:
1.初始化EGL,这是干嘛用?首先介绍下EGL,EGL是OpenGL ES和底层Native平台视窗系统之间的接口,也就是说初始化了openGL的API。
2.初始化H/W composer,也就是HardWare的一些事,具体不去研究
3.获得一个显示器的渲染引擎,RendEngine,这是OPENGL发挥作用的平台
4.初始化显示器的一些东西,代码太多,没看懂做了哪些事。
5.启动了线程,EventThread,这个线程在以后的研究中会涉及到。
6.初始化了一些状态条件等。
好了先告一段落,初始化做了一些事情,肯定是为以后做铺垫,暂且继续研究下去。
前一篇文章,研究到了addService(),接下去的一行是:flinger->run();
我们来看下run的实体函数,他定义在SF类中:
void SurfaceFlinger::run() { do { waitForEvent(); } while (true); }
最核心的代码就是waitForEvent();继续跟踪:
void SurfaceFlinger::waitForEvent() { mEventQueue.waitMessage(); }
再继续:
void MessageQueue::waitMessage() { do { IPCThreadState::self()->flushCommands(); int32_t ret = mLooper->pollOnce(-1); switch (ret) { case ALOOPER_POLL_WAKE: case ALOOPER_POLL_CALLBACK: continue; case ALOOPER_POLL_ERROR: ALOGE("ALOOPER_POLL_ERROR"); case ALOOPER_POLL_TIMEOUT: // timeout (should not happen) continue; default: // should not happen ALOGE("Looper::pollOnce() returned unknown status %d", ret); continue; } } while (true); }
到这里,晕了没,看出眉头来了没,这是个庞大的事件机制,稍后给出一张图诠释一下这个事件机制,这张图是网上的大牛画的佩服的五体投地,一看马上拨开云雾见青天。我们还是看下代码把,关键代码在第四行pollOnece(),其实我不敢在写下去,因为里面文章太多,我查阅了网上的一些资料网址如下,大家可参考下:http://blog.csdn.net/broadview2006/article/details/8552148 ,然后我简单说下这里扯到了Looper,这可不是一个好鸟,庞大的事件机制军团中的一员,他配合着Message Handle Thread MessageQueue 完成了太多的事情,以后再去讨论。在这里简单说就是它搞了一个睡眠等待事件,然后等着被唤醒。结合到SF中就是说,这里开了一个线程等待surface的刷新,而做出相关的操作。至于是怎么唤醒的可以参考那个连接博文,这里不再赘述。
既然被睡眠了,那研究该如何进行下去,于是我开始研究是谁把它唤醒的。开始复杂了,要费脑袋了。
这里我先给一张图:
这张图是网上一位大牛博文中的,忘记链接地址了,如有侵权,还请告知我。好了开始正文:
我刚刚说的那个睡眠事件其实就是蓝色框框流程图的走向,图中标的是线程2。这里说一下其他线程分别是什么时候创建的
主线程:在SF中的onFirstRef()创建的,这里有个问题,是谁调用onFirstRef()?android里面 当一个对象第一次被一个强指针应用时,那么这个对象的成员函数onFirstRef就会被调用,如上所说它一早就被调用了,我们看看它的实体:
void SurfaceFlinger::onFirstRef() { mEventQueue.init(this); }
继续跟踪:
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) { mFlinger = flinger; mLooper = new Looper(true); mHandler = new Handler(*this); }
这里new了Looper和Handle,关于这两个什么东西,推荐一片博文:http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html 里面讲的很详细。好了这个是主线程1的创建。
线程2:前面说过,当调用SF::run();时就开始了。
线程3:在SF::init();中创建。也就是初始化中创建:创建关键代码如下:
mEventThread = new EventThread(vsyncSrc); sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, false); mSFEventThread = new EventThread(sfVsyncSrc); mEventQueue.setEventThread(mSFEventThread);
这里我们分两个路线来讲:
1.EventThread继承了Thread线程类,还有它的基类中有RefBase所以当其定义的时候会调用onFirstRef,这个函数里面就一句 run();这里EventThread中的 threadLoop成员函数会被调用,这里看一下函数实体:
bool EventThread::threadLoop() { DisplayEventReceiver::Event event; Vector< sp<EventThread::Connection> > signalConnections; signalConnections = waitForEvent(&event); // dispatch events to listeners... const size_t count = signalConnections.size(); for (size_t i=0 ; i<count ; i++) { const sp<Connection>& conn(signalConnections[i]); // now see if we still need to report this event status_t err = conn->postEvent(event); if (err == -EAGAIN || err == -EWOULDBLOCK) { // The destination doesn't accept events anymore, it's probably // full. For now, we just drop the events on the floor. // FIXME: Note that some events cannot be dropped and would have // to be re-sent later. // Right-now we don't have the ability to do this. ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type, conn.get()); } else if (err < 0) { // handle any other error on the pipe as fatal. the only // reasonable thing to do is to clean-up this connection. // The most common error we'll get here is -EPIPE. removeDisplayEventConnection(signalConnections[i]); } } return true; }
这里的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有关联,这里打住。我们看看这个函数的实体:
void MessageQueue::setEventThread(const sp<EventThread>& eventThread) { mEventThread = eventThread; mEvents = eventThread->createEventConnection();// 这里创建了一个到EventThread的连接
mEventTube = mEvents->getDataChannel();//得到发送VSync事件通知的BitTube
mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT, MessageQueue::cb_eventReceiver, this);
在这里addFd当中的第一个参数就是获得套接字队中的信息,一旦有东西就会回调cb_eventReceiver这个函数,我们跟踪那个回调函数:
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) { MessageQueue* queue = reinterpret_cast<MessageQueue *>(data); return queue->eventReceiver(fd, events); }
第二行是得到事件的queue,以便于下面返回事件接收者。继续跟踪:
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) { #if INVALIDATE_ON_VSYNC mHandler->dispatchInvalidate(); #else mHandler->dispatchRefresh(); #endif break; } } } return 1; }
这个函数大概的意思就是,主循环一直在等待事件的接收,并判断事件的类型是不是DISPLAY_EVENT_VSYNC,如果是就开始执行下一步了,因为文件头有定义#define INVALIDATE_ON_VSYNC 1 所以走的是mHandler->dispatchInvalidate();这个函数。好了到这里,已经出现太多跟VSync有关的字眼,好像也起了很大的作用,这里暂不做研究,之后就会真相大白。不过还是推荐一篇博文大家参考下http://blog.csdn.net/broadview2006/article/details/8541727 继续跟踪dispatchInvalidate()这个函数。
void MessageQueue::Handler::dispatchInvalidate() { if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) { mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE)); } }
看到了一个关键的函数,sendMessage();发出去的消息是 INVALIDATE.看过事件机制的就知道,这里发出的消息是由handleMessage()来接收处理的。到底是哪边的handleMessage()来处理了,还记得之前的主线程2在睡眠等待消息?对就是在它里面。看上面那张图可以知道应该是在pollInner中处理消息的,由于这个消息机制过于复杂这里就略过了,不过推荐大家一篇博文很详细的阐述了 pollOnce和pollInner之间的关系 :http://book.2cto.com/201208/1946.html ,你会发现在函数pollInner中有个处理函数handleMessage();这里继续跟踪:
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; case TRANSACTION: android_atomic_and(~eventMaskTransaction, &mEventMask); mQueue.mFlinger->onMessageReceived(message.what); break; } }
用switch来判断接收的消息到底是什么,刚刚发送的是INVALDATE,所以执行第一条,跟踪onMessageReceived();
void SurfaceFlinger::onMessageReceived(int32_t what) { ATRACE_CALL(); if(mDelayFlag) { usleep(20000); mDelayFlag = 0; } switch (what) { case MessageQueue::TRANSACTION: handleMessageTransaction(); break; case MessageQueue::INVALIDATE: handleMessageTransaction(); handleMessageInvalidate(); signalRefresh(); break; case MessageQueue::REFRESH: handleMessageRefresh(); break; } }
这里走的是第二个分支,第一个函数handleTransaction();这里处理了各种事务,如窗口状态属性变化,继续跟踪handleMessageInvalidate,他调用了一个handlePageFlip()函数,该函数的作用是便利各图层,计算得到需要更新的区域。在走下一个函数会发现其实最终都是走到第三个分支。那么就跟踪handleMessageRefresh():
void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); preComposition(); rebuildLayerStacks(); setUpHWComposer(); doDebugFlashRegions(); doComposition(); postComposition(); /* Dynamic check debug.sf.fps ,if 1 then print fps*/ if(frm_count++%300==0) { frm_count = 1; char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.fps", value, "0"); mDebugFPS = atoi(value); }
到这里为止还是属于SF这一层,在接下去就是Layer层对surface的绘制问题了