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

五 SF到底做了什么事     

   接上篇文章,我们来看一下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,EGLOpenGL 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的绘制问题了

 

 

 


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值