SurfaceFlinger原理(一):SurfaceFlinger的初始化

SurfaceFlinger是Android的一個native進程,負責將圖層進行合成,圖層疊加起來就構成了咱們看到的界面。合成的方式分爲在線合成和離線合成。在線合成是指如今一塊buffer畫好全部的內容,而後直接交給linux圖像驅動framebuffer顯示出來;離線合成是指將一些圖層的buffer直接遞交HWComposer,HWComposer指的是可以處理圖像數據並組合的現實硬件模塊(有些設備上可能沒有),當須要顯示某一行的數據時,再將這些圖層的數據進行處理組合後再交給framebuffer顯示出來,合成方式有MDP,DYN,C2D等,反正不是GPU,於是減輕了GPU負擔。 
  SurfaceFlinger啓動的main函數在main_surfaceflinger.cpp中。最後的run函數使SurfaceFlinger進程陷入do…while循環中,不會退出。咱們重點關注SurfaceFlinger的init函數。linux

/frameworks/native/services/surfaceflinger/main_surfaceflinger.cppapp

int main(int, char**) {
    // When SF is launched in its own process, limit the number of
    // binder threads to 4.
    ProcessState::self()->setThreadPoolMaxThreadCount(4);composer

    // start the thread pool
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();async

    // instantiate surfaceflinger
    sp<SurfaceFlinger> flinger = new SurfaceFlinger();ide

#if defined(HAVE_PTHREADS)
    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
#endif
    set_sched_policy(0, SP_FOREGROUND);函數

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

    // publish surface flinger
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);ui

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

    return 0;
}
下面介紹的狀況均以只有一個主屏幕(id爲0)爲前提,實際上Android支持三種屏幕:主屏幕,外接屏幕(HDMI等),虛擬屏幕(投屏)。init函數的主要工做有:1.初始化EGL的一些環境以及設置;2.啓動hwc;3.搜尋可用的屏幕,初始化屏幕的一些信息,新建DisplayDevice和FramebufferSurface,並分別做爲生產者和消費者;4.分別爲app端和SurfaceFlinger創建一個EventThread以響應vysnc信號;5.啓動bootanimation。線程

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

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
    //初始化EGL環境
    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.
    //初始化hwc
    mHwc = new HWComposer(this,
            *static_cast<HWComposer::EventHandler *>(this));

    // get a RenderEngine for the given display / config (can't fail)
    //建立RenderEngine,RenderEngine封裝了一些OpenGL的操做
    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());

    // retrieve the EGL context that was selected/created
    //獲取EGL上下文
    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;
            //建立內置屏幕,每一個屏幕id對應一個binder對象
            createBuiltinDisplayLocked(type);
            wp<IBinder> token = mBuiltinDisplays[i];

            //建立生產者和消費者
            sp<IGraphicBufferProducer> producer;
            sp<IGraphicBufferConsumer> consumer;
            BufferQueue::createBufferQueue(&producer, &consumer,
                    new GraphicBufferAlloc());
            //新建FramebufferSurface做爲消費者,向framebuffer傳遞數據就靠它了
            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
                    consumer);
            //爲屏幕建立hwc層的id
            int32_t hwcId = allocateHwcDisplayId(type);
            //新建DisplayDevice生產者,與顯示畫面有關
            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);
            }
            //屏幕id的對應的binder對象和DisplayDevice組成鍵值對,保存在mDisplays
            mDisplays.add(token, hw);
        }
    }

    // make the GLContext current so that we can create textures when creating Layers
    // (which may happens before we render something)
    //DisplayDevice::makeCurrent會調用到eglMakeCurrent,libagl.so的實現裏eglMakeCurrent會dequeue一塊buffer
    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);

    // start the EventThread
    //基於不一樣的vsync信號模型建立的EventThread,mEventThread是app端對vsync信號的處理線程,mSFEventThread是SurfaceFlinger端對vysnc信號的處理線程
    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);
    //mEventControlThread線程用來開關vsync
    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);

    // set a fake vsync period if there is no HWComposer
    //hwc層初始化失敗後,使用1/16666667的屏幕刷新週期
    if (mHwc->initCheck() != NO_ERROR) {
        mPrimaryDispSync.setPeriod(16666667);
    }

    // initialize our drawing state
    //初始化mDrawingState
    mDrawingState = mCurrentState;

    // set initial conditions (e.g. unblank default device)
    //初始化主屏幕的一些flag和信息
    initializeDisplays();

    // start boot animation
    //啓動bootanimation
    startBootAnim();
}

  先看看hwc的初始化。vsync信號分爲兩種:1.硬件產生的vsync;2.軟件模擬的vsync。這份源碼對應的是Android 5.1,使用的hwc HAL版本是1.4,因此不會打開framebuffer設備,在有hwc設備的狀況下不會開啓軟件模擬vysnc。 
並且硬件vsync一開始是出於關閉狀態的。

/frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp

HWComposer::HWComposer(
        const sp<SurfaceFlinger>& flinger,
        EventHandler& handler)
    : mFlinger(flinger),
      mFbDev(0), mHwc(0), mNumDisplays(1),
      mCBContext(new cb_context),
      mEventHandler(handler),
      mDebugForceFakeVSync(false)
{
    for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
        mLists[i] = 0;
    }

    for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
        mLastHwVSync[i] = 0;
        mVSyncCounts[i] = 0;
    }

    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.no_hw_vsync", value, "0");
    //mDebugForceFakeVSync決定咱們是否啓用硬件vsync,爲true時永久關閉硬件vsync
    mDebugForceFakeVSync = atoi(value);
    //表示是否須要軟件模擬vsync
    bool needVSyncThread = true;

    // Note: some devices may insist that the FB HAL be opened before HWC.
    //加載framebuffer和hwc的HAL模塊
    int fberr = loadFbHalModule();
    loadHwcModule();

    if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
        // close FB HAL if we don't needed it.
        // FIXME: this is temporary until we're not forced to open FB HAL
        // before HWC.
        //若是framebuffer和hwc的硬件設備都被成功加載,且hwc HAL版本大於等於1.1,關閉framebuffer硬件設備
        framebuffer_close(mFbDev);
        mFbDev = NULL;
    }

    // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
    if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
            && !mFbDev) {
        ALOGE("ERROR: failed to open framebuffer (%s), aborting",
                strerror(-fberr));
        abort();
    }

    // these display IDs are always reserved
    //NUM_BUILTIN_DISPLAYS(2)之內的id已被佔用,申請hwc id須要從NUM_BUILTIN_DISPLAYS開始申請
    for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
        mAllocatedDisplayIDs.markBit(i);
    }

    if (mHwc) {
        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
              (hwcApiVersion(mHwc) >> 24) & 0xff,
              (hwcApiVersion(mHwc) >> 16) & 0xff);
        if (mHwc->registerProcs) {
            //註冊hwc HAL層回調事件
            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
        //有hwc模塊就不須要軟件模擬vysnc了
        needVSyncThread = false;
        // always turn vsync off when we start
        //hwc初始化時先關閉硬件vysnc
        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;
        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
            // 1.1 adds support for multiple displays
            mNumDisplays = NUM_BUILTIN_DISPLAYS;
        } else {
            mNumDisplays = 1;
        }
    }

    if (mFbDev) {
        //hwc HAL1.1以上的版本mFbDev爲null,不會走到該分支
        ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
                "should only have fbdev if no hwc or hwc is 1.0");

        DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
        disp.connected = true;
        disp.format = mFbDev->format;
        DisplayConfig config = DisplayConfig();
        config.width = mFbDev->width;
        config.height = mFbDev->height;
        config.xdpi = mFbDev->xdpi;
        config.ydpi = mFbDev->ydpi;
        config.refresh = nsecs_t(1e9 / mFbDev->fps);
        disp.configs.push_back(config);
        disp.currentConfig = 0;
    } else if (mHwc) {
        // here we're guaranteed to have at least HWC 1.1
        //執行到這裏說明是hwc HAL1.1以上的版本,這裏從HAL層獲取屏幕信息填充mDisplayData成員變量
        for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
            queryDisplayProperties(i);
        }
    }

    if (needVSyncThread) {
        // we don't have VSYNC support, we need to fake it
        //不支持硬件vsyn,就開啓軟件模擬vysnc線程
        mVSyncThread = new VSyncThread(*this);
    }
}

  再看看DisplayDevice的初始化。

/frameworks/native/services/surfaceflinger/DisplayDevice.cpp

DisplayDevice::DisplayDevice(
        const sp<SurfaceFlinger>& flinger,
        DisplayType type,
        int32_t hwcId,
        int format,
        bool isSecure,
        const wp<IBinder>& displayToken,
        const sp<DisplaySurface>& displaySurface,
        const sp<IGraphicBufferProducer>& producer,
        EGLConfig config)
    : lastCompositionHadVisibleLayers(false),
      mFlinger(flinger),
      mType(type), mHwcDisplayId(hwcId),
      mDisplayToken(displayToken),
      mDisplaySurface(displaySurface),
      mDisplay(EGL_NO_DISPLAY),
      mSurface(EGL_NO_SURFACE),
      mDisplayWidth(), mDisplayHeight(), mFormat(),
      mFlags(),
      mPageFlipCount(),
      mIsSecure(isSecure),
      mSecureLayerVisible(false),
      mLayerStack(NO_LAYER_STACK),
      mOrientation(),
      mPowerMode(HWC_POWER_MODE_OFF),
      mActiveConfig(0)
{
    //DisplayDevice新建一個Surface做爲生產者
    mNativeWindow = new Surface(producer, false);
    ANativeWindow* const window = mNativeWindow.get();

    /*
     * Create our display's surface
     */

    EGLSurface surface;
    EGLint w, h;
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (config == EGL_NO_CONFIG) {
        config = RenderEngine::chooseEglConfig(display, format);
    }
    //建立EGLSurface
    surface = eglCreateWindowSurface(display, config, window, NULL);
    //獲取Surface的寬高,保存在mDisplayWidth和mDisplayHeight中,這兩個值在消費者FrameBufferSurfcae建立時從hwc HAL層得到,就是屏幕的寬高值
    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);

    // Make sure that composition can never be stalled by a virtual display
    // consumer that isn't processing buffers fast enough. We have to do this
    // in two places:
    // * Here, in case the display is composed entirely by HWC.
    // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
    //   window's swap interval in eglMakeCurrent, so they'll override the
    //   interval we set here.
    if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
        window->setSwapInterval(window, 0);

    mConfig = config;
    mDisplay = display;
    mSurface = surface;
    mFormat  = format;
    mPageFlipCount = 0;
    mViewport.makeInvalid();
    mFrame.makeInvalid();

    // virtual displays are always considered enabled
    //主屏幕的電源模式初始化爲關閉狀態,在SurfaceFlinger::onInitializeDisplays中,會將主屏幕的電源模式設爲HWC_POWER_MODE_NORMAL
    mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
                  HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;

    // Name the display.  The name will be replaced shortly if the display
    // was created with createDisplay().
    switch (mType) {
        case DISPLAY_PRIMARY:
            mDisplayName = "Built-in Screen";
            break;
        case DISPLAY_EXTERNAL:
            mDisplayName = "HDMI Screen";
            break;
        default:
            mDisplayName = "Virtual Screen";    // e.g. Overlay #n
            break;
    }

    // initialize the display orientation transform.
    //調整顯示設備視角的大小、位移、旋轉等參數,eOrientationDefault指的是默認的旋轉方向,mViewport指的是邏輯顯示區域,mFrame指的是物理顯示區域
    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
}

  再看看雙EventThread的初始化。咱們能夠在基於物理vsync的基礎上添加相移,做爲獨立的vsync起始位置mPhase,再根據vsync的週期mPeriod,能夠獨立就算出一個獨立的vsync模型,供app和SurfaceFlinger兩個EventThread使用。並且還能夠在後續的過程當中動態更新這個vsync模型,這樣作可使物理vsync,app繪製下一幀,SurfaceFlinger合成圖層錯開工做,避免同一時間同時執行這三個操做,提升效率。 
  vsyncPhaseOffsetNs是app端的DispSyncSource使用的相移mPhase由VSYNC_EVENT_PHASE_OFFSET_NS宏指定,能夠在在mk文件加入LOCAL_CFLAGS := -DVSYNC_EVENT_PHASE_OFFSET_NS=xxx指定;而SurfaceFlinger端使用的相移SF_VSYNC_EVENT_PHASE_OFFSET_NS則由SF_VSYNC_EVENT_PHASE_OFFSET_NS指定,也能夠在mk文件中指定。而mPeriod在兩個DispSyncSource構建時爲0。

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

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

  mPrimaryDispSync是一個DispSync對象,其在構造時會執行一個DispSyncThread線程。該線程負責在使能vync的時候執行一些回調操做,從而觸發更新圖層或者app繪製下一幀的動做。這個在之後篇幅再介紹。

/frameworks/native/services/surfaceflinger/DispSync.cpp

DispSync::DispSync() :
        mRefreshSkipCount(0),
        mThread(new DispSyncThread()) {

    mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);

    reset();
    beginResync();

    if (kTraceDetailedInfo) {
        // If we're not getting present fences then the ZeroPhaseTracer
        // would prevent HW vsync event from ever being turned off.
        // Even if we're just ignoring the fences, the zero-phase tracing is
        // not needed because any time there is an event registered we will
        // turn on the HW vsync events.
        if (!kIgnorePresentFences) {
            addEventListener(0, new ZeroPhaseTracer());
        }
    }
}

  SurfaceFlinger::initializeDisplays用來初始化一些狀態。

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::initializeDisplays() {
    class MessageScreenInitialized : public MessageBase {
        SurfaceFlinger* flinger;
    public:
        MessageScreenInitialized(SurfaceFlinger* flinger) : flinger(flinger) { }
        virtual bool handler() {
            flinger->onInitializeDisplays();
            return true;
        }
    };
    sp<MessageBase> msg = new MessageScreenInitialized(this);
    postMessageAsync(msg);  // we may be called from main thread, use async message
}

  DisplayState用來記錄一個屏幕設備的狀態信息。這裏將主屏幕的變化flag設爲eDisplayProjectionChanged |eLayerStackChanged;將layerStack 設爲0(一般一個屏幕對應一個layerstack);將orientation設爲默認旋轉方向等等。這些信息都會被封裝到DisplayState中,這個DisplayState會被添加到裝載DisplayState的vector displays中,經過setTransactionState–>setDisplayStateLocked傳遞給mCurrentState的displays成員。SurfaceFlinger維持了兩個成員變量mCurrentState和mDrawingState,mCurrentState記錄了SurfaceFlinger當前屏幕的相關信息,mDrawingState記錄了上一次更新圖層時屏幕的相關信息。經過對比mCurrentState和mDrawingState,能夠知道屏幕的哪些參數發生了改變,並更新這些信息到mCurrentState中。若是發生了變化,還會觸發一次signalTransaction以更新圖層。

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::onInitializeDisplays() {
    // reset screen orientation and use primary layer stack
    Vector<ComposerState> state;
    Vector<DisplayState> displays;
    DisplayState d;
    d.what = DisplayState::eDisplayProjectionChanged |
             DisplayState::eLayerStackChanged;
    d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
    d.layerStack = 0;
    d.orientation = DisplayState::eOrientationDefault;
    d.frame.makeInvalid();
    d.viewport.makeInvalid();
    d.width = 0;
    d.height = 0;
    displays.add(d);
    setTransactionState(state, displays, 0);
    setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);

    const nsecs_t period =
            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
    mAnimFrameTracker.setDisplayRefreshPeriod(period);
}

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::setTransactionState(
        const Vector<ComposerState>& state,
        const Vector<DisplayState>& displays,
        uint32_t flags)
{
    ATRACE_CALL();
    Mutex::Autolock _l(mStateLock);
    uint32_t transactionFlags = 0;

    if (flags & eAnimation) {
        // For window updates that are part of an animation we must wait for
        // previous animation "frames" to be handled.
        while (mAnimTransactionPending) {
            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
            if (CC_UNLIKELY(err != NO_ERROR)) {
                // just in case something goes wrong in SF, return to the
                // caller after a few seconds.
                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
                        "waiting for previous animation frame");
                mAnimTransactionPending = false;
                break;
            }
        }
    }

    size_t count = displays.size();
    for (size_t i=0 ; i<count ; i++) {
        const DisplayState& s(displays[i]);
        //更新屏幕信息到mCurrentState
        transactionFlags |= setDisplayStateLocked(s);
    }

    count = state.size();
    for (size_t i=0 ; i<count ; i++) {
        const ComposerState& s(state[i]);
        // Here we need to check that the interface we're given is indeed
        // one of our own. A malicious client could give us a NULL
        // IInterface, or one of its own or even one of our own but a
        // different type. All these situations would cause us to crash.
        //
        // NOTE: it would be better to use RTTI as we could directly check
        // that we have a Client*. however, RTTI is disabled in Android.
        if (s.client != NULL) {
            sp<IBinder> binder = s.client->asBinder();
            if (binder != NULL) {
                String16 desc(binder->getInterfaceDescriptor());
                if (desc == ISurfaceComposerClient::descriptor) {
                    sp<Client> client( static_cast<Client *>(s.client.get()) );
                    transactionFlags |= setClientStateLocked(client, s.state);
                }
            }
        }
    }

    if (transactionFlags) {
        // this triggers the transaction
        //屏幕信息發生了變化,觸發更新圖層
        setTransactionFlags(transactionFlags);

        // if this is a synchronous transaction, wait for it to take effect
        // before returning.
        if (flags & eSynchronous) {
            mTransactionPending = true;
        }
        if (flags & eAnimation) {
            mAnimTransactionPending = true;
        }
        while (mTransactionPending) {
            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
            if (CC_UNLIKELY(err != NO_ERROR)) {
                // just in case something goes wrong in SF, return to the
                // called after a few seconds.
                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
                mTransactionPending = false;
                break;
            }
        }
    }
}

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
{
    ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
    if (dpyIdx < 0)
        return 0;

    uint32_t flags = 0;
    DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
    if (disp.isValid()) {
        const uint32_t what = s.what;
        if (what & DisplayState::eSurfaceChanged) {
            if (disp.surface->asBinder() != s.surface->asBinder()) {
                disp.surface = s.surface;
                flags |= eDisplayTransactionNeeded;
            }
        }
        if (what & DisplayState::eLayerStackChanged) {
            if (disp.layerStack != s.layerStack) {
                disp.layerStack = s.layerStack;
                flags |= eDisplayTransactionNeeded;
            }
        }
        if (what & DisplayState::eDisplayProjectionChanged) {
            if (disp.orientation != s.orientation) {
                disp.orientation = s.orientation;
                flags |= eDisplayTransactionNeeded;
            }
            if (disp.frame != s.frame) {
                disp.frame = s.frame;
                flags |= eDisplayTransactionNeeded;
            }
            if (disp.viewport != s.viewport) {
                disp.viewport = s.viewport;
                flags |= eDisplayTransactionNeeded;
            }
        }
        if (what & DisplayState::eDisplaySizeChanged) {
            if (disp.width != s.width) {
                disp.width = s.width;
                flags |= eDisplayTransactionNeeded;
            }
            if (disp.height != s.height) {
                disp.height = s.height;
                flags |= eDisplayTransactionNeeded;
            }
        }
    }
    return flags;
}

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
        int mode) {
    ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
            this);
    int32_t type = hw->getDisplayType();
    int currentMode = hw->getPowerMode();

    if (mode == currentMode) {
        ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
        return;
    }

    hw->setPowerMode(mode);
    if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
        ALOGW("Trying to set power mode for virtual display");
        return;
    }

    if (currentMode == HWC_POWER_MODE_OFF) {
        getHwComposer().setPowerMode(type, mode);
        if (type == DisplayDevice::DISPLAY_PRIMARY) {
            // FIXME: eventthread only knows about the main display right now
            mEventThread->onScreenAcquired();
            resyncToHardwareVsync(true);
        }

        mVisibleRegionsDirty = true;
        repaintEverything();
    } else if (mode == HWC_POWER_MODE_OFF) {
        if (type == DisplayDevice::DISPLAY_PRIMARY) {
            disableHardwareVsync(true); // also cancels any in-progress resync

            // FIXME: eventthread only knows about the main display right now
            mEventThread->onScreenReleased();
        }

        getHwComposer().setPowerMode(type, mode);
        mVisibleRegionsDirty = true;
        // from this point on, SF will stop drawing on this display
    } else {
        getHwComposer().setPowerMode(type, mode);
    }
}

  :initializeDisplays還有一步操做是設置DisplayDevice的PowerMode。主屏幕初始化時的PowerMode爲HWC_POWER_MODE_OFF,如今要更新爲HWC_POWER_MODE_NORMAL。

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
        int mode) {
    ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
            this);
    int32_t type = hw->getDisplayType();
    int currentMode = hw->getPowerMode();

    if (mode == currentMode) {
        ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
        return;
    }
    //更新DisplayDevice的PowerMode
    hw->setPowerMode(mode);
    if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
        ALOGW("Trying to set power mode for virtual display");
        return;
    }

    if (currentMode == HWC_POWER_MODE_OFF) {
        //設置hwc的PowerMode
        getHwComposer().setPowerMode(type, mode);
        if (type == DisplayDevice::DISPLAY_PRIMARY) {
            // FIXME: eventthread only knows about the main display right now
            mEventThread->onScreenAcquired();
            //須要打開硬件vsync同步
            resyncToHardwareVsync(true);
        }

        mVisibleRegionsDirty = true;
        //觸發重繪操做
        repaintEverything();
    } else if (mode == HWC_POWER_MODE_OFF) {
        if (type == DisplayDevice::DISPLAY_PRIMARY) {
            disableHardwareVsync(true); // also cancels any in-progress resync

            // FIXME: eventthread only knows about the main display right now
            mEventThread->onScreenReleased();
        }

        getHwComposer().setPowerMode(type, mode);
        mVisibleRegionsDirty = true;
        // from this point on, SF will stop drawing on this display
    } else {
        getHwComposer().setPowerMode(type, mode);
    }
}

  這裏會更新vysnc週期mPeriod爲hwc層的硬件Vysnc週期,通常爲1/60s,由於從滅屏狀態進入到點亮屏幕狀態須要重建vsync模型。mPrimaryHWVsyncEnabled被初始化爲false,因此經過EventControlThread::setVsyncEnabled就能夠打開硬件Vsync了,今後開始進入Vsync的世界。

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
    Mutex::Autolock _l(mHWVsyncLock);

    if (makeAvailable) {
        mHWVsyncAvailable = true;
    } else if (!mHWVsyncAvailable) {
        ALOGE("resyncToHardwareVsync called when HW vsync unavailable");
        return;
    }

    const nsecs_t period =
            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);

    mPrimaryDispSync.reset();
    mPrimaryDispSync.setPeriod(period);

    if (!mPrimaryHWVsyncEnabled) {         mPrimaryDispSync.beginResync();         //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);         mEventControlThread->setVsyncEnabled(true);         mPrimaryHWVsyncEnabled = true;     } }  

相關文章
相關標籤/搜索