五 SF到底做了什么事
接上篇文章,我们来看一下init()都做了什么事。以下是源码:
- void SurfaceFlinger::init() {
- ALOGI( "SurfaceFlinger's main thread ready to run. "
- "Initializing graphics H/W...");
-
- status_t err;
- Mutex::Autolock _l(mStateLock);
-
-
- mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(mEGLDisplay, NULL, NULL);
-
-
-
- mHwc = new HWComposer(this,
- *static_cast<HWComposer::EventHandler *>(this));
-
-
- err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT,
- &mEGLConfig);
- if (err != NO_ERROR) {
-
- err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(),
- EGL_OPENGL_ES_BIT, &mEGLConfig);
- }
-
- if (err != NO_ERROR) {
-
-
- ALOGW("no suitable EGLConfig found, trying a simpler query");
- err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig);
- }
-
- if (err != NO_ERROR) {
-
- LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
- }
-
-
- 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);
-
-
- mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig);
-
-
- mEGLContext = mRenderEngine->getEGLContext();
-
-
- eglGetConfigAttrib(mEGLDisplay, mEGLConfig,
- EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId);
-
- LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
- "couldn't create EGLContext");
-
-
- for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
- DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
-
- if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
-
- 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) {
-
-
-
- ALOGD("marking display %d as acquired/unblanked", i);
- hw->acquireScreen();
- }
- mDisplays.add(token, hw);
- }
- }
-
-
-
- getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
-
-
- 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);
-
-
- if (mHwc->initCheck() != NO_ERROR) {
- mPrimaryDispSync.setPeriod(16666667);
- }
-
-
- mDrawingState = mCurrentState;
-
-
- initializeDisplays();
-
- char value[PROPERTY_VALUE_MAX];
- memset(value,0,PROPERTY_VALUE_MAX);
- property_get("sys.enable.wfd.optimize", value, "0");
- mWfdOptimize = atoi(value);
-
- 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:
-
- continue;
- default:
-
- 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);
-
-
- 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;
- }
这里的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();
- mEventTube = mEvents->getDataChannel();
- 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();
-
- 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的绘制问题了