2017年10月11日 星期三

Android系統筆記 - Surface simple flow (2) Surface Flinger 的創建

作為一個 Native 的 Service, 想當然爾是在某個 main_xxx 帶起來的.
讓我們看看 init.rc, 果然找到了服務如下:


service surfaceflinger /system/bin/surfaceflinger
    class core
    user system
    group graphics drmrpc
    onrestart restart zygote

surfaceflinger 的 Makefile 放在 frameworks/native/services/surfaceflinger 下面
=> main_surfaceflinger.cpp

int main(int, char**) {
    ...
    // instantiate surfaceflinger
    sp<SurfaceFlinger> flinger = new SurfaceFlinger();

    // initialize before clients can connect
    flinger->init();

    // publish surface flinger
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
    ...

    // run in this thread
    flinger->run();
}

1.) new SurfaceFlinger();
=> 建構子讀了一些 property 並設置對應的 debug 訊息, 暫時跳過.
     這邊可以看到它繼承了 BnSurfaceComposer

SurfaceFlinger::SurfaceFlinger()
    :   BnSurfaceComposer(), xxx

=> 第一次建立 SurfaceFlinger 時, 呼叫 MessageQueue 的 init
void SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);
}

=> 這裡保存了 mFlinger, 並生出 Looper & Handler
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)  
{  
    mFlinger = flinger;  
    mLooper = new Looper(true);  
    mHandler = new Handler(*this);  
}

# mHandler 是定義在 MessageQueue 裡面的 subClass,
  它繼承了 MessageHandler, 並在 mQueue 保存了自己這個 MessageQueue

    class Handler : public MessageHandler {
 enum {
     eventMaskInvalidate     = 0x1,
     eventMaskRefresh        = 0x2,
     eventMaskTransaction    = 0x4
 };
 MessageQueue& mQueue;
 int32_t mEventMask;
    public:
 Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }
 virtual void handleMessage(const Message& message);
 void dispatchRefresh();
 void dispatchInvalidate();
 void dispatchTransaction();
    };

2.) flinger->init();

這邊先貼上完整的代碼, 下面一步一步分析

void SurfaceFlinger::init() {
    ALOGI(  "SurfaceFlinger's main thread ready to run. "
            "Initializing graphics H/W...");

    Mutex::Autolock _l(mStateLock);

    // initialize EGL for the default display
    // EGL 是 OpenGL ES 的接點, 主要功能是完成 OpenGL 創建 Context, 繪製Surface, 配置Framebuffer属性、Swap提交繪製結果
    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(mEGLDisplay, NULL, NULL);

    // start the EventThread
    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            vsyncPhaseOffsetNs, true, "app");
    mEventThread = new EventThread(vsyncSrc);
    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            sfVsyncPhaseOffsetNs, true, "sf");
    mSFEventThread = new EventThread(sfVsyncSrc);
    mEventQueue.setEventThread(mSFEventThread);

    // 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));

    // get a RenderEngine for the given display / config (can't fail)
    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());

    // retrieve the EGL context that was selected/created
    mEGLContext = mRenderEngine->getEGLContext();

    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<IGraphicBufferProducer> producer;
            sp<IGraphicBufferConsumer> consumer;
            BufferQueue::createBufferQueue(&producer, &consumer,
                    new GraphicBufferAlloc());
            // 為什麼這裡要自己 new GraphicBufferAlloc() 而不是跟 Layer 一樣只有呼叫 producer & consumer ?

            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
                    consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                    fbs, producer,
                    mRenderEngine->getEGLConfig());
            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 %zu as acquired/unblanked", i);
                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
            }
            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);

    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();

    // start boot animation
    startBootAnim();
}

=> 先跳過EGL, 來看 DispSyncSource,
     它繼承了 VSyncSource 跟 DispSync::Callback, 並傳入了 mPrimaryDispSync 的 address.
     這個 mPrimaryDispSync 的類型是 DispSync, 它會啟動一個 DispSyncThread
DispSync::DispSync() :
 mRefreshSkipCount(0),
 mThread(new DispSyncThread()) {
    
    mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
  
    reset();
    beginResync();
}

=> 這個 threadLoop 會進行計時, 並在計時結束時,
             把所有需要觸發 callback 的 listener 蒐集到 callbackInvocations 裡面一起觸發
        while (true) {
            Vector<CallbackInvocation> callbackInvocations;

            nsecs_t targetTime = 0;

     // Scope for lock
            {
                if (mPeriod == 0) {
                    err = mCond.wait(mMutex);
                    continue;
                }

                nextEventTime = computeNextEventTimeLocked(now);
                targetTime = nextEventTime;

                bool isWakeup = false;

                if (now < targetTime) {
                    err = mCond.waitRelative(mMutex, targetTime - now);

                    if (err == TIMED_OUT) {
                        isWakeup = true;
                    }
                }
                now = systemTime(SYSTEM_TIME_MONOTONIC);

                if (isWakeup) {
                    mWakeupLatency = ((mWakeupLatency * 63) +
                            (now - targetTime)) / 64;
                    if (mWakeupLatency > 500000) {
                        // Don't correct by more than 500 us
                        mWakeupLatency = 500000;
                    }
                }

                callbackInvocations = gatherCallbackInvocationsLocked(now);
            }

            if (callbackInvocations.size() > 0) {
                fireCallbackInvocations(callbackInvocations);
            }
        }

=> 觸發就是呼叫 onDispSyncEvent
void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
   for (size_t i = 0; i < callbacks.size(); i++) {
       callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
   }
}

=> 回到一開始 DispSyncSource 繼承的 DispSync::Callback 如下, 需要 implement onDispSyncEvent
class Callback: public virtual RefBase {
public:
    virtual ~Callback() {};
    virtual void onDispSyncEvent(nsecs_t when) = 0;
};

=> 可以看到在內部的實作如下
class DispSyncSource : public VSyncSource, private DispSync::Callback {
private:
    virtual void onDispSyncEvent(nsecs_t when) {
        sp<VSyncSource::Callback> callback;
        {
            Mutex::Autolock lock(mCallbackMutex);
            callback = mCallback;
            if (mTraceVsync) {
                mValue = (mValue + 1) % 2;
                ATRACE_INT(mVsyncEventLabel.string(), mValue);
            }
        }
        if (callback != NULL) {
            callback->onVSyncEvent(when);
        }
    }
}

=> 那麼 mCallback 又是從哪來的?
=> 答案是透過 setCallback 來的,
                   下一行的 mEventThread = new EventThread(vsyncSrc);
  透過它的 EventThread::enableVSyncLocked function 來呼叫,
   他的 Callback class 如下:
class Callback: public virtual RefBase {
    public:
        virtual ~Callback() {}
        virtual void onVSyncEvent(nsecs_t when) = 0;
};

=> 而實作的形式為
void EventThread::onVSyncEvent(nsecs_t timestamp) {
    Mutex::Autolock _l(mLock);
    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    mVSyncEvent[0].header.id = 0;
    mVSyncEvent[0].header.timestamp = timestamp;
    mVSyncEvent[0].vsync.count++;
    mCondition.broadcast();
}
所以當一個 DispSync 的 Event 來時, 會透過 onDispSyncEvent => onVSyncEvent

=> 下一行的 mSFEventThread 也做了差不多的事情,
   只是這邊多呼叫了 mEventQueue.setEventThread(mSFEventThread),
   將 mSFEventThread 保存到 MessageQueue 裡面的 mEventThread 變量
   (這邊看不出來要幹嘛...好像沒用到?)

=> 再來生成了一個 HW Composer
    mHwc = new HWComposer(this,
            *static_cast<HWComposer::EventHandler *>(this));

=> 這裡會跟 VSync 掛勾 (mCBContext->procs.vsync = &hook_vsync,
              把Callback function註冊給HWC)

HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger, EventHandler& handler)
{
    ...
    // Note: some devices may insist that the FB HAL be opened before HWC.
    int fberr = loadFbHalModule();
    loadHwcModule();
    if (mHwc) {
        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
           (hwcApiVersion(mHwc) >> 24) & 0xff,
           (hwcApiVersion(mHwc) >> 16) & 0xff);
        if (mHwc->registerProcs) {
             mCBContext->hwc = this;
             mCBContext->procs.invalidate = &hook_invalidate;
             mCBContext->procs.vsync = &hook_vsync;
             if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
                 mCBContext->procs.hotplug = &hook_hotplug;
             else
                 mCBContext->procs.hotplug = NULL;
             memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
             mHwc->registerProcs(mHwc, &mCBContext->procs);
        }

        // don't need a vsync thread if we have a hardware composer
        needVSyncThread = false;
        // always turn vsync off when we start
        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
        // the number of displays we actually have depends on the
        // hw composer version
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
            // 1.3 adds support for virtual displays
            mNumDisplays = MAX_HWC_DISPLAYS;
        }
    }
}

=> 呼叫 RenderEngine::create(), 將 EGLDisplay 與 hwc format 放入

 RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) {
     RenderEngine* engine = NULL;
     switch (version) {
        engine = new GLESXXRenderEngine();
     }
     engine->setEGLHandles(config, ctxt);

     return engine;
 }

=> 對所有 non-virtual diplay 進行初始化

    // 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<IGraphicBufferProducer> producer;
            sp<IGraphicBufferConsumer> consumer;
            BufferQueue::createBufferQueue(&producer, &consumer,
                    new GraphicBufferAlloc());
            /* 不曉得為什麼這裡要自己 new GraphicBufferAlloc(),
               而不是跟 Layer 一樣只有呼叫 producer & consumer ? */

            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
                    consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                    fbs, producer,
                    mRenderEngine->getEGLConfig());
            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 %zu as acquired/unblanked", i);
                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
            }
            mDisplays.add(token, hw);
        }
    }

=> createBufferQueue 之前會先 new 一個 allocator 出來 (new GraphicBufferAlloc())
           不過在 createBufferQueue 內部也會檢查 allocator 是否為 NULL ... 然後最終還是會呼叫到 new GraphicBufferAlloc()

=> 之後在 BufferQueueProducer 呼叫 dequeueBuffer / allocateBuffers 時會透過這個 allocator 生成 GraphicBuffer
  透過 GraphicBuffer 與 GraphicBufferAlloctor 也就是 gralloc module 進行交互 (注意是 GraphicBufferAlloctor 而不是 GraphicBufferAlloc ...)
                   主要是透過 gralloc module 去進行緩衝區的分配 (Either on RAM or Framebuffer)

=> createBufferQueue 對 producer 跟 consumer 進行了配置, 分別對應到 BufferQueueProducer 跟 BufferQueueConsumer
  他們藉由 BufferQueueCore(allocator) 進行交互. (另外雖然 allocator 也帶入了 core, 但好像沒有拿來用)

=> 接下來生成一個 FramebufferSurface, 並帶入了 HWComposer 與剛剛生成的 consumer
=> consumer 作為 FramebufferSurface 繼承的父類別的 ConsumerBase 內部的 mConsumer 對象被保存起來
  hwc 則保存在 mHwc 對象中, 稍微爬了一下代碼, 裡面會呼叫 Hwc 對於 fence 的操作等功能

=> 後面在 BufferQueueProducer 的內部, 我們會看到它取出了 frameAvailableListener = mCore->mConsumerListener;
  並去呼叫 frameAvailableListener->onFrameAvailable(item);
  mCore->mConsumerListener = consumerListener; 則是在 BufferQueueConsumer::connect() 賦值的, 這個我們後面會再看到.

=> 再來, 生成 DisplayDevice, 這裡將 producer 帶入

  DisplayDevice::DisplayDevice()
  {
      mNativeWindow = new Surface(producer, false);
      ANativeWindow* const window = mNativeWindow.get();

      /*
       * Create our display's surface
       */

      EGLSurface surface;
      EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
      if (config == EGL_NO_CONFIG) {
   config = RenderEngine::chooseEglConfig(display, format);
      }
      surface = eglCreateWindowSurface(display, config, window, NULL);

      ...

      if (mType >= DisplayDevice::DISPLAY_VIRTUAL) {
   // reset virtual display buffer format.
   // because it is changed by eglCreateWindowSurface().
   native_window_set_buffers_format(window, format);
   window->setSwapInterval(window, 0);
      }
  }


=> 可以看到這邊又生成了一個 Surface 對象,
     把 producer 帶入, 保存在 mGraphicBufferProducer 內

   Surface::Surface(
    const sp<IGraphicBufferProducer>& bufferProducer,
    bool controlledByApp)
       : mGraphicBufferProducer(bufferProducer),
         mGenerationNumber(0)
   {
       // Initialize the ANativeWindow function pointers.
       ANativeWindow::setSwapInterval  = hook_setSwapInterval;
       ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
       ANativeWindow::cancelBuffer     = hook_cancelBuffer;
       ...
   }
=> 之後會透過 Surface 對象來呼叫 BufferQueueProducer 的 allocateBuffers / dequeueBuffer 等動作

=> 取得剛剛設定好的 Surface 對象, 在 Constructor 裡面已經完成了一些指定 ANativeWindow* const window = mNativeWindow.get();
  生成 EGL 用的 surface, display 等對象

      /*
       * Create our display's surface
       */
      EGLSurface surface;
      EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
      if (config == EGL_NO_CONFIG) {
   config = RenderEngine::chooseEglConfig(display, format);
      }
      surface = eglCreateWindowSurface(display, config, window, NULL);

      mSurface = surface;
      mDisplay = display;

=> 先總結一下, 現在的 producer 藉由 DisplayDevice 的 mNativeWindow 傳遞給了 EGL
  而 consumer 則是給了 FramebufferSurface, 等收到了 onFrameAvailable 之後, 就會呼叫 HWComposer 的 fbPost 函數開始輸出

void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {  
    sp<GraphicBuffer> buf;  
    sp<Fence> acquireFence;  
    status_t err = nextBuffer(buf, acquireFence);  
    if (err != NO_ERROR) {  
        ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",  
            strerror(-err), err);  
        return;  
    }  
    err = mHwc.fbPost(mDisplayType, acquireFence, buf);  
    if (err != NO_ERROR) {  
        ALOGE("error posting framebuffer: %d", err);  
    }
}

=> 啟動 EventControlThread, 並呼叫一次 eventControl (一開始 mVsyncEnabled 是 false)
    mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,
            mVsyncEnabled);

=> 這個 eventControl 最終會呼叫到 HWComposer 的 HAL 的 eventControl, 以 mx6 為例,
  它會呼叫 hwc_eventControl, 並設定 VSyncThread 的 mEnabled 值
ctx->m_vsync_thread->setEnabled(enabled);

=> mEnabled = false 的時候會讓 threadLoop 卡在這邊等 mCondition


bool VSyncThread::threadLoop()
{
    { // scope for lock
        Mutex::Autolock _l(mLock);
        while (!mEnabled) {
            mCondition.wait(mLock);
        }
    }
    if (mFakeVSync) {
        performFakeVSync();
    }
    else {
        performVSync();
    }
    return true;
}


=> 呼叫 initializeDisplays(); 送出一個 Async 的 command (MessageScreenInitialized)
=> 前面追過了, 收到之後會執行 handler, 所以會呼叫 onInitializeDisplays

=> SurfaceFlinger 啟動完成, 呼叫 property_set 來啟動 bootAnimation

沒有留言:

張貼留言

不定參數印 log

From the UNIXProcess_md.c #ifdef DEBUG_PROCESS   /* Debugging process code is difficult; where to write debug output? */ static void deb...