Android SurfaceFlinger服务(五) ----- VSync信号的产生

Android为了增强界面流畅度引入了VSync机制。VSync信号一般由硬件产生,为了兼容一些老的机器,也可以软件产生。因些,就可以分为硬件VSync和软件VSync。VSync的生成逻辑主要在HWComposer里面。相关文件如下:

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

HWComposer在SurfaceFlinger的init函数里创建:

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

    ......

    // 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));
    
    ......
    
}
  • SurfaceFlinger成员变量保存了HWComposer对象指针
  • 创建HWComposer时,使用SurfaceFlinger作为参数传入
HWComposer::HWComposer(
        const sp<SurfaceFlinger>& flinger,
        EventHandler& handler)
    : mFlinger(flinger),
      mFbDev(0), mHwc(0), mNumDisplays(1),
      mCBContext(new cb_context),
      mEventHandler(handler),
      mDebugForceFakeVSync(false)
{
    ......

    bool needVSyncThread = true;

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

        ......
    }

    ......

    if (needVSyncThread) {
        // we don't have VSYNC support, we need to fake it
        mVSyncThread = new VSyncThread(*this);
    }
}
  • 在构造函数里把SurfaceFlinger对象指针赋值给成员变量mFlinger和mEventHandler
  • 首先尝试加载HWC模块,如果加载成功就使用硬件vsync,加载失败就使用软件模拟vsync

在加载HWC硬件模块时,会注册vsync回调函数HWComposer::hook_vsync。当硬件vsync到来时会调用些函数。代码如下:

void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
        int64_t timestamp) {
    cb_context* ctx = reinterpret_cast<cb_context*>( 
            const_cast<hwc_procs_t*>(procs));
    ctx->hwc->vsync(disp, timestamp);
}
  • 调用hwc对象的vsync函数
void HWComposer::vsync(int disp, int64_t timestamp) { 
    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {                                                                                                                                   
        {
            Mutex::Autolock _l(mLock);                                                                                                                                                       

            // There have been reports of HWCs that signal several vsync events
            // with the same timestamp when turning the display off and on. This
            // is a bug in the HWC implementation, but filter the extra events
            // out here so they don't cause havoc downstream.
            if (timestamp == mLastHwVSync[disp]) {
                ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",                                                                                                             
                        timestamp);            
                return;
            }

            mLastHwVSync[disp] = timestamp;                                                                                                                                                  
        }

        char tag[16];
        snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
        ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);                                                                                                                                           

        mEventHandler.onVSyncReceived(disp, timestamp);                                                                                                                                      
    }  
}
  • 最终调用mEventHandler的onVSyncReceived函数,也既SurfaceFlinger的onVSyncReceived

软件vsync在VSyncThread线程中实现,看看线程循环函数:

bool HWComposer::VSyncThread::threadLoop() {
    { // scope for lock
        Mutex::Autolock _l(mLock);     
        while (!mEnabled) {
            mCondition.wait(mLock);    
        }
    }  

    const nsecs_t period = mRefreshPeriod;
    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
    nsecs_t next_vsync = mNextFakeVSync;
    nsecs_t sleep = next_vsync - now; 
    if (sleep < 0) {
        // we missed, find where the next vsync should be
        sleep = (period - ((now - next_vsync) % period)); 
        next_vsync = now + sleep;  
    }  
    mNextFakeVSync = next_vsync + period;                                                                                                                                                    

    struct timespec spec;
    spec.tv_sec  = next_vsync / 1000000000;
    spec.tv_nsec = next_vsync % 1000000000;                                                                                                                                                  

    int err;
    do {
        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);                                                                                                                  
    } while (err<0 && errno == EINTR);                                                                                                                                                       

    if (err == 0) {
        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);                                                                                                                                   
    }  

    return true;
}
  • 以固定的时间间隔发送vsync信号
  • 调用mEventHandler的onVSyncReceived函数,最终调用SurfaceFlinger的onVSyncReceived函数。
  • 这样不管是硬件vsync还是软件vsync都达成了统一。当VSync信号产生时调用SurfaceFlinger的回调函数onVSyncReceived。

猜你喜欢

转载自www.cnblogs.com/qzhang1535/p/9228434.html