App的启动过程(9)surfaceflinger对vsync的处理

这个onVSyncReceived函数不复杂,感觉就是打开vsync,关掉vsync,但是要弄明白,还是要从surfaceflinger的初始化开始:

         先简单概括下vsync信号的传递:首先是HWComposer产生vsync,通过回调hook_vsync,在通过mEventHandler.onVSyncReceived(disp,timestamp);surfaceflingeronVSyncReceived,接着到DispSyncthreadLoop,通过回调mCallback->onDispSyncEvent到,DispSyncSource中的onDispSyncEvent,然后到EventThread中的onVSyncEvent,最后在EventThreadthreadLoop中通过postEventvsync传给需要的用户,这里主要是surfaceflinger的合成线程和应用程序的渲染线程。

         下面详细分析这个过程:

void SurfaceFlinger::init() {

         sp<VSyncSource>vsyncSrc = new DispSyncSource(&mPrimaryDispSync,

                   vsyncPhaseOffsetNs,true, "app");

         mEventThread= new EventThread(vsyncSrc, *this);

 

         sp<VSyncSource>sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,

                   sfVsyncPhaseOffsetNs,true, "sf");

         mSFEventThread= new EventThread(sfVsyncSrc, *this);

         mEventQueue.setEventThread(mSFEventThread);

}

         这里创建了2EventThread线程,一个跟app的渲染线程有关,每个app都对应一个渲染线程RenderThread,这个线程也需要接收vsync事件,具体就是通过在RenderThread中创建DisplayEventReceiver实例,通过这个mDisplayEventReceiver调用surfaceflinger的函数:createDisplayEventConnection,这个函数会注册回调到EventThread中,这样EventThread就可以把vsync通知到RenderThread

一个跟surfaceflinger的合成线程有关,同时把这个EventThreadsurfaceflinger的事件管理mEventQueue建立了联系,具体就是通过函数:mEventQueue.setEventThread(mSFEventThread);

创建EventThread时,还有2个类:DispSyncSourceDispSync,其实appsurfaceflinger使用的vsync信号并不是真正的硬件vsync,而是属于sw vsync,这两个sw vsync是根据硬件HWCvsync添加一定的偏移计算出来的,目的是为了防止appsurfaceflinger同时被唤醒进行渲染、合成显示,造成争夺cpu资源。完成这个任务就是DispSyncDispSync利用显示设备的硬件vsync信号周期性的特征,在硬件vsync信号特定的偏移处周期性执行回调函数,也就是说只要硬件的vsync周期性地到来,DispSync就会在vsync信号到来的特定时间偏移点,调用相应的回调函数。每次收到一个硬件产生的vsync信号,都会判断是否有必要继续产生硬件vsync,这个判断是通过:addPresentFenceaddResyncSample来确定的,只有认为与硬件的vsync信号有偏离时,才要启动硬件产生vsync,否则就关闭硬件的vsync,它代表硬件的vsync信号。具体代码如下:

void SurfaceFlinger::onVSyncReceived(inttype, nsecs_t timestamp) {

//这里是接收到硬件vsync后,判断是否要硬件继续产生vsync,是就调用:enableHardwareVsync();否则调用:disableHardwareVsync(false)

needsHwVsync =mPrimaryDispSync.addResyncSample(timestamp);

if (needsHwVsync){

         enableHardwareVsync();

} else {

         disableHardwareVsync(false);         }

}

         classDispSyncSource : public VSyncSource, private DispSync::Callback {}

         另外一个类:DispSyncSource,它继承自VSyncSource,并实现了DispSync的回调接口,DispSyncSource代表了一个vsync源,实际是通过DispSync定义的事件模型来维护一个vsync信号源,当有vsync信号时,就通知到EventThread类,DispSyncSource可以认为是DispSyncEventThread之间的桥梁,vsync源是否依赖于硬件真实的vsyncEventThread不用关心。

         surfaceflinger初始化时,除了2EventThread外,还有一个线程:EventControlThread

这个线程是控制打开、关闭硬件的vsync源。

bool EventControlThread::threadLoop() {

         mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY,mVsyncEnabled);

         mFlinger->eventControl(HWC_DISPLAY_PRIMARY,SurfaceFlinger::EVENT_VSYNC,

                   mVsyncEnabled);

}

void SurfaceFlinger::eventControl(int disp,int event, int enabled) {

         getHwComposer().eventControl(disp,event, enabled);

}

         EventThreadEventControlThread这两个线程实例化时都会执行其onFirstRef方法,然后run起来,都进入了wait,等待后续被唤醒,什么时候被唤醒,下面的分析中会有答案。

         接下来看下vsync是怎样触发了surfaceflinger的合成、显示工作的。

         先从init中的这句调用开始:mEventQueue.setEventThread(mSFEventThread);

         mEventQueueMessageQueue)是surfaceflinger的消息循环机制的管理者,这个函数调用就把MessageQueueEventThread建立了连接,这样surfaceflinger才能真正收到HWCvsync信号。

void MessageQueue::setEventThread(constsp<EventThread>& eventThread){

//首先通过eventThread创建了一个Connection,这个Connection会保存在一个容器中:mDisplayEventConnections,接着得到了vsync信号通知的BitTube,本质上是UDS,然后监听这个BitTube中的socket,并指定了回调函数:MessageQueue::cb_eventReceiver,这样一旦把vsync写入到BitTubecb_eventReceiver就会被调用,这就实现了进程间通信。
         mEventThread = eventThread;

         mEvents= eventThread->createEventConnection();

         mEventTube= mEvents->getDataChannel();

         mLooper->addFd(mEventTube->getFd(),0, Looper::EVENT_INPUT,

                   MessageQueue::cb_eventReceiver,this);

}

         在继续分析vsync的处理前,先看surfaceflingerinit中一段跟显示初始化相关的代码。就是:initializeDisplays();

void SurfaceFlinger::initializeDisplays() {

         flinger->onInitializeDisplays(); -->void SurfaceFlinger::onInitializeDisplays(){}  --> void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,);

}

void SurfaceFlinger:: setPowerModeInternal (…){

// setPowerModeInternal这个函数在屏幕点亮时也会被调用,

         if(currentMode == HWC_POWER_MODE_OFF) {

                   mEventThread->onScreenAcquired();

                   resyncToHardwareVsync(true);

}

}

//前面说过,EventThread运行后就wait了,这里的mCondition.broadcast()会唤醒这个线程。

void EventThread::onScreenAcquired() {

         mCondition.broadcast();

}

//这个函数的功能就是打开HWCvsync功能,

void SurfaceFlinger::resyncToHardwareVsync(boolmakeAvailable) {

//获取Hwc的信号发送间隔,然后设置到mPrimaryDispSync

         constnsecs_t period = getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);

         mPrimaryDispSync.setPeriod(period);

//调用mEventControlThread打开HWCvsync功能。

         if(!mPrimaryHWVsyncEnabled) {

                   mPrimaryDispSync.beginResync();

                   mEventControlThread->setVsyncEnabled(true);

//onVSyncReceived时,mPrimaryHWVsyncEnabled这个值是其中一个判断条件。

                   mPrimaryHWVsyncEnabled= true;

         }

}

         下面就分析EventThread这个线程的核心函数:threadLoop

// threadLoop中先调用了waitForEvent,然后循环分发vsync给监听者。

bool EventThread::threadLoop() {

         signalConnections= waitForEvent(&event);

         constsize_t count = signalConnections.size();

         for(size_t i=0 ; i<count ; i++) {

                   constsp<Connection>& conn(signalConnections[i]);

                   status_terr = conn->postEvent(event);

         }

}

// waitForEvent中也有关闭、开启vsync信号的调用,真正开关vsync的是EventControlThread,这里的调用enableVSyncLockeddisableVSyncLocked并不是真的开关硬件的vsync功能,只是向DispSync添加和删除信号的监听者,通过添加监听者,新的监听者就能收到HwcVsync信号,而一旦删除,EventThread就不再接收消息,就等于关闭了vsync信号。

Vector<sp<EventThread::Connection> > EventThread::waitForEvent(){

         if(timestamp && !waitForVSync) {

                   disableVSyncLocked();

} else if(!timestamp && waitForVSync) {

         enableVSyncLocked();

}

}

void EventThread::enableVSyncLocked() {

         mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));

         mVSyncSource->setVSyncEnabled(true);

}

virtual void DispSyncSource ::setVSyncEnabled(boolenable) {

         if(enable) {

                   status_terr = mDispSync->addEventListener(mName, mPhaseOffset,

                            static_cast<DispSync::Callback*>(this));

} else {

status_t err =mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this));

}

}

接下来waitforEvent会通过mCondition.waitRelative()mCondition.wait()进入等待,等待vsync信号的到来。

下面看当vsync到来时,系统到底是怎么处理的?

不管vsync是硬件发出、还是软件发出,surfaceflingerEventHandler)收到vsync后的处理函数都是:onVSyncReceived

void SurfaceFlinger::onVSyncReceived(inttype, nsecs_t timestamp) {

//返回值会决定是否要关闭硬件的vsync

         needsHwVsync= mPrimaryDispSync.addResyncSample(timestamp);

         if(needsHwVsync) {

                   enableHardwareVsync();

         }else {     

                   disableHardwareVsync(false);         }

}

         先看addResyncSample,这个函数一方面会唤醒DispSyncThread线程,调用注册的回调,另一方面返回值决定是否关闭Hwcvsync源。只关注重点函数的调用。

bool DispSync::addResyncSample(nsecs_ttimestamp) {

         updateModelLocked();

}

void DispSync::updateModelLocked() {

// mThread就是DispSyncThreadmCond.signal()会唤醒处于等待中的这个线程

         mThread->updateModel(mPeriod,mPhase, mReferenceTime);à mCond.signal();

// mModelUpdated这个值为true,会让addResyncSample的返回值为false,进而会调用disableHardwareVsync(false);关闭Hwcvsync源,关闭了vsync源后,关闭vsync后,Hwc不会再周期性的调用SurfaceFlinger::onVSyncReceived了,等于说后续是DispSync代替Hwc维护了一个vsync源。什么时候可能会再次打开?一种情况是每次点亮屏幕时,还有一种情况就是处理显示合成时会判断要不要打开Hwcvsync源,具体是函数在函数:SurfaceFlinger::postComposition中。

         mModelUpdated= true;

}

         接着看DispSyncThread醒来后,怎样执行回调函数的?

virtual bool DispSyncThread::threadLoop() {

//计算下一次的vsync时间

         targetTime= computeNextEventTimeLocked(now);

// gatherCallbackInvocationsLocked是从mEventListeners中取出之前注册的监听者,放到容器callbackInvocations中,而监听者的来源,在EventThread中已经分析了,就是通过waitForEventà enableVSyncLockedà setVSyncEnabledà addEventListener添加的。

         callbackInvocations= gatherCallbackInvocationsLocked(now);

//调用容器中的所有回调。

         fireCallbackInvocations(callbackInvocations);

}

void fireCallbackInvocations(constVector<CallbackInvocation>& callbacks) {

         for(size_t i = 0; i < callbacks.size(); i++) {

                   callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);    }

}

这里的onDispSyncEvent就是EventThread的函数。

void EventThread::onVSyncEvent(nsecs_ttimestamp) {

//设置事件的类型,唤醒EventThread线程,进入threadLoop中。

         mVSyncEvent[0].header.type= DisplayEventReceiver::DISPLAY_EVENT_VSYNC;

         mCondition.broadcast();

}

//通过postEvent循环分发事件给监听者。

bool EventThread::threadLoop() {

         constsize_t count = signalConnections.size();

         for(size_t i=0 ; i<count ; i++) {

                   constsp<Connection>& conn(signalConnections[i]);

                   status_terr = conn->postEvent(event);

}

}

status_tEventThread::Connection::postEvent(){

         ssize_tsize = DisplayEventReceiver::sendEvents(mChannel, &event, 1);

}

//当往BitTube中的socket写数据时,之前注册的回调函数:MessageQueue::cb_eventReceiver就会被调用

ssize_tDisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,…){

         returnBitTube::sendObjects(dataChannel, events, count);

}

// MessageQueue中,经过looperhandlerhandleMessage的分发处理,最终以INVALIDATE消息的形式进入了SurfaceFlingeronMessageReceived

int MessageQueue::cb_eventReceiver(int fd,int events, void* data) {

         MessageQueue*queue = reinterpret_cast<MessageQueue *>(data);

         returnqueue->eventReceiver(fd, events);

}

voidMessageQueue::Handler::handleMessage(const Message& message) {

         mQueue.mFlinger->onMessageReceived(message.what);

}

//到这里vsync的产生、接收就分析完了。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值