关闭

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

标签: onVSyncReceivedDispSyncSourceresyncToHardwareVsyn
592人阅读 评论(2) 收藏 举报
分类:

这个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
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

Vsync从HWC到APP的传递过程

主要可以分成两个阶段:从HWC到SurfaceFlinger和从SurfaceFlinger到APP。 1.从HWC到SurfaceFlinger Android系统中VSYNC信号分为两种,一种是硬...
  • sosesoA
  • sosesoA
  • 2016-04-07 17:32
  • 1746

Android6.0 显示系统(五) SurfaceFlinger服务

SurfaceFlinger是一个独立的进程,我们来看下init.rc关于SurfaceFlinger的代码,我们可以看到SurfaceFlinger是属于core服务的。 service surfa...
  • kc58236582
  • kc58236582
  • 2016-10-10 10:57
  • 5804

Android SurfaceFlinger对VSync信号的处理过程分析

在Android SurfaceFlinger服务的消息循环过程源码分析中分析了SurfaceFlinger的消息循环过程,SurfaceFlinger通过维护一个消息队列来实现消息的异步处理。A...
  • yangwen123
  • yangwen123
  • 2013-11-28 12:14
  • 4585

GUI系统之SurfaceFlinger(12)VSync信号的产生和处理

文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。 转载请注明:From LXS. http://blog.csdn.net/uiop78uiop78...
  • virus026
  • virus026
  • 2013-07-30 11:15
  • 658

GUI系统之SurfaceFlinger(12)VSync信号的产生和处理

文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。转载请注明:From LXS. http://blog.csdn.net/uiop78uiop78/...
  • uiop78uiop78
  • uiop78uiop78
  • 2013-05-21 13:51
  • 10284

App的启动过程(10)surfaceflinger对数据合成,送显

下面就是SurfaceFlinger执行实际的数据合成,然后刷新到屏幕上。 voidSurfaceFlinger::onMessageReceived(int32_t what) {       ...
  • lin20044140410
  • lin20044140410
  • 2017-06-01 17:43
  • 353

App的启动过程(8)surfaceflinger的启动

接下来就是怎样把BufferQueue中数据,也就是GraphicBuffer中的数据显示到屏幕上,这就是surfaceflinger做的事情。          先说surfaceflinger的...
  • lin20044140410
  • lin20044140410
  • 2017-06-01 17:37
  • 397

Android4.2.2 SurfaceFlinger之图形渲染queueBuffer实现和VSYNC的存在感

前一博文总结了Android4.2.2 SurfaceFlinger之图形缓存区申请与分配dequeueBuffer的实现,由于受到OpenGL Es的中介作用(内部实现图层绘制并写入到分配好的图形缓...
  • gzzaigcn
  • gzzaigcn
  • 2014-03-25 22:24
  • 5004

Android 5.1 SurfaceFlinger VSYNC详解

原文网址(转载请注明出处): http://blog.csdn.net/newchenxf/article/details/49131167VSYNC是自android 4.1版本以后加入的,目的是...
  • newchenxf
  • newchenxf
  • 2015-10-14 21:15
  • 5119

Vsync垂直同步信号分发和SurfaceFlinger响应执行渲染流程分析(一)

自己平时的学习积累,怕忘记,方便查阅,如果能给大家带来帮助,那就更好了,谢谢!
  • sinat_22657459
  • sinat_22657459
  • 2016-10-04 13:01
  • 607
    个人资料
    • 访问:35513次
    • 积分:1686
    • 等级:
    • 排名:千里之外
    • 原创:130篇
    • 转载:38篇
    • 译文:0篇
    • 评论:9条
    最新评论